openct-tasks/_common/modules/pemFioi/quiz/grader.js

124 lines
4.7 KiB
JavaScript

(function() {
function isArrayAnswerEmpty(answers) {
for(var i=0; i<answers.length; i++) {
if(typeof answers[i] != "undefined") { return false; }
}
return true;
}
function testMultiple(valid, answers) {
var mistakes = [];
for(var i=0; i<answers.length; i++) {
if(valid.indexOf(answers[i]) === -1) {
mistakes.push(answers[i]);
}
}
return mistakes.length == 0 && valid.length == answers.length ? true : mistakes;
}
function testStrict(valid, answers) {
var mistakes = [];
for(var i=0; i<answers.length; i++) {
if(valid[i] !== answers[i]) {
mistakes.push(answers[i]);
}
}
return mistakes.length == 0 && valid.length == answers.length ? true : mistakes;
}
window.Quiz.grader.handler = function(grader_data, answer, versions, score_settings) {
var res = {
score_settings: score_settings,
score: 0,
mistakes: [],
messages: []
};
var isValid;
var nb_valid = 0;
var nb_mistakes = 0;
for (var i = 0; i < grader_data.length; i++) {
var grader = grader_data[i];
if(versions && i in versions) {
grader = grader[versions[i]];
}
if (typeof grader === "function") {
if(typeof answer[i] == 'undefined') { continue; }
var fres = grader(answer[i]);
if (typeof fres === "object") {
var score =
"score" in fres ? parseFloat(fres.score) || 0 : 0;
isValid = score > 0;
if ("message" in fres && fres.message) {
res.messages[i] = fres.message;
}
nb_valid += score;
nb_mistakes += score > 0 ? 0 : 1;
} else {
isValid = !!fres;
nb_valid += isValid ? 1 : 0;
nb_mistakes += isValid ? 0 : 1;
}
res.mistakes.push(isValid ? null : answer[i]);
} else if (Array.isArray(grader)) {
if(isArrayAnswerEmpty(answer[i])) { continue; }
var test = testMultiple(grader, answer[i]);
isValid = test === true;
res.mistakes.push(isValid ? [] : test);
nb_valid += isValid ? 1 : 0;
nb_mistakes += isValid ? 0 : 1;
} else if (typeof grader == 'object') {
if(Array.isArray(grader.value)) {
if(isArrayAnswerEmpty(answer[i])) { continue; }
if(grader.strict) {
var test = testStrict(grader.value, answer[i]);
} else {
var test = testMultiple(grader.value, answer[i]);
}
isValid = test === true;
var mistakes = isValid ? [] : test;
res.mistakes.push(mistakes);
if(grader.messages && mistakes.length) {
res.messages[i] = [];
for(var j=0; j<mistakes.length; j++) {
if(grader.messages[mistakes[j]]) {
res.messages[i][mistakes[j]] = grader.messages[mistakes[j]];
}
}
}
} else {
if(typeof answer[i] == 'undefined') { continue; }
isValid = grader == answer[i] ? 1 : 0;
res.mistakes.push(isValid ? null : answer[i]);
if(grader.messages && !isValid && grader.messages[answer[i]]) {
res.messages[i] = grader.messages[answer[i]];
}
}
nb_valid += isValid ? 1 : 0;
nb_mistakes += isValid ? 0 : 1;
} else {
if(typeof answer[i] == 'undefined') { continue; }
isValid = grader == answer[i] ? 1 : 0;
res.mistakes.push(isValid ? null : answer[i]);
nb_valid += isValid ? 1 : 0;
nb_mistakes += isValid ? 0 : 1;
}
}
var nb_total = grader_data.length;
if(score_settings) {
res.score = (nb_valid * score_settings.maxScore
+ nb_mistakes * score_settings.minScore
+ (nb_total - nb_valid - nb_mistakes) * score_settings.noScore) / nb_total;
} else {
res.score = nb_valid / nb_total;
}
res.score = Math.round(res.score);
return res;
};
})();