Trainer Store Module
Overview
Section titled “Overview”The Trainer Store is the reactive engine behind Trainer Mode in the Dice Chess PWA. It coordinates user predictions (guesses) on the board, compares them with the actual game moves, handles the “No legal moves” automatic turn skipping sequence, manages trainer stats submission, and controls navigation/saving options.
To address rising complexity, the previous monolithic implementation has been refactored into a highly-cohesive composed architecture under frontend-pwa/src/lib/trainer/.
Architectural Layout
Section titled “Architectural Layout”A delegating facade is maintained at the root of frontend-pwa/src/lib/trainerStore.svelte.ts to ensure 100% backward compatibility for all consuming Svelte components (such as TrainerGameView.svelte) and sibling stores.
graph TD
Facade["trainerStore (Facade File)"] -->|Delegates to| Coordinator["TrainerStore (Composed Coordinator)"]
Coordinator -->|Composes| Guess["TrainerGuessEngine"]
Coordinator -->|Composes| Session["TrainerSessionManager"]
Sub-System Responsibilities
Section titled “Sub-System Responsibilities”1. TrainerStore (Composed Coordinator)
Section titled “1. TrainerStore (Composed Coordinator)”The central coordinating class that sets up the Svelte 5 root-level $effect sync mechanisms and delegates interface requests.
- Composition:
guessEngine: An instance ofTrainerGuessEngine.sessionManager: An instance ofTrainerSessionManager.
- Reactive derived fields:
canGoToStart/canGoToEnd: Evaluates if the player is allowed to navigate the board boundaries manually.nextGame: Peeks at the siblinggameListStoreto find the next game in sequence.hasNextGame: Boolean flag indicating if a next game is available to load.
- Duties:
- Automatically resets/synchronizes the guess engine’s baseline FEN, guess history, and timer when the active game’s FEN position or active game ID changes.
- Automatically resets guess validation feedback (
guessFeedback = 'idle') when users click away or navigate moves.
2. TrainerGuessEngine (Guess Tracking & Move Input)
Section titled “2. TrainerGuessEngine (Guess Tracking & Move Input)”Manages visual guess previews, piece move overrides on the board, takebacks, and guess validation states.
- State (
$state):guessFeedback: Neutral (idle),correct, orincorrectvalidation badge state.lastValidatedGuessMoveIndex: Anchor index of the last evaluated move.guessedMovesUci: List of UCI moves predicted by the user during the current turn.predictedBoardFenPart/predictedBoardFenFull: Preview board FEN created by dragging pieces.guessStartedAtMs: Timestamp noting when the user began predicting.
- Duties:
- Listens to board actions (
handleBoardMove) and updates overrides for the board FEN (currentBoardFenOverride) and dice pools (currentDiceOverride). - Auto-advances the turn if no legal moves remain for the active player’s remaining dice pool (leveraging
tick()to wait for derived engine evaluations).
- Listens to board actions (
3. TrainerSessionManager (Session Navigation & Saving)
Section titled “3. TrainerSessionManager (Session Navigation & Saving)”Governs turn-based transitions, auto-archiving options, puzzle saving, logs delivery, and the “No legal moves” asynchronous notice.
- State (
$state):evaluatedPuzzleSnapshot: Cache of FEN/solution sequence when an attempt is validated.boardResetSignal: Reactive trigger to revert the board before replaying an incorrect guess.guessFlashToken: Visual trigger to flash badge feedback.
- Duties:
- Peeks at the destination turn boundary, scores user guess accuracy (
isMatch), submits structured training log telemetry to the backend, and fires navigation animations. - Implements the asynchronous “No legal moves” auto-advance chain, flashing notice popups and stepping turns forward safely.
- Wraps puzzle-saving operations in a safe write try/catch block to prevent unhandled database promise rejections.
- Peeks at the destination turn boundary, scores user guess accuracy (
Defensive Engineering
Section titled “Defensive Engineering”1. Circular Dependency & Type Loops
Section titled “1. Circular Dependency & Type Loops”In Svelte 5 and TypeScript, mutually referencing coordinator classes can create circular type-inference loops.
- Solution: Explicitly type-annotated
guessEngineandsessionManagerinTrainerStorerather than relying on automatic property initialization inference. - Context interface: Constructed a typed
TrainerSessionManagerContextinside the session manager to avoid direct class dependency references.
2. Auto-Advance Race Conditions
Section titled “2. Auto-Advance Race Conditions”The “No legal moves” auto-advance sequence is highly asynchronous, employing multiple sleep pauses (setTimeout). If a user quickly switches games or exits trainer mode mid-pause, late timers could fire on the wrong state.
- Solution: The loop enforces
selectedGameId === gameIdchecks at every timing and navigation boundary:if (activeGameStore.selectedGameId !== gameId) break;
Key Files
Section titled “Key Files”frontend-pwa/src/lib/trainerStore.svelte.ts— The backward-compatible facade store.frontend-pwa/src/lib/trainer/trainerStore.svelte.ts— Composed orchestrator class.frontend-pwa/src/lib/trainer/trainerGuessEngine.svelte.ts— Guess validation and moves input service.frontend-pwa/src/lib/trainer/trainerSessionManager.svelte.ts— Session navigation, auto-advance, and saving.frontend-pwa/src/lib/trainer/index.ts— Module exports index.