1use crate::preludes::funky::{BCardType, BuffoonCard, MPip};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(
6 Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, Serialize, Deserialize,
7)]
8pub enum HandType {
9 #[default]
10 HighCard,
11 Pair,
12 TwoPair,
13 ThreeOfAKind,
14 Straight,
15 Flush,
16 FullHouse,
17 FourOfAKind,
18 StraightFlush,
19 RoyalFlush,
20 FiveOfAKind,
21 FlushHouse,
22 FlushFive,
23}
24
25#[derive(
26 Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd, Serialize, Deserialize,
27)]
28pub struct PokerHand {
29 pub hand_type: HandType,
30 pub level: usize,
31 pub chips: usize,
32 pub mult: usize,
33 pub times_played: usize,
34}
35
36impl PokerHand {
37 #[must_use]
38 pub fn new(hand_type: HandType, chips: usize, mult: usize) -> Self {
39 Self {
40 hand_type,
41 level: 1,
42 chips,
43 mult,
44 times_played: 0,
45 }
46 }
47}
48
49#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
50pub struct PokerHands {
51 pub hands: HashMap<HandType, PokerHand>,
52}
53
54impl PokerHands {
55 #[must_use]
56 pub fn new() -> Self {
57 let mut hands = HashMap::new();
58 hands.insert(HandType::HighCard, PokerHand::new(HandType::HighCard, 5, 1));
59 hands.insert(HandType::Pair, PokerHand::new(HandType::Pair, 10, 2));
60 hands.insert(HandType::TwoPair, PokerHand::new(HandType::TwoPair, 20, 2));
61 hands.insert(
62 HandType::ThreeOfAKind,
63 PokerHand::new(HandType::ThreeOfAKind, 30, 3),
64 );
65 hands.insert(
66 HandType::Straight,
67 PokerHand::new(HandType::Straight, 30, 4),
68 );
69 hands.insert(HandType::Flush, PokerHand::new(HandType::Flush, 35, 4));
70 hands.insert(
71 HandType::FullHouse,
72 PokerHand::new(HandType::FullHouse, 40, 4),
73 );
74 hands.insert(
75 HandType::FourOfAKind,
76 PokerHand::new(HandType::FourOfAKind, 50, 7),
77 );
78 hands.insert(
79 HandType::StraightFlush,
80 PokerHand::new(HandType::StraightFlush, 100, 8),
81 );
82 hands.insert(
83 HandType::FiveOfAKind,
84 PokerHand::new(HandType::FiveOfAKind, 120, 12),
85 );
86 hands.insert(
87 HandType::FlushHouse,
88 PokerHand::new(HandType::FlushHouse, 140, 14),
89 );
90 hands.insert(
91 HandType::FlushFive,
92 PokerHand::new(HandType::FlushFive, 160, 16),
93 );
94 Self { hands }
95 }
96
97 #[must_use]
98 pub fn get(&self, hand_type: &HandType) -> Option<&PokerHand> {
99 self.hands.get(hand_type)
100 }
101
102 pub fn get_mut(&mut self, hand_type: &HandType) -> Option<&mut PokerHand> {
103 self.hands.get_mut(hand_type)
104 }
105
106 pub fn increment(&mut self, planet_card: BuffoonCard) {
107 if planet_card.card_type == BCardType::Planet {
108 if let MPip::ChipsMultPlusOnHand(chips, mult, hand_type) = planet_card.enhancement {
109 if let Some(poker_hand) = self.get_mut(&hand_type) {
110 poker_hand.chips += chips;
111 poker_hand.mult += mult;
112 poker_hand.level += 1;
113 }
114 }
115 }
116 }
117
118 pub fn play_hand(&mut self, hand_type: &HandType) {
119 if let Some(poker_hand) = self.get_mut(hand_type) {
120 poker_hand.times_played += 1;
121 }
122 }
123
124 const LEVEL_UP: [(HandType, usize, usize); 12] = [
132 (HandType::HighCard, 10, 1),
133 (HandType::Pair, 15, 1),
134 (HandType::TwoPair, 20, 1),
135 (HandType::ThreeOfAKind, 20, 2),
136 (HandType::Straight, 30, 3),
137 (HandType::Flush, 15, 2),
138 (HandType::FullHouse, 25, 2),
139 (HandType::FourOfAKind, 30, 3),
140 (HandType::StraightFlush, 40, 4),
141 (HandType::FiveOfAKind, 35, 3),
142 (HandType::FlushHouse, 40, 4),
143 (HandType::FlushFive, 50, 3),
144 ];
145
146 pub fn increment_all(&mut self) {
150 for (hand_type, chips, mult) in Self::LEVEL_UP {
151 if let Some(poker_hand) = self.get_mut(&hand_type) {
152 poker_hand.chips += chips;
153 poker_hand.mult += mult;
154 poker_hand.level += 1;
155 }
156 }
157 }
158}
159
160impl Default for PokerHands {
161 fn default() -> Self {
162 Self::new()
163 }
164}
165
166#[cfg(test)]
167#[allow(non_snake_case, unused_imports)]
168mod funky__types__hands_tests {
169 use super::*;
170 use crate::funky::decks::planet;
171 use crate::preludes::funky::*;
172 use rstest::rstest;
173
174 #[test]
175 fn increment() {
176 let mut hands = PokerHands::default();
177 let expected = PokerHand {
178 hand_type: HandType::HighCard,
179 level: 2,
180 chips: 15,
181 mult: 2,
182 times_played: 0,
183 };
184
185 hands.increment(planet::card::PLUTO);
186
187 assert_eq!(hands.get(&HandType::HighCard).unwrap(), &expected);
188 }
189
190 #[test]
191 fn increment_all__levels_every_hand_by_one() {
192 let mut hands = PokerHands::default();
193 hands.increment_all();
194
195 let high = hands.get(&HandType::HighCard).unwrap();
197 assert_eq!((high.level, high.chips, high.mult), (2, 15, 2));
198
199 for hand_type in [
201 HandType::Pair,
202 HandType::TwoPair,
203 HandType::ThreeOfAKind,
204 HandType::Straight,
205 HandType::Flush,
206 HandType::FullHouse,
207 HandType::FourOfAKind,
208 HandType::StraightFlush,
209 HandType::FiveOfAKind,
210 HandType::FlushHouse,
211 HandType::FlushFive,
212 ] {
213 assert_eq!(hands.get(&hand_type).unwrap().level, 2, "{hand_type:?}");
214 }
215 }
216
217 #[test]
218 fn play_hand() {
219 let mut hands = PokerHands::default();
220 let expected = PokerHand {
221 hand_type: HandType::HighCard,
222 level: 1,
223 chips: 5,
224 mult: 1,
225 times_played: 1,
226 };
227
228 hands.play_hand(&HandType::HighCard);
229
230 assert_eq!(hands.get(&HandType::HighCard).unwrap(), &expected);
231 }
232
233 #[test]
234 fn hand_type__serde_round_trip() {
235 for hand_type in [
236 HandType::HighCard,
237 HandType::Pair,
238 HandType::TwoPair,
239 HandType::ThreeOfAKind,
240 HandType::Straight,
241 HandType::Flush,
242 HandType::FullHouse,
243 HandType::FourOfAKind,
244 HandType::StraightFlush,
245 HandType::RoyalFlush,
246 HandType::FiveOfAKind,
247 HandType::FlushHouse,
248 HandType::FlushFive,
249 ] {
250 let json = serde_json::to_string(&hand_type).unwrap();
251
252 assert_eq!(serde_json::from_str::<HandType>(&json).unwrap(), hand_type);
253 }
254 }
255
256 #[test]
258 fn hand_type__serde_format() {
259 assert_eq!(
260 serde_json::to_string(&HandType::FlushFive).unwrap(),
261 r#""FlushFive""#
262 );
263 }
264}