use crate::cards::HandValidator;
use crate::{CKCNumber, HandError, PokerCard, Shifty};
use core::slice::Iter;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Four([CKCNumber; 4]);
impl Four {
pub const OMAHA_PERMUTATIONS: [[u8; 2]; 6] = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]];
#[must_use]
pub fn second(&self) -> CKCNumber {
self.0[1]
}
#[must_use]
pub fn third(&self) -> CKCNumber {
self.0[2]
}
#[must_use]
pub fn forth(&self) -> CKCNumber {
self.0[3]
}
pub fn set_first(&mut self, card_number: CKCNumber) {
self.0[0] = card_number;
}
pub fn set_second(&mut self, card_number: CKCNumber) {
self.0[1] = card_number;
}
pub fn set_third(&mut self, card_number: CKCNumber) {
self.0[2] = card_number;
}
pub fn set_forth(&mut self, card_number: CKCNumber) {
self.0[3] = card_number;
}
#[must_use]
pub fn to_arr(&self) -> [CKCNumber; 4] {
self.0
}
fn from_index(index: &str) -> Option<[CKCNumber; 4]> {
let mut esses = index.split_whitespace();
let first = CKCNumber::from_index(esses.next()?);
let second = CKCNumber::from_index(esses.next()?);
let third = CKCNumber::from_index(esses.next()?);
let forth = CKCNumber::from_index(esses.next()?);
let hand: [CKCNumber; 4] = [first, second, third, forth];
Some(hand)
}
}
impl From<[CKCNumber; 4]> for Four {
fn from(array: [CKCNumber; 4]) -> Self {
Four(array)
}
}
impl HandValidator for Four {
fn are_unique(&self) -> bool {
(self.first() != self.second())
&& (self.first() != self.third())
&& (self.first() != self.forth())
&& (self.second() != self.third())
&& (self.second() != self.forth())
&& (self.third() != self.forth())
}
fn first(&self) -> CKCNumber {
self.0[0]
}
fn sort(&self) -> Four {
let mut array = *self;
array.sort_in_place();
array
}
fn sort_in_place(&mut self) {
self.0.sort_unstable();
self.0.reverse();
}
fn iter(&self) -> Iter<'_, CKCNumber> {
self.0.iter()
}
}
impl TryFrom<&'static str> for Four {
type Error = HandError;
fn try_from(index: &'static str) -> Result<Self, Self::Error> {
match Four::from_index(index) {
None => Err(HandError::InvalidIndex),
Some(four) => Ok(Four::from(four)),
}
}
}
impl Shifty for Four {
fn shift_suit(&self) -> Self {
Four([
self.first().shift_suit(),
self.second().shift_suit(),
self.third().shift_suit(),
self.forth().shift_suit(),
])
}
}
#[cfg(test)]
#[allow(non_snake_case)]
mod cards_four_tests {
use super::*;
use crate::CardNumber;
#[test]
fn sort() {
let four = Four::try_from("KC QD A♠ T♠").unwrap().sort();
let expected = Four::try_from("A♠ KC QD T♠").unwrap();
assert_eq!(four, expected);
}
#[test]
fn default() {
let four = Four::default();
assert_eq!(four.first(), CardNumber::BLANK);
assert_eq!(four.second(), CardNumber::BLANK);
assert_eq!(four.third(), CardNumber::BLANK);
assert_eq!(four.forth(), CardNumber::BLANK);
assert!(four.contain_blank());
assert!(!four.are_unique());
assert!(!four.is_valid());
}
#[test]
fn try_from__index() {
let four = Four::try_from("A♠ K♠ Q♠ J♠");
assert!(four.is_ok());
let four = four.unwrap();
assert_eq!(four.first(), CardNumber::ACE_SPADES);
assert_eq!(four.second(), CardNumber::KING_SPADES);
assert_eq!(four.third(), CardNumber::QUEEN_SPADES);
assert_eq!(four.forth(), CardNumber::JACK_SPADES);
assert!(!four.contain_blank());
assert!(four.are_unique());
assert!(four.is_valid());
}
#[test]
fn try_from__index__blank() {
let four = Four::try_from("A♠ K♠ XX J♠");
assert!(four.is_ok());
let four = four.unwrap();
assert_eq!(four.first(), CardNumber::ACE_SPADES);
assert_eq!(four.second(), CardNumber::KING_SPADES);
assert_eq!(four.third(), CardNumber::BLANK);
assert_eq!(four.forth(), CardNumber::JACK_SPADES);
assert!(four.contain_blank());
assert!(!four.is_valid());
}
#[test]
fn try_from__index__too_short() {
let four = Four::try_from("A♠ K♠ Q♠");
assert!(four.is_err());
}
#[test]
fn shifty__shift_suit() {
assert_eq!(
Four::try_from("AH KH QH JH").unwrap().shift_suit(),
Four::try_from("AD KD QD JD").unwrap()
)
}
}