Skip to content

Commit 2d7b6f7

Browse files
committed
Only init exam storage after questions are ready
Now that questions can take some time to become ready after the list is initialised, the total marks available for the exam aren't calculated at the time Exam.init runs. This moves the storage initialisation to happen after the questions are all ready. I don't think that anything can use the storage in the intervening time, so it should be safe.
1 parent 119541e commit 2d7b6f7

File tree

3 files changed

+91
-20
lines changed

3 files changed

+91
-20
lines changed

runtime/scripts/exam.js

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -636,24 +636,20 @@ Exam.prototype = /** @lends Numbas.Exam.prototype */ {
636636
init: function()
637637
{
638638
var exam = this;
639-
if(exam.store) {
640-
job(exam.store.init,exam.store,exam); //initialise storage
641-
job(exam.set_exam_variables, exam);
642-
}
643639
job(exam.chooseQuestionSubset,exam); //choose questions to use
644640
job(exam.makeQuestionList,exam); //create question objects
645-
exam.signals.on('question list initialised', function() {
646-
if(exam.store) {
647-
job(exam.store.init_questions,exam.store,exam); //initialise question storage
648-
job(exam.store.save,exam.store); //make sure data get saved to LMS
649-
}
650-
});
651641
var ready_signals = ['question list initialised'];
652642
if(exam.settings.navigateMode=='diagnostic') {
653643
ready_signals.push('diagnostic controller initialised');
654644
}
655645
exam.signals.on(ready_signals, function() {
656646
job(function() {
647+
if(exam.store) {
648+
exam.store.init(exam); //initialise storage
649+
exam.set_exam_variables();
650+
exam.store.init_questions(); //initialise question storage
651+
exam.store.save(); //make sure data get saved to LMS
652+
}
657653
exam.calculateScore();
658654
exam.signals.trigger('ready');
659655
});

tests/numbas-runtime.js

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24903,24 +24903,20 @@ Exam.prototype = /** @lends Numbas.Exam.prototype */ {
2490324903
init: function()
2490424904
{
2490524905
var exam = this;
24906-
if(exam.store) {
24907-
job(exam.store.init,exam.store,exam); //initialise storage
24908-
job(exam.set_exam_variables, exam);
24909-
}
2491024906
job(exam.chooseQuestionSubset,exam); //choose questions to use
2491124907
job(exam.makeQuestionList,exam); //create question objects
24912-
exam.signals.on('question list initialised', function() {
24913-
if(exam.store) {
24914-
job(exam.store.init_questions,exam.store,exam); //initialise question storage
24915-
job(exam.store.save,exam.store); //make sure data get saved to LMS
24916-
}
24917-
});
2491824908
var ready_signals = ['question list initialised'];
2491924909
if(exam.settings.navigateMode=='diagnostic') {
2492024910
ready_signals.push('diagnostic controller initialised');
2492124911
}
2492224912
exam.signals.on(ready_signals, function() {
2492324913
job(function() {
24914+
if(exam.store) {
24915+
exam.store.init(exam); //initialise storage
24916+
exam.set_exam_variables();
24917+
exam.store.init_questions(); //initialise question storage
24918+
exam.store.save(); //make sure data get saved to LMS
24919+
}
2492424920
exam.calculateScore();
2492524921
exam.signals.trigger('ready');
2492624922
});

tests/parts/part-tests.mjs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2498,6 +2498,85 @@ mark:
24982498
}
24992499
return API;
25002500
}
2501+
2502+
2503+
QUnit.test('SCORM initialisation', async function(assert) {
2504+
var done = assert.async();
2505+
var exam_def = {
2506+
name: "Exam",
2507+
question_groups: [
2508+
{
2509+
questions: [
2510+
{
2511+
name: "Q",
2512+
variables: {
2513+
x: {
2514+
name: "x",
2515+
definition: "random(1..100#0)",
2516+
description: "A random number between 1 and 100",
2517+
templateType: "anything"
2518+
}
2519+
},
2520+
parts: [
2521+
{
2522+
type: 'numberentry',
2523+
minvalue: '5',
2524+
maxvalue: '6',
2525+
marks: 3
2526+
}
2527+
]
2528+
}
2529+
]
2530+
}
2531+
]
2532+
};
2533+
await with_scorm(
2534+
async function(data, results, scorm) {
2535+
var e = Numbas.createExamFromJSON(exam_def,Numbas.store,false);
2536+
e.init();
2537+
await e.signals.on('ready');
2538+
const expected_data = {
2539+
"cmi.objectives._count": 1,
2540+
"cmi.interactions._count": 1,
2541+
"cmi.learner_name": "",
2542+
"cmi.learner_id": "",
2543+
"cmi.location": "",
2544+
"cmi.score.raw": 0,
2545+
"cmi.score.scaled": 0,
2546+
"cmi.score.min": 0,
2547+
"cmi.score.max": "3",
2548+
"cmi.total_time": 0,
2549+
"cmi.success_status": "unknown",
2550+
"cmi.completion_status": "incomplete",
2551+
"cmi.exit": "suspend",
2552+
"cmi.progress_measure": "0",
2553+
"cmi.session_time": "PT0H0M0S",
2554+
"cmi.objectives.0.id": "q0",
2555+
"cmi.objectives.0.score.min": "0",
2556+
"cmi.objectives.0.score.max": "3",
2557+
"cmi.objectives.0.score.raw": "0",
2558+
"cmi.objectives.0.success_status": "unknown",
2559+
"cmi.objectives.0.completion_status": "not attempted",
2560+
"cmi.objectives.0.progress_measure": "0",
2561+
"cmi.objectives.0.description": "Q",
2562+
"cmi.interactions.0.id": "q0p0",
2563+
"cmi.interactions.0.objectives.0.id": "q0",
2564+
"cmi.interactions.0.objectives._count": 1,
2565+
"cmi.interactions.0.weighting": "3",
2566+
"cmi.interactions.0.result": "0",
2567+
"cmi.interactions.0.description": "numberentry",
2568+
"cmi.interactions.0.type": "fill-in",
2569+
"cmi.interactions.0.correct_responses.0.pattern": "5[:]6",
2570+
"cmi.interactions.0.correct_responses._count": 1,
2571+
};
2572+
Object.entries(expected_data).forEach(([k,v]) => {
2573+
assert.equal(scorm.GetValue(k), v, `${k} = ${v}`);
2574+
});
2575+
done();
2576+
}
2577+
);
2578+
});
2579+
25012580
QUnit.test('Resume an exam',async function(assert) {
25022581
var done = assert.async();
25032582
var exam_def = {

0 commit comments

Comments
 (0)