use crate::types::U32Card;
use ckc_rs::{CKCNumber, CardNumber, PokerCard};
use serde::de::Deserializer;
use serde::ser::{Serialize, Serializer};
use serde::Deserialize;
use std::fmt;
#[derive(Deserialize, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PlayingCard(#[serde(deserialize_with = "deserialize_card_index")] U32Card);
impl PlayingCard {
pub const ACE_SPADES: PlayingCard = PlayingCard(CardNumber::ACE_SPADES);
pub const KING_SPADES: PlayingCard = PlayingCard(CardNumber::KING_SPADES);
pub const QUEEN_SPADES: PlayingCard = PlayingCard(CardNumber::QUEEN_SPADES);
pub const JACK_SPADES: PlayingCard = PlayingCard(CardNumber::JACK_SPADES);
pub const TEN_SPADES: PlayingCard = PlayingCard(CardNumber::TEN_SPADES);
pub const NINE_SPADES: PlayingCard = PlayingCard(CardNumber::NINE_SPADES);
pub const EIGHT_SPADES: PlayingCard = PlayingCard(CardNumber::EIGHT_SPADES);
pub const SEVEN_SPADES: PlayingCard = PlayingCard(CardNumber::SEVEN_SPADES);
pub const SIX_SPADES: PlayingCard = PlayingCard(CardNumber::SIX_SPADES);
pub const FIVE_SPADES: PlayingCard = PlayingCard(CardNumber::FIVE_SPADES);
pub const FOUR_SPADES: PlayingCard = PlayingCard(CardNumber::FOUR_SPADES);
pub const TREY_SPADES: PlayingCard = PlayingCard(CardNumber::TREY_SPADES);
pub const DEUCE_SPADES: PlayingCard = PlayingCard(CardNumber::DEUCE_SPADES);
pub const ACE_HEARTS: PlayingCard = PlayingCard(CardNumber::ACE_HEARTS);
pub const KING_HEARTS: PlayingCard = PlayingCard(CardNumber::KING_HEARTS);
pub const QUEEN_HEARTS: PlayingCard = PlayingCard(CardNumber::QUEEN_HEARTS);
pub const JACK_HEARTS: PlayingCard = PlayingCard(CardNumber::JACK_HEARTS);
pub const TEN_HEARTS: PlayingCard = PlayingCard(CardNumber::TEN_HEARTS);
pub const NINE_HEARTS: PlayingCard = PlayingCard(CardNumber::NINE_HEARTS);
pub const EIGHT_HEARTS: PlayingCard = PlayingCard(CardNumber::EIGHT_HEARTS);
pub const SEVEN_HEARTS: PlayingCard = PlayingCard(CardNumber::SEVEN_HEARTS);
pub const SIX_HEARTS: PlayingCard = PlayingCard(CardNumber::SIX_HEARTS);
pub const FIVE_HEARTS: PlayingCard = PlayingCard(CardNumber::FIVE_HEARTS);
pub const FOUR_HEARTS: PlayingCard = PlayingCard(CardNumber::FOUR_HEARTS);
pub const TREY_HEARTS: PlayingCard = PlayingCard(CardNumber::TREY_HEARTS);
pub const DEUCE_HEARTS: PlayingCard = PlayingCard(CardNumber::DEUCE_HEARTS);
pub const ACE_DIAMONDS: PlayingCard = PlayingCard(CardNumber::ACE_DIAMONDS);
pub const KING_DIAMONDS: PlayingCard = PlayingCard(CardNumber::KING_DIAMONDS);
pub const QUEEN_DIAMONDS: PlayingCard = PlayingCard(CardNumber::QUEEN_DIAMONDS);
pub const JACK_DIAMONDS: PlayingCard = PlayingCard(CardNumber::JACK_DIAMONDS);
pub const TEN_DIAMONDS: PlayingCard = PlayingCard(CardNumber::TEN_DIAMONDS);
pub const NINE_DIAMONDS: PlayingCard = PlayingCard(CardNumber::NINE_DIAMONDS);
pub const EIGHT_DIAMONDS: PlayingCard = PlayingCard(CardNumber::EIGHT_DIAMONDS);
pub const SEVEN_DIAMONDS: PlayingCard = PlayingCard(CardNumber::SEVEN_DIAMONDS);
pub const SIX_DIAMONDS: PlayingCard = PlayingCard(CardNumber::SIX_DIAMONDS);
pub const FIVE_DIAMONDS: PlayingCard = PlayingCard(CardNumber::FIVE_DIAMONDS);
pub const FOUR_DIAMONDS: PlayingCard = PlayingCard(CardNumber::FOUR_DIAMONDS);
pub const TREY_DIAMONDS: PlayingCard = PlayingCard(CardNumber::TREY_DIAMONDS);
pub const DEUCE_DIAMONDS: PlayingCard = PlayingCard(CardNumber::DEUCE_DIAMONDS);
pub const ACE_CLUBS: PlayingCard = PlayingCard(CardNumber::ACE_CLUBS);
pub const KING_CLUBS: PlayingCard = PlayingCard(CardNumber::KING_CLUBS);
pub const QUEEN_CLUBS: PlayingCard = PlayingCard(CardNumber::QUEEN_CLUBS);
pub const JACK_CLUBS: PlayingCard = PlayingCard(CardNumber::JACK_CLUBS);
pub const TEN_CLUBS: PlayingCard = PlayingCard(CardNumber::TEN_CLUBS);
pub const NINE_CLUBS: PlayingCard = PlayingCard(CardNumber::NINE_CLUBS);
pub const EIGHT_CLUBS: PlayingCard = PlayingCard(CardNumber::EIGHT_CLUBS);
pub const SEVEN_CLUBS: PlayingCard = PlayingCard(CardNumber::SEVEN_CLUBS);
pub const SIX_CLUBS: PlayingCard = PlayingCard(CardNumber::SIX_CLUBS);
pub const FIVE_CLUBS: PlayingCard = PlayingCard(CardNumber::FIVE_CLUBS);
pub const FOUR_CLUBS: PlayingCard = PlayingCard(CardNumber::FOUR_CLUBS);
pub const TREY_CLUBS: PlayingCard = PlayingCard(CardNumber::TREY_CLUBS);
pub const DEUCE_CLUBS: PlayingCard = PlayingCard(CardNumber::DEUCE_CLUBS);
pub const BLANK: PlayingCard = PlayingCard(CardNumber::BLANK);
#[must_use]
pub fn as_card(&self) -> cardpack::Card {
let rank = cardpack::Rank::from_french_deck_char(self.get_rank_char());
let suit = cardpack::Suit::from_french_deck_index(self.get_suit_char());
if rank.is_blank() && suit.is_blank() {
return cardpack::Card::default();
}
cardpack::Card::new(rank, suit)
}
#[must_use]
pub fn simple_index(&self) -> String {
format!("{}{}", self.get_rank_char(), self.get_suit_letter())
}
}
impl ckc_rs::PokerCard for PlayingCard {
fn as_u32(&self) -> u32 {
self.0
}
fn is_blank(&self) -> bool {
self.0 == CardNumber::BLANK
}
}
impl fmt::Display for PlayingCard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", self.get_rank_char(), self.get_suit_char())
}
}
impl From<&cardpack::Card> for PlayingCard {
fn from(value: &cardpack::Card) -> PlayingCard {
let suit: u32 = value.suit.binary_signature_revised();
let bits = 1 << (16 + value.rank.weight);
let rank_eight = value.rank.weight << 8;
PlayingCard::from(bits | value.rank.prime | rank_eight | suit)
}
}
impl From<&'static u32> for PlayingCard {
fn from(value: &'static u32) -> Self {
PlayingCard::from(*value)
}
}
impl From<&'static str> for PlayingCard {
fn from(value: &'static str) -> PlayingCard {
PlayingCard(CKCNumber::from_index(value))
}
}
impl From<U32Card> for PlayingCard {
fn from(value: U32Card) -> Self {
PlayingCard(ckc_rs::CardNumber::filter(value))
}
}
impl From<String> for PlayingCard {
fn from(string: String) -> Self {
PlayingCard::from(&cardpack::Standard52::card_from_string(string))
}
}
impl Serialize for PlayingCard {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_newtype_struct("PlayingCard", &self.to_string())
}
}
fn deserialize_card_index<'de, D>(deserializer: D) -> Result<U32Card, D::Error>
where
D: Deserializer<'de>,
{
let buf = String::deserialize(deserializer)?;
Ok(PlayingCard::from(buf).as_u32())
}
#[cfg(test)]
#[allow(non_snake_case)]
mod holdem_playing_card_tests {
use super::*;
use crate::types::poker_deck::PokerDeck;
use cardpack::Standard52;
use ckc_rs::PokerCard;
use serde_test::{assert_tokens, Token};
#[test]
fn compare() {
assert!(PlayingCard::KING_SPADES > PlayingCard::QUEEN_CLUBS);
assert!(PlayingCard::ACE_CLUBS > PlayingCard::KING_SPADES);
assert!(PlayingCard::TEN_CLUBS < PlayingCard::KING_SPADES);
}
#[test]
fn from__card() {
let card = cardpack::Standard52::card_from_index("QH");
let playing_card = PlayingCard::from(&card);
assert!(!playing_card.is_blank());
assert_eq!("Q♥", playing_card.to_string());
}
#[test]
fn from__card__invalid() {
let card = cardpack::Standard52::card_from_index("JK");
let playing_card = PlayingCard::from(&card);
assert!(playing_card.is_blank());
assert_eq!("__", playing_card.to_string());
}
#[test]
fn from__card_number() {
let playing_card = PlayingCard::from(PlayingCard::SIX_SPADES);
assert!(!playing_card.is_blank());
assert_eq!("6♠", playing_card.to_string());
}
#[test]
fn from__card_number__invalid() {
let playing_card = PlayingCard::from(12);
assert!(playing_card.is_blank());
assert_eq!("__", playing_card.to_string());
}
#[test]
fn from__index() {
let playing_card = PlayingCard::from("QH");
assert!(!playing_card.is_blank());
assert_eq!("Q♥", playing_card.to_string());
}
#[test]
fn from__index__invalid() {
let playing_card = PlayingCard::from("JK");
assert!(playing_card.is_blank());
assert_eq!("__", playing_card.to_string());
}
#[test]
fn display() {
let card = cardpack::Standard52::card_from_index("QH");
let playing_card = PlayingCard::from("QH");
assert_eq!("QH", format!("{}", card));
assert_eq!("Q♥", format!("{}", playing_card));
}
#[test]
fn display__blank() {
assert_eq!("__", PlayingCard::default().to_string())
}
#[test]
fn simple_index() {
let playing_card = PlayingCard::from("QH");
assert_eq!("QH", playing_card.simple_index());
}
#[test]
fn deck() {
let standard52 = Standard52::default();
for (i, card) in standard52.deck.into_iter().enumerate() {
let playing_card = PlayingCard::from(&card);
assert_eq!(PokerDeck::get(i), playing_card.as_u32());
assert_eq!(playing_card.as_card(), card);
}
}
#[test]
fn serialize() {
let playing_card = PlayingCard::from("QH");
assert_tokens(
&playing_card,
&[
Token::NewtypeStruct {
name: "PlayingCard",
},
Token::Str("Q♥"),
],
);
}
}