3 // TODO: onglets pour chaque groupe + section déroulante questionnaire (chargé avec réponses)
4 // NOM Prenom (par grp, puis alphabétique)
5 // réponse : vert si OK (+ choix), rouge si faux, gris si texte (clic pour voir)
7 // click sur en-tête de colonne : tri alphabétique, tri décroissant...
8 // Affiché si (hash du) mdp du cours est correctement entré
9 // Doit reprendre les données en base si refresh (sinon : sockets)
11 // Also buttons "start exam", "end exam" for logged in teacher
13 // TODO: réutiliser le component... trouver un moyen
15 let socket
= null; //monitor answers in real time
17 function libsRefresh()
19 // Run Prism + MathJax on questions text
20 $("#statements").find("code[class^=language-]").each( (i
,elem
) => {
21 Prism
.highlightElement(elem
);
23 MathJax
.Hub
.Queue(["Typeset",MathJax
.Hub
,"statements"]);
29 password: "", //from password field
30 assessment: null, //obtained after authentication
31 // Stage 0: unauthenticated (password),
32 // 1: authenticated (password hash validated), start monitoring
37 props: ['assessment','inputs','student','stage'],
38 // TODO: general render function for nested exercises
39 // There should be a questions navigator below, or next (visible if display=='all')
40 // Full questions tree is rendered, but some parts hidden depending on display settings
43 let questions
= (assessment
.questions
|| [ ]).map( (q
,i
) => {
44 let questionContent
= [ ];
58 let optionsOrder
= _
.range(q
.options
.length
);
60 optionsOrder
= _
.shuffle(optionsOrder
);
62 optionsOrder
.forEach( idx
=> {
69 checked: this.inputs
.length
> 0 && this.inputs
[i
][idx
],
72 id: this.inputId(i
,idx
),
76 change: e
=> { this.inputs
[i
][idx
] = e
.target
.checked
; },
86 innerHTML: q
.options
[idx
],
89 "for": this.inputId(i
,idx
),
100 choiceCorrect: this.stage
== 4 && assessment
.questions
[i
].answer
.includes(idx
),
101 choiceWrong: this.stage
== 4 && this.inputs
[i
][idx
] && !assessment
.questions
[i
].answer
.includes(idx
),
108 questionContent
.push(
124 "hide": this.stage
== 2 && assessment
.display
== 'one' && assessment
.indices
[assessment
.index
] != i
,
137 "waves-effect": true,
143 "margin-left": "auto",
144 "margin-right": "auto",
147 click: () => this.sendAnswer(assessment
.indices
[assessment
.index
]),
164 mounted: function() {
168 inputId: function(i
,j
) {
169 return "q" + i
+ "_" + "input" + j
;
176 startMonitoring: function() {
177 $.ajax("/start/monitoring", {
187 return this.warning(s
.errmsg
);
192 // TODO: 2-level sockets, for prof and monitors
193 socket
= io
.connect("/" + assessment
.name
, {
194 query: "number=" + this.student
.number
+ "&password=" + this.password
196 socket
.on(message
.allAnswers
, this.setAnswers
);
197 initializeStage2(s
.questions
, s
.paper
);
201 // stage 2 --> 3 (or 4)
202 // from a message by statements component, or time over
203 // TODO: also function startAssessment (for main teacher only)
204 endAssessment: function() {
205 // Set endTime, destroy password
206 $("#leftButton, #rightButton").show();
207 if (assessment
.mode
== "open")
212 $.ajax("/end/assessment", {
216 number: this.student
.number
,
217 password: this.student
.password
,
222 return this.warning(ret
.errmsg
);
223 assessment
.conclusion
= ret
.conclusion
;
225 delete this.student
["password"]; //unable to send new answers now