summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjetil Orbekk <kj@orbekk.com>2022-11-16 09:10:41 -0500
committerKjetil Orbekk <kj@orbekk.com>2022-11-16 09:10:41 -0500
commit8fbf71b667d8b02777361adb7189939bd2d6fd02 (patch)
treefcadeede5218622d84aac467f1a692f4b106c3fd
parentb114fe7940e77090861ac9ba60f4d0b8caec8978 (diff)
Generate and display table in the webapp
-rw-r--r--server/src/error.rs3
-rw-r--r--server/src/main.rs12
-rw-r--r--server/src/play.rs15
-rw-r--r--webapp/src/components/table.rs27
4 files changed, 45 insertions, 12 deletions
diff --git a/server/src/error.rs b/server/src/error.rs
index 03735a7..6c2dc41 100644
--- a/server/src/error.rs
+++ b/server/src/error.rs
@@ -50,6 +50,9 @@ pub enum BridgeError {
#[error("Duration out of range")]
DurationOutOfRange(#[from] time::OutOfRangeError),
+ #[error("Not found: {0}")]
+ NotFound(String),
+
#[error("Sequence number mismatch: {0} ≠ {1}")]
UpdateConflict(i64, i64),
}
diff --git a/server/src/main.rs b/server/src/main.rs
index dd7956a..900d261 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -9,7 +9,7 @@ use axum::{
routing::{delete, get, post},
Json, Router,
};
-use protocol::{Table, UserInfo};
+use protocol::{Table, UserInfo, bridge_engine};
use server::ContextExtension;
use tower_cookies::{Cookie, CookieManagerLayer, Cookies};
use tower_http::trace::TraceLayer;
@@ -82,11 +82,15 @@ async fn main() {
async fn get_table_view(
_session: AuthenticatedSession,
- _extension: ContextExtension,
+ extension: ContextExtension,
Path(id): Path<Uuid>
-) -> Result<Json<protocol::TableView>, BridgeError> {
+) -> Result<Json<protocol::bridge_engine::GameState>, BridgeError> {
info!("Getting table state for table {id:}");
- Ok(Json(protocol::TableView { m: format!("hello") }))
+ let jnl = DbJournal::new(extension.db.clone(), id);
+ let table = play::Table::new_or_replay(jnl).await?;
+ let response: Json<bridge_engine::GameState> = Json(table.game().clone());
+ info!("Response: {response:#?}");
+ Ok(response)
}
async fn leave_table(
diff --git a/server/src/play.rs b/server/src/play.rs
index 2632b24..01f4847 100644
--- a/server/src/play.rs
+++ b/server/src/play.rs
@@ -76,6 +76,10 @@ where
}
impl<J: Journal> Table<J> {
+ pub fn game(&self) -> &GameState { &self.game }
+}
+
+impl<J: Journal> Table<J> {
pub async fn new(mut journal: J) -> Result<Self, BridgeError> {
let game = GameState::Bidding {
dealer: Player::East,
@@ -88,7 +92,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::Internal(format!("empty journal")));
+ return Err(BridgeError::NotFound("table journal missing".to_string()));
+ }
+ let game = serde_json::from_value(games[games.len() - 1].clone())?;
+ Ok(Table { journal, game } )
+ }
+
+ pub async fn new_or_replay(mut journal: J) -> Result<Self, BridgeError> {
+ let games = journal.replay(0).await?;
+ if games.is_empty() {
+ return Self::new(journal).await;
}
let game = serde_json::from_value(games[games.len() - 1].clone())?;
Ok(Table { journal, game } )
diff --git a/webapp/src/components/table.rs b/webapp/src/components/table.rs
index bccbfe4..3561131 100644
--- a/webapp/src/components/table.rs
+++ b/webapp/src/components/table.rs
@@ -1,3 +1,4 @@
+use gloo_net::http::Request;
use log::info;
use yew::prelude::*;
@@ -7,15 +8,26 @@ use crate::use_app_context;
pub fn table(props: &TableProps) -> Html {
let ctx = use_app_context();
- // let table_state: UseStateHandle<Option<protocol::TableView>> = use_state(|| None);
+ let table_state: UseStateHandle<Option<String>> = use_state(|| None);
{
// TODO update this from server state
- // let table_state = table_state.clone();
- let ctx = ctx.clone();
- ctx.spawn_async(async move {
- info!("Getting table state");
- Err(anyhow::anyhow!("Not implemented yet"))
- });
+ let table_state = table_state.clone();
+ let props = props.clone();
+ let ctx = ctx.clone();
+ use_effect_with_deps(
+ move |_| {
+ ctx.spawn_async(async move {
+ let response = Request::get(&format!("/api/table/{}", props.table.id))
+ .send()
+ .await?;
+ let table: protocol::bridge_engine::GameState = response.json().await?;
+ table_state.set(Some(format!("{:#?}", table)));
+ Ok(())
+ });
+ || ()
+ },
+ (),
+ );
}
let leave_table = {
@@ -31,6 +43,7 @@ pub fn table(props: &TableProps) -> Html {
<button onclick={leave_table}>
{ "Leave table" }
</button>
+ <pre>{ table_state.as_ref().map_or("".to_string(), |t| format!("{}", t)) }</pre>
</>
}
}