felt/.planning/phases/01-tournament-engine/01-09-SUMMARY.md
2026-03-01 08:14:00 +01:00

8.7 KiB

phase plan subsystem tags requires provides affects tech-stack key-files key-decisions patterns-established requirements-completed duration completed
01-tournament-engine 09 api, tournament, financial
tournament-lifecycle
multi-tournament
icm
chop
deal
malmuth-harville
monte-carlo
lobby
phase provides
01-tournament-engine/04 Clock engine with registry, ticker, state machine
phase provides
01-tournament-engine/06 Financial engine with transactions, prize pool, payouts
phase provides
01-tournament-engine/07 Player management, rankings, buy-in flow
phase provides
01-tournament-engine/08 Seating engine with tables, balancing, break table
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)
01-11
01-12
01-14
phase-02
added patterns
tournament-scoped-state
template-first-creation
local-copy-semantics
proposal-confirm-workflow
icm-dispatcher-pattern
created modified
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
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
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
MULTI-01
MULTI-02
FIN-11
SEAT-06
25min 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