diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2022-12-21 08:10:38 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2022-12-21 08:10:38 -0500 |
commit | 10ecb9e30568bf20287b053a620252d7a80dbd6b (patch) | |
tree | c6a82f7cb4d24071234a1429dbb91815709052be /server | |
parent | 27f74d8c366be675e7ab64ca746496a66b3cf024 (diff) |
Add struct for the player view of a hand in play
Diffstat (limited to 'server')
-rw-r--r-- | server/src/play.rs | 116 |
1 files changed, 87 insertions, 29 deletions
diff --git a/server/src/play.rs b/server/src/play.rs index 79d241c..86a4e06 100644 --- a/server/src/play.rs +++ b/server/src/play.rs @@ -1,5 +1,9 @@ use async_trait::async_trait; -use protocol::{bridge_engine::{GameState, Player, Bid, Deal, BiddingStatePlayerView}, simple_bots::AlwaysPassBiddingBot, bot::BiddingBot}; +use protocol::{ + bot::BiddingBot, + bridge_engine::{Bid, BiddingStatePlayerView, Deal, GameState, Player}, + simple_bots::AlwaysPassBiddingBot, +}; use rand::random; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -15,16 +19,23 @@ pub trait Journal { fn next(&self) -> i64; // Append payload to the journal at sequence number `seq`. - async fn append(&mut self, seq: i64, payload: serde_json::Value) -> Result<(), BridgeError>; + async fn append( + &mut self, + seq: i64, + payload: serde_json::Value, + ) -> Result<(), BridgeError>; // Fetch all journal entries with sequence number greater or equal to `seq`. - async fn replay(&mut self, seq: i64) -> Result<Vec<serde_json::Value>, BridgeError>; + async fn replay( + &mut self, + seq: i64, + ) -> Result<Vec<serde_json::Value>, BridgeError>; } pub struct DbJournal { db: PgPool, id: Uuid, - seq: i64 + seq: i64, } impl DbJournal { @@ -35,7 +46,11 @@ impl DbJournal { #[async_trait] impl Journal for DbJournal { - async fn append(&mut self, seq: i64, payload: serde_json::Value) -> Result<(), BridgeError> { + async fn append( + &mut self, + seq: i64, + payload: serde_json::Value, + ) -> Result<(), BridgeError> { let result = query!( r#" insert into object_journal (id, seq, payload) @@ -46,18 +61,24 @@ impl Journal for DbJournal { payload, ) .execute(&self.db) - .await; + .await; if let Err(sqlx::Error::Database(e)) = result { if e.constraint() == Some("journal_entry") { - return Err(BridgeError::JournalConflict(format!("{}", self.id), seq)); + return Err(BridgeError::JournalConflict( + format!("{}", self.id), + seq, + )); } } self.seq += 1; Ok(()) } - async fn replay(&mut self, seq: i64) -> Result<Vec<serde_json::Value>, BridgeError> { - let rows =query!( + async fn replay( + &mut self, + seq: i64, + ) -> Result<Vec<serde_json::Value>, BridgeError> { + let rows = query!( r#" select seq, payload from object_journal where id = $1 and seq >= $2 @@ -67,8 +88,8 @@ impl Journal for DbJournal { seq ) .fetch_all(&self.db) - .await?; - let mut payloads = vec!(); + .await?; + let mut payloads = vec![]; for v in rows { payloads.push(v.payload); self.seq = v.seq; @@ -106,13 +127,19 @@ where } impl<J: Journal> Table<J> { - pub fn game(&self) -> &GameState { &self.game } + pub fn game(&self) -> &GameState { + &self.game + } } impl<J: Journal> Table<J> { pub async fn new(mut journal: J) -> Result<Self, BridgeError> { let game = Self::init(&mut journal).await?; - Ok(Table { journal, game, settings: Default::default() }) + Ok(Table { + journal, + game, + settings: Default::default(), + }) } async fn init(journal: &mut J) -> Result<GameState, BridgeError> { @@ -123,7 +150,9 @@ impl<J: Journal> Table<J> { pub async fn bid(&mut self, bid: Bid) -> Result<(), BridgeError> { let game = self.game.clone().bid(bid)?; - self.journal.append(self.journal.next(), json!(game)).await?; + self.journal + .append(self.journal.next(), json!(game)) + .await?; self.game = game; Ok(()) } @@ -131,10 +160,16 @@ impl<J: Journal> Table<J> { pub async fn replay(mut journal: J) -> Result<Self, BridgeError> { let games = journal.replay(0).await?; if games.is_empty() { - return Err(BridgeError::NotFound("table journal missing".to_string())); + return Err(BridgeError::NotFound( + "table journal missing".to_string(), + )); } let game = serde_json::from_value(games[games.len() - 1].clone())?; - Ok(Table { journal, game, settings: Default::default() } ) + Ok(Table { + journal, + game, + settings: Default::default(), + }) } pub async fn new_or_replay(mut journal: J) -> Result<Self, BridgeError> { @@ -142,29 +177,43 @@ impl<J: Journal> Table<J> { if let Err(BridgeError::JournalConflict(..)) = game { return Self::replay(journal).await; } - Ok(Self { journal, game: game?, settings: Default::default() } ) + Ok(Self { + journal, + game: game?, + settings: Default::default(), + }) } } - -pub async fn advance_play<J: Journal>(table: &mut Table<J>) -> Result<(), BridgeError> { +pub async fn advance_play<J: Journal>( + table: &mut Table<J>, +) -> Result<(), BridgeError> { let current_player = match table.game().current_player() { Some(player) => player, None => { info!("Could not make play. Game: {:#?}", table.game()); - return Err(BridgeError::InvalidRequest(format!("No play to make for game"))); - }, + return Err(BridgeError::InvalidRequest(format!( + "No play to make for game" + ))); + } }; match table.game() { GameState::Bidding(bidding) => { - let player_view = BiddingStatePlayerView::from_bidding_state(bidding, current_player); + let player_view = BiddingStatePlayerView::from_bidding_state( + bidding, + current_player, + ); let bot = AlwaysPassBiddingBot {}; let bid = bot.bid(&player_view).await; table.bid(bid).await?; Ok(()) - }, + } GameState::Play(_) => todo!(), - GameState::PassedOut { dealer, deal, bidding } => todo!(), + GameState::PassedOut { + dealer, + deal, + bidding, + } => Err(BridgeError::InvalidRequest(format!("The game is over"))), } } @@ -185,13 +234,19 @@ mod test { payload: serde_json::Value, ) -> Result<(), BridgeError> { if seq != self.log.len() as i64 { - return Err(BridgeError::UpdateConflict(self.log.len() as i64, seq)); + return Err(BridgeError::UpdateConflict( + self.log.len() as i64, + seq, + )); } self.log.push(Some(payload)); Ok(()) } - async fn replay(&mut self, seq: i64) -> Result<Vec<serde_json::Value>, BridgeError> { + async fn replay( + &mut self, + seq: i64, + ) -> Result<Vec<serde_json::Value>, BridgeError> { Ok(self.log[seq as usize..] .into_iter() .filter_map(|e| e.clone()) @@ -218,7 +273,8 @@ mod test { #[tokio::test] async fn test_new_table() { - let t1: Table<TestJournal> = Table::new(Default::default()).await.unwrap(); + let t1: Table<TestJournal> = + Table::new(Default::default()).await.unwrap(); match t1.game { GameState::Bidding { .. } => (), _ => panic!("should be Bidding"), @@ -227,7 +283,8 @@ mod test { #[tokio::test] async fn test_replay_table() { - let t1: Table<TestJournal> = Table::new(Default::default()).await.unwrap(); + let t1: Table<TestJournal> = + Table::new(Default::default()).await.unwrap(); let game = t1.game; let journal = t1.journal; @@ -237,7 +294,8 @@ mod test { #[tokio::test] async fn test_advance_play() { - let mut t1: Table<TestJournal> = Table::new(Default::default()).await.unwrap(); + let mut t1: Table<TestJournal> = + Table::new(Default::default()).await.unwrap(); let player = t1.game().current_player(); advance_play(&mut t1).await.unwrap(); assert_ne!(player, t1.game().current_player()); |