feat: Represent session game outcome as win/loss/draw#288
Merged
Conversation
Replace GameResult.Won (bool) with a three-state GameOutcome enum so draws are recorded as draws instead of silently counting as losses. The outcome is derived from the Wins/Losses deltas (Losses was previously unused), with validation rejecting impossible single-game movement. The session-at wire field changes from "won": bool to "outcome": "win"|"loss"|"draw". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates session game results to model the outcome as a three-state enum (win/loss/draw) instead of a boolean, and wires that through the session-at JSON response to correctly represent rare draw games.
Changes:
- Replace
domain.GameResult.Won boolwithdomain.GameOutcome(Outcomefield). - Derive outcome from per-game
Wins/Lossesdeltas inbuildGameSegment, including validation that rejects impossible deltas (falls back toGame: nil). - Update
session-atresponse schema from"won": boolto"outcome": "win" | "loss" | "draw", plus updated tests (including draw + invalid-delta cases).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| internal/domain/game_result.go | Introduces GameOutcome enum and updates GameResult to use Outcome. |
| internal/app/session_at.go | Computes Outcome from wins/losses deltas and validates impossible single-game movements. |
| internal/app/session_at_test.go | Updates assertions to outcomes and adds coverage for draw + invalid win/loss delta scenarios. |
| internal/ports/rainbow_converters.go | Adds gameOutcomeToRainbowOutcome converter for stable JSON contract strings. |
| internal/ports/session_at.go | Updates session-at wire format to emit outcome and performs conversion. |
| internal/ports/session_at_test.go | Updates handler tests to expect outcome instead of won. |
Comment on lines
+242
to
+244
| // unreachable | ||
| reporting.Report(ctx, | ||
| fmt.Errorf("weird Wins/Losses delta for single-game segment"), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the
Won boolon session-detail game results with a three-stateGameOutcomeenum (win/loss/draw). Draws are rare but do happen inBedwars; today they are silently miscounted as losses because
Winsdoesn'tincrement.
Changes
domain.GameResult.Won bool→Outcome GameOutcome(win/loss/draw), anew enum mirroring the existing
domain.Gamemodepattern.Wins/Lossesdeltas inbuildGameSegment(theLossescounter was previously never read). Added a validation guardrejecting impossible single-game movement (deltas outside
{0,1}, or bothwin and loss advancing), consistent with the existing FinalDeaths/BedsLost
guard → falls back to
Game: nil.session-at:"won": boolbecomes"outcome": "win" | "loss" | "draw", with a newgameOutcomeToRainbowOutcomeconverter.Detection assumption
A draw is treated as "one game played, but neither
WinsnorLossesincremented". This relies on a draw still advancing
GamesPlayedby 1 whilecrediting neither counter (otherwise it's filtered out upstream as a non-game).
The enum modeling is correct regardless, but worth confirming against real draw
data if any exists.
This changes the
session-atJSON contract (won→outcome). Rainbow PR#256 must be updated to work with this updated schema:
Amund211/rainbow#256
🤖 Generated with Claude Code