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