improvements to local question cache

This commit is contained in:
Ross
2021-03-10 10:07:33 +00:00
parent 91e2308386
commit 5f64d0dd1e
3 changed files with 165 additions and 103 deletions
+15
View File
@@ -613,6 +613,21 @@ img {
overflow: auto;
}
.fullscreen-overlay-transparent {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
cursor: pointer;
color: lightgray;
overflow: auto;
}
#review-overlay {
overflow: scroll;
padding: 20px;
+1 -1
View File
@@ -163,7 +163,7 @@
</div>
</div>
</div>
<div id="question-loading" class="fullscreen-overlay">
<div id="question-loading" class="fullscreen-overlay-transparent">
<div class="progress-block">
<div class="lds-ripple"><div></div><div></div></div>
</div>
+103 -56
View File
@@ -30,13 +30,17 @@ let question_type = null;
let loaded_question = null;
window.review = false;
let exam_time = null;
let packet_time = null;
let date_started = null;
let score = 0;
let packet_generated = null;
let allow_self_marking = true;
let timer = null;
let use_local_question_cache = false;
//window.dfile = null;
window.config = config;
@@ -131,6 +135,8 @@ async function loadExamList(data) {
window.exam_list.forEach(function (exam) {
let name = exam["name"];
let url = exam["url"];
let eid = exam["eid"];
let generated = exam["json_creation_time"];
let c = "";
if (exams_started.indexOf(name) > -1) {
c = " session-started";
@@ -156,7 +162,7 @@ async function loadExamList(data) {
$(`<div class='packet-button${c}' title='Load packet'></div>`)
.text(name)
.click(function () {
loadPacketFromAjax(url);
loadPacketFromAjax(url, eid, generated);
})
);
});
@@ -256,7 +262,38 @@ async function loadPacketList(data) {
* Loads the requisite packet into the quiz system
* @param {string} path - relative path to the packet json file
*/
function loadPacketFromAjax(path) {
function loadPacketFromAjax(path, eid, generated) {
if (eid != undefined) {
// try and load the exam from the local indexedDB
question_db.saved_exams
.get(eid)
.then((exam) => {
if (
exam == undefined ||
Date.parse(exam["generated"]) != Date.parse(generated)
) {
ajaxRequestionPacket();
} else {
console.log(exam);
// We have an up to date exam in the database
// TODO: check the questions are valid
use_local_question_cache = true;
setUpPacket(exam, path);
$("#options-panel").hide();
}
})
.catch(function (error) {
// Will be triggered if eid does not exist in database
console.log("Unable to load exam:", eid);
console.log("error-", error);
console.log("Exam will be downloaded");
ajaxRequestionPacket();
});
return;
}
function ajaxRequestionPacket() {
//console.log("loading packet from " + path);
$("#progress").html(`Requesting packet: ${path}`);
@@ -275,16 +312,13 @@ function loadPacketFromAjax(path) {
},
})
.done(function (data) {
//setUpPacket(data, path.split("/").pop());
if (data.hasOwnProperty("cached") && data["cached"]) {
//console.log("loading cached packet");
}
setUpPacket(data, path);
$("#options-panel").hide();
})
.fail(function () {
//console.log("Unable to load packet at: " + path);
console.log("Unable to load packet at: " + path);
});
}
}
/**
@@ -292,9 +326,9 @@ function loadPacketFromAjax(path) {
*/
function setUpQuestions(load_previous) {
if (questions == undefined) {
return;
}
//return;
} else {
if (!use_local_question_cache) {
Object.keys(questions).forEach(function (e) {
// Store question data into dexie
let d = {
@@ -305,6 +339,7 @@ function setUpQuestions(load_previous) {
question_db.question_data.put(d);
});
}
// Set an order for the questions
if (!load_previous) {
@@ -328,13 +363,13 @@ function setUpQuestions(load_previous) {
question_order = helper.shuffleArray(question_order);
}
}
window.number_of_questions = Object.keys(questions).length;
}
window.number_of_questions = question_order.length;
window.review = false;
// Horrible way to get type of questions
// We assume they are all of the same type....
question_type =
questions[Object.keys(questions)[0]].type;
//question_type = questions[Object.keys(questions)[0]].type;
if (window.exam_details.exam_mode) {
$("#options-button, #review-overlay-button").hide();
@@ -344,7 +379,6 @@ function setUpQuestions(load_previous) {
questions = null;
//console.log(question_type);
// exam_time can be defined in packets
@@ -425,10 +459,10 @@ db.version(1).stores({
const question_db = new Dexie("question_database");
question_db.version(1).stores({
question_data: "[eid+qid], eid, data",
question_data: "[eid+qid], eid",
saved_exams: "eid, type, exam_mode, name, order, time, generated",
});
//db = db;
/**
* Parse the packet and extract metadata (if it exists)
@@ -447,12 +481,16 @@ function setUpPacket(data, path) {
window.exam_details.eid = data.eid;
}
if (data.hasOwnProperty("type")) {
question_type = data.type;
if (data.hasOwnProperty("exam_type")) {
question_type = data.exam_type;
}
if (data.hasOwnProperty("generated")) {
packet_generated = data.generated;
}
if (data.hasOwnProperty("exam_mode")) {
window.exam_details.exam_mode = data.exam_mode;
exam_details.exam_mode = data.exam_mode;
}
if (data.hasOwnProperty("questions")) {
@@ -467,8 +505,20 @@ function setUpPacket(data, path) {
if (data.hasOwnProperty("exam_time")) {
exam_time = data.exam_time;
// packet time is the time specificed by the packet
packet_time = data.exam_time;
}
if (use_local_question_cache) {
// If loading form cache nothing else to do here
loadSession();
return;
}
// Save the details to the question database
var clone_data = Object.assign({}, data, { questions: undefined });
question_db.saved_exams.put(clone_data);
// If the question_requests is set we need to do a request for each question
if (data.hasOwnProperty("question_requests") && data["question_requests"]) {
const question_total = Object.keys(data["questions"]).length;
@@ -506,7 +556,19 @@ function setUpPacket(data, path) {
//requests.push(request)
//request_numbers.push(n)
data["questions"][n] = question_json;
// Using indexed db means that we can avoid loading all data into memory
//data["questions"][n] = question_json;
// Store question data into dexie
let d = {
eid: window.exam_details.eid,
qid: n,
data: question_json,
};
question_db.question_data.put(d);
use_local_question_cache = true;
}
// Once all questions have been downloaded we carry on loading
loadSession();
@@ -524,10 +586,7 @@ function loadSession() {
// .where("status")
// .equals("active")
.where("[packet+aid]")
.between(
[packet_name, Dexie.minKey],
[packet_name, Dexie.maxKey]
)
.between([packet_name, Dexie.minKey], [packet_name, Dexie.maxKey])
.toArray()
.then((sessions) => {
//console.log("sessions", sessions);
@@ -621,20 +680,18 @@ function loadSession() {
* @param {boolean} force_reload - Force question to be reloaded if already loaded
*/
async function loadQuestion(n, section = 1, force_reload = false) {
$("#question-loading").show();
const aid = window.exam_details.aid;
const cid = window.exam_details.cid;
const eid = window.exam_details.eid;
// Make sure we have an integer
n = parseInt(n);
//console.log("loading question (n)", n);
const qid = question_order[n];
let q = {qid: qid.toString(), eid: eid};
let q = { qid: qid.toString(), eid: eid };
let return_data = await question_db.question_data.get(q);
const question_data = return_data.data;
@@ -645,6 +702,7 @@ async function loadQuestion(n, section = 1, force_reload = false) {
if (n == loaded_question && force_reload == false) {
// Question already loaded
setFocus(section);
$("#question-loading").hide();
return;
}
@@ -856,9 +914,9 @@ async function loadQuestion(n, section = 1, force_reload = false) {
// db.answers.put({aid: [cid, eid, qidn], ans: evt.target.value});
db.answers.put(answer);
$(
"#question-list-item-" + question_order.indexOf(qid) + "-2"
).addClass("question-saved-localdb");
$("#question-list-item-" + question_order.indexOf(qid) + "-2").addClass(
"question-saved-localdb"
);
saveSession();
updateQuestionListPanel(answer);
@@ -938,9 +996,9 @@ async function loadQuestion(n, section = 1, force_reload = false) {
// db.answers.put({aid: [cid, eid, qidn], ans: evt.target.value});
db.answers.put(answer);
$(
"#question-list-item-" + question_order.indexOf(qid) + "-1"
).addClass("question-saved-localdb");
$("#question-list-item-" + question_order.indexOf(qid) + "-1").addClass(
"question-saved-localdb"
);
saveSession();
updateQuestionListPanel(answer);
});
@@ -1008,10 +1066,7 @@ async function loadQuestion(n, section = 1, force_reload = false) {
if (evt.target.value.length < 1) {
db.answers.delete([aid, cid, eid, qid, qidn]);
$(
"#question-list-item-" +
question_order.indexOf(qid) +
"-" +
qidn
"#question-list-item-" + question_order.indexOf(qid) + "-" + qidn
).removeClass("question-saved-localdb");
return;
}
@@ -1029,10 +1084,7 @@ async function loadQuestion(n, section = 1, force_reload = false) {
console.log("SAVE", qid, qidn, evt.target.value);
$(
"#question-list-item-" +
question_order.indexOf(qid) +
"-" +
qidn
"#question-list-item-" + question_order.indexOf(qid) + "-" + qidn
).addClass("question-saved-localdb");
saveSession();
updateQuestionListPanel(answer);
@@ -1081,8 +1133,8 @@ async function loadQuestion(n, section = 1, force_reload = false) {
//rebuildQuestionListPanel();
setTimeout(() => {
setFocus(section);
$("#question-loading").hide();
}, 200);
$("#question-loading").hide();
}
/**
@@ -1121,17 +1173,15 @@ function updateQuestionListPanel(answer) {
if (question_type == "rapid" && answer.qidn == "1") {
if (answer.ans == "Abnormal") {
$(
"#question-list-item-" +
question_order.indexOf(answer.qid) +
"-2"
).css("display", "block");
$("#question-list-item-" + question_order.indexOf(answer.qid) + "-2").css(
"display",
"block"
);
} else {
$(
"#question-list-item-" +
question_order.indexOf(answer.qid) +
"-2"
).css("display", "none");
$("#question-list-item-" + question_order.indexOf(answer.qid) + "-2").css(
"display",
"none"
);
}
}
}
@@ -1651,10 +1701,7 @@ function reviewQuestions() {
score = correct_count;
$("#review-score").text(
"Score: " +
correct_count +
" out of " +
question_order.length
"Score: " + correct_count + " out of " + question_order.length
);
if (question_type == "rapid") {