use super::{
deck::DeckConfig,
suit_rank::{Rank, Suit},
};
use std::{
cmp::Ordering,
fmt::{Debug, Display},
hash::Hash,
sync::Arc,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CardData {
pub rank: Rank,
pub suit: Suit,
}
#[derive(Clone)]
pub struct Card {
pub(crate) rank: Rank,
pub(crate) suit: Suit,
pub(crate) deck_config: Arc<DeckConfig>,
}
impl Card {
pub fn data(&self) -> CardData {
CardData {
rank: self.rank,
suit: self.suit,
}
}
pub fn deck_config(&self) -> Arc<DeckConfig> {
self.deck_config.clone()
}
pub fn value(&self) -> u8 {
if self.suit == Suit::Joker || self.rank == Rank::Joker {
return 0;
}
let max_rank = Rank::King as u8;
let highest_rank = match self.deck_config.high_rank {
None => max_rank,
Some(high_rank) => high_rank as u8,
};
let rank_offset = max_rank - highest_rank;
let mut relative_self_rank = (self.rank as u8 + rank_offset) % (max_rank + 1);
if let Some(highest_rank) = self.deck_config.high_rank {
if self.rank >= Rank::Ace && self.rank <= highest_rank {
relative_self_rank -= 1;
}
}
4 * relative_self_rank + self.suit as u8
}
pub fn score_value(&self) -> u8 {
match self.rank {
Rank::Jack | Rank::Queen | Rank::King => 10,
other => other as u8,
}
}
pub(crate) fn same_suit_consecutive_rank(&self, other: &Card) -> bool {
self.value() + 4 == other.value()
}
pub(crate) fn is_wildcard(&self) -> bool {
Some(self.rank) == self.deck_config.wildcard_rank
}
pub(crate) fn from_card_data(card_data: CardData, deck_config: Arc<DeckConfig>) -> Self {
Self {
deck_config,
rank: card_data.rank,
suit: card_data.suit,
}
}
}
impl PartialEq for Card {
fn eq(&self, other: &Self) -> bool {
self.rank == other.rank && self.suit == other.suit
}
}
impl Eq for Card {}
impl Ord for Card {
fn cmp(&self, other: &Self) -> Ordering {
self.value().cmp(&other.value())
}
}
impl PartialOrd for Card {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Debug for Card {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("")
.field("Card", &format!("{self}"))
.finish()
}
}
impl Display for Card {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{}", self.rank.as_str(), self.suit.as_str())
}
}
impl Hash for Card {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(self.rank as u8).hash(state);
(self.suit as u8).hash(state);
}
}
impl Display for CardData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{}", self.rank.as_str(), self.suit.as_str())
}
}