Add Head-to-Head kill stats

Add basic head-to-head kill analysis and the corresponding matrix display in the UI
This commit is contained in:
Lol3rrr
2024-11-05 07:50:43 +01:00
parent ecfed6b739
commit fa21804cc3
15 changed files with 350 additions and 12 deletions

View File

@@ -2,7 +2,7 @@ use leptos::*;
use leptos_router::Outlet;
pub mod general;
pub mod utility;
pub mod headtohead;
use crate::demo::TabBar;
@@ -12,7 +12,7 @@ pub fn scoreboard() -> impl leptos::IntoView {
let id = move || params.with(|params| params.get("id").cloned().unwrap_or_default());
view! {
<TabBar prefix=move || format!("/demo/{}/scoreboard", id()) parts=&[("general", "General"), ("utility", "Utility")] />
<TabBar prefix=move || format!("/demo/{}/scoreboard", id()) parts=&[("general", "General"), ("headtohead", "Head-to-Head")] />
<Outlet />
}

View File

@@ -0,0 +1,98 @@
use leptos::*;
use leptos::Suspense;
#[leptos::component]
pub fn head_to_head() -> impl leptos::IntoView {
let head_to_head_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/headtohead", id))
.send()
.await
.unwrap();
res.json::<common::demo_analysis::HeadToHead>()
.await
.unwrap()
});
let style = stylers::style! {
"Head-to-Head-root",
div {
display: grid;
}
};
let matrix_view = move || head_to_head_resource.get().map(|r| view! {
<Matrix data=r />
});
view! {
class=style,
<Suspense fallback=move || view! { <p>Loading Head-to-Head data...</p> }>
<div>
{ matrix_view }
</div>
</Suspense>
}
}
#[leptos::component]
fn matrix(data: common::demo_analysis::HeadToHead) -> impl leptos::IntoView {
let row_player_view = move || {
data.row_players.iter().enumerate().map(|(idx, name)| {
view! {
<span style=format!("grid-row: {}; grid-column: 1;", idx + 2)> {name} </span>
}
}).collect::<Vec<_>>()
};
let column_player_view = move || {
data.column_players.iter().enumerate().map(|(idx, name)| {
view! {
<span style=format!("grid-row: 1; grid-column: {}; text-align: right", idx + 2)> {name} </span>
}
}).collect::<Vec<_>>()
};
let style = stylers::style! {
"Head-to-Head-Matrix-Cell",
.cell {
display: grid;
}
.cell_back {
grid-row: 1/3;
grid-column: 1/3;
background-color: var(--color-surface-a0);
background-image: linear-gradient(to right top, var(--color-surface-a0) 50%, var(--color-surface-a10) 50%);
}
};
let entry_view = move || {
data.entries.iter().enumerate().flat_map(|(row, row_data)| {
row_data.iter().enumerate().map(move |(column, &(row_kills, column_kills))| {
let entry = move || view! {
<div style="grid-row: 2; grid-column: 1; text-align: center;">{ row_kills }</div>
<div style="grid-row: 1; grid-column: 2; text-align: center;">{ column_kills }</div>
};
view! {
class = style,
<div class="cell" style=format!("grid-row: {}; grid-column: {};", row + 2, column + 2)>
<div class="cell_back"></div>
{ entry }
</div>
}
})
}).collect::<Vec<_>>()
};
view! {
{ row_player_view }
{ column_player_view }
{ entry_view }
}
}

View File

@@ -1,8 +0,0 @@
use leptos::*;
#[leptos::component]
pub fn utility() -> impl leptos::IntoView {
view! {
Utility
}
}

View File

@@ -22,7 +22,7 @@ fn main() {
<Route path="/demo/:id" view=Demo>
<Route path="scoreboard" view=frontend::demo::scoreboard::Scoreboard>
<Route path="general" view=frontend::demo::scoreboard::general::General />
<Route path="utility" view=frontend::demo::scoreboard::utility::Utility />
<Route path="headtohead" view=frontend::demo::scoreboard::headtohead::HeadToHead />
<Route path="" view=frontend::demo::scoreboard::general::General />
</Route>
<Route path="perround" view=frontend::demo::perround::PerRound />