diff options
author | Kjetil Orbekk <kj@orbekk.com> | 2022-12-18 13:40:53 -0500 |
---|---|---|
committer | Kjetil Orbekk <kj@orbekk.com> | 2022-12-18 13:40:53 -0500 |
commit | 4512c5ead9406206de32e37490b7a4ac792d93bf (patch) | |
tree | d3905c1e951b834f674f9c4c868e9dabe1fd0587 /server | |
parent | 3746208a1fbc71d104fc04bd50a54921ac8eca90 (diff) |
Add bidding API
Diffstat (limited to 'server')
-rw-r--r-- | server/src/main.rs | 70 | ||||
-rw-r--r-- | server/src/play.rs | 2 |
2 files changed, 55 insertions, 17 deletions
diff --git a/server/src/main.rs b/server/src/main.rs index 68baab7..a8429ec 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -9,8 +9,8 @@ use axum::{ routing::{delete, get, post}, Json, Router, }; +use protocol::bridge_engine::{Bid, GameStatePlayerView, Player}; use protocol::{Table, UserInfo}; -use protocol::bridge_engine::{GameStatePlayerView, Player}; use server::ContextExtension; use tower_cookies::{Cookie, CookieManagerLayer, Cookies}; use tower_http::trace::TraceLayer; @@ -18,37 +18,46 @@ use tracing::{info, log::warn}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; mod auth; mod error; -mod play; -mod server; #[cfg(debug_assertions)] mod fake_auth; +mod play; +mod server; use crate::{ auth::{OauthAuthenticator, SessionId}, - server::ServerContext, play::advance_play, + play::advance_play, + server::ServerContext, }; use crate::{ error::BridgeError, play::{DbJournal, Journal}, }; -use sqlx::{postgres::PgPoolOptions, PgPool}; use auth::Authenticator; +use sqlx::{postgres::PgPoolOptions, PgPool}; -async fn create_default_authenticator(db_pool: &PgPool) -> Box<dyn Authenticator + Send + Sync> { +async fn create_default_authenticator( + db_pool: &PgPool, +) -> Box<dyn Authenticator + Send + Sync> { Box::new(OauthAuthenticator::from_env(db_pool.clone()).await) } #[cfg(debug_assertions)] -async fn create_authenticator(db_pool: &PgPool) -> Box<dyn Authenticator + Send + Sync> { +async fn create_authenticator( + db_pool: &PgPool, +) -> Box<dyn Authenticator + Send + Sync> { const FAKE_AUTHENTICATOR: &str = "fake"; - if std::env::var("AUTHENTICATOR").unwrap_or("".to_string()) == FAKE_AUTHENTICATOR { - Box::new(fake_auth::FakeAuthenticator::new()) + if std::env::var("AUTHENTICATOR").unwrap_or("".to_string()) + == FAKE_AUTHENTICATOR + { + Box::new(fake_auth::FakeAuthenticator::new()) } else { create_default_authenticator(db_pool).await } } #[cfg(not(debug_assertions))] -async fn create_authenticator(db_pool: &PgPool) -> Box<dyn Authenticator + Send + Sync> { +async fn create_authenticator( + db_pool: &PgPool, +) -> Box<dyn Authenticator + Send + Sync> { create_default_authenticator(db_pool) } @@ -96,14 +105,14 @@ async fn main() { let app = Router::new(); #[cfg(debug_assertions)] - let app = app - .route("/api/fake_login", get(fake_login)); + let app = app.route("/api/fake_login", get(fake_login)); let app = app .route("/api/user/info", get(user_info)) .route("/api/table", post(create_table)) .route("/api/table", delete(leave_table)) .route("/api/table/:id", get(get_table_view)) + .route("/api/table/:id/bid", post(post_bid)) // .route("/api/user/table", get(user_table)) .route("/api/login", get(login)) .route(auth::LOGIN_CALLBACK, get(login_callback)) @@ -119,7 +128,8 @@ async fn main() { #[cfg(debug_assertions)] async fn fake_login() -> Html<&'static str> { - Html(r#" + Html( + r#" <!DOCTYPE html> <html lang="en"> <body> @@ -129,7 +139,8 @@ async fn fake_login() -> Html<&'static str> { </ul> </body> </html> - "#) + "#, + ) } async fn get_table_view( @@ -145,12 +156,39 @@ async fn get_table_view( while table.game().current_player() != Some(player_position) { advance_play(&mut table).await?; } - let response = - Json(GameStatePlayerView::from_game_state(table.game(), player_position)); + let response = Json(GameStatePlayerView::from_game_state( + table.game(), + player_position, + )); info!("Response: {response:#?}"); Ok(response) } +async fn post_bid( + _session: AuthenticatedSession, + extension: ContextExtension, + Path(id): Path<Uuid>, + Json(bid): Json<Bid>, +) -> Result<Json<()>, BridgeError> { + info!("Getting table state for {id:}"); + let jnl = DbJournal::new(extension.db.clone(), id); + let mut table = play::Table::new_or_replay(jnl).await?; + if !table.game().is_bidding() { + return Err(BridgeError::InvalidRequest( + "Posting a bid requires that the game is in the bidding phase" + .to_string(), + )); + } + let player_position = Player::South; + if table.game().current_player() != Some(player_position) { + return Err(BridgeError::InvalidRequest(format!( + "It is not {player_position:?} to play" + ))); + } + table.bid(bid).await?; + Ok(Json(())) +} + async fn leave_table( session: AuthenticatedSession, extension: ContextExtension, diff --git a/server/src/play.rs b/server/src/play.rs index a6e78f2..e78a19e 100644 --- a/server/src/play.rs +++ b/server/src/play.rs @@ -115,7 +115,7 @@ impl<J: Journal> Table<J> { Ok(game) } - async fn bid(&mut self, bid: Bid) -> Result<(), BridgeError> { + 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.game = game; |