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
+21 -21
View File
@@ -21,7 +21,7 @@
//! active opens the overlay as normal.
use bevy::prelude::*;
use solitaire_core::DrawMode;
use solitaire_core::DrawStockConfig;
use solitaire_data::save_game_state_to;
use crate::events::{
@@ -86,10 +86,10 @@ struct ForfeitConfirmButton;
/// Returns the human-readable label for a draw mode.
///
/// Used on the pause overlay draw-mode toggle button.
pub fn draw_mode_label(mode: DrawMode) -> &'static str {
pub fn draw_mode_label(mode: DrawStockConfig) -> &'static str {
match mode {
DrawMode::DrawOne => "Draw 1",
DrawMode::DrawThree => "Draw 3",
DrawStockConfig::DrawOne => "Draw 1",
DrawStockConfig::DrawThree => "Draw 3",
}
}
@@ -273,9 +273,9 @@ fn handle_pause_draw_buttons(
}
let Some(mut settings) = settings else { return };
let new_mode = if pressed_one {
DrawMode::DrawOne
DrawStockConfig::DrawOne
} else {
DrawMode::DrawThree
DrawStockConfig::DrawThree
};
if settings.0.draw_mode == new_mode {
return;
@@ -477,7 +477,7 @@ fn spawn_pause_screen(
commands: &mut Commands,
level: Option<u32>,
streak: Option<u32>,
draw_mode: Option<DrawMode>,
draw_mode: Option<DrawStockConfig>,
font_res: Option<&FontResource>,
) {
spawn_modal(commands, PauseScreen, ui_theme::Z_PAUSE, |card| {
@@ -516,7 +516,7 @@ fn spawn_pause_screen(
/// `Tertiary` (recessed), giving an obvious selection state at a glance.
fn spawn_draw_mode_row(
parent: &mut ChildSpawnerCommands,
mode: DrawMode,
mode: DrawStockConfig,
font_res: Option<&FontResource>,
) {
let label_font = TextFont {
@@ -530,8 +530,8 @@ fn spawn_draw_mode_row(
..default()
};
let (one_variant, three_variant) = match mode {
DrawMode::DrawOne => (ButtonVariant::Secondary, ButtonVariant::Tertiary),
DrawMode::DrawThree => (ButtonVariant::Tertiary, ButtonVariant::Secondary),
DrawStockConfig::DrawOne => (ButtonVariant::Secondary, ButtonVariant::Tertiary),
DrawStockConfig::DrawThree => (ButtonVariant::Tertiary, ButtonVariant::Secondary),
};
parent
.spawn(Node {
@@ -800,20 +800,20 @@ mod tests {
#[test]
fn draw_mode_label_draw_one() {
assert_eq!(draw_mode_label(DrawMode::DrawOne), "Draw 1");
assert_eq!(draw_mode_label(DrawStockConfig::DrawOne), "Draw 1");
}
#[test]
fn draw_mode_label_draw_three() {
assert_eq!(draw_mode_label(DrawMode::DrawThree), "Draw 3");
assert_eq!(draw_mode_label(DrawStockConfig::DrawThree), "Draw 3");
}
/// Both variants are covered so the match is exhaustive — this test would
/// fail to compile if a new DrawMode variant were added without updating
/// fail to compile if a new DrawStockConfig variant were added without updating
/// `draw_mode_label`.
#[test]
fn draw_mode_label_covers_all_variants() {
for mode in [DrawMode::DrawOne, DrawMode::DrawThree] {
for mode in [DrawStockConfig::DrawOne, DrawStockConfig::DrawThree] {
let label = draw_mode_label(mode);
assert!(
!label.is_empty(),
@@ -842,7 +842,7 @@ mod tests {
app.world_mut()
.resource_mut::<SettingsResource>()
.0
.draw_mode = DrawMode::DrawOne;
.draw_mode = DrawStockConfig::DrawOne;
// Set paused so handle_pause_draw_toggle acts.
app.world_mut().resource_mut::<PausedResource>().0 = true;
@@ -856,7 +856,7 @@ mod tests {
let mode = &app.world().resource::<SettingsResource>().0.draw_mode;
assert_eq!(
*mode,
DrawMode::DrawThree,
DrawStockConfig::DrawThree,
"pressing Draw 3 must set mode to DrawThree"
);
@@ -869,7 +869,7 @@ mod tests {
let mode2 = &app.world().resource::<SettingsResource>().0.draw_mode;
assert_eq!(
*mode2,
DrawMode::DrawOne,
DrawStockConfig::DrawOne,
"pressing Draw 1 must set mode to DrawOne"
);
@@ -965,11 +965,11 @@ mod tests {
/// Provides a fresh `GameStateResource` (not won) so the modal can
/// open. `move_count` doesn't matter — the gate is just `!is_won`.
fn forfeit_app() -> App {
use solitaire_core::{DrawMode, game_state::GameState};
use solitaire_core::{DrawStockConfig, game_state::GameState};
let mut app = App::new();
app.add_plugins(MinimalPlugins).add_plugins(PausePlugin);
app.init_resource::<ButtonInput<KeyCode>>();
app.insert_resource(GameStateResource(GameState::new(1, DrawMode::DrawOne)));
app.insert_resource(GameStateResource(GameState::new(1, DrawStockConfig::DrawOne)));
app.update();
app
}
@@ -1020,11 +1020,11 @@ mod tests {
/// hotkey was received but is currently a no-op.
#[test]
fn forfeit_request_emits_toast_and_skips_modal_when_game_is_won() {
use solitaire_core::{DrawMode, game_state::GameState};
use solitaire_core::{DrawStockConfig, game_state::GameState};
let mut app = App::new();
app.add_plugins(MinimalPlugins).add_plugins(PausePlugin);
app.init_resource::<ButtonInput<KeyCode>>();
let mut game = GameState::new(1, DrawMode::DrawOne);
let mut game = GameState::new(1, DrawStockConfig::DrawOne);
game.set_test_won(true);
app.insert_resource(GameStateResource(game));
app.update();