Skip to content

Add an end-game recap with canned parting shots - #123

Open
ejsmith wants to merge 5 commits into
mainfrom
end-game-recap
Open

ejsmith wants to merge 5 commits into
mainfrom
end-game-recap

Conversation

@ejsmith

@ejsmith ejsmith commented Oct 23, 2026

Copy link
Copy Markdown
Owner

Summary

When a multiplayer game ends, the Game Over panel now recaps the game and gives both players a last word.

  • Rating: each player's rating before → after.
  • Feats & defeats each player earned in this game, including milestones the game unlocked (up to 3 shown per player, then "+N more").
  • Stat sheet, paged so the screen never scrolls:
    • Punches: thrown, landed, counterpunches landed, biggest score deleted.
    • Moments: best turn, Suckers rolled, Sucker Deals, lead changes, biggest lead.
    • Tokens: spent on Extra Rolls, Mulligans, and Punches; earned from Sucker Deals; left over.
  • Parting shots (canned only, no free text): each player picks one shot from the lines for their result (win, loss, or tie), plus one comeback once the other player's shot lands. At most four lines per game. Each line returns the game to the recipient's list and sends a push. Rage Quit games keep their single reply and show no recap.

Implementation

  • Migration 20261023120000_add_end_game_recap.sql: the parting_shot action type, and get_game_recap(target_game_id), which is participant-only. player_feats and other players' results stay closed to direct reads. schema.sql and the database types are updated to match.
  • game-action: a new parting_shot { gameId, lineId } action appends to state.partingShots through commit_game_move. Its version check keeps the cap race-safe across devices, as with Rage Quit replies.
  • shared/partingShots.ts holds the lines and the rules for who can send what. It's mirrored into supabase/functions/_shared, and a test keeps the two copies in step.
  • shared/gameRecap.ts builds the stat sheet from turns and actions that participants can already read.
  • src/ui/GameRecap.tsx renders the recap; src/multiplayer/gameRecap.ts loads it once per finished game.
  • docs/end-game-recap.md describes the feature.

Independent of #122. With #122 merged, instant feats are already stored before the game ends; the recap reads them the same way.

Needs the migration applied and a game-action deploy.

Testing

  • npm run typecheck, npm run typecheck:edge, npm run test, npm run test:edge, npm run lint
  • New unit tests for the recap tallies and the parting-shot rules.
  • npm run test:integration:supabase (48 passed): a new test covers the one-shot-plus-one-comeback cap, wrong-result and free-text lines being rejected, result_seen_at being reset, and get_game_recap refusing non-participants.
  • Visual check at 393×852 and 375×667, including the tallest state (three lines sent plus the comeback picker). No vertical scrolling at either size.

🤖 Generated with Claude Code

When a multiplayer game ends, the Game Over panel now shows each player's
rating change, the feats and defeats earned that game, and a paged stat
sheet for punches, big moments, and the token ledger. Each player may send
one canned parting shot for their result and one comeback once the other
player's shot lands. Rage Quit games keep their single reply instead.

get_game_recap reads feats and ratings for a game's own players only, and
the parting_shot action appends to the game state through commit_game_move
so the four-line cap holds across devices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-03T04:34:50.109315Z e1d2f33 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 482fe80911

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread shared/gameRecap.ts
const effectiveTurns = getEffectiveStatTurns(turns);

return {
...scoreSwings(effectiveTurns, players),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Replay score removals when calculating historical leads

When a scored turn is subsequently punched or mulliganed, getEffectiveStatTurns excludes it entirely, so scoreSwings calculates a history in which that score never existed. For example, Alice scoring 20, Bob scoring 50, and Alice punching Bob before he rescores 10 produces zero lead changes and a biggest lead of Alice by 20; the actual game had two lead changes and Bob leading by 30. Replay submissions and their later removals chronologically for these historical metrics rather than using only the turns that survive in the final scorecard.

Useful? React with 👍 / 👎.

ejsmith and others added 3 commits November 2, 2026 11:23
Move the recap migration after main's Glicko and feat migrations so it
applies in order on the hosted database.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a recap page

The Game Over panel now tells one story: the result and margin, rating
changes on the score cards, the three best highlights, the latest parting
shot with one button to answer it, then Rematch and Recap. Lines are picked
in a bottom sheet and sent with Send. The numbers moved to a scrollable Tale
of the Tape page with mirrored bars, every feat, and head-to-head stats.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1d2f33d1a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1868 to +1869
data: { result_seen_at: null },
match: { game_id: gameId, player_id: recipientId },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resurface new parting shots on games older than seven days

When a player sends a parting shot on a game completed more than seven days ago, clearing result_seen_at does not return it to the recipient's active list. get_unseen_game_results still requires game.completed_at > now() - interval '7 days' (supabase/schema.sql:537), and the lobby only resurfaces completed games with has_unseen_result. Consequently, these newly delivered messages remain under Completed Games, or disappear from the loaded list entirely if the game is outside the latest 25 completions. Since parting shots explicitly have no time limit, update the unseen-result lookup to recognize fresh post-game messages rather than relying solely on the original completion date.

Useful? React with 👍 / 👎.

Rendered by CI on Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant