X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=public%2Fjavascripts%2Fassessment.js;h=2a451e4a19ad8df24be8ae4dcad59d93d0778533;hb=73609d3bc662cf4c8a21746c5d1ad736ea0eecbd;hp=95cd4d74ca5cffe0c9ca479f8206a661a1b7553d;hpb=db5571d67f6b6b3b841fa1eeaf2099cecf2bcffc;p=qomet.git diff --git a/public/javascripts/assessment.js b/public/javascripts/assessment.js index 95cd4d7..2a451e4 100644 --- a/public/javascripts/assessment.js +++ b/public/javascripts/assessment.js @@ -10,7 +10,7 @@ function checkWindowSize() return true; // 3 is arbitrary, but a small tolerance is required (e.g. in Firefox) return window.innerWidth >= screen.width-3 && window.innerHeight >= screen.height-3; -}; +} new Vue({ el: "#assessment", @@ -23,63 +23,52 @@ new Vue({ // 2: locked: password set, exam started // 3: completed // 4: show answers + remainingTime: assessment.time, //integer or array stage: assessment.mode != "open" ? 0 : 1, - remainingTime: 0, //global, in seconds warnMsg: "", }, computed: { countdown: function() { - let seconds = this.remainingTime % 60; - let minutes = Math.floor(this.remainingTime / 60); + const remainingTime = assessment.display == "one" && _.isArray(assessment.time) + ? this.remainingTime[this.answers.index] + : this.remainingTime; + let seconds = remainingTime % 60; + let minutes = Math.floor(remainingTime / 60); return this.padWithZero(minutes) + ":" + this.padWithZero(seconds); }, - showAnswers: function() { - return this.stage == 4; - }, }, mounted: function() { $(".modal").modal(); - if (assessment.mode != "open") - { - window.addEventListener("keydown", e => { - // Ignore F12 (avoid accidental window resize due to devtools) - // NOTE: in Chromium at least, fullscreen mode exit with F11 cannot be prevented. - // Workaround: disable key at higher level. Possible xbindkey config: - // "false" - // m:0x10 + c:95 - // Mod2 + F11 - if (e.keyCode == 123) - e.preventDefault(); - }, false); - } + if (["exam","open"].includes(assessment.mode)) + return; window.addEventListener("blur", () => { - if (!socket) + if (this.stage != 2) return; if (assessment.mode == "secure") { - this.trySendCurrentAnswer(); + this.sendAnswer(); document.location.href= "/noblur"; } - else if (assessment.mode == "exam") + else //"watch" mode socket.emit(message.studentBlur, {number:this.student.number}); }, false); - if (assessment.mode == "exam") + if (assessment.mode == "watch") { window.addEventListener("focus", () => { - if (!socket) + if (this.stage != 2) return; socket.emit(message.studentFocus, {number:this.student.number}); }, false); } window.addEventListener("resize", e => { - if (!socket) + if (this.stage != 2) return; if (assessment.mode == "secure") { - this.trySendCurrentAnswer(); - document.location.href= "/fullscreen"; + this.sendAnswer(); + document.location.href = "/fullscreen"; } - else if (assessment.mode == "exam") + else //"watch" mode { if (checkWindowSize()) socket.emit(message.studentFullscreen, {number:this.student.number}); @@ -89,7 +78,7 @@ new Vue({ }, false); }, methods: { - // In case of AJAX errors + // In case of AJAX errors (not blur-ing) showWarning: function(message) { this.warnMsg = message; $("#warning").modal("open"); @@ -99,13 +88,9 @@ new Vue({ return "0" + x; return x; }, - trySendCurrentAnswer: function() { - if (this.stage == 2) - this.sendAnswer(); - }, // stage 0 --> 1 - getStudent: function(cb) { - $.ajax("/get/student", { + getStudent: function() { + $.ajax("/courses/student", { method: "GET", data: { number: this.student.number, @@ -118,8 +103,6 @@ new Vue({ this.stage = 1; this.student = s.student; Vue.nextTick( () => { Materialize.updateTextFields(); }); - if (!!cb) - cb(); }, }); }, @@ -129,15 +112,14 @@ new Vue({ }, // stage 1 --> 2 (get all questions, set password) startAssessment: function() { - let initializeStage2 = (questions,paper) => { + let initializeStage2 = paper => { $("#leftButton, #rightButton").hide(); - if (assessment.time > 0) - { - const deltaTime = !!paper ? Date.now() - paper.startTime : 0; - this.remainingTime = assessment.time * 60 - Math.round(deltaTime / 1000); - this.runTimer(); - } // Initialize structured answer(s) based on questions type and nesting (TODO: more general) + + // if display == "all" getQuestionS + // otherwise get first question + + if (!!questions) assessment.questions = questions; this.answers.inputs = [ ]; @@ -156,6 +138,24 @@ new Vue({ let remainingIndices = _.difference( _.range(assessment.questions.length).map(String), indices ); this.answers.indices = indices.concat( _.shuffle(remainingIndices) ); } + + + + + + + + if (assessment.time > 0) + { + +// TODO: distinguish total exam time AND question time + + const deltaTime = !!paper ? Date.now() - paper.startTime : 0; + this.remainingTime = assessment.time * 60 - Math.round(deltaTime / 1000); + this.runTimer(); + } + + this.answers.index = !!paper ? paper.inputs.length : 0; this.answers.displayAll = assessment.display == "all"; this.answers.showSolution = false; @@ -163,8 +163,8 @@ new Vue({ }; if (assessment.mode == "open") return initializeStage2(); - $.ajax("/start/assessment", { - method: "GET", + $.ajax("/assessments/start", { + method: "PUT", data: { number: this.student.number, aid: assessment._id @@ -193,8 +193,10 @@ new Vue({ }, }); }, + + // stage 2 - runTimer: function() { + runGlobalTimer: function() { if (assessment.time <= 0) return; let self = this; @@ -208,6 +210,23 @@ new Vue({ } }, 1000); }, + runQuestionTimer: function(idx) { + if (assessment.questions[idx].time <= 0) + return; + let self = this; //TODO: question remaining time + setInterval( function() { + self.remainingTime--; + if (self.remainingTime <= 0) + { + if (self.stage == 2) + self.endAssessment(); + clearInterval(this); + } + }, 1000); + }, + +//TODO: get question after sending answer + // stage 2 sendOneAnswer: function() { const realIndex = this.answers.indices[this.answers.index]; @@ -232,8 +251,8 @@ new Vue({ number: this.student.number, password: this.student.password, }; - $.ajax("/send/answer", { - method: "GET", + $.ajax("/assessments/answer", { + method: "PUT", data: answerData, dataType: "json", success: ret => { @@ -263,8 +282,8 @@ new Vue({ this.answers.displayAll = true; return; } - $.ajax("/end/assessment", { - method: "GET", + $.ajax("/assessments/end", { + method: "PUT", data: { aid: assessment._id, number: this.student.number,