]> git.cworth.org Git - empires-server/commitdiff
Add scoring of kudos along with word groups
authorCarl Worth <cworth@cworth.org>
Mon, 29 Jun 2020 20:53:20 +0000 (13:53 -0700)
committerCarl Worth <cworth@cworth.org>
Mon, 6 Jul 2020 01:42:09 +0000 (18:42 -0700)
The kudos act as a tiebreaker when regular points are otherwise
identical.

The test suite is updated here to pass the new information expected by
the server when receiving a word list during judging, (now wants an
object with two properties: 1. words, a list of words, 2. kudos, a
Boolean).

With this the test suite is still fully passing.

empathy.js
test

index c1d150f354d9bb4207f985b7da65540d4caa8ccd..01836df853df89760bc33794724d3a51611c4601 100644 (file)
@@ -46,6 +46,7 @@ class Empathy extends Game {
     this.judging_start_time_ms = 0;
     this.next_prompt_id = 1;
     this.equivalencies = {};
+    this.kudos = {};
   }
 
   reset() {
@@ -110,6 +111,7 @@ class Empathy extends Game {
     this.judging_idle_timer = 0;
     this.judging_start_time_ms = 0;
     this.equivalencies = {};
+    this.kudos = {};
 
     this.broadcast_event('game-state', this.game_state_json());
   }
@@ -345,15 +347,19 @@ class Empathy extends Game {
      */
     for (let group of word_groups) {
 
-      for (let i = 0; i < group.length - 1; i++) {
-        for (let j = i + 1; j < group.length; j++) {
-          let eq = [group[i], group[j]];
+      const words = group.words;
+      if (group.kudos)
+        this.kudos[player.name] = [...words];
+
+      for (let i = 0; i < words.length - 1; i++) {
+        for (let j = i + 1; j < words.length; j++) {
+          let eq = [words[i], words[j]];
 
           /* Put the two words into a reliable order so that we don't
            * miss a pair of equivalent equivalencies just because they
            * happen to be in the opposite order. */
           if (eq[0].localeCompare(eq[1]) > 0) {
-            eq = [group[j], group[i]];
+            eq = [words[j], words[i]];
           }
 
           const key=`${this.canonize(eq[0])}:${this.canonize(eq[1])}`;
@@ -480,7 +486,11 @@ class Empathy extends Game {
       if (! group)
         group = word_maps[word1_canon];
       if (! group)
-        group = { words: [], players: new Set()};
+        group = {
+          words: [],
+          players: new Set(),
+          kudos: new Set()
+        };
 
       if (! word_maps[word0_canon]) {
         word_maps[word0_canon] = group;
@@ -502,13 +512,29 @@ class Empathy extends Game {
         if (word_maps[word_canon]) {
           word_maps[word_canon].players.add(a.player);
         } else {
-          const group = { words: [word], players: new Set() };
+          const group = {
+            words: [word],
+            players: new Set(),
+            kudos: new Set()
+          };
           group.players.add(a.player);
           word_maps[word_canon] = group;
         }
       }
     }
 
+    /* Apply kudos from each player to the word maps, (using a set so
+     * that no word_map can get multiple kudos from a single
+     * player). */
+    for (let player of Object.keys(this.kudos)) {
+      for (let word of this.kudos[player]) {
+        const word_canon = this.canonize(word);
+        if (! word_maps[word_canon])
+          continue;
+        word_maps[word_canon].kudos.add(player);
+      }
+    }
+
     /* Now that we've assigned the players to these word maps, we now
      * want to collapse the groups down to a single array of
      * word_groups.
@@ -527,33 +553,52 @@ class Empathy extends Game {
      *
      * Note: We do this by going through the word groups, (as opposed
      * to the list of words from the players again), specifically to
-     * avoid giving a player points for a wrod group twice (in the
+     * avoid giving a player points for a word group twice (in the
      * case where a player submits two different words that the group
      * ends up judging as equivalent).
      */
-    this.players.forEach(p => p.round_score = 0);
+    this.players.forEach(p => {
+      p.round_score = 0;
+      p.round_kudos = 0;
+    });
     for (let group of word_groups) {
-      group.players.forEach(p => p.round_score += group.players.size);
+      group.players.forEach(p => {
+        p.round_score += group.players.size;
+        p.round_kudos += group.kudos.size;
+      });
     }
 
     const scores = this.players.filter(p => p.active).map(p => {
       return {
         player: p.name,
-        score: p.round_score
+        score: p.round_score,
+        kudos: p.round_kudos
       };
     });
 
     scores.sort((a,b) => {
-      return b.score - a.score;
+      const delta = b.score - a.score;
+      if (delta)
+        return delta;
+      return b.kudos - a.kudos;
     });
 
     /* After sorting individual players by score, group players
      * together who have the same score. */
     const reducer = (list, next) => {
-      if (list.length && list[list.length-1].score == next.score)
+      if (list.length
+          && list[list.length-1].score == next.score
+          && list[list.length-1].kudos == next.kudos
+         )
+      {
         list[list.length-1].players.push(next.player);
-      else
-        list.push({players: [next.player], score: next.score});
+      } else {
+        list.push({
+          players: [next.player],
+          score: next.score,
+          kudos: next.kudos,
+        });
+      }
       return list;
     };
 
@@ -565,13 +610,17 @@ class Empathy extends Game {
       group => {
         return {
           word: group.words.join('/'),
-          players: Array.from(group.players).map(p => p.name)
+          players: Array.from(group.players).map(p => p.name),
+          kudos: Array.from(group.kudos)
         };
       }
     );
 
     words_submitted.sort((a,b) => {
-      return b.players.length - a.players.length;
+      const delta = b.players.length - a.players.length;
+      if (delta !== 0)
+        return delta;
+      return b.kudos.length - a.kudos.length;
     });
 
     /* Put this round's scores into the game state object so it will
diff --git a/test b/test
index 646cdcabc0654af15ecbe90b1d5870c7e9846b29..c6c87508d50dab970b6ff7298f05152eb0f36a49 100755 (executable)
--- a/test
+++ b/test
@@ -655,12 +655,12 @@ empathy_judged()
 }
 
 TEST "Submit word groups from alice"
-result=$(empathy_judged alice $prompt_id '[["sun","SunLight","SunShine"],["sand","sands","Grains of Sand"],["water","wafer"]]')
+result=$(empathy_judged alice $prompt_id '[{"words":["sun","SunLight","SunShine"],"kudos":false},{"words":["sand","sands","Grains of Sand"],"kudos":false},{"words":["water","wafer"],"kudos":false}]')
 test "$result" = '{"valid":true}'
 TEST_END
 
 TEST "Submit word groups from bob"
-result=$(empathy_judged bob $prompt_id '[["sands","grains of sand"],["water","wafer"]]')
+result=$(empathy_judged bob $prompt_id '[{"words":["sands","grains of sand"],"kudos":false},{"words":["water","wafer"],"kudos":false}]')
 test "$result" = '{"valid":true}'
 TEST_END
 
@@ -676,7 +676,7 @@ test "$result" = "null"
 TEST_END
 
 TEST "Submit word groups from charlie"
-result=$(empathy_judged charlie $prompt_id '[["SunLight","SunShine"],["sand","Grains of Sand"]]')
+result=$(empathy_judged charlie $prompt_id '[{"words":["SunLight","SunShine"],"kudos":false},{"words":["sand","Grains of Sand"],"kudos":false}]')
 test "$result" = '{"valid":true}'
 TEST_END
 
@@ -892,7 +892,7 @@ test "$?" = "0"
 TEST_END
 
 TEST "1 player votes for a match"
-empathy_judged alice $prompt_id '[["truth","true"]]' >/dev/null
+empathy_judged alice $prompt_id '[{"words":["truth","true"],"kudos":false}]' >/dev/null
 result=$(empathy_judged bob $prompt_id '[]')
 test "$result" = '{"valid":true}'
 TEST_END