subtr-actor 0.8.10

Rocket League replay transformer
Documentation
use super::*;
use crate::stats::calculators::*;
use crate::*;

pub struct ContinuousBallControlNode {
    tracker: ContinuousBallControlTracker<BallCarryKind>,
    state: ContinuousBallControlState,
}

impl ContinuousBallControlNode {
    pub fn new() -> Self {
        Self {
            tracker: ContinuousBallControlTracker::default(),
            state: ContinuousBallControlState::default(),
        }
    }
}

impl Default for ContinuousBallControlNode {
    fn default() -> Self {
        Self::new()
    }
}

impl AnalysisNode for ContinuousBallControlNode {
    type State = ContinuousBallControlState;

    fn name(&self) -> &'static str {
        "continuous_ball_control"
    }

    fn dependencies(&self) -> Vec<AnalysisDependency> {
        vec![
            frame_info_dependency(),
            ball_frame_state_dependency(),
            player_frame_state_dependency(),
            touch_state_dependency(),
            live_play_dependency(),
        ]
    }

    fn evaluate(&mut self, ctx: &AnalysisStateContext<'_>) -> SubtrActorResult<()> {
        let frame = ctx.get::<FrameInfo>()?;
        let touch_state = ctx.get::<TouchState>()?;
        let players = ctx.get::<PlayerFrameState>()?;
        let candidate = if frame.dt > 0.0 {
            BallCarryCalculator::control_candidate(
                ctx.get::<BallFrameState>()?,
                players,
                ctx.get::<LivePlayState>()?.is_live_play,
                touch_state,
            )
        } else {
            None
        };
        let player_statuses = BallCarryCalculator::control_player_statuses(players);
        let touches = BallCarryCalculator::control_touches(touch_state, players);
        self.state.completed_sequences.extend(self.tracker.update(
            frame,
            candidate,
            &player_statuses,
            &touches,
            BallCarryCalculator::min_duration_for_kind,
            BallCarryCalculator::kind_requires_airborne,
        ));
        Ok(())
    }

    fn finish(&mut self, _ctx: &AnalysisStateContext<'_>) -> SubtrActorResult<()> {
        if let Some(sequence) = self
            .tracker
            .finish(BallCarryCalculator::min_duration_for_kind)
        {
            self.state.completed_sequences.push(sequence);
        }
        Ok(())
    }

    fn state(&self) -> &Self::State {
        &self.state
    }
}

pub(crate) fn boxed_default() -> Box<dyn AnalysisNodeDyn> {
    Box::new(ContinuousBallControlNode::new())
}