From 118a25aa9aa0710ec2a152d3544f48827d7708bc Mon Sep 17 00:00:00 2001 From: Lol3rrr Date: Tue, 17 Sep 2024 22:31:36 +0200 Subject: [PATCH] Add scoreboard with data to demo view --- backend/src/api/demos.rs | 42 ++++++++++++++++++++++ common/src/lib.rs | 15 ++++++++ frontend/src/demo.rs | 78 +++++++++++++++++++++++++++++++--------- 3 files changed, 119 insertions(+), 16 deletions(-) diff --git a/backend/src/api/demos.rs b/backend/src/api/demos.rs index a306432..5610a3c 100644 --- a/backend/src/api/demos.rs +++ b/backend/src/api/demos.rs @@ -22,6 +22,7 @@ where .layer(axum::extract::DefaultBodyLimit::max(500 * 1024 * 1024)), ) .route("/:id/info", axum::routing::get(info)) + .route("/:id/analysis/scoreboard", axum::routing::get(scoreboard)) .route("/:id/reanalyse", axum::routing::get(analyise)) .with_state(Arc::new(DemoState { upload_folder: upload_folder.into(), @@ -178,3 +179,44 @@ async fn info( map: result.map, })) } + +#[tracing::instrument(skip(session))] +async fn scoreboard(session: UserSession, Path(demo_id): Path) -> Result, axum::http::StatusCode> { + let query = crate::schema::demo_players::dsl::demo_players + .inner_join(crate::schema::demo_player_stats::dsl::demo_player_stats.on(crate::schema::demo_players::dsl::demo_id.eq(crate::schema::demo_player_stats::dsl::demo_id).and(crate::schema::demo_players::dsl::steam_id.eq(crate::schema::demo_player_stats::dsl::steam_id)))) + .filter(crate::schema::demo_players::dsl::demo_id.eq(demo_id)); + + let mut db_con = crate::db_connection().await; + + let response: Vec<(crate::models::DemoPlayer, crate::models::DemoPlayerStats)> = match query.load(&mut db_con).await { + Ok(d) => d, + Err(e) => { + tracing::error!("Querying DB: {:?}", e); + return Err(axum::http::StatusCode::INTERNAL_SERVER_ERROR); + } + }; + + if response.is_empty() { + tracing::error!("DB Response was empty"); + return Err(axum::http::StatusCode::INTERNAL_SERVER_ERROR); + } + + let team1_number: i16 = response.last().map(|(p, _)| p.team).unwrap(); + + let mut team1 = Vec::new(); + let mut team2 = Vec::new(); + for (player, stats) in response { + let team_vec = if player.team == team1_number { &mut team1 } else { &mut team2 }; + + team_vec.push(common::demo_analysis::ScoreBoardPlayer { + name: player.name, + kills: stats.kills as usize, + deaths: stats.deaths as usize, + }); + } + + Ok(axum::Json(common::demo_analysis::ScoreBoard { + team1, + team2, + })) +} diff --git a/common/src/lib.rs b/common/src/lib.rs index e38be11..b926088 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -15,3 +15,18 @@ pub struct DemoInfo { pub id: i64, pub map: String, } + +pub mod demo_analysis { + #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + pub struct ScoreBoard { + pub team1: Vec, + pub team2: Vec, + } + + #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + pub struct ScoreBoardPlayer { + pub name: String, + pub kills: usize, + pub deaths: usize, + } +} diff --git a/frontend/src/demo.rs b/frontend/src/demo.rs index 9487eeb..2f0fdbe 100644 --- a/frontend/src/demo.rs +++ b/frontend/src/demo.rs @@ -70,26 +70,72 @@ pub fn demo() -> impl leptos::IntoView { #[leptos::component] pub fn scoreboard() -> impl leptos::IntoView { + use leptos::Suspense; + + let scoreboard_resource = create_resource(leptos_router::use_params_map(), |params| async move { + let id = params.get("id").unwrap(); + + let res = reqwasm::http::Request::get(&format!("/api/demos/{}/analysis/scoreboard", id)) + .send() + .await + .unwrap(); + res.json::().await.unwrap() + }); + + let team_display_func = |team: &[common::demo_analysis::ScoreBoardPlayer]| { + team.iter().map(|player| { + view! { + + { player.name.clone() } + { player.kills } + { player.deaths } + + } + }).collect::>() + }; + view! {

Scoreboard

-
-

Team 1

- - - - -
Name
-
+ Loading Scoreboard data

} + > +
+

Team 1

+ + + + + + + { + move || { + scoreboard_resource.get().map(|s| { + let team = s.team1; + team_display_func(&team) + }) + } + } +
NameKillsDeaths
+
-
-

Team 2

- - - - -
Name
-
+
+

Team 2

+ + + + + { + move || { + scoreboard_resource.get().map(|s| { + let team = s.team2; + team_display_func(&team) + }) + } + } +
Name
+
+
} }