ckc_rs/cards/
seven.rs

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