refactor: replace local DrawMode with upstream klondike::DrawStockConfig (#82)

DrawMode was a 1:1 mirror of klondike::DrawStockConfig (DrawOne/DrawThree).
Delete it and use the upstream type everywhere; re-export DrawStockConfig from
solitaire_core. config_for assigns draw_stock directly and draw_mode() returns
session.config().inner.draw_stock.

Serde is unchanged — DrawStockConfig serialises to the same "DrawOne"/"DrawThree"
named variants, so persisted game_state.json / replay JSON stay byte-compatible
(no migration). Field/method/variable names containing draw_mode are unchanged.

35 files, mechanical type swap across all crates. Implemented via a multi-agent
workflow (core → per-crate consumers → verify). cargo test --workspace and
clippy --workspace --all-targets -- -D warnings green.

Closes #82

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-11 16:01:11 -07:00
parent d045781119
commit 5c992cbdca
35 changed files with 257 additions and 274 deletions
+17 -17
View File
@@ -23,7 +23,7 @@ use solitaire_core::{Foundation, KlondikePile, Tableau};
use serde::{Deserialize, Serialize};
use solitaire_core::card::Suit;
use solitaire_core::error::MoveError;
use solitaire_core::{DrawMode, game_state::{GameMode, GameState}};
use solitaire_core::{DrawStockConfig, game_state::{GameMode, GameState}};
use solitaire_core::klondike_adapter::{
SavedInstruction, SavedKlondikePile, SavedKlondikePileStack, tableau_from_index,
};
@@ -48,7 +48,7 @@ pub struct Replay {
#[serde(default)]
pub schema_version: u32,
pub seed: u64,
pub draw_mode: DrawMode,
pub draw_mode: DrawStockConfig,
pub mode: GameMode,
pub time_seconds: u64,
pub final_score: i32,
@@ -332,7 +332,7 @@ pub struct DebugInvariantReport {
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct DebugSnapshot {
pub seed: u64,
pub draw_mode: DrawMode,
pub draw_mode: DrawStockConfig,
pub mode: GameMode,
pub state: GameSnapshot,
pub legal_moves: Vec<DebugMove>,
@@ -726,9 +726,9 @@ impl SolitaireGame {
#[cfg(feature = "console_error_panic_hook")]
console_error_panic_hook::set_once();
let dm = if draw_three {
DrawMode::DrawThree
DrawStockConfig::DrawThree
} else {
DrawMode::DrawOne
DrawStockConfig::DrawOne
};
SolitaireGame {
game: GameState::new_with_mode(seed as u64, dm, GameMode::Classic),
@@ -952,7 +952,7 @@ mod tests {
key
}
fn run_autonomous(seed: u64, draw_mode: DrawMode, max_steps: usize) -> DebugSnapshot {
fn run_autonomous(seed: u64, draw_mode: DrawStockConfig, max_steps: usize) -> DebugSnapshot {
let mut game = SolitaireGame {
game: GameState::new_with_mode(seed, draw_mode, GameMode::Classic),
};
@@ -983,7 +983,7 @@ mod tests {
#[test]
fn debug_snapshot_exposes_replayable_seed_and_history() {
let seed = 42_u64;
let final_snapshot = run_autonomous(seed, DrawMode::DrawOne, 1500);
let final_snapshot = run_autonomous(seed, DrawStockConfig::DrawOne, 1500);
assert_eq!(final_snapshot.seed, seed);
assert!(
!final_snapshot.state_json.is_empty(),
@@ -1000,7 +1000,7 @@ mod tests {
#[test]
fn replay_moves_export_is_json_compatible_and_replayable() {
let seed = 7_u64;
let draw_mode = DrawMode::DrawThree;
let draw_mode = DrawStockConfig::DrawThree;
let mut game = SolitaireGame {
game: GameState::new_with_mode(seed, draw_mode, GameMode::Classic),
};
@@ -1098,9 +1098,9 @@ mod tests {
fn debug_api_autonomous_seed_batch_smoke() {
for seed in 0_u64..128_u64 {
let draw_mode = if seed % 2 == 0 {
DrawMode::DrawOne
DrawStockConfig::DrawOne
} else {
DrawMode::DrawThree
DrawStockConfig::DrawThree
};
let snapshot = run_autonomous(seed, draw_mode, 2000);
assert_invariants(&snapshot, seed);
@@ -1112,9 +1112,9 @@ mod tests {
fn debug_api_autonomous_thousands_seed_soak() {
for seed in 10_000_u64..12_000_u64 {
let draw_mode = if seed % 2 == 0 {
DrawMode::DrawOne
DrawStockConfig::DrawOne
} else {
DrawMode::DrawThree
DrawStockConfig::DrawThree
};
let snapshot = run_autonomous(seed, draw_mode, 3000);
assert_invariants(&snapshot, seed);
@@ -1125,7 +1125,7 @@ mod tests {
fn serialize_from_saved_round_trip() {
let seed = 55_u64;
let mut game = SolitaireGame {
game: GameState::new_with_mode(seed, DrawMode::DrawOne, GameMode::Classic),
game: GameState::new_with_mode(seed, DrawStockConfig::DrawOne, GameMode::Classic),
};
// Advance a few moves so there is non-trivial state to round-trip.
for _ in 0..20 {
@@ -1160,7 +1160,7 @@ mod tests {
fn undo_reverts_to_prior_state() {
let seed = 99_u64;
let mut game = SolitaireGame {
game: GameState::new_with_mode(seed, DrawMode::DrawOne, GameMode::Classic),
game: GameState::new_with_mode(seed, DrawStockConfig::DrawOne, GameMode::Classic),
};
let before_key = board_key(&game.debug_snapshot_native().state);
@@ -1198,7 +1198,7 @@ mod tests {
fn draw_one_advances_waste_by_one() {
let seed = 1_u64;
let mut game = SolitaireGame {
game: GameState::new_with_mode(seed, DrawMode::DrawOne, GameMode::Classic),
game: GameState::new_with_mode(seed, DrawStockConfig::DrawOne, GameMode::Classic),
};
let stock_before = game.game.stock_cards().len();
@@ -1224,7 +1224,7 @@ mod tests {
fn draw_three_advances_waste_by_three() {
let seed = 1_u64;
let mut game = SolitaireGame {
game: GameState::new_with_mode(seed, DrawMode::DrawThree, GameMode::Classic),
game: GameState::new_with_mode(seed, DrawStockConfig::DrawThree, GameMode::Classic),
};
let stock_before = game.game.stock_cards().len();
@@ -1254,7 +1254,7 @@ mod tests {
fn debug_apply_move_json_stock_click_advances_waste() {
let seed = 3_u64;
let mut game = SolitaireGame {
game: GameState::new_with_mode(seed, DrawMode::DrawOne, GameMode::Classic),
game: GameState::new_with_mode(seed, DrawStockConfig::DrawOne, GameMode::Classic),
};
let waste_before = game.game.waste_cards().len();