Skip to main content

subtr_actor/stats/accumulators/
controlled_play.rs

1use super::*;
2
3/// Accumulated controlled-play stats: counts, times, and ball advance.
4#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, ts_rs::TS)]
5#[ts(export)]
6pub struct ControlledPlayStats {
7    pub count: u32,
8    pub total_time: f32,
9    pub longest_time: f32,
10    pub touch_count: u32,
11    pub total_advance_distance: f32,
12}
13
14impl ControlledPlayStats {
15    pub fn avg_time(&self) -> f32 {
16        if self.count == 0 {
17            0.0
18        } else {
19            self.total_time / self.count as f32
20        }
21    }
22}
23
24/// Accumulates controlled-play stats over the replay.
25#[derive(Debug, Clone, Default, PartialEq)]
26pub struct ControlledPlayStatsAccumulator {
27    player_stats: HashMap<PlayerId, ControlledPlayStats>,
28    team_zero_stats: ControlledPlayStats,
29    team_one_stats: ControlledPlayStats,
30}
31
32impl ControlledPlayStatsAccumulator {
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    pub fn player_stats(&self) -> &HashMap<PlayerId, ControlledPlayStats> {
38        &self.player_stats
39    }
40
41    pub fn team_zero_stats(&self) -> &ControlledPlayStats {
42        &self.team_zero_stats
43    }
44
45    pub fn team_one_stats(&self) -> &ControlledPlayStats {
46        &self.team_one_stats
47    }
48
49    pub fn apply_event(&mut self, event: &ControlledPlayEvent) {
50        Self::apply_event_to_stats(
51            self.player_stats
52                .entry(event.player_id.clone())
53                .or_default(),
54            event,
55        );
56        let team_stats = if event.is_team_0 {
57            &mut self.team_zero_stats
58        } else {
59            &mut self.team_one_stats
60        };
61        Self::apply_event_to_stats(team_stats, event);
62    }
63
64    fn apply_event_to_stats(stats: &mut ControlledPlayStats, event: &ControlledPlayEvent) {
65        stats.count += 1;
66        stats.total_time += event.duration;
67        stats.longest_time = stats.longest_time.max(event.duration);
68        stats.touch_count += event.touch_count;
69        stats.total_advance_distance += event.total_advance_distance;
70    }
71}