From caff5093aeb10a1aa67679941f08309752b1a8a4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 11 Sep 2026 18:25:15 +0000 Subject: [PATCH] Report a Semi-Final slot that was emptied without being refilled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The re-seed banner listed only the slots that were filled, so a re-seed that just vacated one — un-recording an Elimination Final result takes its winner back out of the semi — rendered as "Re-seeded the Semi-Finals: ." with nothing after the colon. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01MSDeNWAXvK7nznJqjxn7Jo --- ...-seasons.bracket.reseed-afl-semifinals.test.ts | 14 ++++++++++++++ ...-seasons.$id.events.$eventId.bracket.server.ts | 15 +++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/app/routes/__tests__/admin.sports-seasons.bracket.reseed-afl-semifinals.test.ts b/app/routes/__tests__/admin.sports-seasons.bracket.reseed-afl-semifinals.test.ts index f05434c..2bd5b4e 100644 --- a/app/routes/__tests__/admin.sports-seasons.bracket.reseed-afl-semifinals.test.ts +++ b/app/routes/__tests__/admin.sports-seasons.bracket.reseed-afl-semifinals.test.ts @@ -87,6 +87,20 @@ describe("reseed-afl-semifinals", () => { }); }); + it("reports a slot that was emptied without being refilled", async () => { + // Un-recording an Elimination Final result takes its winner back out of the semi. + vi.mocked(reseedAflSemiFinals).mockResolvedValue({ + vacated: [1, 2], + filled: [{ matchNumber: 2, participantId: "adelaide" }], + }); + + expect(await run()).toEqual({ + success: + "Re-seeded the Semi-Finals: match 1 is back to TBD, " + + "match 2 now hosts Adelaide Crows.", + }); + }); + it("says so when the pairings are already right", async () => { vi.mocked(reseedAflSemiFinals).mockResolvedValue({ vacated: [], filled: [] }); diff --git a/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.server.ts b/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.server.ts index 897b03f..e8d16e1 100644 --- a/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.server.ts +++ b/app/routes/admin.sports-seasons.$id.events.$eventId.bracket.server.ts @@ -935,9 +935,20 @@ export async function action({ request, params }: Route.ActionArgs) { // Only the qualifier slots move, so there is nothing to re-score: no placement, // score or elimination changes, and so nothing to announce. - const moves = reseed.filled + // + // A slot can be vacated without being refilled — un-recording an Elimination Final + // result takes its winner back out — so report those too rather than rendering an + // empty list. + const filled = reseed.filled.map((slot) => ({ + matchNumber: slot.matchNumber, + text: `match ${slot.matchNumber} now hosts ${nameOf(slot.participantId)}`, + })); + const emptied = reseed.vacated + .filter((matchNumber) => !reseed.filled.some((slot) => slot.matchNumber === matchNumber)) + .map((matchNumber) => ({ matchNumber, text: `match ${matchNumber} is back to TBD` })); + const moves = [...filled, ...emptied] .toSorted((a, b) => a.matchNumber - b.matchNumber) - .map((slot) => `match ${slot.matchNumber} now hosts ${nameOf(slot.participantId)}`) + .map((move) => move.text) .join(", "); return {