]> git.cworth.org Git - lmno-server/blobdiff - empathy.js
Accept votes to advance game at /end-answers and /end-judging endpoints
[lmno-server] / empathy.js
index cfe0618d76f211a0e3ceeb69b017c3c90a187100..eaf12bf8deb0a6b74d8358922643052da1afc7c2 100644 (file)
@@ -9,9 +9,13 @@ class Empathy extends Game {
     this.state = {
       prompts: [],
       active_prompt: null,
-      players_answered: 0,
+      players_answered: [],
+      players_answering: new Set(),
+      end_answers: new Set(),
       ambiguities: null,
-      players_judged: 0,
+      players_judged: [],
+      players_judging: new Set(),
+      end_judging: new Set(),
       scores: null
     };
     this.answers = [];
@@ -45,9 +49,13 @@ class Empathy extends Game {
       );
 
     this.state.active_prompt = null;
-    this.state.players_answered = 0;
+    this.state.players_answered = [];
+    this.state.players_answering = new Set();
+    this.state.end_answers = new Set();
     this.state.ambiguities = 0;
-    this.state.players_judged = 0;
+    this.state.players_judged = [];
+    this.state.players_judging = new Set();
+    this.state.end_judging = new Set();
     this.state.scores = null;
 
     this.answers = [];
@@ -127,13 +135,32 @@ class Empathy extends Game {
       answers: answers
     });
 
-    /* And notify players how many players have answered. */
-    this.state.players_answered++;
-    this.broadcast_event_object('answered', this.state.players_answered);
+    /* And notify all players that this player has answered. */
+    this.state.players_answered.push(player.name);
+    this.broadcast_event_object('player-answered', player.name);
 
     return { valid: true };
   }
 
+  /* Returns true if vote toggled, false for player or prompt not found */
+  toggle_end_answers(prompt_id, session_id) {
+    const player = this.players_by_session[session_id];
+
+    const prompt = this.state.prompts.find(p => p.id === prompt_id);
+    if (! prompt || ! player)
+      return false;
+
+    if (this.state.end_answers.has(player.name)) {
+      this.state.end_answers.delete(player.name);
+      this.broadcast_event_object('unvote-end-answers', player.name);
+    } else {
+      this.state.end_answers.add(player.name);
+      this.broadcast_event_object('vote-end-answers', player.name);
+    }
+
+    return true;
+  }
+
   perform_judging() {
     const word_map = {};
 
@@ -198,13 +225,32 @@ class Empathy extends Game {
       }
     }
 
-    /* And notify players how many players have completed judging. */
-    this.state.players_judged++;
-    this.broadcast_event_object('judged', this.state.players_judged);
+    /* And notify all players this this player has judged. */
+    this.state.players_judged.push(player.name);
+    this.broadcast_event_object('player-judged', player.name);
 
     return { valid: true };
   }
 
+  /* Returns true if vote toggled, false for player or prompt not found */
+  toggle_end_judging(prompt_id, session_id) {
+    const player = this.players_by_session[session_id];
+
+    const prompt = this.state.prompts.find(p => p.id === prompt_id);
+    if (! prompt || ! player)
+      return false;
+
+    if (this.state.end_judging.has(player.name)) {
+      this.state.end_judging.delete(player.name);
+      this.broadcast_event_object('unvote-end-judging', player.name);
+    } else {
+      this.state.end_judging.add(player.name);
+      this.broadcast_event_object('vote-end-judging', player.name);
+    }
+
+    return true;
+  }
+
   canonize(word) {
     return word.toLowerCase();
   }
@@ -378,8 +424,18 @@ router.post('/answer/:prompt_id([0-9]+)', (request, response) => {
                                      request.session.id,
                                      request.body.answers);
   response.json(result);
+});
+
+router.post('/end-answers/:prompt_id([0-9]+)', (request, response) => {
+  const game = request.game;
+  const prompt_id = parseInt(request.params.prompt_id, 10);
+
+  if (game.toggle_end_answers(prompt_id, request.session.id))
+    response.send('');
+  else
+    response.sendStatus(404);
 
-  if (game.state.players_answered >= game.players.length)
+  if (game.state.end_answers.size > (game.state.players_answered.length / 2))
     game.perform_judging();
 });
 
@@ -391,8 +447,18 @@ router.post('/judging/:prompt_id([0-9]+)', (request, response) => {
                                       request.session.id,
                                       request.body.word_groups);
   response.json(result);
+});
+
+router.post('/end-judging/:prompt_id([0-9]+)', (request, response) => {
+  const game = request.game;
+  const prompt_id = parseInt(request.params.prompt_id, 10);
+
+  if (game.toggle_end_judging(prompt_id, request.session.id))
+    response.send('');
+  else
+    response.sendStatus(404);
 
-  if (game.state.players_judged >= game.players.length)
+  if (game.state.end_judging.size > (game.state.players_judged.length / 2))
     game.compute_scores();
 });