Bump tui branch to using Gamelog v0.7.1 #13

Closed
Cutieguwu wants to merge 3 commits from gamelog into tui
8 changed files with 1300 additions and 1411 deletions
Showing only changes of commit e4db3e3a20 - Show all commits

View File

@@ -4,13 +4,10 @@
[ [
Game( Game(
version: "0.6.0", version: "0.7.0",
flags: [Interval(2), IgnoreScore], flags: [Interval(2), IgnoreScore],
periods: [
Period(
start: First,
end: Second,
events: [ events: [
Quarter(First),
Kickoff(ArizonaState), Kickoff(ArizonaState),
Play( Play(
action: Unknown, action: Unknown,
@@ -47,6 +44,7 @@
down: Third, down: Third,
terrain: Yards(7), terrain: Yards(7),
), ),
Quarter(Second),
Play( Play(
action: HalfbackSweep, action: HalfbackSweep,
down: Fourth, down: Fourth,
@@ -83,12 +81,7 @@
down: First, down: First,
terrain: Yards(10), terrain: Yards(10),
), ),
] Quarter(Third),
),
Period(
start: Third,
end: None,
events: [
Kickoff(TexasAnM), Kickoff(TexasAnM),
Play( Play(
action: Unknown, // PA Comebacks or Curls? Original note: Spike Centre action: Unknown, // PA Comebacks or Curls? Original note: Spike Centre
@@ -132,12 +125,7 @@
down: Third, down: Third,
terrain: Yards(15), terrain: Yards(15),
), ),
] Quarter(Fourth),
),
Period(
start: Fourth,
end: None,
events: [
Play( Play(
action: PlayActionComebacks, // Original note: Dupe Spike Centre action: PlayActionComebacks, // Original note: Dupe Spike Centre
down: Fourth, down: Fourth,
@@ -186,16 +174,11 @@
Kickoff(ArizonaState), Kickoff(ArizonaState),
] ]
), ),
]
),
Game( Game(
version: "0.6.0", version: "0.7.0",
flags: [Interval(2), IgnoreScore], flags: [Interval(2), IgnoreScore],
periods: [
Period(
start: First,
end: None,
events: [ events: [
Quarter(First),
Kickoff(Syracuse), Kickoff(Syracuse),
Play( Play(
action: Unknown, action: Unknown,
@@ -227,12 +210,7 @@
down: First, down: First,
terrain: Yards(10), terrain: Yards(10),
), ),
] Quarter(Second),
),
Period(
start: Second,
end: None,
events: [
Play( Play(
action: Unknown, // Original note: PA Throw Centre action: Unknown, // Original note: PA Throw Centre
down: Second, down: Second,
@@ -284,12 +262,7 @@
down: Fourth, down: Fourth,
terrain: Unknown, terrain: Unknown,
), ),
] Quarter(Third),
),
Period(
start: Third,
end: None,
events: [
Kickoff(Colorado), Kickoff(Colorado),
Play( Play(
action: Unknown, // Original note: Throw Right action: Unknown, // Original note: Throw Right
@@ -311,12 +284,7 @@
down: Second, down: Second,
terrain: Yards(6), terrain: Yards(6),
), ),
] Quarter(Fourth),
),
Period(
start: Fourth,
end: None,
events: [
Play( Play(
action: CrackStudentBodyRightTackle, action: CrackStudentBodyRightTackle,
down: Third, down: Third,
@@ -340,16 +308,11 @@
), ),
] ]
), ),
]
),
Game( Game(
version: "0.6.0", version: "0.7.0",
flags: [Interval(2)], flags: [Interval(2)],
periods: [
Period(
start: First,
end: None,
events: [ events: [
Quarter(First),
Kickoff(Nebraska), Kickoff(Nebraska),
Play( Play(
action: Curls, action: Curls,
@@ -382,12 +345,7 @@
down: First, down: First,
terrain: Yards(10), terrain: Yards(10),
), ),
] Quarter(Second),
),
Period(
start: Second,
end: None,
events: [
Play( Play(
action: Unknown, // Original note: Throw Centre action: Unknown, // Original note: Throw Centre
down: First, down: First,
@@ -432,12 +390,7 @@
down: Second, down: Second,
terrain: Yards(10) terrain: Yards(10)
), ),
] Quarter(Third),
),
Period(
start: Third,
end: None,
events: [
Kickoff(SouthCarolina), Kickoff(SouthCarolina),
Play( Play(
action: Unknown, action: Unknown,
@@ -472,12 +425,7 @@
down: Third, down: Third,
terrain: Yards(3), terrain: Yards(3),
), ),
] Quarter(Fourth),
),
Period(
start: Fourth,
end: None,
events: [
Play( Play(
action: Unknown, // Original note: Throw Centre action: Unknown, // Original note: Throw Centre
down: Fourth, down: Fourth,
@@ -550,19 +498,14 @@
action: Unknown, action: Unknown,
down: Second, down: Second,
terrain: Yards(18), terrain: Yards(18),
)
]
), ),
] ]
), ),
Game( Game(
version: "0.6.0", version: "0.7.0",
flags: [Interval(2)], flags: [Interval(2)],
periods: [
Period(
start: First,
end: None,
events: [ events: [
Quarter(First),
Kickoff(Colorado), Kickoff(Colorado),
Play( Play(
action: Unknown, action: Unknown,
@@ -589,12 +532,7 @@
down: First, down: First,
terrain: Yards(10), terrain: Yards(10),
), ),
] Quarter(Second),
),
Period(
start: Second,
end: None,
events: [
Play( Play(
action: Unknown, // Original note: Pass Back, Dash action: Unknown, // Original note: Pass Back, Dash
down: Second, down: Second,
@@ -665,12 +603,7 @@
terrain: GoalLine, terrain: GoalLine,
), ),
Score(FieldGoal), Score(FieldGoal),
] Quarter(Third),
),
Period(
start: Third,
end: None,
events: [
Kickoff(Iowa), Kickoff(Iowa),
Play( Play(
action: Unknown, // HB? Original note: Run Back, Throw Centre, Run Centre action: Unknown, // HB? Original note: Run Back, Throw Centre, Run Centre
@@ -707,12 +640,7 @@
down: First, down: First,
terrain: Yards(10), terrain: Yards(10),
), ),
] Quarter(Fourth),
),
Period(
start: Fourth,
end: None,
events: [
Play( Play(
action: Unknown, // Original note: Throw Left, Run Left action: Unknown, // Original note: Throw Left, Run Left
down: Second, down: Second,
@@ -759,20 +687,14 @@
down: Third, down: Third,
terrain: Yards(15), terrain: Yards(15),
), ),
//Field Goal
Score(FieldGoal) Score(FieldGoal)
] ]
)
]
), ),
Game( Game(
version: "0.6.0", version: "0.7.0",
flags: [Interval(2)], flags: [Interval(2)],
periods: [
Period(
start: First,
end: None,
events: [ events: [
Quarter(First),
Kickoff(Nebraska), Kickoff(Nebraska),
Play( Play(
action: CrackStudentBodyRightTackle, action: CrackStudentBodyRightTackle,
@@ -798,13 +720,8 @@
action:SlotOut, action:SlotOut,
down:Second, down:Second,
terrain:Yards(1) terrain:Yards(1)
)
]
), ),
Period( Quarter(Second),
start:Second,
end:None,
events:[
Play( Play(
action:PlayActionComebacks, action:PlayActionComebacks,
down: First, down: First,
@@ -868,13 +785,8 @@
action:SlantBubble, action:SlantBubble,
down: First, down: First,
terrain: GoalLine, terrain: GoalLine,
)
]
), ),
Period( Quarter(Third),
start:Third,
end: Fourth,
events: [
Kickoff(Iowa), Kickoff(Iowa),
Play( Play(
action:Unknown, action:Unknown,
@@ -924,6 +836,7 @@
down: Second, down: Second,
terrain: GoalLine, terrain: GoalLine,
), ),
Quarter(Fourth),
Play( Play(
action: SpeedOption, action: SpeedOption,
down: Third, down: Third,
@@ -987,32 +900,22 @@
terrain: None terrain: None
) )
] ]
)
]
), ),
Game( Game(
// TexasAnM were opponents, but not recorded as // TexasAnM were opponents, but not recorded as
// they were not present; Miller played in place. // they were not present; Miller played in place.
version: "0.6.0", version: "0.7.0",
flags: [Interval(2), IgnoreTeam(TexasAnM)], flags: [Interval(2), IgnoreTeam(TexasAnM)],
periods: [
Period(
start: First,
end: None,
events: [ events: [
Quarter(First),
Turnover(SouthCarolina), Turnover(SouthCarolina),
Play( Play(
action: FleaFlicker, action: FleaFlicker,
down: None, down: None,
terrain: None terrain: None
), ),
Turnover(TexasAnM) Turnover(TexasAnM),
] Quarter(Second),
),
Period(
start: Second,
end: None,
events:[
Turnover(SouthCarolina), Turnover(SouthCarolina),
Play( Play(
action: SpeedOption, action: SpeedOption,
@@ -1025,13 +928,8 @@
terrain: None, terrain: None,
), ),
Turnover(TexasAnM), Turnover(TexasAnM),
Score(FieldGoal) Score(FieldGoal),
] Quarter(Third),
),
Period(
start: Third,
end: Fourth,
events: [
Kickoff(SouthCarolina), Kickoff(SouthCarolina),
Play( Play(
action: Unknown, // Rush action: Unknown, // Rush
@@ -1067,6 +965,7 @@
down: First, down: First,
terrain: Yards(10) terrain: Yards(10)
), ),
Quarter(Fourth),
Play( Play(
action: Unknown,//DoubleFlex Throw action: Unknown,//DoubleFlex Throw
down: Second, down: Second,
@@ -1104,6 +1003,4 @@
//Texas 17, SouthCarolina 0 //Texas 17, SouthCarolina 0
] ]
) )
]
)
] ]

2
gamelog/Cargo.lock generated
View File

@@ -19,7 +19,7 @@ dependencies = [
[[package]] [[package]]
name = "gamelog" name = "gamelog"
version = "0.6.0" version = "0.7.0"
dependencies = [ dependencies = [
"ron", "ron",
"semver", "semver",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "gamelog" name = "gamelog"
version = "0.6.0" version = "0.7.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]

View File

@@ -1,4 +1,4 @@
use crate::{Down, Play, TerrainState, error}; use crate::{Down, Play, Quarter, TerrainState, error};
use serde::Deserialize; use serde::Deserialize;
type Offence = Team; type Offence = Team;
@@ -10,6 +10,7 @@ pub enum Event {
Turnover(Offence), Turnover(Offence),
Penalty(TerrainState), Penalty(TerrainState),
Score(ScorePoints), Score(ScorePoints),
Quarter(Quarter),
} }
impl Event { impl Event {
@@ -74,6 +75,14 @@ impl Event {
_ => Err(error::NoTeamAttribute), _ => Err(error::NoTeamAttribute),
} }
} }
pub fn quarter(&self) -> Option<Quarter> {
if let Event::Quarter(quarter) = self {
Some(quarter.to_owned())
} else {
None
}
}
} }
#[derive(Debug, Deserialize, Clone, PartialEq)] #[derive(Debug, Deserialize, Clone, PartialEq)]
@@ -171,6 +180,20 @@ mod tests {
terrain: Some(TerrainState::Inches), terrain: Some(TerrainState::Inches),
}); });
let quarter = Event::Quarter(Quarter::First);
assert!(None == quarter.delta(&kickoff));
assert!(None == quarter.delta(&first_down));
assert!(None == quarter.delta(&second_down));
assert!(None == quarter.delta(&third_down));
assert!(None == quarter.delta(&fourth_down));
assert!(None == quarter.delta(&turnover));
assert!(None == quarter.delta(&penalty));
assert!(None == quarter.delta(&goal_line));
assert!(None == quarter.delta(&inches));
assert!(None == quarter.delta(&score));
assert!(None == quarter.delta(&quarter));
assert!(10_i8 == kickoff.delta(&first_down).unwrap()); assert!(10_i8 == kickoff.delta(&first_down).unwrap());
assert!(0_i8 == kickoff.delta(&second_down).unwrap()); assert!(0_i8 == kickoff.delta(&second_down).unwrap());
assert!(None == kickoff.delta(&penalty)); assert!(None == kickoff.delta(&penalty));
@@ -248,9 +271,9 @@ mod tests {
assert!(None == inches.delta(&kickoff)); assert!(None == inches.delta(&kickoff));
assert!(None == inches.delta(&first_down)); assert!(None == inches.delta(&first_down));
assert!(-10_i8 == goal_line.delta(&second_down).unwrap()); assert!(-10_i8 == inches.delta(&second_down).unwrap());
assert!(-13_i8 == goal_line.delta(&third_down).unwrap()); assert!(-13_i8 == inches.delta(&third_down).unwrap());
assert!(-5_i8 == goal_line.delta(&fourth_down).unwrap()); assert!(-5_i8 == inches.delta(&fourth_down).unwrap());
assert!(None == inches.delta(&turnover)); assert!(None == inches.delta(&turnover));
assert!(None == inches.delta(&penalty)); assert!(None == inches.delta(&penalty));
assert!(None == inches.delta(&goal_line)); assert!(None == inches.delta(&goal_line));

View File

@@ -1,11 +1,12 @@
use crate::{Event, Period, Team, error}; use crate::{Event, Quarter, Team, error};
use serde::Deserialize; use serde::Deserialize;
use strum::IntoEnumIterator;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct Game { pub struct Game {
pub version: semver::Version, pub version: semver::Version,
pub flags: Vec<Flags>, pub flags: Vec<Flags>,
pub periods: Vec<Period>, pub events: Vec<Event>,
} }
impl Game { impl Game {
@@ -25,14 +26,12 @@ impl Game {
let mut teams = vec![]; let mut teams = vec![];
self.periods.iter().for_each(|period| { self.events.iter().for_each(|event| {
for event in period.events.iter() {
if let Ok(team) = event.team() { if let Ok(team) = event.team() {
if !ignore.contains(&team) && !teams.contains(&team) { if !ignore.contains(&team) && !teams.contains(&team) {
teams.push(team) teams.push(team)
} }
} }
}
}); });
if teams.len() == 2 || ignore.len() != 0 { if teams.len() == 2 || ignore.len() != 0 {
@@ -43,12 +42,17 @@ impl Game {
} }
pub fn deltas(&self, team: Team) -> Vec<i8> { pub fn deltas(&self, team: Team) -> Vec<i8> {
let events = self let events: Vec<Event> = self
.periods .team_events(team)
.iter() .iter()
.filter_map(|period| Some(period.team_events(team.to_owned(), None).ok().unwrap())) .filter_map(|event| {
.collect::<Vec<Vec<Event>>>() if let Event::Quarter(_) = event {
.concat(); None
} else {
Some(event.to_owned())
}
})
.collect();
let len = events.len() - 1; let len = events.len() - 1;
let mut idx: usize = 0; let mut idx: usize = 0;
let mut deltas: Vec<i8> = vec![]; let mut deltas: Vec<i8> = vec![];
@@ -65,33 +69,30 @@ impl Game {
} }
pub fn team_plays(&self, team: Team) -> usize { pub fn team_plays(&self, team: Team) -> usize {
self.periods self.team_events(team)
.iter() .iter()
.filter_map(|period| { .filter_map(|event| {
if !period.is_overtime() { if let Event::Play(_) = event {
let plays = period.team_plays(team.to_owned(), None); Some(event)
Some(plays.unwrap().len())
} else { } else {
None None
} }
}) })
.collect::<Vec<usize>>() .collect::<Vec<&Event>>()
.iter() .len()
.sum::<usize>()
} }
/// The average number of plays in a quarter. /// The average number of plays in a quarter.
/// Does not include OT plays or quarters where team indeterminate.
pub fn avg_plays_per_quarter(&self, team: Team) -> f32 { pub fn avg_plays_per_quarter(&self, team: Team) -> f32 {
// Handle if teams known at start or not override via index calculation of all game events. let periods: Vec<Period> = Quarter::iter()
.filter_map(|quarter| Some(self.to_owned().get_period(quarter.to_owned())).to_owned())
.collect();
let quarterly_avgs: Vec<f32> = self let quarterly_avgs: Vec<f32> = periods
.periods
.iter() .iter()
.filter_map(|period| { .filter_map(|period| {
if !period.is_overtime() { if !period.is_overtime() {
let plays = period.team_plays(team.to_owned(), None); Some(period.team_plays(team.to_owned()) as f32)
Some(plays.unwrap().len() as f32 / period.quarters().len() as f32)
} else { } else {
None None
} }
@@ -142,14 +143,7 @@ impl Game {
} }
pub fn penalties(&self, team: Team) -> usize { pub fn penalties(&self, team: Team) -> usize {
// Knock down nesting? self.team_events(team)
self.periods
.iter()
.filter_map(|period| {
Some(
period
.team_events(team.to_owned(), None)
.ok()?
.iter() .iter()
.filter_map(|event| { .filter_map(|event| {
if let Event::Penalty(_) = event { if let Event::Penalty(_) = event {
@@ -158,13 +152,129 @@ impl Game {
None None
} }
}) })
.collect::<Vec<Event>>(), .collect::<Vec<Event>>()
)
})
.collect::<Vec<Vec<Event>>>()
.concat()
.len() .len()
} }
pub fn get_period(&self, quarter: Quarter) -> Period {
let mut record = false;
Period {
period: quarter.to_owned(),
events: self
.events
.iter()
.filter_map(|event| {
if let Event::Quarter(_) = event {
record = Event::Quarter(quarter.to_owned()) == *event;
}
if record {
return Some(event.to_owned());
}
None
})
.collect::<Vec<Event>>(),
}
}
pub fn team_events(&self, team: Team) -> Vec<Event> {
let mut events: Vec<Event> = vec![];
let mut first = true;
let mut record: bool = true;
self.events.iter().for_each(|event| {
if let Event::Kickoff(_) | Event::Turnover(_) = event {
record = {
if team == event.team().unwrap() {
// Wipe events vec if the start of quarter was opposition
// on offence.
if first {
events = vec![];
}
true
} else {
events.push(event.to_owned());
false
}
};
first = false;
}
if record {
events.push(event.to_owned());
}
});
// If already handled or assumption override applicable
events
}
}
#[derive(Debug, Clone)]
pub struct Period {
period: Quarter,
events: Vec<Event>,
}
impl Period {
pub fn team_events(&self, team: Team) -> Vec<Event> {
let mut events: Vec<Event> = vec![];
let mut first = true;
let mut record: bool = true;
self.events.iter().for_each(|event| {
if let Event::Kickoff(_) | Event::Turnover(_) = event {
record = {
if team == event.team().unwrap() {
// Wipe events vec if the start of quarter was opposition
// on offence.
if first {
events = vec![];
}
true
} else {
events.push(event.to_owned());
false
}
};
first = false;
}
if record {
events.push(event.to_owned());
}
});
events
}
pub fn team_plays(&self, team: Team) -> usize {
self.team_events(team)
.iter()
.filter_map(|event| {
if let Event::Play(_) = event {
Some(event)
} else {
None
}
})
.collect::<Vec<&Event>>()
.len()
}
pub fn is_overtime(&self) -> bool {
if let Quarter::Overtime(_) = self.period {
true
} else {
false
}
}
} }
#[derive(Debug, Deserialize, Clone, PartialEq)] #[derive(Debug, Deserialize, Clone, PartialEq)]
@@ -175,6 +285,7 @@ pub enum Flags {
Interval(u8), Interval(u8),
} }
/*
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::*; use crate::*;
@@ -184,20 +295,12 @@ mod tests {
let a = Game { let a = Game {
version: crate::MIN_VER, version: crate::MIN_VER,
flags: vec![], flags: vec![],
periods: vec![
Period {
start: Quarter::First,
end: None,
events: vec![ events: vec![
Event::Quarter(Quarter::First),
Event::Kickoff(Team::Nebraska), Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()), Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState), Event::Turnover(Team::ArizonaState),
], Event::Quarter(Quarter::Second),
},
Period {
start: Quarter::Second,
end: Some(Quarter::Fourth),
events: vec![
Event::Turnover(Team::Nebraska), Event::Turnover(Team::Nebraska),
Event::Play(Play::default()), Event::Play(Play::default()),
Event::Play(Play::default()), Event::Play(Play::default()),
@@ -207,8 +310,6 @@ mod tests {
Event::Play(Play::default()), Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState), Event::Turnover(Team::ArizonaState),
], ],
},
],
}; };
let b = Game { let b = Game {
@@ -409,4 +510,146 @@ mod tests {
assert!(game.deltas(Team::Nebraska) == vec![10_i8, -3_i8, 5_i8, -2_i8, 12_i8]); assert!(game.deltas(Team::Nebraska) == vec![10_i8, -3_i8, 5_i8, -2_i8, 12_i8]);
assert!(game.deltas(Team::ArizonaState) == vec![10_i8, 0_i8]); assert!(game.deltas(Team::ArizonaState) == vec![10_i8, 0_i8]);
} }
#[test]
fn team_events() {
let a = Period {
start: Quarter::First,
end: None,
events: vec![
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState),
Event::Play(Play::default()),
Event::Play(Play::default()),
Event::Kickoff(Team::Nebraska),
Event::Score(ScorePoints::Touchdown),
Event::Kickoff(Team::SouthCarolina),
],
};
let b = Period {
start: Quarter::Second,
end: None,
events: vec![
Event::Play(Play::default()),
Event::Turnover(Team::SouthCarolina),
],
};
let c = Period {
start: Quarter::Second,
end: None,
events: vec![
Event::Play(Play::default()),
Event::Turnover(Team::Nebraska),
],
};
let d = Period {
start: Quarter::Second,
end: None,
events: vec![Event::Play(Play::default())],
};
assert!(
a.team_events(Team::Nebraska, None).unwrap()
== vec![
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState),
Event::Kickoff(Team::Nebraska),
Event::Score(ScorePoints::Touchdown),
Event::Kickoff(Team::SouthCarolina),
]
);
assert!(
b.team_events(Team::Nebraska, None).unwrap()
== vec![
Event::Play(Play::default()),
Event::Turnover(Team::SouthCarolina)
]
);
assert!(
c.team_events(Team::Nebraska, None).unwrap() == vec![Event::Turnover(Team::Nebraska)]
);
assert!(true == d.team_events(Team::Nebraska, None).is_err());
assert!(false == d.team_events(Team::Nebraska, Some(true)).is_err())
}
#[test]
fn team_plays() {
let period = Period {
start: Quarter::First,
end: None,
events: vec![
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState),
Event::Play(Play::default()),
Event::Play(Play::default()),
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Score(ScorePoints::default()),
Event::Kickoff(Team::SouthCarolina),
Event::Play(Play::default()),
Event::Turnover(Team::Nebraska),
Event::Play(Play::default()),
],
};
assert!(
period.team_plays(Team::Nebraska, None).unwrap()
== vec![Play::default(), Play::default(), Play::default()]
);
}
#[test]
fn quarters() {
let first = Period {
start: Quarter::First,
end: None,
events: vec![],
};
let second_fourth = Period {
start: Quarter::Second,
end: Some(Quarter::Fourth),
events: vec![],
};
let third_ot_three = Period {
start: Quarter::Third,
end: Some(Quarter::Overtime(3)),
events: vec![],
};
let ot_one_three = Period {
start: Quarter::Overtime(1),
end: Some(Quarter::Overtime(3)),
events: vec![],
};
assert!(first.quarters() == vec![Quarter::First]);
assert!(second_fourth.quarters() == vec![Quarter::Second, Quarter::Third, Quarter::Fourth]);
assert!(
third_ot_three.quarters()
== vec![
Quarter::Third,
Quarter::Fourth,
Quarter::Overtime(1),
Quarter::Overtime(2),
Quarter::Overtime(3)
]
);
assert!(
ot_one_three.quarters()
== vec![
Quarter::Overtime(1),
Quarter::Overtime(2),
Quarter::Overtime(3)
]
)
}
} }
*/

View File

@@ -9,7 +9,7 @@ mod play;
mod terrain; mod terrain;
#[allow(unused)] #[allow(unused)]
pub const MIN_VER: semver::Version = semver::Version::new(0, 6, 0); pub const MIN_VER: semver::Version = semver::Version::new(0, 7, 0);
// I'm lazy. // I'm lazy.
pub use action::*; pub use action::*;

View File

@@ -1,125 +1,7 @@
use crate::{Event, Play, Team, error};
use serde::Deserialize; use serde::Deserialize;
use strum::EnumIter;
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone, PartialEq, EnumIter)]
pub struct Period {
pub start: Quarter,
pub end: Option<Quarter>,
pub events: Vec<Event>,
}
impl Period {
pub fn team_events(
&self,
team: Team,
assume_team_known: Option<bool>,
) -> Result<Vec<Event>, error::CannotDetermineTeams> {
let mut events: Vec<Event> = vec![];
let mut first = true;
let mut record: bool = true;
let assume_team_known = assume_team_known.unwrap_or(false);
self.events.iter().for_each(|event| {
if let Event::Kickoff(_) | Event::Turnover(_) = event {
record = {
if team == event.team().unwrap() {
// Wipe events vec if the start of quarter was opposition
// on offence.
if first {
events = vec![];
}
true
} else {
events.push(event.to_owned());
false
}
};
first = false;
}
if record {
events.push(event.to_owned());
}
});
// If already handled or assumption override applicable
if !first || (first && assume_team_known) {
Ok(events)
} else {
Err(error::CannotDetermineTeams)
}
}
pub fn team_plays(
&self,
team: Team,
assume_team_known: Option<bool>,
) -> Result<Vec<Play>, error::CannotDetermineTeams> {
Ok(self
.team_events(team, assume_team_known)?
.iter()
.filter_map(|event| {
if let Event::Play(play) = event {
Some(play.to_owned())
} else {
None
}
})
.collect())
}
pub fn quarters(&self) -> Vec<Quarter> {
let mut quarters: Vec<Quarter> = vec![self.start.to_owned()];
if self.end.is_none() {
return quarters;
}
let order = vec![
Quarter::First,
Quarter::Second,
Quarter::Third,
Quarter::Fourth,
];
let start = if let Quarter::Overtime(x) = self.start {
(3 + x) as usize
} else {
order.iter().position(|q| q == &self.start).unwrap()
};
let end = if let Quarter::Overtime(x) = self.end.as_ref().unwrap() {
(3 + x) as usize
} else {
order
.iter()
.position(|q| q == self.end.as_ref().unwrap())
.unwrap()
};
let range: Vec<usize> = ((start + 1)..=end).collect();
for i in range {
quarters.push(match i {
0 => Quarter::First,
1 => Quarter::Second,
2 => Quarter::Third,
3 => Quarter::Fourth,
_ => Quarter::Overtime((i - 3) as u8),
});
}
quarters
}
pub fn is_overtime(&self) -> bool {
self.start.is_overtime() || self.end.as_ref().is_some_and(|some| some.is_overtime())
}
}
#[derive(Debug, Deserialize, Clone, PartialEq)]
pub enum Quarter { pub enum Quarter {
First, First,
Second, Second,
@@ -127,159 +9,3 @@ pub enum Quarter {
Fourth, Fourth,
Overtime(u8), Overtime(u8),
} }
impl Quarter {
pub fn is_overtime(&self) -> bool {
if let Self::Overtime(_) = self {
true
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn team_events() {
let a = Period {
start: Quarter::First,
end: None,
events: vec![
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState),
Event::Play(Play::default()),
Event::Play(Play::default()),
Event::Kickoff(Team::Nebraska),
Event::Score(ScorePoints::Touchdown),
Event::Kickoff(Team::SouthCarolina),
],
};
let b = Period {
start: Quarter::Second,
end: None,
events: vec![
Event::Play(Play::default()),
Event::Turnover(Team::SouthCarolina),
],
};
let c = Period {
start: Quarter::Second,
end: None,
events: vec![
Event::Play(Play::default()),
Event::Turnover(Team::Nebraska),
],
};
let d = Period {
start: Quarter::Second,
end: None,
events: vec![Event::Play(Play::default())],
};
assert!(
a.team_events(Team::Nebraska, None).unwrap()
== vec![
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState),
Event::Kickoff(Team::Nebraska),
Event::Score(ScorePoints::Touchdown),
Event::Kickoff(Team::SouthCarolina),
]
);
assert!(
b.team_events(Team::Nebraska, None).unwrap()
== vec![
Event::Play(Play::default()),
Event::Turnover(Team::SouthCarolina)
]
);
assert!(
c.team_events(Team::Nebraska, None).unwrap() == vec![Event::Turnover(Team::Nebraska)]
);
assert!(true == d.team_events(Team::Nebraska, None).is_err());
assert!(false == d.team_events(Team::Nebraska, Some(true)).is_err())
}
#[test]
fn team_plays() {
let period = Period {
start: Quarter::First,
end: None,
events: vec![
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Turnover(Team::ArizonaState),
Event::Play(Play::default()),
Event::Play(Play::default()),
Event::Kickoff(Team::Nebraska),
Event::Play(Play::default()),
Event::Score(ScorePoints::default()),
Event::Kickoff(Team::SouthCarolina),
Event::Play(Play::default()),
Event::Turnover(Team::Nebraska),
Event::Play(Play::default()),
],
};
assert!(
period.team_plays(Team::Nebraska, None).unwrap()
== vec![Play::default(), Play::default(), Play::default()]
);
}
#[test]
fn quarters() {
let first = Period {
start: Quarter::First,
end: None,
events: vec![],
};
let second_fourth = Period {
start: Quarter::Second,
end: Some(Quarter::Fourth),
events: vec![],
};
let third_ot_three = Period {
start: Quarter::Third,
end: Some(Quarter::Overtime(3)),
events: vec![],
};
let ot_one_three = Period {
start: Quarter::Overtime(1),
end: Some(Quarter::Overtime(3)),
events: vec![],
};
assert!(first.quarters() == vec![Quarter::First]);
assert!(second_fourth.quarters() == vec![Quarter::Second, Quarter::Third, Quarter::Fourth]);
assert!(
third_ot_three.quarters()
== vec![
Quarter::Third,
Quarter::Fourth,
Quarter::Overtime(1),
Quarter::Overtime(2),
Quarter::Overtime(3)
]
);
assert!(
ot_one_three.quarters()
== vec![
Quarter::Overtime(1),
Quarter::Overtime(2),
Quarter::Overtime(3)
]
)
}
}

2
miller/Cargo.lock generated
View File

@@ -64,7 +64,7 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]] [[package]]
name = "gamelog" name = "gamelog"
version = "0.6.0" version = "0.7.0"
dependencies = [ dependencies = [
"ron", "ron",
"semver", "semver",