1use crate::cards::HandValidator;
2use crate::{CKCNumber, HandError, PokerCard, Shifty};
3use core::slice::Iter;
4use serde::{Deserialize, Serialize};
5
6#[derive(Serialize, Deserialize, Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub struct Four([CKCNumber; 4]);
8
9impl Four {
10 pub const OMAHA_PERMUTATIONS: [[u8; 2]; 6] = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]];
11
12 #[must_use]
15 pub fn second(&self) -> CKCNumber {
16 self.0[1]
17 }
18
19 #[must_use]
20 pub fn third(&self) -> CKCNumber {
21 self.0[2]
22 }
23
24 #[must_use]
25 pub fn forth(&self) -> CKCNumber {
26 self.0[3]
27 }
28
29 pub fn set_first(&mut self, card_number: CKCNumber) {
30 self.0[0] = card_number;
31 }
32
33 pub fn set_second(&mut self, card_number: CKCNumber) {
34 self.0[1] = card_number;
35 }
36
37 pub fn set_third(&mut self, card_number: CKCNumber) {
38 self.0[2] = card_number;
39 }
40
41 pub fn set_forth(&mut self, card_number: CKCNumber) {
42 self.0[3] = card_number;
43 }
44
45 #[must_use]
46 pub fn to_arr(&self) -> [CKCNumber; 4] {
47 self.0
48 }
49
50 fn from_index(index: &str) -> Option<[CKCNumber; 4]> {
53 let mut esses = index.split_whitespace();
54
55 let first = CKCNumber::from_index(esses.next()?);
56 let second = CKCNumber::from_index(esses.next()?);
57 let third = CKCNumber::from_index(esses.next()?);
58 let forth = CKCNumber::from_index(esses.next()?);
59 let hand: [CKCNumber; 4] = [first, second, third, forth];
60 Some(hand)
61 }
62}
63
64impl From<[CKCNumber; 4]> for Four {
65 fn from(array: [CKCNumber; 4]) -> Self {
66 Four(array)
67 }
68}
69
70impl HandValidator for Four {
71 fn are_unique(&self) -> bool {
72 (self.first() != self.second())
73 && (self.first() != self.third())
74 && (self.first() != self.forth())
75 && (self.second() != self.third())
76 && (self.second() != self.forth())
77 && (self.third() != self.forth())
78 }
79
80 fn first(&self) -> CKCNumber {
81 self.0[0]
82 }
83
84 fn sort(&self) -> Four {
85 let mut array = *self;
86 array.sort_in_place();
87 array
88 }
89
90 fn sort_in_place(&mut self) {
91 self.0.sort_unstable();
92 self.0.reverse();
93 }
94
95 fn iter(&self) -> Iter<'_, CKCNumber> {
96 self.0.iter()
97 }
98}
99
100impl TryFrom<&'static str> for Four {
101 type Error = HandError;
102
103 fn try_from(index: &'static str) -> Result<Self, Self::Error> {
104 match Four::from_index(index) {
105 None => Err(HandError::InvalidIndex),
106 Some(four) => Ok(Four::from(four)),
107 }
108 }
109}
110
111impl Shifty for Four {
112 fn shift_suit(&self) -> Self {
113 Four([
114 self.first().shift_suit(),
115 self.second().shift_suit(),
116 self.third().shift_suit(),
117 self.forth().shift_suit(),
118 ])
119 }
120}
121
122#[cfg(test)]
123#[allow(non_snake_case)]
124mod cards_four_tests {
125 use super::*;
126 use crate::CardNumber;
127
128 #[test]
129 fn sort() {
130 let four = Four::try_from("KC QD A♠ T♠").unwrap().sort();
131
132 let expected = Four::try_from("A♠ KC QD T♠").unwrap();
133
134 assert_eq!(four, expected);
135 }
136
137 #[test]
138 fn default() {
139 let four = Four::default();
140
141 assert_eq!(four.first(), CardNumber::BLANK);
142 assert_eq!(four.second(), CardNumber::BLANK);
143 assert_eq!(four.third(), CardNumber::BLANK);
144 assert_eq!(four.forth(), CardNumber::BLANK);
145 assert!(four.contain_blank());
146 assert!(!four.are_unique());
147 assert!(!four.is_valid());
148 }
149
150 #[test]
151 fn try_from__index() {
152 let four = Four::try_from("A♠ K♠ Q♠ J♠");
153
154 assert!(four.is_ok());
155 let four = four.unwrap();
156 assert_eq!(four.first(), CardNumber::ACE_SPADES);
157 assert_eq!(four.second(), CardNumber::KING_SPADES);
158 assert_eq!(four.third(), CardNumber::QUEEN_SPADES);
159 assert_eq!(four.forth(), CardNumber::JACK_SPADES);
160 assert!(!four.contain_blank());
161 assert!(four.are_unique());
162 assert!(four.is_valid());
163 }
164
165 #[test]
166 fn try_from__index__blank() {
167 let four = Four::try_from("A♠ K♠ XX J♠");
168
169 assert!(four.is_ok());
170 let four = four.unwrap();
171 assert_eq!(four.first(), CardNumber::ACE_SPADES);
172 assert_eq!(four.second(), CardNumber::KING_SPADES);
173 assert_eq!(four.third(), CardNumber::BLANK);
174 assert_eq!(four.forth(), CardNumber::JACK_SPADES);
175 assert!(four.contain_blank());
176 assert!(!four.is_valid());
177 }
178
179 #[test]
180 fn try_from__index__too_short() {
181 let four = Four::try_from("A♠ K♠ Q♠");
182
183 assert!(four.is_err());
184 }
185
186 #[test]
187 fn shifty__shift_suit() {
188 assert_eq!(
189 Four::try_from("AH KH QH JH").unwrap().shift_suit(),
190 Four::try_from("AD KD QD JD").unwrap()
191 )
192 }
193}