summaryrefslogtreecommitdiff
path: root/server/src/table.rs
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2023-01-01 11:52:28 -0500
committerKjetil Orbekk <kj@orbekk.com>2023-01-01 11:52:28 -0500
commitbb2ed3a2926384df063e476d10613fa310cd7ffa (patch)
treecc9c6ea4979eef3850d78cd0b1390dfbccb5921b /server/src/table.rs
parent1e3014a777805d3dcb691ee6ebe59c62f58f8222 (diff)
Add Table to be used with db schema
Diffstat (limited to 'server/src/table.rs')
-rw-r--r--server/src/table.rs115
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,
+// }