From 589dbd55d008d0de26b19505986f34cfa01ec9d2 Mon Sep 17 00:00:00 2001 From: Cutieguwu Date: Fri, 4 Apr 2025 18:50:57 -0400 Subject: [PATCH] Implemented delta-ing methods w/ unit tests. --- gamelog/src/event.rs | 75 +++++++++++++++++++++++++++++++++++++++++-- gamelog/src/game.rs | 8 +++++ gamelog/src/period.rs | 65 +++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 2 deletions(-) diff --git a/gamelog/src/event.rs b/gamelog/src/event.rs index 706399a..e2d8fa0 100644 --- a/gamelog/src/event.rs +++ b/gamelog/src/event.rs @@ -57,13 +57,14 @@ impl Event { unreachable!() }; - Some((a - b) as i8) + Some(a as i8 - b as i8) } } } -#[derive(Debug, Deserialize, Clone, PartialEq)] +#[derive(Debug, Deserialize, Clone, PartialEq, Default)] pub enum ScorePoints { + #[default] Touchdown, FieldGoal, Safety, @@ -86,3 +87,73 @@ impl ScorePoints { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Action, Down, Team, TerrainState}; + + #[test] + fn delta() { + let kickoff = Event::Kickoff(Team::Nebraska); + let first_down = Event::Play(Play { + action: Action::Unknown, + down: Some(Down::First), + terrain: Some(TerrainState::Yards(10)), + }); + let second_down = Event::Play(Play { + action: Action::Unknown, + down: Some(Down::Second), + terrain: Some(TerrainState::Yards(10)), + }); + let third_down = Event::Play(Play { + action: Action::Unknown, + down: Some(Down::Third), + terrain: Some(TerrainState::Yards(13)), + }); + let fourth_down = Event::Play(Play { + action: Action::Unknown, + down: Some(Down::Fourth), + terrain: Some(TerrainState::Yards(5)), + }); + let penalty = Event::Penalty(TerrainState::Yards(15)); + let turnover = Event::Turnover(Team::Nebraska); + let noned_down = Event::Play(Play { + action: Action::Unknown, + down: None, + terrain: None, + }); + let score = Event::Score(ScorePoints::default()); + let goal_line = Event::Play(Play { + action: Action::Unknown, + down: Some(Down::First), + terrain: Some(TerrainState::GoalLine), + }); + let inches = Event::Play(Play { + action: Action::Unknown, + down: Some(Down::First), + terrain: Some(TerrainState::Inches), + }); + + assert!(10_i8 == kickoff.delta(&first_down).unwrap()); + assert!(0_i8 == first_down.delta(&second_down).unwrap()); + assert!(-3_i8 == second_down.delta(&third_down).unwrap()); + assert!(10_i8 == first_down.delta(&kickoff).unwrap()); + assert!(10_i8 == first_down.delta(&goal_line).unwrap()); + assert!(10_i8 == first_down.delta(&inches).unwrap()); + assert!(13_i8 == third_down.delta(&kickoff).unwrap()); + assert!(8_i8 == third_down.delta(&fourth_down).unwrap()); + assert!(13_i8 == third_down.delta(&goal_line).unwrap()); + assert!(None == fourth_down.delta(&turnover)); + assert!(None == kickoff.delta(&penalty)); + assert!(None == first_down.delta(&penalty)); + assert!(None == noned_down.delta(&kickoff)); + assert!(None == noned_down.delta(&turnover)); + assert!(None == kickoff.delta(&score)); + assert!(None == first_down.delta(&score)); + assert!(None == turnover.delta(&score)); + assert!(None == goal_line.delta(&first_down)); + assert!(None == inches.delta(&first_down)); + assert!(None == goal_line.delta(&inches)); + } +} diff --git a/gamelog/src/game.rs b/gamelog/src/game.rs index be625a5..d99ccd8 100644 --- a/gamelog/src/game.rs +++ b/gamelog/src/game.rs @@ -32,6 +32,14 @@ impl Game { Err(error::TeamsError::NumberFound(teams.len())) } } + + pub fn deltas(&self) -> Vec { + self.periods + .iter() + .map(|period| period.deltas()) + .collect::>>() + .concat() + } } impl PlayHandle for Game { diff --git a/gamelog/src/period.rs b/gamelog/src/period.rs index 3099b84..5412afd 100644 --- a/gamelog/src/period.rs +++ b/gamelog/src/period.rs @@ -23,6 +23,24 @@ impl PlayHandle for Period { } } +impl Period { + pub fn deltas(&self) -> Vec { + let len = self.events.len() - 1; + let mut idx: usize = 0; + let mut deltas: Vec = vec![]; + + while idx < len { + if let Some(value) = self.events[idx].delta(&self.events[idx + 1]) { + deltas.push(value); + } + + idx += 1 + } + + deltas + } +} + #[derive(Debug, Deserialize, Clone, PartialEq)] pub enum Quarter { First, @@ -31,3 +49,50 @@ pub enum Quarter { Fourth, Overtime(u8), } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Action, Down, Team, TerrainState}; + + #[test] + fn deltas() { + let period = Period { + start: Quarter::First, + end: None, + events: vec![ + Event::Kickoff(Team::Nebraska), + Event::Play(Play { + action: Action::Unknown, + down: Some(Down::First), + terrain: Some(TerrainState::Yards(10)), + }), + Event::Play(Play { + action: Action::Unknown, + down: Some(Down::Second), + terrain: Some(TerrainState::Yards(13)), + }), + Event::Play(Play { + action: Action::Unknown, + down: Some(Down::Third), + terrain: Some(TerrainState::Yards(8)), + }), + Event::Turnover(Team::Nebraska), + Event::Play(Play { + action: Action::Unknown, + down: Some(Down::First), + terrain: Some(TerrainState::Yards(10)), + }), + Event::Play(Play { + action: Action::Unknown, + down: Some(Down::First), + terrain: Some(TerrainState::Yards(10)), + }), + ], + }; + + let expected: Vec = vec![10, -3, 5, 10]; + + assert!(period.deltas() == expected) + } +}