ckc_rs/cards/
six.rs

1use crate::cards::five::Five;
2use crate::cards::three::Three;
3use crate::cards::two::Two;
4use crate::cards::{HandRanker, HandValidator, Permutator};
5use crate::hand_rank::HandRankValue;
6use crate::{CKCNumber, HandError, PokerCard, Shifty};
7use core::slice::Iter;
8use serde::{Deserialize, Serialize};
9
10#[derive(Serialize, Deserialize, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
11pub struct Six([CKCNumber; 6]);
12
13impl Six {
14    /// permutations to evaluate all 6 card combinations.
15    pub const FIVE_CARD_PERMUTATIONS: [[u8; 5]; 6] = [
16        [0, 1, 2, 3, 4],
17        [0, 1, 2, 3, 5],
18        [0, 1, 2, 4, 5],
19        [0, 1, 3, 4, 5],
20        [0, 2, 3, 4, 5],
21        [1, 2, 3, 4, 5],
22    ];
23
24    #[must_use]
25    pub fn from_1_and_2_and_3(one: CKCNumber, two: Two, three: Three) -> Self {
26        Self::from([
27            one,
28            two.first(),
29            two.second(),
30            three.first(),
31            three.second(),
32            three.third(),
33        ])
34    }
35
36    //region accessors
37
38    #[must_use]
39    pub fn second(&self) -> CKCNumber {
40        self.0[1]
41    }
42
43    #[must_use]
44    pub fn third(&self) -> CKCNumber {
45        self.0[2]
46    }
47
48    #[must_use]
49    pub fn forth(&self) -> CKCNumber {
50        self.0[3]
51    }
52
53    #[must_use]
54    pub fn fifth(&self) -> CKCNumber {
55        self.0[4]
56    }
57
58    #[must_use]
59    pub fn sixth(&self) -> CKCNumber {
60        self.0[5]
61    }
62
63    pub fn set_first(&mut self, card_number: CKCNumber) {
64        self.0[0] = card_number;
65    }
66
67    pub fn set_second(&mut self, card_number: CKCNumber) {
68        self.0[1] = card_number;
69    }
70
71    pub fn set_third(&mut self, card_number: CKCNumber) {
72        self.0[2] = card_number;
73    }
74
75    pub fn set_forth(&mut self, card_number: CKCNumber) {
76        self.0[3] = card_number;
77    }
78
79    pub fn set_fifth(&mut self, card_number: CKCNumber) {
80        self.0[4] = card_number;
81    }
82
83    pub fn set_sixth(&mut self, card_number: CKCNumber) {
84        self.0[5] = card_number;
85    }
86
87    #[must_use]
88    pub fn to_arr(&self) -> [CKCNumber; 6] {
89        self.0
90    }
91
92    //endregion
93
94    fn from_index(index: &str) -> Option<[CKCNumber; 6]> {
95        let mut esses = index.split_whitespace();
96
97        let first = CKCNumber::from_index(esses.next()?);
98        let second = CKCNumber::from_index(esses.next()?);
99        let third = CKCNumber::from_index(esses.next()?);
100        let forth = CKCNumber::from_index(esses.next()?);
101        let fifth = CKCNumber::from_index(esses.next()?);
102        let sixth = CKCNumber::from_index(esses.next()?);
103        let hand: [CKCNumber; 6] = [first, second, third, forth, fifth, sixth];
104        Some(hand)
105    }
106}
107
108impl From<[CKCNumber; 6]> for Six {
109    fn from(array: [CKCNumber; 6]) -> Self {
110        Six(array)
111    }
112}
113
114impl HandRanker for Six {
115    fn hand_rank_value_and_hand(&self) -> (HandRankValue, Five) {
116        let mut best_hrv: HandRankValue = 0u16;
117        let mut best_hand = Five::default();
118
119        for perm in Six::FIVE_CARD_PERMUTATIONS {
120            let hand = self.five_from_permutation(perm);
121            let hrv = hand.hand_rank_value();
122            if (best_hrv == 0) || hrv != 0 && hrv < best_hrv {
123                best_hrv = hrv;
124                best_hand = hand;
125            }
126        }
127
128        (best_hrv, best_hand.sort())
129    }
130
131    fn hand_rank_value_validated(&self) -> HandRankValue {
132        if !self.is_valid() {
133            return crate::hand_rank::NO_HAND_RANK_VALUE;
134        }
135        self.hand_rank_value()
136    }
137}
138
139impl HandValidator for Six {
140    fn are_unique(&self) -> bool {
141        let sorted = self.sort();
142        let mut last: CKCNumber = u32::MAX;
143        for c in sorted.iter() {
144            if *c >= last {
145                return false;
146            }
147            last = *c;
148        }
149        true
150    }
151
152    fn first(&self) -> CKCNumber {
153        self.0[0]
154    }
155
156    fn sort(&self) -> Six {
157        let mut array = *self;
158        array.sort_in_place();
159        array
160    }
161
162    fn sort_in_place(&mut self) {
163        self.0.sort_unstable();
164        self.0.reverse();
165    }
166
167    fn iter(&self) -> Iter<'_, CKCNumber> {
168        self.0.iter()
169    }
170}
171
172impl Permutator for Six {
173    fn five_from_permutation(&self, permutation: [u8; 5]) -> Five {
174        Five::new(
175            self.0[permutation[0] as usize],
176            self.0[permutation[1] as usize],
177            self.0[permutation[2] as usize],
178            self.0[permutation[3] as usize],
179            self.0[permutation[4] as usize],
180        )
181    }
182}
183
184impl Shifty for Six {
185    fn shift_suit(&self) -> Self {
186        Six([
187            self.first().shift_suit(),
188            self.second().shift_suit(),
189            self.third().shift_suit(),
190            self.forth().shift_suit(),
191            self.fifth().shift_suit(),
192            self.sixth().shift_suit(),
193        ])
194    }
195}
196
197impl TryFrom<&'static str> for Six {
198    type Error = HandError;
199
200    fn try_from(index: &'static str) -> Result<Self, Self::Error> {
201        match Six::from_index(index) {
202            None => Err(HandError::InvalidIndex),
203            Some(six) => Ok(Six::from(six)),
204        }
205    }
206}
207
208#[cfg(test)]
209#[allow(non_snake_case)]
210mod cards_six_tests {
211    use super::*;
212    use crate::CardNumber;
213
214    #[test]
215    fn five_from_permutation() {
216        let six = Six::try_from("A♠ K♠ Q♠ J♠ T♠ 9♠").unwrap();
217
218        assert_eq!(
219            six.five_from_permutation(Six::FIVE_CARD_PERMUTATIONS[0]),
220            Five::try_from("A♠ K♠ Q♠ J♠ T♠").unwrap()
221        );
222        assert_eq!(
223            six.five_from_permutation(Six::FIVE_CARD_PERMUTATIONS[1]),
224            Five::try_from("A♠ K♠ Q♠ J♠ 9♠").unwrap()
225        );
226        assert_eq!(
227            six.five_from_permutation(Six::FIVE_CARD_PERMUTATIONS[2]),
228            Five::try_from("A♠ K♠ Q♠ T♠ 9♠").unwrap()
229        );
230        assert_eq!(
231            six.five_from_permutation(Six::FIVE_CARD_PERMUTATIONS[3]),
232            Five::try_from("A♠ K♠ J♠ T♠ 9♠").unwrap()
233        );
234        assert_eq!(
235            six.five_from_permutation(Six::FIVE_CARD_PERMUTATIONS[4]),
236            Five::try_from("A♠ Q♠ J♠ T♠ 9♠").unwrap()
237        );
238        assert_eq!(
239            six.five_from_permutation(Six::FIVE_CARD_PERMUTATIONS[5]),
240            Five::try_from("K♠ Q♠ J♠ T♠ 9♠").unwrap()
241        );
242    }
243
244    #[test]
245    fn hand_rank_value() {
246        assert_eq!(1, Six::try_from("T♠ A♠ K♠ J♠ Q♠ 9♠").unwrap().hand_rank_value());
247        assert_eq!(2, Six::try_from("T♠ 8♠ K♠ J♠ Q♠ 9♠").unwrap().hand_rank_value());
248        assert_eq!(3, Six::try_from("T♠ 8♠ 7♠ J♠ Q♠ 9♠").unwrap().hand_rank_value());
249        assert_eq!(7450, Six::try_from("8D 7C 5D 4♥ 3D 2D").unwrap().hand_rank_value());
250    }
251
252    #[test]
253    fn hand_rank_value_validated() {
254        assert_eq!(
255            0,
256            Six::try_from("8D 8D 5D 4♥ 3D 2D").unwrap().hand_rank_value_validated()
257        );
258    }
259
260    #[test]
261    fn sort() {
262        let six = Six::try_from("KC 8C QD A♠ 9h T♠").unwrap().sort();
263
264        let expected = Six::try_from("A♠ KC QD T♠ 9h 8c").unwrap();
265
266        assert_eq!(six, expected);
267    }
268
269    #[test]
270    fn default() {
271        let six = Six::default();
272
273        assert_eq!(six.first(), CardNumber::BLANK);
274        assert_eq!(six.second(), CardNumber::BLANK);
275        assert_eq!(six.third(), CardNumber::BLANK);
276        assert_eq!(six.forth(), CardNumber::BLANK);
277        assert_eq!(six.fifth(), CardNumber::BLANK);
278        assert_eq!(six.sixth(), CardNumber::BLANK);
279        assert!(six.contain_blank());
280        assert!(!six.are_unique());
281        assert!(!six.is_valid());
282    }
283
284    #[test]
285    fn shifty__shift_suit() {
286        assert_eq!(
287            Six::try_from("T♠ A♠ K♠ J♠ Q♠ 9♠").unwrap().shift_suit(),
288            Six::try_from("T♥ A♥ K♥ J♥ Q♥ 9♥").unwrap()
289        )
290    }
291
292    #[test]
293    fn try_from__index() {
294        let six = Six::try_from("A♠ K♠ Q♠ J♠ T♠ 9♠");
295
296        assert!(six.is_ok());
297        let six = six.unwrap();
298        assert_eq!(six.first(), CardNumber::ACE_SPADES);
299        assert_eq!(six.second(), CardNumber::KING_SPADES);
300        assert_eq!(six.third(), CardNumber::QUEEN_SPADES);
301        assert_eq!(six.forth(), CardNumber::JACK_SPADES);
302        assert_eq!(six.fifth(), CardNumber::TEN_SPADES);
303        assert_eq!(six.sixth(), CardNumber::NINE_SPADES);
304        assert!(!six.contain_blank());
305        assert!(six.are_unique());
306        assert!(six.is_valid());
307    }
308
309    #[test]
310    fn try_from__index__blank() {
311        let six = Six::try_from("A♠ K♠ XX J♠ T♠ 9♠");
312
313        assert!(six.is_ok());
314        let six = six.unwrap();
315        assert_eq!(six.first(), CardNumber::ACE_SPADES);
316        assert_eq!(six.second(), CardNumber::KING_SPADES);
317        assert_eq!(six.third(), CardNumber::BLANK);
318        assert_eq!(six.forth(), CardNumber::JACK_SPADES);
319        assert_eq!(six.fifth(), CardNumber::TEN_SPADES);
320        assert_eq!(six.sixth(), CardNumber::NINE_SPADES);
321        assert!(six.contain_blank());
322        assert!(!six.is_valid());
323    }
324
325    #[test]
326    fn try_from__index__too_short() {
327        let six = Six::try_from("A♠ K♠ Q♠ J♠ T♠");
328
329        assert!(six.is_err());
330    }
331}