remove extra step in end assessment process
[qomet.git] / entities / assessment.js
1 const db = require("../utils/database");
2
3 const AssessmentEntity =
4 {
5 /*
6 * Structure:
7 * _id: BSON id
8 * cid: course ID
9 * name: varchar
10 * active: boolean true/false
11 * mode: secure | exam | open (decreasing security)
12 * fixed: bool (questions in fixed order; default: false)
13 * display: "one" or "all" (generally "all" for open questions, but...)
14 * time: 0, //<=0 means "untimed"; otherwise, time in seconds
15 * introduction: "",
16 * coefficient: number, default 1
17 * questions: array of
18 * index: for paper test, like 2.1.a (?!); and quiz: 0, 1, 2, 3...
19 * wording: varchar (HTML)
20 * options: array of varchar --> if present, question type == quiz!
21 * fixed: bool, options in fixed order (default: false)
22 * answer: array of integers (for quiz) or html text (for paper); striped in exam mode
23 * active: boolean, is question in current assessment?
24 * points: points for this question (default 1)
25 * papers : array of
26 * number: student number
27 * inputs: array of indexed arrays of integers (or html text if not quiz)
28 * startTime, endTime
29 * discoTime, totalDisco: last disconnect timestamp (if relevant) + total
30 * discoCount: total disconnections
31 * password: random string identifying student for exam session TEMPORARY
32 */
33
34 getById: function(aid, callback)
35 {
36 db.assessments.findOne(
37 { _id: aid },
38 callback
39 );
40 },
41
42 getByPath: function(cid, name, callback)
43 {
44 db.assessments.findOne(
45 {
46 cid: cid,
47 name: name,
48 },
49 callback
50 );
51 },
52
53 insert: function(cid, name, callback)
54 {
55 db.assessments.insert(
56 {
57 name: name,
58 cid: cid,
59 active: false,
60 mode: "exam",
61 fixed: false,
62 display: "one",
63 time: 0,
64 introduction: "",
65 coefficient: 1,
66 questions: [ ],
67 papers: [ ],
68 },
69 callback
70 );
71 },
72
73 getByCourse: function(cid, callback)
74 {
75 db.assessments.find(
76 { cid: cid },
77 callback
78 );
79 },
80
81 // arg: full assessment without _id field
82 replace: function(aid, assessment, cb)
83 {
84 // Should be: (but unsupported by mongojs)
85 // db.assessments.replaceOne(
86 // { _id: aid },
87 // assessment,
88 // cb
89 // );
90 // Temporary workaround:
91 db.assessments.update(
92 { _id: aid },
93 { $set: assessment },
94 cb
95 );
96 },
97
98 getQuestions: function(aid, callback)
99 {
100 db.assessments.findOne(
101 { _id: aid },
102 { questions: 1},
103 (err,res) => {
104 callback(err, !!res ? res.questions : null);
105 }
106 );
107 },
108
109 getPaperByNumber: function(aid, number, callback)
110 {
111 db.assessments.findOne(
112 {
113 _id: aid,
114 "papers.number": number,
115 },
116 (err,a) => {
117 if (!!err || !a)
118 return callback(err,a);
119 for (let p of a.papers)
120 {
121 if (p.number == number)
122 return callback(null,p); //reached for sure
123 }
124 }
125 );
126 },
127
128 startSession: function(aid, number, password, callback)
129 {
130 db.assessments.update(
131 { _id: aid },
132 { $push: { papers: {
133 number: number,
134 startTime: Date.now(),
135 endTime: undefined,
136 password: password,
137 totalDisco: 0,
138 discoCount: 0,
139 inputs: [ ], //TODO: this is stage 1, stack indexed answers.
140 // then build JSON tree for easier access / correct
141 }}},
142 callback
143 );
144 },
145
146 // NOTE: no callbacks for 2 next functions, failures are not so important
147 // (because monitored: teachers can see what's going on)
148
149 addDisco: function(aid, number, deltaTime)
150 {
151 db.assessments.update(
152 {
153 _id: aid,
154 "papers.number": number,
155 },
156 { $inc: {
157 "papers.$.discoCount": 1,
158 "papers.$.totalDisco": deltaTime,
159 } },
160 { $set: { "papers.$.discoTime": null } }
161 );
162 },
163
164 setDiscoTime: function(aid, number)
165 {
166 db.assessments.update(
167 {
168 _id: aid,
169 "papers.number": number,
170 },
171 { $set: { "papers.$.discoTime": Date.now() } }
172 );
173 },
174
175 getDiscoTime: function(aid, number, cb)
176 {
177 db.assessments.findOne(
178 { _id: aid },
179 (err,a) => {
180 if (!!err)
181 return cb(err, null);
182 const idx = a.papers.findIndex( item => { return item.number == number; });
183 cb(null, a.papers[idx].discoTime);
184 }
185 );
186 },
187
188 hasInput: function(aid, number, password, idx, cb)
189 {
190 db.assessments.findOne(
191 {
192 _id: aid,
193 "papers.number": number,
194 "papers.password": password,
195 },
196 (err,a) => {
197 if (!!err || !a)
198 return cb(err,a);
199 let papIdx = a.papers.findIndex( item => { return item.number == number; });
200 for (let i of a.papers[papIdx].inputs)
201 {
202 if (i.index == idx)
203 return cb(null,true);
204 }
205 cb(null,false);
206 }
207 );
208 },
209
210 // https://stackoverflow.com/questions/27874469/mongodb-push-in-nested-array
211 setInput: function(aid, number, password, input, callback) //input: index + arrayOfInt (or txt)
212 {
213 db.assessments.update(
214 {
215 _id: aid,
216 "papers.number": number,
217 "papers.password": password,
218 },
219 { $push: { "papers.$.inputs": input } },
220 callback
221 );
222 },
223
224 endAssessment: function(aid, number, password, callback)
225 {
226 db.assessments.update(
227 {
228 _id: aid,
229 "papers.number": number,
230 "papers.password": password,
231 },
232 { $set: {
233 "papers.$.endTime": Date.now(),
234 "papers.$.password": "",
235 } },
236 callback
237 );
238 },
239
240 remove: function(aid, cb)
241 {
242 db.assessments.remove(
243 { _id: aid },
244 cb
245 );
246 },
247
248 removeGroup: function(cid, cb)
249 {
250 db.assessments.remove(
251 { cid: cid },
252 cb
253 );
254 },
255 }
256
257 module.exports = AssessmentEntity;