From 3bf6cc52ab9d556b8bf714365ebbe505c28304fe Mon Sep 17 00:00:00 2001 From: Adrian Wannenmacher Date: Mon, 16 Feb 2026 22:45:15 +0100 Subject: [PATCH] switch round over to a general change event --- models/game.js | 47 +++++++++++++++++++++++++------------------- models/round.js | 7 ++++--- models/round.test.js | 21 +++++++++++++++++++- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/models/game.js b/models/game.js index 2a6ce32..4312ee1 100644 --- a/models/game.js +++ b/models/game.js @@ -60,7 +60,7 @@ export default class Game extends EventTarget { this.#currentRound = new Round(this.#goal, this.#goal); this.#currentRound.addEventListener( - Round.winEvent, this.#boundRoundFinishedHandler); + Round.EVENT_CHANGE, this.#boundHandleRoundChange); } else if (typeof value === "object") { this.#fromStruct(value); } else { @@ -119,29 +119,33 @@ export default class Game extends EventTarget { return {winner, points, ourPoints, theirPoints}; } - /** Handle it when the current round is finished. */ - #handleRoundFinished() { - this.#currentRound.removeEventListener( - Round.winEvent, this.#boundRoundFinishedHandler); - this.#rounds.push( - new RoundResult(this.#currentRound.points, this.#currentRound.winner)); - this.#currentRound = null; + /** Handle changes to the current round. */ + #handleRoundChange() { + if (this.#currentRound.decided) { + this.#currentRound.removeEventListener( + Round.EVENT_CHANGE, this.#boundHandleRoundChange); + this.#rounds.push( + new RoundResult(this.#currentRound.points, this.#currentRound.winner)); + this.#currentRound = null; - let result = this.result; + let result = this.result; - if (result.winner === null) { - this.#currentRound = new Round( - Math.max(this.#goal - result.ourPoints, 2), - Math.max(this.#goal - result.theirPoints, 2)); - this.#currentRound.addEventListener( - Round.winEvent, this.#boundRoundFinishedHandler); - } else { - this.dispatchEvent(new CustomEvent(Game.finishedEvent)); + if (result.winner === null) { + this.#currentRound = new Round( + Math.max(this.#goal - result.ourPoints, 2), + Math.max(this.#goal - result.theirPoints, 2)); + this.#currentRound.addEventListener( + Round.EVENT_CHANGE, this.#boundHandleRoundChange); + } else { + this.dispatchEvent(new CustomEvent(Game.finishedEvent)); + } } + + } - /** #handleRoundFinished, but bound to this instance. */ - #boundRoundFinishedHandler = this.#handleRoundFinished.bind(this); + /** #handleRoundChange, but bound to this instance. */ + #boundHandleRoundChange = this.#handleRoundChange.bind(this); /** Export the data of this `Game` as a plain JS object with fields. * @@ -188,8 +192,11 @@ export default class Game extends EventTarget { if (value.currentRound === null) throw new Error( "struct of ongoing game must contain current round"); - else + else { this.#currentRound = new Round(value.currentRound); + this.#currentRound.addEventListener( + Round.EVENT_CHANGE, this.#boundHandleRoundChange); + } } else if (value.currentRound !== null) throw new Error( "struct of finished game must not contain current round"); diff --git a/models/round.js b/models/round.js index a4b564f..8177b49 100644 --- a/models/round.js +++ b/models/round.js @@ -35,8 +35,8 @@ export const Team = Object.freeze({ * Note that round points are positive, players want to accumulate them. */ export class Round extends EventTarget { - /** The event triggered when the round is won. */ - static winEvent= "roundWon"; + /** The event triggered when something about the round changes. */ + static get EVENT_CHANGE() { return "wb:round:change"; } /** The maximum the "we" team may raise to. */ #ourLimit = 11; @@ -100,7 +100,7 @@ export class Round extends EventTarget { throw new Error("decided round cannot be won again"); this.#winner = team; - this.dispatchEvent(new CustomEvent(Round.winEvent)); + this.dispatchEvent(new CustomEvent(Round.EVENT_CHANGE)); } /** Check whether the round has been decided. */ @@ -147,6 +147,7 @@ export class Round extends EventTarget { this.#raisedLast = team; this.#points += 1; + this.dispatchEvent(new CustomEvent(Round.EVENT_CHANGE)); } /** Export the data of this `Round` as a plain JS object with fields. diff --git a/models/round.test.js b/models/round.test.js index 49387c5..4e7b91b 100644 --- a/models/round.test.js +++ b/models/round.test.js @@ -101,13 +101,32 @@ export default function() { QUnit.test("victory causes event", function(assert) { let round = new Round(); - round.addEventListener(Round.winEvent, function() { + round.addEventListener(Round.EVENT_CHANGE, function() { assert.step("event"); }); round.winner = Team.We; assert.verifySteps(["event"], "event was triggered"); }); + QUnit.test("raising causes event", function(assert) { + let round = new Round(); + round.addEventListener(Round.EVENT_CHANGE, function() { + assert.step("event"); + }); + round.raise(Team.We); + round.raise(Team.They); + assert.verifySteps(["event", "event"], "events were triggered"); + }); + + QUnit.test("winning through raising causes event", function(assert) { + let round = new Round(2, 2); + round.addEventListener(Round.EVENT_CHANGE, function() { + assert.step("event"); + }); + round.raise(Team.We); + assert.verifySteps(["event"], "event was triggered"); + }); + QUnit.test("toStruct - unfinished", function(assert) { let round = new Round(); let struct = round.toStruct();