Stage 3: game domain (lifecycle, rules, hint, word-check, history+GCG, stats) #3
Reference in New Issue
Block a user
Delete Branch "feature/stage-3-game-domain"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements Stage 3 (see PLAN.md).
internal/gamedrives the engine over a single match: event-sourced persistence (games row + append-only decoded move journal, liveengine.Gamewarm in a cache, rebuilt by replay on a miss), play/pass/exchange/resign with validate-at-submit scoring, unlimited score/legality preview, hint (per-game allowance + profile wallet), word-check + complaint capture, per-player state, history and GCG export (Poslfit), per-account stats on finish, and a turn-timeout sweeper honouring each player's daily away window. Service/store layer only — HTTP lands in Stage 6.Engine: additive decoded API (no solver import from internal/game) + Resign fix (resigner keeps score, never wins; the other player wins a 2-player game; timeout reuses Resign). Migration 00002 adds games/game_players/game_moves/complaints/account_stats and away_start/away_end/hint_balance on accounts; go-jet regenerated. New config: BACKEND_DICT_DIR (required), BACKEND_DICT_VERSION, BACKEND_GAME_TIMEOUT_SWEEP_INTERVAL, BACKEND_GAME_CACHE_TTL. Docs (PLAN/ARCHITECTURE/FUNCTIONAL+_ru/TESTING/README) updated. Unit + Postgres integration tests added.
internal/game drives the engine over a single match and owns everything the engine does not: event-sourced persistence (a games row + an append-only decoded move journal, with the live engine.Game kept warm in a cache and rebuilt by replay on a miss), the play/pass/exchange/resign transitions with validate-at-submit scoring, an unlimited score/legality preview, the hint (per-game allowance + profile wallet), the word-check tool with complaint capture, per-player game state, history and GCG export (Poslfit dialect), and a background turn-timeout sweeper that auto-resigns overdue turns honouring each player's daily away window. Like Stages 1-2 it is a service/store layer with no HTTP; the gateway surface lands in Stage 6. Engine: additive decoded domain API (Direction, SubmitPlay/SubmitExchange/ EvaluatePlay/HintView/Hand, MoveRecord.{Dir,MainRow,MainCol}, Registry.Lookup, ParseVariant) so internal/game never imports scrabble-solver; and a Resign fix so the resigner keeps their score yet never wins (the other player wins a two-player game). Timeout reuses Resign. Persistence: migration 00002 adds games, game_players, game_moves, complaints, account_stats and extends accounts with away_start/away_end/hint_balance; go-jet regenerated. account gained SpendHint. Config adds BACKEND_DICT_DIR (required), BACKEND_DICT_VERSION, BACKEND_GAME_TIMEOUT_SWEEP_INTERVAL, BACKEND_GAME_CACHE_TTL; main loads the registry at boot (hard dependency) and starts the sweeper. Tests: engine resign + decoded-API tests; game unit tests (GCG, away-window boundaries, hint budget, cache, keyed mutex, payload); inttest integration (lifecycle, replay equivalence, timeout sweep with away grace, resign stats, hint policy, word-check/complaint, per-game-lock). Docs (PLAN, ARCHITECTURE, FUNCTIONAL +_ru, TESTING, README) updated.