From: Carl Worth Date: Sun, 28 Jun 2020 00:21:38 +0000 (-0700) Subject: Two alterations to player scoring: per-round grouping, and round normalization X-Git-Url: https://git.cworth.org/git?p=lmno-server;a=commitdiff_plain;h=3dae3833cb5247943e27649a9b16639c2187c8c5 Two alterations to player scoring: per-round grouping, and round normalization Previously, we were returning an array of player scores where some succesive players in the array may have had identical scores. Now, instead, we have only one entry per score, and instead of just a single player name, an array of player names in case there is a tie at any score. This should help clients display per-round scores in a way that make all the ties obvious. Second, we were previously accumulating the per-round points directly into a player's total. This had the defect of weighting some rounds more than others, (rounds with more items were worth a higher maximum number of points than rounds with fewer items). Now, instead, we only accumulate into a player's total the number of players that they beat out in each round. This gives an equal weight to every round. The test suite is updated in this commit for the first fix above. But the test suite does not yet cover the player's overall scores so that change is not tested here. --- diff --git a/empathy.js b/empathy.js index fdf62a1..7b27ee4 100644 --- a/empathy.js +++ b/empathy.js @@ -50,17 +50,28 @@ class Empathy extends Game { reset() { - /* Before closing out the current round, we accumulate the score - * for each player into their runnning total. */ - for (let score of this.state.scores.scores) { - const player = this.players.find(p => p.name === score.player); - if (player.score) - player.score += score.score; - else - player.score = score.score; - - /* And broadcast that new score out. */ - this.broadcast_event('player-update', player.info_json()); + /* Before closing out the current round, we accumulate into each + * player's overall score the results from the current round. + * + * Note: Rather than applying the actual points from each round + * into the player's score, we instead accumulate up the number of + * players that they bested in each round. This ensures that each + * round receives an equal weight in the overall scoring. */ + let bested = this.state.scores.scores.reduce( + (total, score) => total + score.players.length, 0); + for (let i = 0; i < this.state.scores.scores.length; i++) { + const score = this.state.scores.scores[i]; + bested -= score.players.length; + for (let player_name of score.players) { + const player = this.players.find(p => p.name === player_name); + if (player.score) + player.score += bested; + else + player.score = bested; + + /* And broadcast that new score out. */ + this.broadcast_event('player-update', player.info_json()); + } } /* Now that we're done with the active prompt, we remove it from @@ -513,6 +524,18 @@ class Empathy extends Game { return b.score - a.score; }); + /* 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) + list[list.length-1].players.push(next.player); + else + list.push({players: [next.player], score: next.score}); + return list; + }; + + const grouped_scores = scores.reduce(reducer, []); + /* Put the word groups into a form the client can consume. */ const words_submitted = word_groups.map( @@ -531,7 +554,7 @@ class Empathy extends Game { /* Put this round's scores into the game state object so it will * be sent to any new clients that join. */ this.state.scores = { - scores: scores, + scores: grouped_scores, words: words_submitted }; diff --git a/test b/test index f62d682..fcb556c 100755 --- a/test +++ b/test @@ -690,7 +690,7 @@ TEST_END # Usage: empathy_scores_names_numbers empathy_scores_names_numbers() { - empathy_get_event $1 game-state | jq '.scores.scores[]|.player,.score' + empathy_get_event $1 game-state | jq '.scores.scores[]|.players[],.score' } TEST_SUBSECTION "Scoring" @@ -890,7 +890,7 @@ TEST_END TEST "Verify the match passed the vote" # echo here is to strip newlines result=$(echo $(empathy_scores_names_numbers alice)) -test "$result" = '"alice" 2 "bob" 2 "charlie" 0 "dale" 0 "eric" 0 "fred" 0' +test "$result" = '"alice" "bob" 2 "charlie" "dale" "eric" "fred" 0' TEST_END echo "" @@ -929,7 +929,7 @@ TEST_END TEST "Verify scores don't include inactive players" # echo here is to strip newlines result=$(echo $(empathy_scores_names_numbers alice)) -test "$result" = '"alice" 1 "bob" 1 "charlie" 0' +test "$result" = '"alice" "bob" 1 "charlie" 0' TEST_END TEST_SUBSECTION "Deactivated players don't block future game phase advances"