subtr-actor 1.0.0

Rocket League replay transformer
Documentation
use super::*;

pub(crate) const RUSH_TEAM_LABELS: [StatLabel; 2] = [
    StatLabel::new("team", "team_zero"),
    StatLabel::new("team", "team_one"),
];
pub(crate) const RUSH_ATTACKER_LABELS: [StatLabel; 2] = [
    StatLabel::new("attackers", "2"),
    StatLabel::new("attackers", "3"),
];
pub(crate) const RUSH_DEFENDER_LABELS: [StatLabel; 3] = [
    StatLabel::new("defenders", "1"),
    StatLabel::new("defenders", "2"),
    StatLabel::new("defenders", "3"),
];

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct RushStats {
    pub team_zero_count: u32,
    pub team_zero_two_v_one_count: u32,
    pub team_zero_two_v_two_count: u32,
    pub team_zero_two_v_three_count: u32,
    pub team_zero_three_v_one_count: u32,
    pub team_zero_three_v_two_count: u32,
    pub team_zero_three_v_three_count: u32,
    pub team_one_count: u32,
    pub team_one_two_v_one_count: u32,
    pub team_one_two_v_two_count: u32,
    pub team_one_two_v_three_count: u32,
    pub team_one_three_v_one_count: u32,
    pub team_one_three_v_two_count: u32,
    pub team_one_three_v_three_count: u32,
    #[serde(default, skip_serializing_if = "LabeledCounts::is_empty")]
    pub labeled_rush_counts: LabeledCounts,
}

impl RushStats {
    pub(crate) fn record(&mut self, event: &RushEvent) {
        self.labeled_rush_counts.increment(event.labels());
        self.sync_legacy_counts();
    }

    pub fn rush_count_with_labels(&self, labels: &[StatLabel]) -> u32 {
        self.labeled_rush_counts.count_matching(labels)
    }

    pub fn complete_labeled_rush_counts(&self) -> LabeledCounts {
        LabeledCounts::complete_from_label_sets(
            &[
                &RUSH_TEAM_LABELS,
                &RUSH_ATTACKER_LABELS,
                &RUSH_DEFENDER_LABELS,
            ],
            &self.labeled_rush_counts,
        )
    }

    pub fn with_complete_labeled_rush_counts(mut self) -> Self {
        self.labeled_rush_counts = self.complete_labeled_rush_counts();
        self
    }

    fn team_count(&self, is_team_zero: bool) -> u32 {
        self.rush_count_with_labels(&[rush_team_label(is_team_zero)])
    }

    fn matchup_count(&self, is_team_zero: bool, attackers: usize, defenders: usize) -> u32 {
        self.rush_count_with_labels(&[
            rush_team_label(is_team_zero),
            rush_attackers_label(attackers),
            rush_defenders_label(defenders),
        ])
    }

    fn sync_legacy_counts(&mut self) {
        self.team_zero_count = self.team_count(true);
        self.team_zero_two_v_one_count = self.matchup_count(true, 2, 1);
        self.team_zero_two_v_two_count = self.matchup_count(true, 2, 2);
        self.team_zero_two_v_three_count = self.matchup_count(true, 2, 3);
        self.team_zero_three_v_one_count = self.matchup_count(true, 3, 1);
        self.team_zero_three_v_two_count = self.matchup_count(true, 3, 2);
        self.team_zero_three_v_three_count = self.matchup_count(true, 3, 3);
        self.team_one_count = self.team_count(false);
        self.team_one_two_v_one_count = self.matchup_count(false, 2, 1);
        self.team_one_two_v_two_count = self.matchup_count(false, 2, 2);
        self.team_one_two_v_three_count = self.matchup_count(false, 2, 3);
        self.team_one_three_v_one_count = self.matchup_count(false, 3, 1);
        self.team_one_three_v_two_count = self.matchup_count(false, 3, 2);
        self.team_one_three_v_three_count = self.matchup_count(false, 3, 3);
    }

    pub fn for_team(&self, is_team_zero: bool) -> RushTeamStats {
        if is_team_zero {
            RushTeamStats {
                count: self.team_zero_count,
                two_v_one_count: self.team_zero_two_v_one_count,
                two_v_two_count: self.team_zero_two_v_two_count,
                two_v_three_count: self.team_zero_two_v_three_count,
                three_v_one_count: self.team_zero_three_v_one_count,
                three_v_two_count: self.team_zero_three_v_two_count,
                three_v_three_count: self.team_zero_three_v_three_count,
            }
        } else {
            RushTeamStats {
                count: self.team_one_count,
                two_v_one_count: self.team_one_two_v_one_count,
                two_v_two_count: self.team_one_two_v_two_count,
                two_v_three_count: self.team_one_two_v_three_count,
                three_v_one_count: self.team_one_three_v_one_count,
                three_v_two_count: self.team_one_three_v_two_count,
                three_v_three_count: self.team_one_three_v_three_count,
            }
        }
    }
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize, ts_rs::TS)]
#[ts(export)]
pub struct RushTeamStats {
    pub count: u32,
    pub two_v_one_count: u32,
    pub two_v_two_count: u32,
    pub two_v_three_count: u32,
    pub three_v_one_count: u32,
    pub three_v_two_count: u32,
    pub three_v_three_count: u32,
}

#[derive(Debug, Clone, Default, PartialEq)]
pub struct RushStatsAccumulator {
    stats: RushStats,
}

impl RushStatsAccumulator {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn stats(&self) -> &RushStats {
        &self.stats
    }

    pub fn apply_event(&mut self, event: &RushEvent) {
        self.stats.record(event);
    }
}