refactor(core): unify Suit/Rank with card_game upstream types
Build and Deploy / build-and-push (push) Failing after 56s
Web E2E / web-e2e (push) Failing after 4m23s

Replace the parallel solitaire_core::Suit and solitaire_core::Rank
definitions with pub-use re-exports from card_game. card_game upstream
gained serde, is_black(), and value() to make this clean.

- card.rs: remove Suit/Rank enums and impls; add pub use card_game::{Suit,Rank}
- klondike_adapter.rs: remove From<card_game::Suit/Rank> bridges (now same type)
- Simplify card_from_kl: .into() calls become direct assignment
- Cargo.toml: switch to git deps (serde feature), Cargo.lock updated

All 62 solitaire_core tests pass; clippy clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-08 10:57:49 -07:00
parent 5e8735886f
commit ae1ecc8559
4 changed files with 71 additions and 140 deletions
+1 -97
View File
@@ -1,102 +1,6 @@
use serde::{Deserialize, Serialize};
/// Card suit.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Suit {
Clubs,
Diamonds,
Hearts,
Spades,
}
impl Suit {
/// All four suits in declaration order.
pub const SUITS: [Self; 4] = [Self::Clubs, Self::Diamonds, Self::Hearts, Self::Spades];
/// Returns `true` for red suits (Diamonds, Hearts).
pub fn is_red(self) -> bool {
matches!(self, Suit::Diamonds | Suit::Hearts)
}
/// Returns `true` for black suits (Clubs, Spades).
pub fn is_black(self) -> bool {
!self.is_red()
}
}
/// Card rank, Ace through King.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Rank {
Ace = 1,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
Six = 6,
Seven = 7,
Eight = 8,
Nine = 9,
Ten = 10,
Jack = 11,
Queen = 12,
King = 13,
}
impl Rank {
/// All thirteen ranks in ascending order.
pub const RANKS: [Self; 13] = [
Self::Ace,
Self::Two,
Self::Three,
Self::Four,
Self::Five,
Self::Six,
Self::Seven,
Self::Eight,
Self::Nine,
Self::Ten,
Self::Jack,
Self::Queen,
Self::King,
];
/// Numeric value: Ace = 1, King = 13.
pub fn value(self) -> u8 {
self as u8
}
const fn new(n: u8) -> Option<Self> {
match n {
1 => Some(Self::Ace),
2 => Some(Self::Two),
3 => Some(Self::Three),
4 => Some(Self::Four),
5 => Some(Self::Five),
6 => Some(Self::Six),
7 => Some(Self::Seven),
8 => Some(Self::Eight),
9 => Some(Self::Nine),
10 => Some(Self::Ten),
11 => Some(Self::Jack),
12 => Some(Self::Queen),
13 => Some(Self::King),
_ => None,
}
}
/// Returns the rank `n` steps above `self`, or `None` if it would exceed King.
pub const fn checked_add(self, n: u8) -> Option<Self> {
Self::new((self as u8).saturating_add(n))
}
/// Returns the rank `n` steps below `self`, or `None` if it would go below Ace.
pub const fn checked_sub(self, n: u8) -> Option<Self> {
match (self as u8).checked_sub(n) {
Some(v) => Self::new(v),
None => None,
}
}
}
pub use card_game::{Rank, Suit};
/// A single playing card.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+2 -35
View File
@@ -156,39 +156,6 @@ impl KlondikeAdapter {
}
}
// ── Type-conversion utilities ─────────────────────────────────────────────
impl From<card_game::Suit> for card::Suit {
fn from(s: card_game::Suit) -> Self {
match s {
card_game::Suit::Clubs => Self::Clubs,
card_game::Suit::Diamonds => Self::Diamonds,
card_game::Suit::Hearts => Self::Hearts,
card_game::Suit::Spades => Self::Spades,
}
}
}
impl From<card_game::Rank> for card::Rank {
fn from(r: card_game::Rank) -> Self {
match r {
card_game::Rank::Ace => Self::Ace,
card_game::Rank::Two => Self::Two,
card_game::Rank::Three => Self::Three,
card_game::Rank::Four => Self::Four,
card_game::Rank::Five => Self::Five,
card_game::Rank::Six => Self::Six,
card_game::Rank::Seven => Self::Seven,
card_game::Rank::Eight => Self::Eight,
card_game::Rank::Nine => Self::Nine,
card_game::Rank::Ten => Self::Ten,
card_game::Rank::Jack => Self::Jack,
card_game::Rank::Queen => Self::Queen,
card_game::Rank::King => Self::King,
}
}
}
/// Convert a zero-based tableau index (0..=6) into [`Tableau`].
pub fn tableau_from_index(index: usize) -> Option<Tableau> {
match index {
@@ -239,8 +206,8 @@ pub fn skip_cards_from_count(skip: usize) -> Option<SkipCards> {
///
/// The id is consistent for the same logical card across all reconstructions.
pub fn card_from_kl(kl_card: &KlCard) -> card::Card {
let suit: card::Suit = kl_card.suit().into();
let rank: card::Rank = kl_card.rank().into();
let suit = kl_card.suit();
let rank = kl_card.rank();
let suit_index = match suit {
card::Suit::Clubs => 0,
card::Suit::Diamonds => 1,