Skip to content

Active Game Store Module

The Active Game Store is the core component of the Dice Chess PWA frontend, responsible for coordinating board and game states for currently loaded games. It acts as the backbone for:

  • Trainer Mode: Synchronizing user guesses, verifying micro-moves against the engine, and logging training attempts.
  • Practice Mode: Rendering pre-loaded game paths and active puzzles.
  • Game Review: Navigating step-by-step through finished matches, highlighting double-offers and declines, and managing autoplay playback.

To resolve high coupling in the previously monolithic ~860-line activeGameStore.svelte.ts class, the module has been cleanly decomposed into a high-cohesion, composed architecture under frontend-pwa/src/lib/activeGame/.

A slim delegating facade is maintained at the root of frontend-pwa/src/lib/ to guarantee 100% backward compatibility for all consuming Svelte components, views, and sibling stores.

graph TD
    Facade["activeGameStore (Facade File)"] -->|Delegates to| Coordinator["ActiveGameStore (Composed Coordinator)"]
    Coordinator -->|Composes| Navigation["ActiveGameNavigation"]
    Coordinator -->|Composes| Playback["ActiveGamePlayback"]
    Coordinator -->|Composes| Stats["ActiveGameStats"]

The central orchestrator that manages loading, saving, and high-level playback triggers.

  • State ($state): selectedGameId, gameData (type GameData | null), loadingGame, syncingMoves, and gameError.
  • Duties:
    • Loads game histories from the local IndexedDB database via getLocalGame or falls back to the FastAPI backend API via ApiClient.
    • Determines player profiles (IDs, names, and ratings) and derives rapid/bullet time control labels.
    • Interfaces with @rabestro/dicechess-engine to calculate legalMovesDests for the active FEN and active dice values.
    • Implements the high-level playTurnForward and playTurnBackward async micro-move loops.

2. ActiveGameNavigation (History & Navigation)

Section titled “2. ActiveGameNavigation (History & Navigation)”

Manages move indices, FEN states, active dice pool overrides, turn boundaries, and double-decline states.

  • State ($state): currentMoveIndex, maxMoveIndex, isNoLegalMovesNoticeVisible, _currentBoardFen (Trainer override), and _currentDiceOverride (Trainer override).
  • Derived ($derived / $derived.by):
    • currentState: Retrieves the specific MoveHistoryState matching the active index.
    • currentBoardFen / currentDiceValues: Returns either the live game FEN/dice pool or the Trainer’s active mid-turn overrides.
    • turnBoundaries: Evaluates critical transition indices (e.g. pre-move rolls, post-move completions, declines, and game-over terminations).
    • doubleDeclineStartIndex: Pinpoints the start of consecutive declined doubling offers.
    • historyBlocks: Assembles raw move sequences into clean, structured visual turn blocks showing White vs. Black moves.

Isolates autoplay flags, auto-run intervals, and thread tokens.

  • State ($state): isPlaying (boolean flag to toggle UI playback play/pause icons).
  • Internal Register: playbackToken (monotonically increasing integer used to safely cancel stale async playback threads when users manually override navigation mid-play).
  • Duties: Initializes playback tokens and handles play/pause triggers.

Isolates evaluation metrics for guesses in Trainer mode.

  • State ($state): correctGuesses, incorrectGuesses, and lastEvaluatedMoveIndex.
  • Duties: Validates new attempts against lastEvaluatedMoveIndex to prevent double-evaluation, increments appropriate score tallies, and resets stats when games close.

The main frontend-pwa/src/lib/activeGameStore.svelte.ts has been refactored into a delegating facade. It preserves original property, getter, setter, and method signatures to protect downstream views like TrainerGameView.svelte and sibling stores like trainerStore.

Under Svelte 5, getters returning plain inline objects break reactive bindings for downstream views trying to observe stats. To maintain perfect reactivity:

  • The facade’s trainingStats getter returns the reactive sub-system class instance stats directly:
    get trainingStats() {
    return this.modularStore.stats;
    }
  • Downstream Svelte components bind directly to activeGameStore.trainingStats.correctGuesses, benefiting from Svelte 5’s deep property tracking.

Pure utilities like DICE_MAP and getDieValue have been migrated to the non-dependent frontend-pwa/src/utils/fenUtils.ts.

  • The facade re-exports them to maintain 100% backward-compatibility.
  • The sub-systems import them directly from frontend-pwa/src/utils/fenUtils.ts.
  • This ensures zero circular imports between the facade and the modular sub-systems.

  • frontend-pwa/src/lib/activeGameStore.svelte.ts — The backward-compatible facade store.
  • frontend-pwa/src/lib/activeGame/activeGameStore.svelte.ts — Composed orchestrator class.
  • frontend-pwa/src/lib/activeGame/activeGameNavigation.svelte.ts — FEN parsing, indices, and boundaries.
  • frontend-pwa/src/lib/activeGame/activeGamePlayback.svelte.ts — Autoplay play/pause states.
  • frontend-pwa/src/lib/activeGame/activeGameStats.svelte.ts — Trainer score tracking.
  • frontend-pwa/src/lib/activeGame/index.ts — Module exports index.
  • frontend-pwa/src/utils/fenUtils.ts — Pure chess FEN and dice mapping utilities.