X-Git-Url: https://git.auder.net/?p=qomet.git;a=blobdiff_plain;f=public%2Fjavascripts%2Fmonitor.js;h=1d32d0c432ff6544e0d11ce7c7f56eff01946961;hp=b58461be1de102cc280d14daede6a05805b65328;hb=e5ec7dead171feebb299430f298e3930864e096d;hpb=6bf4a38e1a82fdcdf1d2742a3e8937b26fe2e873 diff --git a/public/javascripts/monitor.js b/public/javascripts/monitor.js index b58461b..1d32d0c 100644 --- a/public/javascripts/monitor.js +++ b/public/javascripts/monitor.js @@ -9,3 +9,224 @@ // Doit reprendre les données en base si refresh (sinon : sockets) // Also buttons "start exam", "end exam" for logged in teacher + +// TODO: réutiliser le component... trouver un moyen + +let socket = null; //monitor answers in real time + +function libsRefresh() +{ + // Run Prism + MathJax on questions text + $("#statements").find("code[class^=language-]").each( (i,elem) => { + Prism.highlightElement(elem); + }); + MathJax.Hub.Queue(["Typeset",MathJax.Hub,"statements"]); +} + +new Vue({ + el: "#monitor", + data: { + password: "", //from password field + assessment: null, //obtained after authentication + // Stage 0: unauthenticated (password), + // 1: authenticated (password hash validated), start monitoring + stage: 0, + }, + components: { + "statements": { + props: ['assessment','inputs','student','stage'], + // TODO: general render function for nested exercises + // There should be a questions navigator below, or next (visible if display=='all') + // Full questions tree is rendered, but some parts hidden depending on display settings + render(h) { + let self = this; + let questions = (assessment.questions || [ ]).map( (q,i) => { + let questionContent = [ ]; + questionContent.push( + h( + "div", + { + "class": { + wording: true, + }, + domProps: { + innerHTML: q.wording, + }, + } + ) + ); + let optionsOrder = _.range(q.options.length); + if (!q.fixed) + optionsOrder = _.shuffle(optionsOrder); + let optionList = [ ]; + optionsOrder.forEach( idx => { + let option = [ ]; + option.push( + h( + "input", + { + domProps: { + checked: this.inputs.length > 0 && this.inputs[i][idx], + }, + attrs: { + id: this.inputId(i,idx), + type: "checkbox", + }, + on: { + change: e => { this.inputs[i][idx] = e.target.checked; }, + }, + }, + ) + ); + option.push( + h( + "label", + { + domProps: { + innerHTML: q.options[idx], + }, + attrs: { + "for": this.inputId(i,idx), + }, + } + ) + ); + optionList.push( + h( + "div", + { + "class": { + option: true, + choiceCorrect: this.stage == 4 && assessment.questions[i].answer.includes(idx), + choiceWrong: this.stage == 4 && this.inputs[i][idx] && !assessment.questions[i].answer.includes(idx), + }, + }, + option + ) + ); + }); + questionContent.push( + h( + "div", + { + "class": { + optionList: true, + }, + }, + optionList + ) + ); + return h( + "div", + { + "class": { + "question": true, + "hide": this.stage == 2 && assessment.display == 'one' && assessment.indices[assessment.index] != i, + }, + }, + questionContent + ); + }); + if (this.stage == 2) + { + questions.unshift( + h( + "button", + { + "class": { + "waves-effect": true, + "waves-light": true, + "btn": true, + }, + style: { + "display": "block", + "margin-left": "auto", + "margin-right": "auto", + }, + on: { + click: () => this.sendAnswer(assessment.indices[assessment.index]), + }, + }, + "Send" + ) + ); + } + return h( + "div", + { + attrs: { + id: "statements", + }, + }, + questions + ); + }, + mounted: function() { + libsRefresh(); + }, + methods: { + inputId: function(i,j) { + return "q" + i + "_" + "input" + j; + }, + }, + }, + }, + methods: { + // stage 0 --> 1 + startMonitoring: function() { + $.ajax("/start/monitoring", { + method: "GET", + data: { + password: this., + aname: examName, + cname: courseName, + }, + dataType: "json", + success: s => { + if (!!s.errmsg) + return this.warning(s.errmsg); + this.stage = 1; + }, + }); + }, + // TODO: 2-level sockets, for prof and monitors + socket = io.connect("/" + assessment.name, { + query: "number=" + this.student.number + "&password=" + this.password + }); + socket.on(message.allAnswers, this.setAnswers); + initializeStage2(s.questions, s.paper); + }, + }); + }, + // stage 2 --> 3 (or 4) + // from a message by statements component, or time over + // TODO: also function startAssessment (for main teacher only) + endAssessment: function() { + // Set endTime, destroy password + $("#leftButton, #rightButton").show(); + if (assessment.mode == "open") + { + this.stage = 4; + return; + } + $.ajax("/end/assessment", { + method: "GET", + data: { + aid: assessment._id, + number: this.student.number, + password: this.student.password, + }, + dataType: "json", + success: ret => { + if (!!ret.errmsg) + return this.warning(ret.errmsg); + assessment.conclusion = ret.conclusion; + this.stage = 3; + delete this.student["password"]; //unable to send new answers now + socket.disconnect(); + socket = null; + }, + }); + }, + }, +});