Fix sign of deltaTime for disconnections
[qomet.git] / models / assessment.js
1 const AssessmentEntity = require("../entities/assessment");
2 const CourseEntity = require("../entities/course");
3 const ObjectId = require("bson-objectid");
4 const UserEntity = require("../entities/user");
5 const TokenGen = require("../utils/tokenGenerator");
6
7 const 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
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
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 {
53 const aid = ObjectId(assessment._id);
54 // 1) Check that assessment is owned by user of ID uid
55 AssessmentEntity.getById(aid, (err,assessmentOld) => {
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);
66 AssessmentEntity.replace(aid, assessment, cb);
67 });
68 });
69 },
70
71 // Set password in responses collection
72 startSession: function(aid, number, password, cb)
73 {
74 AssessmentEntity.getPaperByNumber(aid, number, (err,paper) => {
75 if (!!err)
76 return cb(err,null);
77 if (!paper && !!password)
78 return cb({errmsg: "Cannot start a new exam before finishing current"},null);
79 if (!!paper)
80 {
81 if (!password)
82 return cb({errmsg: "Missing password"});
83 if (paper.password != password)
84 return cb({errmsg: "Wrong password"});
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});
91 const pwd = TokenGen.generate(12); //arbitrary number, 12 seems enough...
92 AssessmentEntity.startSession(aid, number, pwd, (err2,ret) => {
93 cb(err2, {
94 questions: questions,
95 password: pwd,
96 });
97 });
98 });
99 });
100 },
101
102 newAnswer: function(aid, number, password, input, cb)
103 {
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) => {
111 if (!!err2 || !ret2)
112 return cb(err2,ret2);
113 return cb(null,ret2);
114 });
115 });
116 },
117
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)
126 AssessmentEntity.addDisco(aid, number, Date.now() - discoTime);
127 });
128 },
129
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
142 module.exports = AssessmentModel;