Add TODO
[qomet.git] / sockets.js
1 const message = require("./public/javascripts/utils/socketMessages");
2 const params = require("./config/parameters");
3 const AssessmentEntity = require("./entities/assessment");
4 const ObjectId = require("bson-objectid");
5
6 // TODO: when teacher connect on monitor, io.of("appropriate namespace").on(connect student) { ... }
7 // --> 2 sockets on monitoring page: one with ns "/" et one dedicated to the exam, triggered after the first
8 // --> The monitoring page should not be closed during exam (otherwise monitors won't receive any more data)
9
10 // TOOD need to re-introduce disconnections count + time (showed in monitoring and stored
11
12 function examRoom(socket) {
13 let students = { };
14 const aid = ObjectId(socket.handshake.query.aid);
15
16 // Student or monitor stuff
17 const isTeacher = !!socket.handshake.query.secret && socket.handshake.query.secret == params.secret;
18
19 if (isTeacher)
20 {
21 socket.on(message.newAnswer, m => { //got answer from student
22 socket.emit(message.newAnswer, m);
23 });
24 socket.on(message.allAnswers, m => { //send feedback to student (answers)
25 if (!!students[m.number]) //TODO: namespace here... room quiz
26 socket.broadcast.to(students[m.number]).emit(message.allAnswers, m);
27 });
28 socket.on("disconnect", m => {
29 // Reset student array if no more active teacher connections (TODO: condition)
30 students = { };
31 });
32 }
33
34 else //student
35 {
36 const number = socket.handshake.query.number;
37 const password = socket.handshake.query.password;
38 AssessmentEntity.checkPassword(aid, number, password, (err,ret) => {
39 if (!!err || !ret)
40 return; //wrong password, or some unexpected error...
41 // Prevent socket connection (just ignore) if student already connected
42 if (!!students[number])
43 return;
44 students[number] = {
45 sid: socket.id,
46 password: password,
47 };
48 socket.on(message.allAnswers, () => { //got all answers from teacher
49 socket.emit(message.allAnswers, m);
50 });
51 socket.on("disconnect", () => {
52 // ..
53 //TODO: notify monitor (highlight red), redirect
54 });
55 // NOTE: nothing on disconnect --> teacher disconnect trigger students cleaning
56 });
57 }
58 }
59
60 module.exports = function(io) {
61
62 // NOTE: if prof connected with 2 tabs and close 1, quizz should not break, thus following counter
63 let namespaces = { };
64
65 io.of("/").on("connection", socketProf => {
66 function closeQuizz(fullPath) {
67 namespaces[fullPath].counter--;
68 if (namespaces[fullPath].counter == 0)
69 {
70 // https://stackoverflow.com/questions/26400595/socket-io-how-do-i-remove-a-namespace
71 const connectedSockets = Object.keys(namespaces[fullPath].nsp.connected);
72 connectedSockets.forEach( sid => {
73 namespaces[fullPath].nsp.connected[sid].disconnect();
74 });
75 namespaces[fullPath].nsp.removeAllListeners();
76 delete io.nsps[fullPath];
77 }
78 }
79 // Only prof account can connect default namespace
80 socketProf.on(message.startQuizz, m => {
81 // m contient quizz ID + fullPath (initials+path+name)
82 const quizzNamespace = io.of(m.fullPath);
83 if (!namespaces[m.fullPath])
84 {
85 namespaces[m.fullPath] = { nsp:quizzNamespace, counter:1 };
86 quizzNamespace.on("connection", quizzRoom); //après ça : prof can connect in quizz too
87 socketProf.emit(message.quizzReady);
88 socketProf.on(message.endQuizz, m2 => {
89 closeQuizz(m.fullPath);
90 });
91 socketProf.on("disconnect", m2 => {
92 closeQuizz(m.fullPath); //TODO: this should delete all students in array
93 });
94 }
95 else
96 namespaces[m.fullPath]++;
97 });
98 });
99 }