add game start time
authorGeoffrey Allott <geoffrey@allott.email>
Sat, 20 Mar 2021 20:37:44 +0000 (20:37 +0000)
committerGeoffrey Allott <geoffrey@allott.email>
Sat, 20 Mar 2021 20:37:44 +0000 (20:37 +0000)
src/game/mod.rs
src/game/poker/holdem.rs
src/game/whist.rs

index 3fea22f0eb1713965a5df7f40805913626d0db42..552e0f2c8dba7d1136428da486961eb20355c3c9 100644 (file)
@@ -115,3 +115,16 @@ impl GameSummary {
         self.id
     }
 }
+
+#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
+#[serde(untagged)]
+enum StartCondition {
+    WhenFull,
+    AtTime(Timestamp),
+}
+
+impl Default for StartCondition {
+    fn default() -> Self {
+        StartCondition::WhenFull
+    }
+}
index 7fab4893b6353a7ed74446c2e76f419ee7dbd55c..dd624faa7d2b752b04902f402723bd9662cc26ef 100644 (file)
@@ -10,7 +10,7 @@ use crate::seats::Seats;
 use crate::username::Username;
 use crate::util::{max::IteratorMaxItems, timestamp::Timestamp};
 
-use super::super::{Action, ActionError, DealerAction, Game, UserAction, ValidatedUserAction};
+use super::super::{Action, ActionError, DealerAction, Game, StartCondition, UserAction, ValidatedUserAction};
 
 use super::classify::rank_7_card_hand;
 
@@ -47,6 +47,8 @@ pub struct TexasHoldEmSettings {
     round_length: Option<i64>,
     tournament_length: Option<i64>,
     action_timeout: Option<i64>,
+    #[serde(default)]
+    start_time: StartCondition,
 }
 
 impl TexasHoldEmSettings {
@@ -480,13 +482,24 @@ impl Game for TexasHoldEm {
         let mut rng = self.rng.clone();
         match self.state {
             State::NotStarted => {
-                if self.seats.players_len() == self.settings.max_players as usize {
-                    // TODO
-                    if let Some(username) = rng.choose_from(self.seats.player_set()) {
-                        return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }));
+                match self.settings.start_time {
+                    StartCondition::WhenFull => {
+                        if self.seats.players_len() == self.settings.max_players as usize {
+                            if let Some(username) = rng.choose_from(self.seats.player_set()) {
+                                return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }));
+                            }
+                        }
+                        DealerAction::WaitForPlayer
+                    }
+                    StartCondition::AtTime(start_time) => {
+                        if timestamp >= start_time && self.seats.players_len() >= 2 {
+                            if let Some(username) = rng.choose_from(self.seats.player_set()) {
+                                return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }));
+                            }
+                        }
+                        DealerAction::WaitUntil(start_time)
                     }
                 }
-                DealerAction::WaitForPlayer
             }
             State::Dealing => {
                 if let Some(username) = self.receiver {
@@ -658,6 +671,7 @@ mod tests {
             round_length: None,
             tournament_length: None,
             action_timeout: None,
+            start_time: StartCondition::WhenFull,
         };
 
         assert_eq!(50, settings.level(0).small_blind);
@@ -677,6 +691,7 @@ mod tests {
             round_length: Some(20 * 60 * 1000),
             tournament_length: Some(4 * 60 * 60 * 1000),
             action_timeout: None,
+            start_time: StartCondition::WhenFull,
         };
 
         assert_eq!(25, settings.level(0).small_blind);
index 262f1ad8621c9ce63c9fb8e9811a0350932864ae..912ac6a6b900fdb325bb278d069f14d5fb0290c0 100644 (file)
@@ -6,7 +6,7 @@ use crate::seats::Seats;
 use crate::username::Username;
 use crate::util::{max::IteratorMaxItems, timestamp::Timestamp};
 
-use super::{Action, ActionError, DealerAction, Game, UserAction, ValidatedUserAction};
+use super::{Action, ActionError, DealerAction, Game, StartCondition, UserAction, ValidatedUserAction};
 
 #[derive(Copy, Clone, Debug)]
 enum State {
@@ -23,6 +23,8 @@ enum State {
 pub struct KnockOutWhistSettings {
     title: String,
     max_players: u32,
+    #[serde(default)]
+    start_time: StartCondition,
 }
 
 impl KnockOutWhistSettings {
@@ -305,13 +307,24 @@ impl Game for KnockOutWhist {
         let mut rng = self.rng.clone();
         match self.state {
             State::NotStarted => {
-                if self.seats.players_len() == self.settings.max_players as usize {
-                    // TODO
-                    if let Some(username) = rng.choose_from(self.seats.player_set()) {
-                        return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }));
+                match self.settings.start_time {
+                    StartCondition::WhenFull => {
+                        if self.seats.players_len() == self.settings.max_players as usize {
+                            if let Some(username) = rng.choose_from(self.seats.player_set()) {
+                                return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }));
+                            }
+                        }
+                        DealerAction::WaitForPlayer
+                    }
+                    StartCondition::AtTime(start_time) => {
+                        if timestamp >= start_time && self.seats.players_len() >= 2 {
+                            if let Some(username) = rng.choose_from(self.seats.player_set()) {
+                                return DealerAction::TakeAction(ValidatedUserAction(UserAction { timestamp, username, action: Action::NextToDeal }));
+                            }
+                        }
+                        DealerAction::WaitUntil(start_time)
                     }
                 }
-                DealerAction::WaitForPlayer
             }
             State::Dealing => {
                 if let Some(username) = self.receiver {
@@ -413,6 +426,24 @@ mod tests {
         }
     }
 
+    #[test]
+    fn start_game_at_time() {
+        let actions = r#"[
+            {"timestamp":1616272415014,"username":"geoff","action":{"action":"Join","seat":0,"chips":0}},
+            {"timestamp":1616272415018,"username":"kat","action":{"action":"Join","seat":1,"chips":0}},
+            {"timestamp":1616280000000,"username":"geoff","action":{"action":"NextToDeal"}}
+        ]"#;
+        let actions = serde_json::from_str(actions).unwrap();
+
+        let settings = r#"{"format":"KnockOutWhist","title":"2-Player Knock-Out Whist Test","max_players":4,"start_time":1616280000000}"#;
+        let settings = serde_json::from_str(settings).unwrap();
+
+        let seed = r#"{"rng":"ChaCha20","seed":"0bc81b871dca272486f7c848a3c84102f501e934aaf87b311fc21e65327bf1f4"}"#;
+        let seed = serde_json::from_str(seed).unwrap();
+
+        test_game(actions, settings, seed);
+    }
+
     #[test]
     fn complete_2_player_knock_out_whist() {
         let actions = r#"[