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 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 #[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 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}