Fix sign of deltaTime for disconnections
[qomet.git] / models / assessment.js
CommitLineData
e99c53fb
BA
1const AssessmentEntity = require("../entities/assessment");
2const CourseEntity = require("../entities/course");
3const ObjectId = require("bson-objectid");
4const UserEntity = require("../entities/user");
5const TokenGen = require("../utils/tokenGenerator");
6
7const AssessmentModel =
8{
9 getByRefs: function(initials, code, name, cb)
10 {
11 UserEntity.getByInitials(initials, (err,user) => {
12 if (!!err || !user)
13 return cb(err || {errmsg: "User not found"});
14 CourseEntity.getByPath(user._id, code, (err2,course) => {
15 if (!!err2 || !course)
16 return cb(err2 || {errmsg: "Course not found"});
17 AssessmentEntity.getByPath(course._id, name, (err3,assessment) => {
18 if (!!err3 || !assessment)
19 return cb(err3 || {errmsg: "Assessment not found"});
20 cb(null,assessment);
21 });
22 });
23 });
24 },
25
71d1ca9c
BA
26 checkPassword: function(aid, number, password, cb)
27 {
28 AssessmentEntity.getById(aid, (err,assessment) => {
29 if (!!err || !assessment)
30 return cb(err, assessment);
31 const paperIdx = assessment.papers.findIndex( item => { return item.number == number; });
32 if (paperIdx === -1)
33 return cb({errmsg: "Paper not found"}, false);
34 cb(null, assessment.papers[paperIdx].password == password);
35 });
36 },
37
e99c53fb
BA
38 add: function(uid, cid, name, cb)
39 {
40 // 1) Check that course is owned by user of ID uid
41 CourseEntity.getById(cid, (err,course) => {
42 if (!!err || !course)
43 return cb({errmsg: "Course retrieval failure"});
44 if (!course.uid.equals(uid))
45 return cb({errmsg:"Not your course"},undefined);
46 // 2) Insert new blank assessment
47 AssessmentEntity.insert(cid, name, cb);
48 });
49 },
50
51 update: function(uid, assessment, cb)
52 {
71d1ca9c 53 const aid = ObjectId(assessment._id);
e99c53fb 54 // 1) Check that assessment is owned by user of ID uid
71d1ca9c 55 AssessmentEntity.getById(aid, (err,assessmentOld) => {
e99c53fb
BA
56 if (!!err || !assessmentOld)
57 return cb({errmsg: "Assessment retrieval failure"});
58 CourseEntity.getById(ObjectId(assessmentOld.cid), (err2,course) => {
59 if (!!err2 || !course)
60 return cb({errmsg: "Course retrieval failure"});
61 if (!course.uid.equals(uid))
62 return cb({errmsg:"Not your course"},undefined);
63 // 2) Replace assessment
64 delete assessment["_id"];
65 assessment.cid = ObjectId(assessment.cid);
71d1ca9c 66 AssessmentEntity.replace(aid, assessment, cb);
e99c53fb
BA
67 });
68 });
69 },
70
71 // Set password in responses collection
f03a2ad9 72 startSession: function(aid, number, password, cb)
e99c53fb 73 {
f03a2ad9
BA
74 AssessmentEntity.getPaperByNumber(aid, number, (err,paper) => {
75 if (!!err)
76 return cb(err,null);
71d1ca9c
BA
77 if (!paper && !!password)
78 return cb({errmsg: "Cannot start a new exam before finishing current"},null);
f03a2ad9
BA
79 if (!!paper)
80 {
81 if (!password)
71d1ca9c 82 return cb({errmsg: "Missing password"});
f03a2ad9 83 if (paper.password != password)
71d1ca9c 84 return cb({errmsg: "Wrong password"});
f03a2ad9
BA
85 }
86 AssessmentEntity.getQuestions(aid, (err,questions) => {
87 if (!!err)
88 return cb(err,null);
89 if (!!paper)
90 return cb(null,{paper:paper,questions:questions});
2c545c26
BA
91 const pwd = TokenGen.generate(12); //arbitrary number, 12 seems enough...
92 AssessmentEntity.startSession(aid, number, pwd, (err2,ret) => {
f03a2ad9
BA
93 cb(err2, {
94 questions: questions,
95 password: pwd,
96 });
e99c53fb
BA
97 });
98 });
99 });
100 },
101
f03a2ad9
BA
102 newAnswer: function(aid, number, password, input, cb)
103 {
f03a2ad9
BA
104 // Check that student hasn't already answered
105 AssessmentEntity.hasInput(aid, number, password, input.index, (err,ret) => {
106 if (!!err)
107 return cb(err,null);
108 if (!!ret)
109 return cb({errmsg:"Question already answered"},null);
110 AssessmentEntity.setInput(aid, number, password, input, (err2,ret2) => {
f03a2ad9
BA
111 if (!!err2 || !ret2)
112 return cb(err2,ret2);
113 return cb(null,ret2);
114 });
115 });
116 },
117
29c8b391
BA
118 // NOTE: no callbacks for 2 next functions, failures are not so important
119 // (because monitored: teachers can see what's going on)
120
121 newConnection: function(aid, number)
122 {
123 //increment discoCount, reset discoTime to NULL, update totalDisco
124 AssessmentEntity.getDiscoTime(aid, number, (err,discoTime) => {
125 if (!!discoTime)
5e96e5a2 126 AssessmentEntity.addDisco(aid, number, Date.now() - discoTime);
29c8b391
BA
127 });
128 },
129
e99c53fb
BA
130 endSession: function(aid, number, password, cb)
131 {
132 AssessmentEntity.endAssessment(aid, number, password, (err,ret) => {
133 if (!!err || !ret)
134 return cb(err,ret);
135 AssessmentEntity.getConclusion(aid, (err2,conclusion) => {
136 cb(err2, {conclusion:conclusion});
137 });
138 });
139 },
140};
141
142module.exports = AssessmentModel;