enable texas hold 'em
authorGeoffrey Allott <geoffrey@allott.email>
Sun, 28 Feb 2021 07:54:44 +0000 (07:54 +0000)
committerGeoffrey Allott <geoffrey@allott.email>
Sun, 28 Feb 2021 07:54:44 +0000 (07:54 +0000)
src/game/mod.rs
src/game/poker/holdem.rs
src/game/whist.rs
src/util/max.rs

index c8e01f73c91f75eb956ca0c5a06e89b30afb7b2a..9297388e606e75a5b39046f4c39f929d1a1c9542 100644 (file)
@@ -10,6 +10,7 @@ use crate::username::Username;
 
 use self::chatroom::{Chatroom, ChatroomSettings};
 use self::whist::{KnockOutWhist, KnockOutWhistSettings};
+use self::poker::{TexasHoldEm, TexasHoldEmSettings};
 
 pub use self::action::{Action, ActionError, UserAction, ValidatedUserAction};
 
@@ -43,6 +44,7 @@ impl dyn Game {
         match settings {
             GameSettings::Chatroom(settings) => Box::new(Chatroom::new(id, settings)),
             GameSettings::KnockOutWhist(settings) => Box::new(KnockOutWhist::new(id, settings)),
+            GameSettings::TexasHoldEm(settings) => Box::new(TexasHoldEm::new(id, settings)),
         }
     }
 }
@@ -52,6 +54,7 @@ impl dyn Game {
 pub enum GameSettings {
     Chatroom(ChatroomSettings),
     KnockOutWhist(KnockOutWhistSettings),
+    TexasHoldEm(TexasHoldEmSettings),
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
index 905be7d176c27f4b91f88544b47dd8d916fc436c..9879147f99021fb52a1e6995fde6feb0956f59ac 100644 (file)
@@ -31,7 +31,7 @@ enum State {
     Completed,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
 pub struct TexasHoldEmSettings {
     title: String,
     max_players: u32,
@@ -347,7 +347,7 @@ impl Game for TexasHoldEm {
                 }
             }
             State::Showdown => {
-                let winning_hands = self.hands.iter()
+                let winning_hands: Vec<_> = self.hands.iter()
                     .map(|(&username, hand)| (username, hand.iter().chain(self.community.iter()).cloned().collect::<Vec<_>>()))
                     .filter_map(|(username, cards)| cards.try_into().ok().map(rank_7_card_hand).map(|hand| (username, hand)))
                     .max_items_by_key(|(_, hand)| *hand);
index 9d0017371d869fb24f4d4810e9c63b280359f8aa..da82f69f2483c81b5131d86b98016ef8132cbfb0 100644 (file)
@@ -6,6 +6,7 @@ use rand::thread_rng;
 use crate::card::{Card, Suit, FIFTY_TWO_CARD_DECK};
 use crate::seats::Seats;
 use crate::username::Username;
+use crate::util::max::IteratorMaxItems;
 
 use super::{Action, ActionError, Game, UserAction, ValidatedUserAction};
 
@@ -241,18 +242,16 @@ impl Game for KnockOutWhist {
                 self.led = None;
                 self.trick.clear();
                 if self.tricks_won.values().sum::<u32>() == self.cards_to_deal {
-                    if let Some(&most_tricks_won) = self.tricks_won.values().max() {
-                        self.winners = self.tricks_won.iter().filter(|&(_, &tricks)| tricks == most_tricks_won).map(|(&username, _)| username).collect();
-                        self.cards_to_deal -= 1;
-                        if self.winners.len() == 1 {
-                            self.call = self.winners.iter().next().cloned();
-                        } else {
-                            self.receiver = self.dealer.and_then(|dealer| self.seats.player_after_in(dealer, &self.winners));
-                            self.deck = FIFTY_TWO_CARD_DECK.iter().cloned().collect();
-                            self.hands.clear();
-                            self.trump_card = None;
-                            self.state = State::CutForCall;
-                        }
+                    self.winners = self.tricks_won.iter().max_items_by_key_map(|&(_, &tricks)| tricks, |(&username, _)| username);
+                    self.cards_to_deal -= 1;
+                    if self.winners.len() == 1 {
+                        self.call = self.winners.iter().next().cloned();
+                    } else {
+                        self.receiver = self.dealer.and_then(|dealer| self.seats.player_after_in(dealer, &self.winners));
+                        self.deck = FIFTY_TWO_CARD_DECK.iter().cloned().collect();
+                        self.hands.clear();
+                        self.trump_card = None;
+                        self.state = State::CutForCall;
                     }
                     self.active = None;
                 } else {
index 7a52101ce451ce9c4656529495b90567afbd36e8..b7ef75e47b4646478856d4e97e8b53b9049ddf2e 100644 (file)
@@ -1,4 +1,6 @@
 use std::cmp::Ordering;
+use std::convert::identity;
+use std::iter::FromIterator;
 
 pub trait IteratorMaxItems : Iterator + Sized {
     fn max_items(self) -> Vec<Self::Item>
@@ -8,9 +10,19 @@ pub trait IteratorMaxItems : Iterator + Sized {
         self.max_items_by(Ord::cmp)
     }
 
-    fn max_items_by_key<B: Ord, F>(self, f: F) -> Vec<Self::Item>
+    fn max_items_by_key<B: Ord, F, C>(self, f: F) -> C
     where
-        F: FnMut(&Self::Item) -> B
+        F: FnMut(&Self::Item) -> B,
+        C: FromIterator<Self::Item>,
+    {
+        self.max_items_by_key_map(f, identity)
+    }
+
+    fn max_items_by_key_map<B: Ord, F, T, G, C>(self, f: F, g: G) -> C
+    where
+        F: FnMut(&Self::Item) -> B,
+        G: FnMut(Self::Item) -> T,
+        C: FromIterator<T>,
     {
         #[inline]
         fn key<T, B>(mut f: impl FnMut(&T) -> B) -> impl FnMut(T) -> (B, T) {
@@ -22,10 +34,15 @@ pub trait IteratorMaxItems : Iterator + Sized {
             x_p.cmp(y_p)
         }
 
+        #[inline]
+        fn snd_map<B, S, T>(mut g: impl FnMut(S) -> T) -> impl FnMut((B, S)) -> T {
+            move |(_, x)| g(x)
+        }
+
         self.map(key(f))
             .max_items_by(compare)
             .into_iter()
-            .map(|(_, x)| x)
+            .map(snd_map(g))
             .collect()
     }
 
@@ -81,6 +98,15 @@ mod tests {
 
     #[test]
     fn multiple_max_items_by_key() {
-        assert_eq!(vec![&("a", 5), &("e", 5)], [("a", 5), ("b", 4), ("c", 3), ("d", 2), ("e", 5)].iter().max_items_by_key(|&&(_, x)| x));
+        let result: Vec<_> = [("a", 5), ("b", 4), ("c", 3), ("d", 2), ("e", 5)].iter()
+            .max_items_by_key(|&&(_, x)| x);
+        assert_eq!(vec![&("a", 5), &("e", 5)], result);
+    }
+
+    #[test]
+    fn multiple_max_items_by_key_map() {
+        let result: Vec<_> = [("a", 5), ("b", 4), ("c", 3), ("d", 2), ("e", 5)].iter()
+            .max_items_by_key_map(|&&(_, x)| x, |&(s, _)| s);
+        assert_eq!(vec!["a", "e"], result);
     }
 }