use crate::analysis::eval::Eval;
use crate::analysis::evals::Evals;
use crate::types::arrays::five_card::FiveCard;
use crate::types::arrays::two_card::TwoCard;
use crate::types::arrays::{Evaluable, Vectorable};
use crate::types::playing_card::PlayingCard;
use crate::types::playing_cards::PlayingCards;
use crate::types::poker_cards::PokerCards;
use crate::types::U32Card;
use ckc_rs::cards::seven::Seven;
use ckc_rs::{CardNumber, HandError, PokerCard};
use core::fmt;
use serde::{Deserialize, Serialize};
use std::fmt::Formatter;
#[derive(
Serialize, Deserialize, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
pub struct SevenCard([U32Card; 7]);
impl SevenCard {
#[must_use]
pub fn new(two: TwoCard, five: FiveCard) -> SevenCard {
SevenCard([
two.first(),
two.second(),
five.first(),
five.second(),
five.third(),
five.forth(),
five.fifth(),
])
}
#[must_use]
pub fn first(&self) -> U32Card {
self.0[0]
}
#[must_use]
pub fn second(&self) -> U32Card {
self.0[1]
}
#[must_use]
pub fn third(&self) -> U32Card {
self.0[2]
}
#[must_use]
pub fn forth(&self) -> U32Card {
self.0[3]
}
#[must_use]
pub fn fifth(&self) -> U32Card {
self.0[4]
}
#[must_use]
pub fn sixth(&self) -> U32Card {
self.0[5]
}
#[must_use]
pub fn seventh(&self) -> U32Card {
self.0[6]
}
#[must_use]
pub fn sort(&self) -> SevenCard {
let mut c = *self;
c.sort_in_place();
c
}
pub fn sort_in_place(&mut self) {
self.0.sort_unstable();
self.0.reverse();
}
#[must_use]
pub fn to_arr(&self) -> [U32Card; 7] {
self.0
}
#[must_use]
pub fn to_seven(&self) -> Seven {
Seven::from(self.to_arr())
}
}
impl fmt::Display for SevenCard {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", PlayingCards::from(&self.to_vec()))
}
}
impl Evaluable for SevenCard {
fn evals(&self) -> Evals {
let mut evals = Evals::default();
let mut subhand: [U32Card; 5] = [CardNumber::BLANK; 5];
for ids in &ckc_rs::cards::seven::Seven::FIVE_CARD_PERMUTATIONS {
for i in 0..5 {
subhand[i] = self.0[ids[i] as usize];
}
let (hand, eval) = FiveCard::from(subhand).evaluate();
evals.push(Eval::raw(hand, eval));
}
evals
}
}
impl From<[PlayingCard; 7]> for SevenCard {
fn from(array: [PlayingCard; 7]) -> Self {
SevenCard::from([
array[0].as_u32(),
array[1].as_u32(),
array[2].as_u32(),
array[3].as_u32(),
array[4].as_u32(),
array[5].as_u32(),
array[6].as_u32(),
])
}
}
impl From<[U32Card; 7]> for SevenCard {
fn from(array: [U32Card; 7]) -> Self {
SevenCard(array)
}
}
impl TryFrom<&PlayingCards> for SevenCard {
type Error = HandError;
fn try_from(playing_cards: &PlayingCards) -> Result<Self, Self::Error> {
SevenCard::try_from(&PokerCards::from(playing_cards))
}
}
impl TryFrom<&PokerCards> for SevenCard {
type Error = HandError;
fn try_from(poker_cards: &PokerCards) -> Result<Self, Self::Error> {
match poker_cards.len() {
0..=6 => Err(HandError::NotEnoughCards),
7 => Ok(SevenCard::from([
*poker_cards.get(0).unwrap(),
*poker_cards.get(1).unwrap(),
*poker_cards.get(2).unwrap(),
*poker_cards.get(3).unwrap(),
*poker_cards.get(4).unwrap(),
*poker_cards.get(5).unwrap(),
*poker_cards.get(6).unwrap(),
])),
_ => Err(HandError::TooManyCards),
}
}
}
impl TryFrom<&'static str> for SevenCard {
type Error = HandError;
fn try_from(value: &'static str) -> Result<Self, Self::Error> {
match PokerCards::try_from(value) {
Ok(cards) => SevenCard::try_from(&cards),
Err(e) => Err(e),
}
}
}
impl TryFrom<Vec<&PlayingCard>> for SevenCard {
type Error = HandError;
fn try_from(v: Vec<&PlayingCard>) -> Result<Self, Self::Error> {
SevenCard::try_from(&PlayingCards::from(v))
}
}
impl Vectorable for SevenCard {
#[must_use]
fn to_vec(&self) -> Vec<U32Card> {
self.0.to_vec()
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod types_arrays_seven_card_tests {
use super::*;
use ckc_rs::hand_rank::HandRank;
use ckc_rs::CardNumber;
#[test]
fn sort() {
let seven = SevenCard::try_from("9H AS KS QS JS TS 2H").unwrap().sort();
assert_eq!("A♠ K♠ Q♠ J♠ T♠ 9♥ 2♥", seven.to_string());
}
#[test]
fn sort_in_place() {
let mut seven = SevenCard::try_from("9H AS KS QS JS TS 2H").unwrap();
seven.sort_in_place();
assert_eq!("A♠ K♠ Q♠ J♠ T♠ 9♥ 2♥", seven.to_string());
}
#[test]
fn display() {
let playing_cards = SevenCard::try_from("9H AS KS QS JS TS 2H").unwrap();
assert_eq!("9♥ A♠ K♠ Q♠ J♠ T♠ 2♥", playing_cards.to_string());
}
#[test]
fn from__array() {
let expected = SevenCard([
CardNumber::ACE_CLUBS,
CardNumber::KING_CLUBS,
CardNumber::QUEEN_CLUBS,
CardNumber::JACK_CLUBS,
CardNumber::TEN_CLUBS,
CardNumber::NINE_CLUBS,
CardNumber::EIGHT_CLUBS,
]);
let actual = SevenCard::from([
CardNumber::ACE_CLUBS,
CardNumber::KING_CLUBS,
CardNumber::QUEEN_CLUBS,
CardNumber::JACK_CLUBS,
CardNumber::TEN_CLUBS,
CardNumber::NINE_CLUBS,
CardNumber::EIGHT_CLUBS,
]);
assert_eq!(expected, actual);
}
#[test]
fn eval() {
let five_cards = FiveCard::try_from("AC KC QC JC TC").unwrap();
let two_cards = TwoCard::try_from("9C 8C").unwrap();
let seven = SevenCard::new(two_cards, five_cards);
assert_eq!(five_cards.eval(), seven.eval());
}
#[test]
fn evaluable() {
let five_cards = FiveCard::try_from("AC KC QC JC TC").unwrap();
let two_cards = TwoCard::try_from("9C 8C").unwrap();
let seven = SevenCard::new(two_cards, five_cards);
let (hand, hand_rank) = seven.evaluate();
assert_eq!(HandRank::from(1), hand_rank);
assert_eq!(five_cards, hand);
}
#[test]
fn try_from__playing_cards() {
let playing_cards = PlayingCards::try_from("9H AS KS QS JS TS 2H").unwrap();
let a = SevenCard::try_from(&playing_cards).unwrap();
assert_eq!(playing_cards.get_index(0).unwrap().as_u32(), a.first());
assert_eq!(playing_cards.get_index(1).unwrap().as_u32(), a.second());
assert_eq!(playing_cards.get_index(2).unwrap().as_u32(), a.third());
assert_eq!(playing_cards.get_index(3).unwrap().as_u32(), a.forth());
assert_eq!(playing_cards.get_index(4).unwrap().as_u32(), a.fifth());
assert_eq!(playing_cards.get_index(5).unwrap().as_u32(), a.sixth());
assert_eq!(playing_cards.get_index(6).unwrap().as_u32(), a.seventh());
}
#[test]
fn try_from__poker_cards() {
let poker_cards = PokerCards::try_from("9H AS KS QS JS TS 2H").unwrap();
let a = SevenCard::try_from(&poker_cards).unwrap();
assert_eq!(*poker_cards.get(0).unwrap(), a.first());
assert_eq!(*poker_cards.get(1).unwrap(), a.second());
assert_eq!(*poker_cards.get(2).unwrap(), a.third());
assert_eq!(*poker_cards.get(3).unwrap(), a.forth());
assert_eq!(*poker_cards.get(4).unwrap(), a.fifth());
assert_eq!(*poker_cards.get(5).unwrap(), a.sixth());
assert_eq!(*poker_cards.get(6).unwrap(), a.seventh());
}
#[test]
fn try_from__vec_playing_card() {
let v = vec![
&PlayingCard::ACE_SPADES,
&PlayingCard::KING_SPADES,
&PlayingCard::QUEEN_SPADES,
&PlayingCard::JACK_SPADES,
&PlayingCard::TEN_SPADES,
&PlayingCard::NINE_SPADES,
&PlayingCard::EIGHT_SPADES,
];
let seven = SevenCard::try_from(v).unwrap();
assert_eq!("A♠ K♠ Q♠ J♠ T♠ 9♠ 8♠", seven.to_string())
}
}