use async_trait::async_trait; use protocol::{ bot::{BiddingBot, PlayingBot}, bridge_engine::{ BiddingStatePlayerView, GameState, PlayStatePlayerView, TableState, }, card::Card, simple_bots::{AlwaysPassBiddingBot, RandomPlayingBot}, actions::Bid, }; use rand::random; use crate::error::BridgeError; #[async_trait] pub trait Table { fn state(&self) -> &TableState; async fn bid( self: Box, bid: Bid, ) -> Result, BridgeError>; async fn play( self: Box, card: Card, ) -> Result, BridgeError>; async fn new_deal(self: Box) -> Result, 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, bid: Bid, ) -> Result, 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, card: Card, ) -> Result, 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) -> Result, BridgeError> { Ok(Box::new(Self { state: GameState::new(random(), random()).into(), })) } } pub async fn advance_play( table: Box, ) -> Result, 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, // }