1use rand::Rng;
2
3use crate::{
4 card::Card,
5 evaluator::Evaluator,
6 model::{Board, Deal, Hand, PlayerHand},
7};
8
9static CARDS: [&str; 52] = [
10 "Ac", "Ad", "Ah", "As", "2c", "2d", "2h", "2s", "3c", "3d", "3h", "3s", "4c", "4d", "4h", "4s",
11 "5c", "5d", "5h", "5s", "6c", "6d", "6h", "6s", "7c", "7d", "7h", "7s", "8c", "8d", "8h", "8s",
12 "9c", "9d", "9h", "9s", "Tc", "Td", "Th", "Ts", "Jc", "Jd", "Jh", "Js", "Qc", "Qd", "Qh", "Qs",
13 "Kc", "Kd", "Kh", "Ks",
14];
15
16pub trait CardShuffler {
18 fn shuffle(&self) -> Vec<&'static str>;
19}
20
21pub struct RandomCardShuffler;
23
24impl CardShuffler for RandomCardShuffler {
25 fn shuffle(&self) -> Vec<&'static str> {
26 let mut rng = rand::thread_rng();
27 let mut sample = CARDS.clone();
28 for i in 0..CARDS.len() {
29 let rand: usize = rng.gen_range(0..=i);
30 sample.swap(i, rand);
31 }
32 sample.to_vec()
33 }
34}
35
36struct IndexGenerator {
37 index: usize,
38}
39
40impl IndexGenerator {
41 fn new() -> IndexGenerator {
42 IndexGenerator { index: 0 }
43 }
44}
45
46impl Iterator for IndexGenerator {
47 type Item = usize;
48
49 fn next(&mut self) -> Option<Self::Item> {
50 let current_index = self.index;
51 self.index += 1;
52 Some(current_index)
53 }
54}
55
56pub trait Dealer {
57 fn deal(&self, player_count: usize) -> Deal;
58}
59
60pub struct GameDealer<S: CardShuffler> {
61 shuffler: S,
62}
63
64impl<S: CardShuffler> GameDealer<S> {
65 #[allow(dead_code)]
66 pub fn new(shuffler: S) -> Self {
67 GameDealer { shuffler }
68 }
69}
70
71impl<S: CardShuffler> Dealer for GameDealer<S> {
72 fn deal(&self, player_count: usize) -> Deal {
73 let evaluator = Evaluator::new();
74 let cards = self.shuffler.shuffle();
75 let mut hands: Vec<PlayerHand> = Vec::new();
76 let mut nextn = IndexGenerator::new();
77 let players: Vec<_> = (0..player_count).collect();
78 let pl = players.len();
79 for _ in players {
80 let i = nextn.next().unwrap();
81 let player_hand: Vec<String> = vec![cards[i].to_string(), cards[i + pl].to_string()];
82 let scores: Vec<u32> = player_hand.iter().map(|card| Card::new(card).0).collect();
83 hands.push(PlayerHand {
84 hand: player_hand,
85 score: scores,
86 });
87 }
88 let flop = vec![
89 cards[nextn.next().unwrap() + pl].to_string(),
90 cards[nextn.next().unwrap() + pl].to_string(),
91 cards[nextn.next().unwrap() + pl].to_string(),
92 ];
93 let flop_score: Vec<u32> = flop.iter().map(|card| Card::new(card.as_str()).0).collect();
94 let turn = cards[nextn.next().unwrap() + pl];
95 let turn_score = Card::new(turn).0;
96 let river = cards[nextn.next().unwrap() + pl];
97 let river_score = Card::new(river).0;
98 let mut player_hands: Vec<Hand> = Vec::new();
99 for hand in hands {
100 let mut combined_score = flop_score.clone();
101 combined_score.push(turn_score);
102 combined_score.push(river_score);
103 let hand_score = evaluator.evaluate(hand.score, combined_score);
104 let score = evaluator.get_rank_class(hand_score);
105 let percentage = 1.0 - evaluator.get_five_card_rank_percentage(hand_score);
106 let description = evaluator.class_to_string(score.unwrap());
107 player_hands.push(Hand {
108 cards: hand.hand.clone(),
109 score: percentage,
110 description,
111 });
112 }
113 let board = Board {
114 flop: flop.clone(),
115 turn: turn.to_string(),
116 river: river.to_string(),
117 };
118 Deal {
119 board,
120 hands: player_hands,
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 struct MockCardShuffler;
130
131 impl CardShuffler for MockCardShuffler {
132 fn shuffle(&self) -> Vec<&'static str> {
133 CARDS.to_vec()
134 }
135 }
136
137 #[test]
138 fn test_deal() {
139 let expected_deal = Deal {
140 board: Board {
141 flop: vec!["2h".to_string(), "2s".to_string(), "3c".to_string()],
142 turn: "3d".to_string(),
143 river: "3h".to_string(),
144 },
145 hands: vec![
146 Hand {
147 cards: vec!["Ac".to_string(), "As".to_string()],
148 score: 0.9599303135888502,
149 description: "Full House".to_string(),
150 },
151 Hand {
152 cards: vec!["Ad".to_string(), "2c".to_string()],
153 score: 0.9584561779683731,
154 description: "Full House".to_string(),
155 },
156 Hand {
157 cards: vec!["Ah".to_string(), "2d".to_string()],
158 score: 0.9584561779683731,
159 description: "Full House".to_string(),
160 },
161 ],
162 };
163 let mock_shuffler = MockCardShuffler;
164 let dealer = GameDealer::new(mock_shuffler);
165 let deal = dealer.deal(3);
166 assert!(deal == expected_deal);
167 }
168}