4cb4212829
Test / test (pull_request) Successful in 36m34s
Replays previously persisted only seed + moves and re-dealt the board
from the seed at playback time, so any change to the seed->deal mapping
(RNG bumps, upstream upgrades) silently invalidated every existing
replay. Schema v4 instead embeds a SessionRecording - the upstream
card_game Session serde ({config, initial_state, instructions}) - so
playback rebuilds the exact recorded board; seed/draw_mode/mode remain
caption metadata only.
- core: SessionRecording newtype delegating to Session<Klondike> serde;
GameState::recording() / from_recording(); from_instructions_unchecked
fixture helper; serde_json added to dev-deps (tests only)
- data: Replay v4 (recording replaces moves); v1-v3 files rejected by
the existing version gate
- engine: win-recording and sync upload freeze game.recording();
playback rebuilds from the recording; Playing carries the extracted
move list (+ Box<Replay> for clippy large_enum_variant)
- wasm: replay_export() builds the full v4 upload payload so JS never
hand-assembles it (the old game.js path hardcoded schema_version: 2
and corrupted u64 seeds via Math.round); ReplayPlayer::from_json
enforces schema_version == 4 with a descriptive error
- web: game.js/play.html use replay_export; replay.js surfaces player
construction errors in the caption instead of dying silently
- server: mode validation accepts data-carrying GameMode variants
(Difficulty uploads previously 400'd against the String field)
Both replays on prod are May-era v1 rows with empty move lists - every
shared replay was already unplayable; the viewer now says why.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
64 lines
2.3 KiB
Rust
64 lines
2.3 KiB
Rust
pub mod achievement;
|
|
pub mod error;
|
|
pub mod game_state;
|
|
pub mod klondike_adapter;
|
|
pub mod scoring;
|
|
pub mod spider;
|
|
|
|
// Re-export the upstream types that cross the solitaire_core API boundary so
|
|
// downstream crates (engine, wasm) can import from one place without a direct
|
|
// `klondike` / `card_game` dep.
|
|
//
|
|
// `KlondikePileStack`, `SkipCards` and `TableauStack` are intentionally NOT
|
|
// re-exported — they are only used internally (in `klondike_adapter.rs` and
|
|
// when decoding instructions to piles in `instruction_to_piles`) and do not
|
|
// appear in any public method signature.
|
|
pub use card_game::{Card, Deck, Rank, SolveError, Suit};
|
|
pub use klondike::{
|
|
DrawStockConfig, Foundation, Klondike, KlondikeInstruction, KlondikePile, Tableau,
|
|
};
|
|
|
|
// Solvability check API (delegates to `card_game::Session::solve`); replaces the
|
|
// former `solitaire_data::solver` wrapper module.
|
|
pub use game_state::{
|
|
DEFAULT_SOLVE_MOVES_BUDGET, DEFAULT_SOLVE_STATES_BUDGET, SessionRecording, SolveOutcome,
|
|
};
|
|
|
|
// Spider rules (second `card_game::Game` implementation; engine UI is a
|
|
// later phase — nothing outside solitaire_core consumes these yet).
|
|
pub use spider::{
|
|
RunLength, Spider, SpiderConfig, SpiderGameState, SpiderInstruction, SpiderIter, SpiderMove,
|
|
SpiderScoring, SpiderStats, SpiderSuits, SpiderTableau,
|
|
};
|
|
|
|
/// All four foundation slots, in slot order.
|
|
///
|
|
/// Canonical iteration source for `Foundation` — upstream `klondike` has no
|
|
/// `Foundation::ALL` (unlike `Suit::SUITS` / `Rank::RANKS` in `card_game`),
|
|
/// and inherent impls cannot be added to a foreign type, so the workspace
|
|
/// const lives here. Use this instead of hand-rolling `[Foundation; 4]`
|
|
/// arrays; scattered copies can silently diverge.
|
|
pub const FOUNDATIONS: [Foundation; 4] = [
|
|
Foundation::Foundation1,
|
|
Foundation::Foundation2,
|
|
Foundation::Foundation3,
|
|
Foundation::Foundation4,
|
|
];
|
|
|
|
/// All seven tableau columns, in column order (left to right on screen).
|
|
///
|
|
/// Canonical iteration source for `Tableau` — see [`FOUNDATIONS`] for why
|
|
/// this lives here rather than upstream.
|
|
pub const TABLEAUS: [Tableau; 7] = [
|
|
Tableau::Tableau1,
|
|
Tableau::Tableau2,
|
|
Tableau::Tableau3,
|
|
Tableau::Tableau4,
|
|
Tableau::Tableau5,
|
|
Tableau::Tableau6,
|
|
Tableau::Tableau7,
|
|
];
|
|
|
|
#[cfg(test)]
|
|
mod proptest_tests;
|