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:
52
analysis/src/head_to_head.rs
Normal file
52
analysis/src/head_to_head.rs
Normal 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,
|
||||
})
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod endofgame;
|
||||
pub mod heatmap;
|
||||
pub mod perround;
|
||||
pub mod head_to_head;
|
||||
|
||||
40
analysis/tests/head_to_head.rs
Normal file
40
analysis/tests/head_to_head.rs
Normal 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!()
|
||||
}
|
||||
Reference in New Issue
Block a user