From 14e405c1013e29bca4c986be7c94be584f1c1a5e Mon Sep 17 00:00:00 2001 From: Mikkel Georgsen Date: Sun, 1 Mar 2026 08:14:00 +0100 Subject: [PATCH] docs(01-09): complete Tournament Lifecycle + Multi-Tournament + Chop/Deal plan Co-Authored-By: Claude Opus 4.6 --- .planning/REQUIREMENTS.md | 12 +- .planning/STATE.md | 27 +-- .../01-tournament-engine/01-09-SUMMARY.md | 166 ++++++++++++++++++ 3 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 .planning/phases/01-tournament-engine/01-09-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index be56d60..d0fc4f4 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -69,7 +69,7 @@ Requirements for Phase 1 (Development Focus: Live Tournament Management). Each m - [x] **FIN-08**: Prize pool auto-calculation from all financial inputs - [x] **FIN-09**: Guaranteed pot support (house covers shortfall) - [x] **FIN-10**: Payout structures (percentage, fixed, custom table) with configurable rounding -- [ ] **FIN-11**: Chop/deal support (ICM calculator, chip-chop, even-chop, custom) +- [x] **FIN-11**: Chop/deal support (ICM calculator, chip-chop, even-chop, custom) - [x] **FIN-12**: End-of-season withholding (reserve rake portion for season prizes) - [x] **FIN-13**: Every financial action generates a receipt with full transaction log - [x] **FIN-14**: Transaction editing with audit trail and receipt reprint capability @@ -98,8 +98,8 @@ Requirements for Phase 1 (Development Focus: Live Tournament Management). Each m ### Multi-Tournament -- [ ] **MULTI-01**: Run multiple simultaneous tournaments with independent clocks, financials, and player tracking -- [ ] **MULTI-02**: Tournament lobby view (multi-tournament overview on displays) +- [x] **MULTI-01**: Run multiple simultaneous tournaments with independent clocks, financials, and player tracking +- [x] **MULTI-02**: Tournament lobby view (multi-tournament overview on displays) ### League & Season @@ -333,8 +333,8 @@ Which phases cover which requirements. Updated during roadmap reorganization. | CHIP-02 | Phase 1 | Complete | | CHIP-03 | Phase 1 | Complete | | CHIP-04 | Phase 1 | Complete | -| MULTI-01 | Phase 1 | Pending | -| MULTI-02 | Phase 1 | Pending | +| MULTI-01 | Phase 1 | Complete | +| MULTI-02 | Phase 1 | Complete | | FIN-01 | Phase 1 | Complete | | FIN-02 | Phase 1 | Complete | | FIN-03 | Phase 1 | Complete | @@ -345,7 +345,7 @@ Which phases cover which requirements. Updated during roadmap reorganization. | FIN-08 | Phase 1 | Complete | | FIN-09 | Phase 1 | Complete | | FIN-10 | Phase 1 | Complete | -| FIN-11 | Phase 1 | Pending | +| FIN-11 | Phase 1 | Complete | | FIN-12 | Phase 1 | Complete | | FIN-13 | Phase 1 | Complete | | FIN-14 | Phase 1 | Complete | diff --git a/.planning/STATE.md b/.planning/STATE.md index 30ef1b4..4758d91 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,12 +3,12 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: unknown -last_updated: "2026-03-01T03:35:13.000Z" +last_updated: "2026-03-01T08:12:00.000Z" progress: total_phases: 1 completed_phases: 0 total_plans: 14 - completed_plans: 10 + completed_plans: 11 --- # Project State @@ -23,27 +23,27 @@ See: .planning/PROJECT.md (updated 2026-02-28) ## Current Position Phase: 1 of 7 (Tournament Engine) -Plan: 11 of 14 in current phase +Plan: 12 of 14 in current phase Status: Executing Phase 1 -Last activity: 2026-03-01 — Completed Plan G (Player Management) +Last activity: 2026-03-01 — Completed Plan 09 (Tournament Lifecycle + Multi-Tournament + Chop/Deal) -Progress: [███████░░░] 71% +Progress: [████████░░] 79% ## Performance Metrics **Velocity:** -- Total plans completed: 10 -- Average duration: 8min -- Total execution time: 1.33 hours +- Total plans completed: 11 +- Average duration: 10min +- Total execution time: 1.75 hours **By Phase:** | Phase | Plans | Total | Avg/Plan | |-------|-------|-------|----------| -| 01-tournament-engine | 10 | 80min | 8min | +| 01-tournament-engine | 11 | 105min | 10min | **Recent Trend:** -- Last 5 plans: 01-03 (5min), 01-13 (5min), 01-06 (9min), 01-08 (6min), 01-07 (7min) +- Last 5 plans: 01-13 (5min), 01-06 (9min), 01-08 (6min), 01-07 (7min), 01-09 (25min) - Trend: steady *Updated after each plan completion* @@ -100,6 +100,11 @@ Recent decisions affecting current work: - [01-07]: CSV formula injection neutralized with tab prefix on =, +, -, @ characters - [01-07]: Buy-in flow auto-registers player in tournament_players if not already present - [01-07]: QR code URL format: felt://player/{uuid} for future PWA self-check-in +- [01-09]: ICM dispatcher: exact Malmuth-Harville for <=10 players, Monte Carlo (100K iterations) for 11+ +- [01-09]: Deal proposal/confirm workflow: ProposeDeal returns preview, ConfirmDeal applies payouts +- [01-09]: Full chop sets all players to 'deal' status and completes tournament; partial chop continues play +- [01-09]: Tournament auto-close: 1 remaining = EndTournament, 0 remaining = CancelTournament +- [01-09]: Integration tests use file-based DB with WAL mode for clock ticker goroutine compatibility ### Pending Todos @@ -117,5 +122,5 @@ None yet. ## Session Continuity Last session: 2026-03-01 -Stopped at: Completed 01-07-PLAN.md (Player Management) +Stopped at: Completed 01-09-PLAN.md (Tournament Lifecycle + Multi-Tournament + Chop/Deal) Resume file: None diff --git a/.planning/phases/01-tournament-engine/01-09-SUMMARY.md b/.planning/phases/01-tournament-engine/01-09-SUMMARY.md new file mode 100644 index 0000000..ef12534 --- /dev/null +++ b/.planning/phases/01-tournament-engine/01-09-SUMMARY.md @@ -0,0 +1,166 @@ +--- +phase: 01-tournament-engine +plan: 09 +subsystem: api, tournament, financial +tags: [tournament-lifecycle, multi-tournament, icm, chop, deal, malmuth-harville, monte-carlo, lobby] + +# Dependency graph +requires: + - phase: 01-tournament-engine/04 + provides: Clock engine with registry, ticker, state machine + - phase: 01-tournament-engine/06 + provides: Financial engine with transactions, prize pool, payouts + - phase: 01-tournament-engine/07 + provides: Player management, rankings, buy-in flow + - phase: 01-tournament-engine/08 + provides: Seating engine with tables, balancing, break table +provides: + - Tournament lifecycle service (create, start, pause, resume, end, cancel, auto-close) + - Multi-tournament manager with lobby view (MULTI-01, MULTI-02) + - ICM calculator (exact Malmuth-Harville for <=10, Monte Carlo for 11+) + - Chop/deal engine (ICM, chip chop, even chop, custom, partial chop) + - Tournament state aggregation for WebSocket connect + - Activity feed from audit trail + - Tournament API routes with deal proposal workflow + - Deal proposals migration (007_deal_proposals.sql) +affects: [01-11, 01-12, 01-14, phase-02] + +# Tech tracking +tech-stack: + added: [] + patterns: [tournament-scoped-state, template-first-creation, local-copy-semantics, proposal-confirm-workflow, icm-dispatcher-pattern] + +key-files: + created: + - internal/tournament/tournament.go + - internal/tournament/state.go + - internal/tournament/multi.go + - internal/financial/icm.go + - internal/financial/chop.go + - internal/server/routes/tournaments.go + - internal/store/migrations/007_deal_proposals.sql + - internal/financial/icm_test.go + - internal/financial/chop_test.go + - internal/tournament/tournament_test.go + - internal/tournament/integration_test.go + modified: [] + +key-decisions: + - "ICM dispatcher: exact Malmuth-Harville for <=10 players, Monte Carlo (100K iterations) for 11+" + - "Deal proposal/confirm workflow: ProposeDeal returns preview, ConfirmDeal applies payouts" + - "Full chop sets all players to 'deal' status and completes tournament; partial chop continues play" + - "Integration tests use file-based DB with WAL mode for clock ticker goroutine compatibility" + - "Tournament auto-close: 1 remaining = end, 0 remaining = cancel" + +patterns-established: + - "Tournament-scoped state: all state (clock, players, tables, financials) keyed by tournament_id" + - "Template-first creation: CreateFromTemplate loads expanded template, applies overrides, copies all refs" + - "Proposal-confirm pattern: deal proposals are stored, reviewed, then confirmed or cancelled" + - "ICM dispatcher pattern: CalculateICM auto-selects exact vs Monte Carlo based on player count" + - "Activity feed: audit entries converted to human-readable ActivityEntry structs" + +requirements-completed: [MULTI-01, MULTI-02, FIN-11, SEAT-06] + +# Metrics +duration: 25min +completed: 2026-03-01 +--- + +# Plan 09: Tournament Lifecycle + Multi-Tournament + Chop/Deal Summary + +**Full tournament lifecycle (create/start/pause/resume/end/cancel/auto-close) with multi-tournament lobby, ICM calculator (exact + Monte Carlo), and chop/deal engine supporting 5 deal types** + +## Performance + +- **Duration:** ~25 min +- **Started:** 2026-03-01T07:45:00Z +- **Completed:** 2026-03-01T08:10:00Z +- **Tasks:** 2 +- **Files created:** 11 + +## Accomplishments +- Tournament lifecycle service with all state transitions, template-first creation with local copy semantics, and auto-close on last player standing +- Multi-tournament manager enabling lobby view with independent state per tournament (clocks, financials, players, tables) +- ICM calculator with exact Malmuth-Harville algorithm (<=10 players, <2ms) and Monte Carlo simulation (11+ players, 100K iterations, <25ms) +- Chop/deal engine with 5 deal types (ICM, chip chop, even chop, custom, partial chop) and proposal/confirm workflow +- 31 new tests across 4 test files: 12 ICM, 6 chop, 9 tournament unit, 4 integration + +## Task Commits + +Each task was committed atomically: + +1. **Task I1: Tournament lifecycle and multi-tournament management** - `75ccb6f` (feat) +2. **Task I2: ICM calculator, chop/deal engine, and comprehensive tests** - `2958449` (test) + +## Files Created/Modified +- `internal/tournament/tournament.go` - Tournament service: create from template, start, pause, resume, end, cancel, auto-close, list +- `internal/tournament/state.go` - State aggregation for WebSocket snapshots and activity feed +- `internal/tournament/multi.go` - Multi-tournament manager with lobby view, active tournament listing +- `internal/financial/icm.go` - ICM calculator: exact Malmuth-Harville + Monte Carlo dispatcher +- `internal/financial/chop.go` - Chop engine: 5 deal types, proposal/confirm workflow, position assignment +- `internal/server/routes/tournaments.go` - Tournament API routes: CRUD, lifecycle, deal proposals +- `internal/store/migrations/007_deal_proposals.sql` - Deal proposals table migration +- `internal/financial/icm_test.go` - 12 ICM tests (exact, Monte Carlo, validation, performance, convergence) +- `internal/financial/chop_test.go` - 6 chop/deal tests (all deal types, positions, tournament end) +- `internal/tournament/tournament_test.go` - 9 tournament unit tests (template, start, auto-close, multi, state) +- `internal/tournament/integration_test.go` - 4 integration tests (lifecycle, deal, cancel, pause/resume) + +## Decisions Made +- **ICM dispatcher pattern:** CalculateICM auto-selects exact for <=10 players (factorial complexity manageable) and Monte Carlo with 100K iterations for 11+ (converges to <2% deviation with equal stacks) +- **Deal proposal/confirm workflow:** ProposeDeal calculates and stores proposal without applying; ConfirmDeal applies payouts as chop transactions -- matches the TD review flow from CONTEXT.md +- **Full vs partial chop:** Full chop sets all players to 'deal' status and completes the tournament; partial chop applies partial payouts and lets tournament continue with remaining pool +- **Integration test DB strategy:** In-memory DBs with libsql don't support cross-goroutine access; integration tests use file-based DB with WAL mode and busy_timeout for clock ticker compatibility +- **Auto-close semantics:** CheckAutoClose called after every bust-out; 1 player remaining triggers EndTournament, 0 players triggers CancelTournament + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] Fixed in-memory DB cross-goroutine access in integration tests** +- **Found during:** Task I2 (integration tests) +- **Issue:** `setupTestDB` creates per-test in-memory DBs that aren't accessible from the clock ticker's background goroutine, causing "no such table" errors +- **Fix:** Created `setupIntegrationDB` using file-based temp DB with WAL mode and busy_timeout=5000; added StopTicker call after StartTournament +- **Files modified:** internal/tournament/integration_test.go +- **Verification:** All 4 integration tests pass +- **Committed in:** 2958449 + +**2. [Rule 1 - Bug] Fixed blind_levels notes NULL scan failure** +- **Found during:** Task I2 (tournament tests) +- **Issue:** blind_levels notes column could be NULL, causing scan into string to fail when loading template +- **Fix:** Used sql.NullString for notes scanning in loadLevelsFromDB; added explicit empty string notes to seed data +- **Files modified:** internal/tournament/tournament.go, internal/tournament/tournament_test.go +- **Verification:** TestCreateFromTemplate passes +- **Committed in:** 2958449 + +**3. [Rule 1 - Bug] Fixed payout_brackets column name mismatch** +- **Found during:** Task I2 (tournament tests) +- **Issue:** Test DDL used `payout_structure_id` but service queries use `structure_id` column name +- **Fix:** Renamed column to `structure_id` in test DDL to match production schema +- **Files modified:** internal/tournament/tournament_test.go +- **Verification:** All tournament unit tests pass +- **Committed in:** 2958449 + +--- + +**Total deviations:** 3 auto-fixed (3 Rule 1 bugs) +**Impact on plan:** All auto-fixes necessary for test correctness. No scope creep. + +## Issues Encountered +- libsql PRAGMA handling: `PRAGMA journal_mode=WAL` returns a row, so `Exec` fails with "Execute returned rows" -- must use `QueryRow` with `Scan` instead. This is consistent with the decision logged in 01-02 about libsql PRAGMA inconsistency. + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- Tournament lifecycle is complete and ready for wiring into the full server +- Multi-tournament support enables lobby view for the frontend (Plan 11/14) +- ICM and chop engines ready for frontend deal UI integration +- API routes registered but need wiring into server.go router (will happen in final assembly plan) + +## Self-Check: PASSED + +All 11 created files verified present. Both task commits (75ccb6f, 2958449) verified in git log. + +--- +*Phase: 01-tournament-engine* +*Completed: 2026-03-01*