diff --git a/analysis/src/perround.rs b/analysis/src/perround.rs index fedabd8..562e5ef 100644 --- a/analysis/src/perround.rs +++ b/analysis/src/perround.rs @@ -60,7 +60,16 @@ pub struct Round { pub enum RoundEvent { BombPlanted, BombDefused, - Kill { attacker: u64, died: u64 }, + Kill { + attacker: u64, + died: u64, + #[serde(default)] + weapon: Option, + #[serde(default)] + headshot: bool, + #[serde(default)] + noscope: bool, + }, } #[derive(Debug)] @@ -138,7 +147,7 @@ pub fn parse(buf: &[u8]) -> Result { }; } - let event = match ge.as_ref() { + let event = match *ge { csdemo::game_event::GameEvent::BombPlanted(planted) => RoundEvent::BombPlanted, csdemo::game_event::GameEvent::BombDefused(defused) => RoundEvent::BombDefused, csdemo::game_event::GameEvent::PlayerDeath(death) => { @@ -157,6 +166,9 @@ pub fn parse(buf: &[u8]) -> Result { RoundEvent::Kill { attacker: attacker_player.xuid, died: died_player.xuid, + weapon: death.weapon, + noscope: death.noscope.unwrap_or(false), + headshot: death.headshot.unwrap_or(false), } } _ => continue, diff --git a/backend/src/analysis/perround.rs b/backend/src/analysis/perround.rs index c5e408f..39e8fbd 100644 --- a/backend/src/analysis/perround.rs +++ b/backend/src/analysis/perround.rs @@ -47,7 +47,16 @@ impl Analysis for PerRoundAnalysis { Box::pin(async move { let query = diesel::dsl::insert_into(crate::schema::demo_round::dsl::demo_round) .values(&values) - .on_conflict_do_nothing(); + .on_conflict(( + crate::schema::demo_round::dsl::demo_id, + crate::schema::demo_round::dsl::round_number, + )) + .do_update() + .set( + crate::schema::demo_round::dsl::events.eq(diesel::upsert::excluded( + crate::schema::demo_round::dsl::events, + )), + ); query.execute(connection).await?; diff --git a/backend/src/api/demos.rs b/backend/src/api/demos.rs index 9e247d7..dfd2ced 100644 --- a/backend/src/api/demos.rs +++ b/backend/src/api/demos.rs @@ -505,7 +505,13 @@ async fn perround( analysis::perround::RoundEvent::BombDefused => { common::demo_analysis::RoundEvent::BombDefused } - analysis::perround::RoundEvent::Kill { attacker, died } => { + analysis::perround::RoundEvent::Kill { + attacker, + died, + weapon, + noscope, + headshot, + } => { let attacker_name = players .iter() .find(|p| p.steam_id == attacker.to_string()) @@ -520,6 +526,9 @@ async fn perround( common::demo_analysis::RoundEvent::Killed { attacker: attacker_name, died: died_name, + weapon, + headshot, + noscope, } } }) diff --git a/common/src/demo_analysis.rs b/common/src/demo_analysis.rs index 8906471..cc57b1e 100644 --- a/common/src/demo_analysis.rs +++ b/common/src/demo_analysis.rs @@ -74,5 +74,11 @@ pub enum RoundWinReason { pub enum RoundEvent { BombPlanted, BombDefused, - Killed { attacker: String, died: String }, + Killed { + attacker: String, + died: String, + weapon: Option, + noscope: bool, + headshot: bool, + }, } diff --git a/frontend/src/demo.rs b/frontend/src/demo.rs index f99b701..71b04f3 100644 --- a/frontend/src/demo.rs +++ b/frontend/src/demo.rs @@ -42,13 +42,6 @@ pub fn demo() -> impl leptos::IntoView { None => String::new(), }; - let selected_tab = move || { - let loc = leptos_router::use_location(); - let loc_path = loc.pathname.get(); - let trailing = loc_path.split('/').last(); - trailing.unwrap_or("/").to_owned() - }; - let style = stylers::style! { "Demo", .analysis_bar { @@ -87,13 +80,27 @@ pub fn demo() -> impl leptos::IntoView { } #[leptos::component] -pub fn tab_bar

(prefix: P, parts: &'static [(&'static str, &'static str)]) -> impl leptos::IntoView where P: Fn() -> String + Copy + 'static { +pub fn tab_bar

( + prefix: P, + parts: &'static [(&'static str, &'static str)], +) -> impl leptos::IntoView +where + P: Fn() -> String + Copy + 'static, +{ let selected_tab = move || { let prefix = prefix(); let loc = leptos_router::use_location(); let loc_path = loc.pathname.get(); - let trailing = loc_path.strip_prefix(&prefix).unwrap_or(&loc_path).split('/').filter(|l| !l.is_empty()).next(); - trailing.or(parts.first().map(|p| p.0)).unwrap_or("").to_owned() + let trailing = loc_path + .strip_prefix(&prefix) + .unwrap_or(&loc_path) + .split('/') + .filter(|l| !l.is_empty()) + .next(); + trailing + .or(parts.first().map(|p| p.0)) + .unwrap_or("") + .to_owned() }; let style = stylers::style! { @@ -122,7 +129,8 @@ pub fn tab_bar

(prefix: P, parts: &'static [(&'static str, &'static str)]) -> } }; - let tabs = move || parts.into_iter().map(|(routename, name)| { + let tabs = move || { + parts.into_iter().map(|(routename, name)| { view! {class=style,

} - }).collect::>(); + }).collect::>() + }; view! {class = style,
diff --git a/frontend/src/demo/perround.rs b/frontend/src/demo/perround.rs index b3ab22c..d82d842 100644 --- a/frontend/src/demo/perround.rs +++ b/frontend/src/demo/perround.rs @@ -79,24 +79,33 @@ pub fn per_round() -> impl leptos::IntoView { match (current_round, teams) { (Some(round), Some(teams)) => { - round.events.iter().map(|event| { + round.events.into_iter().map(|event| { match event { common::demo_analysis::RoundEvent::BombPlanted => view! {
  • Bomb has been planted
  • }.into_view(), common::demo_analysis::RoundEvent::BombDefused => view! {
  • Bomb has been defused
  • }.into_view(), - common::demo_analysis::RoundEvent::Killed { attacker, died } => { - let mut attacker_t = teams.iter().find(|t| t.players.contains(attacker)).map(|t| t.name == "TERRORIST").unwrap_or(false); - let mut died_t = teams.iter().find(|t| t.players.contains(died)).map(|t| t.name == "TERRORIST").unwrap_or(false); + common::demo_analysis::RoundEvent::Killed { attacker, died, weapon, headshot, noscope } => { + let mut attacker_t = teams.iter().find(|t| t.players.contains(&attacker)).map(|t| t.name == "TERRORIST").unwrap_or(false); + let mut died_t = teams.iter().find(|t| t.players.contains(&died)).map(|t| t.name == "TERRORIST").unwrap_or(false); if (12..27).contains(&round_index) { attacker_t = !attacker_t; died_t = !died_t; } + let weapon_display = move || { + let parts = weapon.as_ref().into_iter().map(|w| w.as_str()) + .chain(headshot.then_some("Headshot").into_iter()) + .chain(noscope.then_some("Noscope").into_iter()); + + format!("(using {})", parts.collect::>().join(",")) + }; + view! { class=style, -
  • {"'"} - { attacker }{"'"} killed {"'"} - { died }{"'"} +
  • + {"'"}{ attacker }{"'"} + killed { weapon_display } + {"'"}{ died }{"'"}
  • }.into_view() }, diff --git a/frontend/src/main.rs b/frontend/src/main.rs index 093c858..765565c 100644 --- a/frontend/src/main.rs +++ b/frontend/src/main.rs @@ -22,7 +22,7 @@ fn main() { - + diff --git a/frontend/src/navbar.rs b/frontend/src/navbar.rs index e1698bd..401abdb 100644 --- a/frontend/src/navbar.rs +++ b/frontend/src/navbar.rs @@ -31,9 +31,7 @@ fn steam_login(height: &'static str, width: &'static str) -> impl leptos::IntoVi } }; - view! { - { tmp } - } + tmp } #[leptos::component]