use crate::analysis::eval::Eval;
use crate::analysis::evals::Evals;
use crate::types::arrays::five_card::FiveCard;
use crate::types::arrays::three_card::ThreeCard;
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::{CardNumber, HandError, PokerCard};
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct SixCard([U32Card; 6]);
impl SixCard {
pub const PERMUTATIONS: [[u8; 5]; 6] = [
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 5],
[0, 1, 2, 4, 5],
[0, 1, 3, 4, 5],
[0, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
];
#[must_use]
pub fn from_1_and_2_and_3(one: U32Card, two: TwoCard, three: ThreeCard) -> SixCard {
SixCard::from([
one,
two.first(),
two.second(),
three.first(),
three.second(),
three.third(),
])
}
#[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]
}
}
impl Evaluable for SixCard {
fn evals(&self) -> Evals {
let mut evals = Evals::default();
let mut subhand: [U32Card; 5] = [CardNumber::BLANK; 5];
for ids in &crate::types::arrays::six_card::SixCard::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; 6]> for SixCard {
fn from(array: [PlayingCard; 6]) -> Self {
SixCard::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(),
])
}
}
impl From<[U32Card; 6]> for SixCard {
fn from(value: [U32Card; 6]) -> Self {
SixCard(value)
}
}
impl TryFrom<&PlayingCards> for SixCard {
type Error = HandError;
fn try_from(playing_cards: &PlayingCards) -> Result<Self, Self::Error> {
match playing_cards.len() {
0..=5 => Err(HandError::NotEnoughCards),
6 => Ok(SixCard::from([
*playing_cards.get_index(0).unwrap(),
*playing_cards.get_index(1).unwrap(),
*playing_cards.get_index(2).unwrap(),
*playing_cards.get_index(3).unwrap(),
*playing_cards.get_index(4).unwrap(),
*playing_cards.get_index(5).unwrap(),
])),
_ => Err(HandError::TooManyCards),
}
}
}
impl TryFrom<&PokerCards> for SixCard {
type Error = HandError;
fn try_from(poker_cards: &PokerCards) -> Result<Self, Self::Error> {
SixCard::try_from(&PlayingCards::from(poker_cards))
}
}
impl TryFrom<&'static str> for SixCard {
type Error = HandError;
fn try_from(value: &'static str) -> Result<Self, Self::Error> {
match PokerCards::try_from(value) {
Ok(cards) => SixCard::try_from(&cards),
Err(e) => Err(e),
}
}
}
impl Vectorable for SixCard {
#[must_use]
fn to_vec(&self) -> Vec<U32Card> {
self.0.to_vec()
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod types_arrays_six_card_tests {
use super::*;
use ckc_rs::hand_rank::HandRankClass;
use rstest::rstest;
#[test]
fn eval() {
let ckcs = SixCard::try_from("6H AH KH QH JH TH").unwrap().eval();
assert_eq!(ckcs.rank.class, HandRankClass::RoyalFlush);
}
#[rstest]
#[case("9H AH KH QH JH TH", "AH KH QH JH TH")]
#[case("9H AH KS QH JD TH", "A♥ K♠ Q♥ J♦ T♥")]
#[case("9H AH KS QH JD TH", "A♥ K♠ Q♥ J♦ T♥")]
#[case("9H TD KS QH 9D TH", "TH TD 9H 9D KS")]
fn eval__many(#[case] index: &'static str, #[case] best_index: &'static str) {
let hand = SixCard::try_from(index).unwrap().eval();
let expected = FiveCard::try_from(best_index).unwrap();
assert_eq!(hand.hand, expected);
}
#[test]
fn try_from__poker_cards() {
let poker_cards = PokerCards::try_from("9H AS KS QS JS TS").unwrap();
let a = SixCard::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());
}
}