subtr_actor/stats/analysis_graph/nodes/
continuous_ball_control.rs1use super::*;
2use crate::stats::calculators::*;
3use crate::*;
4
5pub struct ContinuousBallControlNode {
7 tracker: ContinuousBallControlTracker<BallCarryKind>,
8 state: ContinuousBallControlState,
9}
10
11impl ContinuousBallControlNode {
12 pub fn new() -> Self {
13 Self {
14 tracker: ContinuousBallControlTracker::default(),
15 state: ContinuousBallControlState::default(),
16 }
17 }
18}
19
20impl Default for ContinuousBallControlNode {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl AnalysisNode for ContinuousBallControlNode {
27 type State = ContinuousBallControlState;
28
29 fn name(&self) -> &'static str {
30 "continuous_ball_control"
31 }
32
33 fn dependencies(&self) -> Vec<AnalysisDependency> {
34 vec![
35 frame_info_dependency(),
36 ball_frame_state_dependency(),
37 player_frame_state_dependency(),
38 touch_state_dependency(),
39 live_play_dependency(),
40 ]
41 }
42
43 fn evaluate(&mut self, ctx: &AnalysisStateContext<'_>) -> SubtrActorResult<()> {
44 let frame = ctx.get::<FrameInfo>()?;
45 let touch_state = ctx.get::<TouchState>()?;
46 let players = ctx.get::<PlayerFrameState>()?;
47 let candidate = if frame.dt > 0.0 {
48 BallCarryCalculator::control_candidate(
49 ctx.get::<BallFrameState>()?,
50 players,
51 ctx.get::<LivePlayState>()?,
52 touch_state,
53 )
54 } else {
55 None
56 };
57 let player_statuses = BallCarryCalculator::control_player_statuses(players);
58 let touches = BallCarryCalculator::control_touches(touch_state, players);
59 self.state.completed_sequences.extend(self.tracker.update(
60 frame,
61 candidate,
62 &player_statuses,
63 &touches,
64 BallCarryCalculator::min_duration_for_kind,
65 BallCarryCalculator::kind_requires_airborne,
66 ));
67 Ok(())
68 }
69
70 fn finish(&mut self, _ctx: &AnalysisStateContext<'_>) -> SubtrActorResult<()> {
71 if let Some(sequence) = self
72 .tracker
73 .finish(BallCarryCalculator::min_duration_for_kind)
74 {
75 self.state.completed_sequences.push(sequence);
76 }
77 Ok(())
78 }
79
80 fn state(&self) -> &Self::State {
81 &self.state
82 }
83}
84
85pub(crate) fn boxed_default() -> Box<dyn AnalysisNodeDyn> {
86 Box::new(ContinuousBallControlNode::new())
87}