refactor: remove card.rs / card_to_id; use card_game::Card directly (#83)
card_to_id was a frankenstein 0..=51 id shim. Replace it with card_game::Card: - feedback_anim deal jitter now seeds off a hash of the Card itself - radial_menu RightClickRadialState.cards: Vec<u32> -> Vec<Card> - wasm CardSnapshot.id: u32 -> Card (serialises transparently as a plain JS number, the same opaque key the renderer already used; new test asserts the JSON id field is a number) - wasm DebugInvariantReport deck-completeness check reworked from a [bool;52] index into a HashSet<Card> + Card::new reference deck; the out-of-range check is dropped since a Card is always valid Delete card.rs entirely: the Card/Deck/Rank/Suit re-exports move to the crate root and the 69 `solitaire_core::card::` import paths flatten to `solitaire_core::`. The JS card.id is purely an opaque identity key (Map key / dataset.cardId, no arithmetic, card faces render from rank+suit), so the value change is safe. cargo test --workspace and clippy --workspace --all-targets -- -D warnings green. Closes #83 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -43,7 +43,7 @@ use std::hash::{Hash, Hasher};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use bevy::window::RequestRedraw;
|
||||
use solitaire_core::card::Card;
|
||||
use solitaire_core::Card;
|
||||
use solitaire_core::KlondikePile;
|
||||
use solitaire_core::klondike_adapter::foundation_from_slot;
|
||||
use solitaire_data::AnimSpeed;
|
||||
@@ -189,10 +189,6 @@ pub fn deal_stagger_jitter(card_id: u32) -> f32 {
|
||||
(jitter_norm - 0.5) * 0.2 // ±0.1 == ±10 %
|
||||
}
|
||||
|
||||
// Per-card jitter keys off the shared stable card id so it matches the
|
||||
// numeric identity used elsewhere (and on the WASM replay side).
|
||||
use solitaire_core::card::card_to_id;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Plugin
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -413,10 +409,14 @@ fn start_deal_anim(
|
||||
|
||||
for (index, (entity, card_marker, transform)) in card_entities.iter().enumerate() {
|
||||
let final_pos = transform.translation;
|
||||
// ±10 % jitter, deterministic per card id, so the deal feels organic
|
||||
// without losing reproducibility (a given seed still produces the
|
||||
// same per-card stagger pattern across runs).
|
||||
let per_card_stagger = stagger_secs * (1.0 + deal_stagger_jitter(card_to_id(&card_marker.card)));
|
||||
// ±10 % jitter, deterministic per card, so the deal feels organic
|
||||
// without losing reproducibility (a given deal produces the same
|
||||
// per-card stagger pattern across runs). The seed is a hash of the
|
||||
// card's own identity — no separate numeric id needed.
|
||||
let mut card_hasher = DefaultHasher::new();
|
||||
card_marker.card.hash(&mut card_hasher);
|
||||
let per_card_stagger =
|
||||
stagger_secs * (1.0 + deal_stagger_jitter(card_hasher.finish() as u32));
|
||||
commands.entity(entity).insert((
|
||||
Transform::from_translation(stock_start.with_z(final_pos.z)),
|
||||
CardAnim {
|
||||
@@ -639,7 +639,7 @@ fn lerp_color(from: Color, to: Color, t: f32) -> Color {
|
||||
fn pile_cards(
|
||||
game: &solitaire_core::game_state::GameState,
|
||||
pile: &KlondikePile,
|
||||
) -> Vec<(solitaire_core::card::Card, bool)> {
|
||||
) -> Vec<(solitaire_core::Card, bool)> {
|
||||
match pile {
|
||||
KlondikePile::Stock => game.waste_cards(),
|
||||
_ => game.pile(*pile),
|
||||
@@ -917,7 +917,7 @@ mod tests {
|
||||
.resource_mut::<Messages<FoundationCompletedEvent>>()
|
||||
.write(FoundationCompletedEvent {
|
||||
slot: 0,
|
||||
suit: solitaire_core::card::Suit::Spades,
|
||||
suit: solitaire_core::Suit::Spades,
|
||||
});
|
||||
app.update();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user