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