From b5ab318e056756e42b14668c978e97c3f0ad59c7 Mon Sep 17 00:00:00 2001 From: josh Date: Sun, 19 Apr 2026 18:47:50 -0400 Subject: [PATCH] fix: drop game_number by one for finished playoff cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scoreboard payloads don't include gameNumber, so the previous fix fell straight through to series_state['game_number'], which is hi+lo+1 — the *next* game. Once a game goes FINAL the win for this game is already banked in seriesStatus, so the card's own number is hi+lo. For the just-played Game 1 of Kings/Avalanche (series now 1-0), this brings the header back to "Game 1 of 7" instead of "Game 2 of 7". Co-Authored-By: Claude Opus 4.7 --- app/playoff.py | 9 +++++++-- tests/test_playoff_series.py | 15 +++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/app/playoff.py b/app/playoff.py index 8d4153a..3953c99 100644 --- a/app/playoff.py +++ b/app/playoff.py @@ -93,11 +93,16 @@ def series_state(series_status): def _game_number(game, state): - """This card's game number. Prefer the raw ``gameNumber`` field so we don't - drift forward once ``seriesStatus`` advances after the game ends.""" + """This card's game number. seriesStatus counts wins through the current + payload, so once a game goes FINAL the win for this game is already banked + and state['game_number'] (hi+lo+1) points at the *next* game. For a finished + card, pin to hi+lo. The scoreboard payload doesn't carry a raw gameNumber, + but we honor it if present (e.g. from the series-detail endpoint).""" raw = game.get("gameNumber") if isinstance(raw, int) and raw > 0: return raw + if game.get("gameState") in ("FINAL", "OFF"): + return max(1, state["hi"] + state["lo"]) return state["game_number"] diff --git a/tests/test_playoff_series.py b/tests/test_playoff_series.py index 51556c2..c8f2192 100644 --- a/tests/test_playoff_series.py +++ b/tests/test_playoff_series.py @@ -149,10 +149,17 @@ class TestSeriesSummary: game = make_playoff_game(top_wins=1, bottom_wins=1) assert series_summary(game) == "Game 3 of 7" - def test_finished_game_keeps_its_own_number(self): - # seriesStatus has advanced to 2-0 after this game finished, but the - # raw gameNumber pins the card to the game it actually represents. - game = make_playoff_game(top_wins=2, bottom_wins=0, game_number=2) + def test_finished_game_uses_pre_advance_number(self): + # Scoreboard payloads don't carry gameNumber. Once a game goes FINAL, + # seriesStatus already includes this game's result, so the card's game + # number is hi+lo, not hi+lo+1. + game = make_playoff_game(top_wins=1, bottom_wins=0, game_state="FINAL") + assert series_summary(game) == "Game 1 of 7" + + def test_finished_game_honors_explicit_game_number(self): + game = make_playoff_game( + top_wins=2, bottom_wins=0, game_state="FINAL", game_number=2 + ) assert series_summary(game) == "Game 2 of 7"