23972a946f6f09b0c381b488214cc3b39e130aae
[qomet.git] / public / javascripts / monitor.js
1 let socket = null; //monitor answers in real time
2
3 new Vue({
4 el: "#monitor",
5 data: {
6 password: "", //from password field
7 assessment: { }, //obtained after authentication
8 // Stage 0: unauthenticated (password),
9 // 1: authenticated (password hash validated), start monitoring
10 stage: 0,
11 answers: {
12 displayAll: true,
13 showSolution: true, //TODO: allow to hide, to let teachers search too
14 inputs: [ ],
15 index : -1,
16 },
17 students: [ ], //to know their names
18 display: "assessment", //or student's answers
19 },
20 methods: {
21 // TODO: redundant code, next 4 funcs already exist in course.js
22 toggleDisplay: function(area) {
23 if (this.display == area)
24 this.display = "";
25 else
26 this.display = area;
27 },
28 studentList: function(group) {
29 return this.students
30 .filter( s => { return group==0 || s.group == group; })
31 .map( s => { return Object.assign({}, s); }) //not altering initial array
32 .sort( (a,b) => {
33 let res = a.name.localeCompare(b.name);
34 if (res == 0)
35 res += a.forename.localeCompare(b.forename);
36 return res;
37 });
38 },
39 groupList: function() {
40 let maxGrp = 1;
41 this.students.forEach( s => {
42 if (s.group > maxGrp)
43 maxGrp = s.group;
44 });
45 return _.range(1,maxGrp+1);
46 },
47 groupId: function(group, prefix) {
48 return (prefix || "") + "group" + group;
49 },
50 getColor: function(number, qIdx) {
51 // For the moment, green if correct and red if wrong; grey if unanswered yet
52 // TODO: in-between color for partially right (especially for multi-questions)
53 const paperIdx = this.assessment.papers.findIndex( item => { return item.number == number; });
54 if (paperIdx === -1)
55 return "grey"; //student didn't start yet
56 const inputIdx = this.assessment.papers[paperIdx].inputs.findIndex( item => {
57 const qNum = parseInt(item.index.split(".")[0]); //indexes separated by dots
58 return qIdx == qNum;
59 });
60 if (inputIdx === -1)
61 return "grey";
62 if (_.isEqual(this.assessment.papers[paperIdx].inputs[inputIdx].input, this.assessment.questions[qIdx].answer))
63 return "green";
64 return "red";
65 },
66 seeDetails: function(number, i) {
67 // UNIMPLEMENTED: see question details, with current answer(s)
68 },
69 // stage 0 --> 1
70 startMonitoring: function() {
71 $.ajax("/start/monitoring", {
72 method: "GET",
73 data: {
74 password: Sha1.Compute(this.password),
75 aname: examName,
76 ccode: courseCode,
77 initials: initials,
78 },
79 dataType: "json",
80 success: s => {
81 if (!!s.errmsg)
82 return alert(s.errmsg);
83 this.assessment = s.assessment;
84 this.answers.inputs = s.assessment.questions.map( q => {
85 let input = _(q.options.length).times( _.constant(false) );
86 q.answer.forEach( idx => { input[idx] = true; });
87 return input;
88 });
89 this.students = s.students;
90 this.stage = 1;
91 socket = io.connect("/", {
92 query: "aid=" + this.assessment._id + "&secret=" + s.secret
93 });
94 socket.on(message.newAnswer, m => {
95 let paperIdx = this.assessment.papers.findIndex( item => {
96 return item.number == m.number;
97 });
98 if (paperIdx === -1)
99 {
100 // First answer
101 paperIdx = this.assessment.papers.length;
102 this.assessment.papers.push({
103 number: m.number,
104 inputs: [ ], //other fields irrelevant here
105 });
106 }
107 // TODO: notations not coherent (input / answer... when, which ?)
108 this.assessment.papers[paperIdx].inputs.push(JSON.parse(m.answer)); //input+index
109 });
110 },
111 });
112 },
113 endMonitoring: function() {
114 // In the end, send answers to students
115 socket.emit(
116 message.allAnswers,
117 { answers: JSON.stringify(this.assessment.questions.map( q => { return q.answer; })) }
118 );
119 },
120 },
121 });