subtr_actor/stats/analysis_graph/
collector.rs1use super::graph::AnalysisGraph;
2use crate::stats::calculators::{FrameInput, ReplayFrameInputBuilder};
3use crate::*;
4
5pub struct AnalysisNodeCollector {
6 graph: AnalysisGraph,
7 frame_input_builder: ReplayFrameInputBuilder,
8 last_sample_time: Option<f32>,
9 last_replay_meta_player_count: Option<usize>,
10}
11
12impl AnalysisNodeCollector {
13 pub fn new(mut graph: AnalysisGraph) -> Self {
14 graph.register_input_state::<FrameInput>();
15 Self {
16 graph,
17 frame_input_builder: ReplayFrameInputBuilder::default(),
18 last_sample_time: None,
19 last_replay_meta_player_count: None,
20 }
21 }
22
23 pub fn graph(&self) -> &AnalysisGraph {
24 &self.graph
25 }
26
27 pub fn graph_mut(&mut self) -> &mut AnalysisGraph {
28 &mut self.graph
29 }
30
31 pub fn into_graph(self) -> AnalysisGraph {
32 self.graph
33 }
34}
35
36impl Collector for AnalysisNodeCollector {
37 fn process_frame(
38 &mut self,
39 processor: &dyn ProcessorView,
40 _frame: &boxcars::Frame,
41 frame_number: usize,
42 current_time: f32,
43 ) -> SubtrActorResult<TimeAdvance> {
44 let player_count = processor.player_count();
45 if self.last_replay_meta_player_count != Some(player_count) {
46 self.graph.on_replay_meta(&processor.get_replay_meta()?)?;
47 self.last_replay_meta_player_count = Some(player_count);
48 }
49
50 let dt = self
51 .last_sample_time
52 .map(|last_time| (current_time - last_time).max(0.0))
53 .unwrap_or(0.0);
54 let frame_input =
55 self.frame_input_builder
56 .aggregate(processor, frame_number, current_time, dt);
57 self.graph.evaluate_with_state(&frame_input)?;
58 self.last_sample_time = Some(current_time);
59
60 Ok(TimeAdvance::NextFrame)
61 }
62
63 fn finish_replay(&mut self, _processor: &dyn ProcessorView) -> SubtrActorResult<()> {
64 self.graph.finish()
65 }
66}