diff --git a/solitaire_core/src/klondike_adapter.rs b/solitaire_core/src/klondike_adapter.rs index 9114e96..fdaacfa 100644 --- a/solitaire_core/src/klondike_adapter.rs +++ b/solitaire_core/src/klondike_adapter.rs @@ -3,7 +3,9 @@ //! [`KlondikeAdapter`] is a pure helper namespace for: //! - building [`KlondikeConfig`] from Ferrous settings //! - translating between local and upstream types -//! - applying Ferrous-specific scoring policy on top of upstream defaults +//! +//! Ferrous-specific scoring policy (the win-time bonus) lives in +//! [`crate::scoring`], not here. //! //! All `From` / `TryFrom` conversions between `solitaire_core` product types and //! upstream `card_game` / `klondike` types live here so that the product modules @@ -14,11 +16,11 @@ use klondike::{ SkipCards, Tableau, }; -/// Bridges `solitaire_core` game config and scoring to the upstream `klondike` crate. +/// Bridges `solitaire_core` game config to the upstream `klondike` crate. /// /// This type is intentionally zero-sized: it does not carry mutable runtime -/// state, and exists only as a namespace for configuration, conversion, and -/// scoring helpers. +/// state, and exists only as a namespace for configuration and conversion +/// helpers. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] pub struct KlondikeAdapter; @@ -81,12 +83,3 @@ pub fn skip_cards_from_count(skip: usize) -> Option { _ => None, } } - -/// Time bonus added to the score on a win: `700_000 / elapsed_seconds`. -/// Returns 0 when `elapsed_seconds` is 0 to avoid division by zero. -pub fn compute_time_bonus(elapsed_seconds: u64) -> i32 { - if elapsed_seconds == 0 { - return 0; - } - (700_000u64 / elapsed_seconds).min(i32::MAX as u64) as i32 -} diff --git a/solitaire_core/src/lib.rs b/solitaire_core/src/lib.rs index 8655f83..41fc988 100644 --- a/solitaire_core/src/lib.rs +++ b/solitaire_core/src/lib.rs @@ -2,6 +2,7 @@ pub mod achievement; pub mod error; pub mod game_state; pub mod klondike_adapter; +pub mod scoring; // 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 diff --git a/solitaire_core/src/scoring.rs b/solitaire_core/src/scoring.rs new file mode 100644 index 0000000..54e73e3 --- /dev/null +++ b/solitaire_core/src/scoring.rs @@ -0,0 +1,15 @@ +//! Ferrous-specific scoring policy layered on top of upstream `klondike`. +//! +//! Upstream [`klondike::KlondikeStats::score`] owns the per-move point values +//! (move-to-foundation, flip-up bonus, recycle penalty, etc.). The functions +//! here are the Ferrous Solitaire house rules that upstream has no opinion on — +//! currently just the win-time bonus shown in the win modal. + +/// Time bonus added to the score on a win: `700_000 / elapsed_seconds`. +/// Returns 0 when `elapsed_seconds` is 0 to avoid division by zero. +pub fn compute_time_bonus(elapsed_seconds: u64) -> i32 { + if elapsed_seconds == 0 { + return 0; + } + (700_000u64 / elapsed_seconds).min(i32::MAX as u64) as i32 +} diff --git a/solitaire_engine/src/win_summary_plugin.rs b/solitaire_engine/src/win_summary_plugin.rs index 25fe070..388c5cf 100644 --- a/solitaire_engine/src/win_summary_plugin.rs +++ b/solitaire_engine/src/win_summary_plugin.rs @@ -12,7 +12,7 @@ use bevy::prelude::*; use solitaire_core::game_state::GameMode; -use solitaire_core::klondike_adapter::compute_time_bonus; +use solitaire_core::scoring::compute_time_bonus; use solitaire_data::AnimSpeed; use crate::achievement_plugin::display_name_for;