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

@@ -0,0 +1,52 @@
use std::collections::HashMap;
#[derive(Debug, PartialEq)]
pub struct Output {
pub players: HashMap<csdemo::UserId, csdemo::parser::Player>,
pub head_to_head: HashMap<csdemo::UserId, HashMap<csdemo::UserId, usize>>,
}
pub fn parse(buf: &[u8]) -> Result<Output, ()> {
let tmp = csdemo::Container::parse(buf).map_err(|e| ())?;
let output = csdemo::lazyparser::LazyParser::new(tmp);
let players = output.player_info();
let mut head_to_head = HashMap::new();
for event in output.events().filter_map(|e| e.ok()) {
let event = match event {
csdemo::DemoEvent::GameEvent(ge) => *ge,
_ => continue,
};
match event {
csdemo::game_event::GameEvent::PlayerDeath(death) => {
let (attacker_player, attacker) = match death.attacker.and_then(|u| players.get(&u).zip(Some(u))) {
Some(a) => a,
None => continue,
};
let (died_player, died) = match death.userid.and_then(|u| players.get(&u).zip(Some(u))) {
Some(d) => d,
None => continue,
};
if attacker_player.team == died_player.team {
continue;
}
let attacker_entry: &mut HashMap<_, _> = head_to_head.entry(attacker).or_default();
let died_killed: &mut usize = attacker_entry.entry(died).or_default();
*died_killed += 1;
}
_ => {}
};
}
Ok(Output {
players,
head_to_head,
})
}

View File

@@ -1,3 +1,4 @@
pub mod endofgame;
pub mod heatmap;
pub mod perround;
pub mod head_to_head;

View File

@@ -0,0 +1,40 @@
use analysis::head_to_head;
use pretty_assertions::assert_eq;
use std::collections::HashMap;
#[test]
#[ignore = "Testing"]
fn head_to_head_nuke() {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/../testfiles/nuke.dem");
dbg!(path);
let input_bytes = std::fs::read(path).unwrap();
let result = head_to_head::parse(&input_bytes).unwrap();
let expected = head_to_head::Output {
players: [(csdemo::UserId(0), csdemo::parser::Player {
xuid: 0,
name: "".to_owned(),
team: 0,
color: 0,
})].into_iter().collect(),
head_to_head: [
(csdemo::UserId(0), HashMap::new()),
(csdemo::UserId(1), HashMap::new()),
(csdemo::UserId(2), HashMap::new()),
(csdemo::UserId(3), HashMap::new()),
(csdemo::UserId(4), HashMap::new()),
(csdemo::UserId(5), HashMap::new()),
(csdemo::UserId(6), HashMap::new()),
(csdemo::UserId(7), HashMap::new()),
(csdemo::UserId(8), HashMap::new()),
(csdemo::UserId(9), HashMap::new()),
].into_iter().collect(),
};
dbg!(&expected, &result);
assert_eq!(result, expected);
todo!()
}