'update'
[qomet.git] / public / javascripts / assessment.js
diff --git a/public/javascripts/assessment.js b/public/javascripts/assessment.js
deleted file mode 100644 (file)
index 2a451e4..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-let socket = null; //monitor answers in real time
-
-if (assessment.mode == "secure" && !checkWindowSize())
-       document.location.href= "/fullscreen";
-
-function checkWindowSize()
-{
-       // NOTE: temporarily accept smartphone (security hole: pretend being a smartphone on desktop browser...)
-       if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/))
-               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",
-       data: {
-               assessment: assessment,
-               answers: { }, //filled later with answering parameters
-               student: { }, //filled later (name, password)
-               // Stage 0: unauthenticated (number),
-               //       1: authenticated (got a name, unvalidated)
-               //       2: locked: password set, exam started
-               //       3: completed
-               //       4: show answers
-               remainingTime: assessment.time, //integer or array
-               stage: assessment.mode != "open" ? 0 : 1,
-               warnMsg: "",
-       },
-       computed: {
-               countdown: function() {
-                       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);
-               },
-       },
-       mounted: function() {
-               $(".modal").modal();
-               if (["exam","open"].includes(assessment.mode))
-                       return;
-               window.addEventListener("blur", () => {
-                       if (this.stage != 2)
-                               return;
-                       if (assessment.mode == "secure")
-                       {
-                               this.sendAnswer();
-                               document.location.href= "/noblur";
-                       }
-                       else //"watch" mode
-                               socket.emit(message.studentBlur, {number:this.student.number});
-               }, false);
-               if (assessment.mode == "watch")
-               {
-                       window.addEventListener("focus", () => {
-                               if (this.stage != 2)
-                                       return;
-                               socket.emit(message.studentFocus, {number:this.student.number});
-                       }, false);
-               }
-               window.addEventListener("resize", e => {
-                       if (this.stage != 2)
-                               return;
-                       if (assessment.mode == "secure")
-                       {
-                               this.sendAnswer();
-                               document.location.href = "/fullscreen";
-                       }
-                       else //"watch" mode
-                       {
-                               if (checkWindowSize())
-                                       socket.emit(message.studentFullscreen, {number:this.student.number});
-                               else
-                                       socket.emit(message.studentResize, {number:this.student.number});
-                       }
-               }, false);
-       },
-       methods: {
-               // In case of AJAX errors (not blur-ing)
-               showWarning: function(message) {
-                       this.warnMsg = message;
-                       $("#warning").modal("open");
-               },
-               padWithZero: function(x) {
-                       if (x < 10)
-                               return "0" + x;
-                       return x;
-               },
-               // stage 0 --> 1
-               getStudent: function() {
-                       $.ajax("/courses/student", {
-                               method: "GET",
-                               data: {
-                                       number: this.student.number,
-                                       cid: assessment.cid,
-                               },
-                               dataType: "json",
-                               success: s => {
-                                       if (!!s.errmsg)
-                                               return this.showWarning(s.errmsg);
-                                       this.stage = 1;
-                                       this.student = s.student;
-                                       Vue.nextTick( () => { Materialize.updateTextFields(); });
-                               },
-                       });
-               },
-               // stage 1 --> 0
-               cancelStudent: function() {
-                       this.stage = 0;
-               },
-               // stage 1 --> 2 (get all questions, set password)
-               startAssessment: function() {
-                       let initializeStage2 = paper => {
-                               $("#leftButton, #rightButton").hide();
-                               // 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 = [ ];
-                               for (let q of assessment.questions)
-                                       this.answers.inputs.push( _(q.options.length).times( _.constant(false) ) );
-                               if (!paper)
-                               {
-                                       this.answers.indices = assessment.fixed
-                                               ? _.range(assessment.questions.length)
-                                               : _.shuffle( _.range(assessment.questions.length) );
-                               }
-                               else
-                               {
-                                       // Resuming
-                                       let indices = paper.inputs.map( input => { return input.index; });
-                                       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;
-                               this.stage = 2;
-                       };
-                       if (assessment.mode == "open")
-                               return initializeStage2();
-                       $.ajax("/assessments/start", {
-                               method: "PUT",
-                               data: {
-                                       number: this.student.number,
-                                       aid: assessment._id
-                               },
-                               dataType: "json",
-                               success: s => {
-                                       if (!!s.errmsg)
-                                               return this.showWarning(s.errmsg);
-                                       if (!!s.paper)
-                                       {
-                                               // Resuming: receive stored answers + startTime
-                                               this.student.password = s.paper.password;
-                                               this.answers.inputs = s.paper.inputs.map( inp => { return inp.input; });
-                                       }
-                                       else
-                                       {
-                                               this.student.password = s.password;
-                                               // Got password: students answers locked to this page until potential teacher
-                                               // action (power failure, computer down, ...)
-                                       }
-                                       socket = io.connect("/", {
-                                               query: "aid=" + assessment._id + "&number=" + this.student.number + "&password=" + this.student.password
-                                       });
-                                       socket.on(message.allAnswers, this.setAnswers);
-                                       initializeStage2(s.questions, s.paper);
-                               },
-                       });
-               },
-
-
-               // stage 2
-               runGlobalTimer: function() {
-                       if (assessment.time <= 0)
-                               return;
-                       let self = this;
-                       setInterval( function() {
-                               self.remainingTime--;
-                               if (self.remainingTime <= 0)
-                               {
-                                       if (self.stage == 2)
-                                               self.endAssessment();
-                                       clearInterval(this);
-                               }
-                       }, 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];
-                       let gotoNext = () => {
-                               if (this.answers.index == assessment.questions.length - 1)
-                                       this.endAssessment();
-                               else
-                                       this.answers.index++;
-                               this.$children[0].$forceUpdate(); //TODO: bad HACK, and shouldn't be required...
-                       };
-                       if (assessment.mode == "open")
-                               return gotoNext(); //only local
-                       let answerData = {
-                               aid: assessment._id,
-                               answer: JSON.stringify({
-                                       index: realIndex.toString(),
-                                       input: this.answers.inputs[realIndex]
-                                               .map( (tf,i) => { return {val:tf,idx:i}; } )
-                                               .filter( item => { return item.val; })
-                                               .map( item => { return item.idx; })
-                               }),
-                               number: this.student.number,
-                               password: this.student.password,
-                       };
-                       $.ajax("/assessments/answer", {
-                               method: "PUT",
-                               data: answerData,
-                               dataType: "json",
-                               success: ret => {
-                                       if (!!ret.errmsg)
-                                               return this.showWarning(ret.errmsg);
-                                       gotoNext();
-                                       socket.emit(message.newAnswer, answerData);
-                               },
-                       });
-               },
-               // TODO: I don't like that + sending should not be definitive in exam mode with display = all
-               sendAnswer: function() {
-                       if (assessment.display == "one")
-                               this.sendOneAnswer();
-                       else
-                               assessment.questions.forEach(this.sendOneAnswer);
-               },
-               // stage 2 --> 3 (or 4)
-               // from a message by statements component, or time over
-               endAssessment: function() {
-                       // Set endTime, destroy password
-                       $("#leftButton, #rightButton").show();
-                       if (assessment.mode == "open")
-                       {
-                               this.stage = 4;
-                               this.answers.showSolution = true;
-                               this.answers.displayAll = true;
-                               return;
-                       }
-                       $.ajax("/assessments/end", {
-                               method: "PUT",
-                               data: {
-                                       aid: assessment._id,
-                                       number: this.student.number,
-                                       password: this.student.password,
-                               },
-                               dataType: "json",
-                               success: ret => {
-                                       if (!!ret.errmsg)
-                                               return this.showWarning(ret.errmsg);
-                                       this.stage = 3;
-                                       delete this.student["password"]; //unable to send new answers now
-                               },
-                       });
-               },
-               // stage 3 --> 4 (on socket message "feedback")
-               setAnswers: function(m) {
-                       const answers = JSON.parse(m.answers);
-                       for (let i=0; i<answers.length; i++)
-                               assessment.questions[i].answer = answers[i];
-                       this.answers.showSolution = true;
-                       this.answers.displayAll = true;
-                       this.stage = 4;
-                       socket.disconnect();
-                       socket = null;
-               },
-       },
-});