diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2023-01-01 11:52:28 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2023-01-01 11:52:28 -0500 |
commit | bb2ed3a2926384df063e476d10613fa310cd7ffa (patch) | |
tree | cc9c6ea4979eef3850d78cd0b1390dfbccb5921b /server/src/table.rs | |
parent | 1e3014a777805d3dcb691ee6ebe59c62f58f8222 (diff) |
Add Table to be used with db schema
Diffstat (limited to 'server/src/table.rs')
-rw-r--r-- | server/src/table.rs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/server/src/table.rs b/server/src/table.rs new file mode 100644 index 0000000..068fb24 --- /dev/null +++ b/server/src/table.rs @@ -0,0 +1,115 @@ +use async_trait::async_trait; +use protocol::{ + bot::{BiddingBot, PlayingBot}, + bridge_engine::{ + Bid, BiddingStatePlayerView, GameState, PlayStatePlayerView, TableState, + }, + card::Card, + simple_bots::{AlwaysPassBiddingBot, RandomPlayingBot}, +}; +use rand::random; + +use crate::error::BridgeError; + +#[async_trait] +pub trait Table { + fn state(&self) -> &TableState; + async fn bid( + self: Box<Self>, + bid: Bid, + ) -> Result<Box<dyn Table>, BridgeError>; + async fn play( + self: Box<Self>, + card: Card, + ) -> Result<Box<dyn Table>, BridgeError>; + async fn new_deal(self: Box<Self>) -> Result<Box<dyn Table>, BridgeError>; +} + +pub struct InMemoryTable { + pub state: TableState, +} + +impl InMemoryTable { + pub fn new() -> Self { + Self { + state: TableState::Unknown, + } + } +} + +#[async_trait] +impl Table for InMemoryTable { + fn state(&self) -> &TableState { + &self.state + } + + async fn bid( + self: Box<Self>, + bid: Bid, + ) -> Result<Box<dyn Table>, BridgeError> { + let game = match self.state { + TableState::Game(game) => game, + _ => { + return Err(BridgeError::InvalidRequest("no game".to_string())) + } + }; + let game = game.bid(bid)?; + Ok(Box::new(Self { state: game.into() })) + } + + async fn play( + self: Box<Self>, + card: Card, + ) -> Result<Box<dyn Table>, BridgeError> { + let game = match self.state { + TableState::Game(game) => game, + _ => { + return Err(BridgeError::InvalidRequest("no game".to_string())) + } + }; + let game = game.play(card)?; + Ok(Box::new(Self { state: game.into() })) + } + + async fn new_deal(self: Box<Self>) -> Result<Box<dyn Table>, BridgeError> { + Ok(Box::new(Self { + state: GameState::new(random(), random()).into(), + })) + } +} + +pub async fn advance_play( + table: Box<dyn Table>, +) -> Result<Box<dyn Table>, BridgeError> { + let game = match table.state() { + TableState::Game(game) => game, + _ => return Err(BridgeError::InvalidRequest("no game".to_string())), + }; + let table = match game { + GameState::Bidding(ref bidding) => { + let player_view = BiddingStatePlayerView::from_bidding_state( + &bidding, + game.current_player(), + ); + let bot = AlwaysPassBiddingBot {}; + let bid = bot.bid(&player_view).await; + table.bid(bid).await + } + GameState::Play(game) => { + let player_view = PlayStatePlayerView::from_play_state( + &game, + game.current_player(), + ); + let bot = RandomPlayingBot {}; + let card = bot.play(&player_view).await; + table.play(card).await + } + }; + table +} + +// pub struct DbTable +// { +// db: PgPool, +// pub state: TableState, +// } |