Fix exam mode
[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 * conclusion: "https://www.youtube.com/watch?v=6-9AjToJYuw",
17 * coefficient: number, default 1
18 * questions: array of
19 * index: for paper test, like 2.1.a (?!); and quiz: 0, 1, 2, 3...
20 * wording: varchar (HTML)
21 * options: array of varchar --> if present, question type == quiz!
22 * fixed: bool, options in fixed order (default: false)
23 * answer: array of integers (for quiz) or html text (for paper); striped in exam mode
24 * active: boolean, is question in current assessment? --> striped if inactive!
25 * points: points for this question (default 1)
26 * papers : array of
27 * number: student number
28 * inputs: array of indexed arrays of integers (or html text if not quiz)
29 * startTime, endTime
30 * password: random string identifying student for exam session TEMPORARY
31 */
32
33 getById: function(aid, callback)
34 {
35 db.assessments.findOne(
36 { _id: aid },
37 callback
38 );
39 },
40
41 getByPath: function(cid, name, callback)
42 {
43 db.assessments.findOne(
44 {
45 cid: cid,
46 name: name,
47 },
48 callback
49 );
50 },
51
52 insert: function(cid, name, callback)
53 {
54 db.assessments.insert(
55 {
56 name: name,
57 cid: cid,
58 active: false,
59 mode: "exam",
60 fixed: false,
61 display: "one",
62 time: 0,
63 introduction: "",
64 conclusion: "",
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 inputs: [ ], //TODO: this is stage 1, stack indexed answers.
138 // then build JSON tree for easier access / correct
139 }}},
140 callback
141 );
142 },
143
144
145 hasInput: function(aid, number, password, idx, cb)
146 {
147 db.assessments.findOne(
148 {
149 _id: aid,
150 "papers.number": number,
151 "papers.password": password,
152 },
153 (err,a) => {
154 if (!!err || !a)
155 return cb(err,a);
156 let papIdx = a.papers.findIndex( item => { return item.number == number; });
157 for (let i of a.papers[papIdx].inputs)
158 {
159 if (i.index == idx)
160 return cb(null,true);
161 }
162 cb(null,false);
163 }
164 );
165 },
166
167 // https://stackoverflow.com/questions/27874469/mongodb-push-in-nested-array
168 setInput: function(aid, number, password, input, callback) //input: index + arrayOfInt (or txt)
169 {
170 db.assessments.update(
171 {
172 _id: aid,
173 "papers.number": number,
174 "papers.password": password,
175 },
176 { $push: { "papers.$.inputs": input } },
177 callback
178 );
179 },
180
181 endAssessment: function(aid, number, password, callback)
182 {
183 db.assessments.update(
184 {
185 _id: aid,
186 "papers.number": number,
187 "papers.password": password,
188 },
189 { $set: {
190 "papers.$.endTime": Date.now(),
191 "papers.$.password": "",
192 } },
193 callback
194 );
195 },
196
197 getConclusion: function(aid, callback)
198 {
199 db.assessments.findOne(
200 { _id: aid },
201 { conclusion: 1},
202 (err,res) => {
203 callback(err, !!res ? res.conclusion : null);
204 }
205 );
206 },
207
208 remove: function(aid, cb)
209 {
210 db.assessments.remove(
211 { _id: aid },
212 cb
213 );
214 },
215
216 removeGroup: function(cid, cb)
217 {
218 db.assessments.remove(
219 { cid: cid },
220 cb
221 );
222 },
223 }
224
225 module.exports = AssessmentEntity;