subtr_actor/stats/accumulators/
double_tap.rs1use super::*;
2
3#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, ts_rs::TS)]
5#[ts(export)]
6pub struct DoubleTapPlayerStats {
7 pub count: u32,
8 pub is_last_double_tap: bool,
9 pub last_double_tap_time: Option<f32>,
10 pub last_double_tap_frame: Option<usize>,
11 pub time_since_last_double_tap: Option<f32>,
12 pub frames_since_last_double_tap: Option<usize>,
13}
14
15#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, ts_rs::TS)]
17#[ts(export)]
18pub struct DoubleTapTeamStats {
19 pub count: u32,
20}
21
22#[derive(Debug, Clone, Default, PartialEq)]
24pub struct DoubleTapStatsAccumulator {
25 player_stats: HashMap<PlayerId, DoubleTapPlayerStats>,
26 team_zero_stats: DoubleTapTeamStats,
27 team_one_stats: DoubleTapTeamStats,
28 current_last_double_tap_player: Option<PlayerId>,
29}
30
31impl DoubleTapStatsAccumulator {
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 pub fn player_stats(&self) -> &HashMap<PlayerId, DoubleTapPlayerStats> {
37 &self.player_stats
38 }
39
40 pub fn team_zero_stats(&self) -> &DoubleTapTeamStats {
41 &self.team_zero_stats
42 }
43
44 pub fn team_one_stats(&self) -> &DoubleTapTeamStats {
45 &self.team_one_stats
46 }
47
48 pub fn begin_sample(&mut self, frame: &FrameInfo) {
49 for stats in self.player_stats.values_mut() {
50 stats.is_last_double_tap = false;
51 stats.time_since_last_double_tap = stats
52 .last_double_tap_time
53 .map(|time| (frame.time - time).max(0.0));
54 stats.frames_since_last_double_tap = stats
55 .last_double_tap_frame
56 .map(|last_frame| frame.frame_number.saturating_sub(last_frame));
57 }
58 }
59
60 pub fn apply_event(&mut self, frame: &FrameInfo, event: &DoubleTapEvent) {
61 let stats = self.player_stats.entry(event.player.clone()).or_default();
62 stats.count += 1;
63 stats.last_double_tap_time = Some(event.time);
64 stats.last_double_tap_frame = Some(event.frame);
65 stats.time_since_last_double_tap = Some((frame.time - event.time).max(0.0));
66 stats.frames_since_last_double_tap = Some(frame.frame_number.saturating_sub(event.frame));
67
68 let team_stats = if event.is_team_0 {
69 &mut self.team_zero_stats
70 } else {
71 &mut self.team_one_stats
72 };
73 team_stats.count += 1;
74 self.current_last_double_tap_player = Some(event.player.clone());
75 }
76
77 pub fn finish_sample(&mut self) {
78 if let Some(player_id) = self.current_last_double_tap_player.as_ref() {
79 if let Some(stats) = self.player_stats.get_mut(player_id) {
80 stats.is_last_double_tap = true;
81 }
82 }
83 }
84}