diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..5432365 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,35 @@ +use std::{fmt, io}; + +#[derive(Debug)] +pub enum LogFileError { + FailedToOpen(io::Error), + RonSpannedError(ron::error::SpannedError), + CompatibilityCheck(semver::Version), +} + +impl fmt::Display for LogFileError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::FailedToOpen(err) => write!(f, "{}", err), + Self::CompatibilityCheck(ver) => write!( + f, + "GameLogs cannot be older than {}, but {} was found in logfile.", + crate::gamelog::GAMELOG_MIN_VER.to_string(), + ver.to_string() + ), + Self::RonSpannedError(err) => write!(f, "{}", err), + } + } +} + +pub enum DownError { + NotKickoff, +} + +impl fmt::Display for DownError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + Self::NotKickoff => write!(f, "Variant was not Down::Kickoff."), + } + } +} diff --git a/src/gamelog.rs b/src/gamelog.rs deleted file mode 100644 index 8860099..0000000 --- a/src/gamelog.rs +++ /dev/null @@ -1,180 +0,0 @@ -use serde::Deserialize; -use std::{fmt, fs::File, io, path::PathBuf, u64}; - -pub const GAMELOG_MIN_VER: semver::Version = semver::Version::new(0, 2, 0); - -#[derive(Debug)] -pub enum LogFileError { - FailedToOpen(io::Error), - RonSpannedError(ron::error::SpannedError), - CompatibilityCheck(semver::Version), -} - -impl fmt::Display for LogFileError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::FailedToOpen(err) => write!(f, "{}", err), - Self::CompatibilityCheck(ver) => write!( - f, - "GameLogs cannot be older than {}, but {} was found in logfile.", - GAMELOG_MIN_VER.to_string(), - ver.to_string() - ), - Self::RonSpannedError(err) => write!(f, "{}", err), - } - } -} - -#[derive(Debug, Deserialize)] -pub struct LogFile(Vec); - -impl TryFrom for LogFile { - type Error = ron::error::SpannedError; - - fn try_from(file: File) -> Result { - ron::de::from_reader(file) - } -} - -impl TryFrom for LogFile { - type Error = LogFileError; - - fn try_from(path: PathBuf) -> Result { - match Self::try_from( - match std::fs::OpenOptions::new() // Defaults to setting all options false. - .read(true) // Only need ensure that reading is possible. - .open(path.as_path()) - { - Ok(f) => f, - Err(err) => return Err(LogFileError::FailedToOpen(err)), - }, - ) { - Ok(f) => Ok(f), - Err(err) => Err(LogFileError::RonSpannedError(err)), - } - } -} - -impl LogFile { - pub fn get_min_ver(&mut self) -> semver::Version { - let mut lowest = semver::Version::new(u64::MAX, u64::MAX, u64::MAX); - - self.0.iter().for_each(|x| { - if x.version.cmp_precedence(&lowest).is_lt() { - lowest = x.version.clone() - } - }); - - lowest - } - - /// Returns if the LogFile min version is compatible. - fn is_compatible(&mut self) -> bool { - self.get_min_ver().cmp_precedence(&GAMELOG_MIN_VER).is_lt() - } - - /// Ensures that the returned gamefile is compatible, else returns Error. - pub fn ensure_compatible(&mut self) -> Result<&mut Self, LogFileError> { - if self.is_compatible() { - Ok(self) - } else { - Err(LogFileError::CompatibilityCheck(self.get_min_ver())) - } - } -} - -#[derive(Debug, Deserialize)] -struct GameRecord { - version: semver::Version, - periods: Vec>, -} - -#[derive(Debug, Deserialize)] -struct Period { - start: Quarter, - end: Option, - plays: Vec, -} - -#[derive(Debug, Deserialize)] -enum Quarter { - First, - Second, - Third, - Fourth, -} - -#[derive(Debug, Deserialize)] -enum TerrainState { - Yards(u8), - GoalLine, - Inches, -} - -#[derive(Debug, Deserialize)] -struct Play { - action: Option, - down: Down, - terrain: TerrainState, -} - -enum DownError { - NotKickoff, -} - -impl fmt::Display for DownError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - Self::NotKickoff => write!(f, "Variant was not Down::Kickoff."), - } - } -} - -#[derive(Debug, Deserialize)] -enum Down { - Kickoff { offence: Team }, - First, - Second, - Third, - Fourth, - PointAfterTouchdown, -} - -impl Down { - fn get_offence(&self) -> Result<&Team, DownError> { - match self { - Self::Kickoff { offence } => Ok(offence), - _ => Err(DownError::NotKickoff), - } - } -} - -#[derive(Debug, Deserialize)] -enum Action { - CrackStudentBodyRightTackle, - Curls, - FleaFlicker, - HalfbackSlam, - HalfbackSlipScreen, - HalfbackSweep, - Mesh, - PlayActionBoot, - PlayActionComebacks, - PlayActionPowerZero, - PowerZero, - SlantBubble, - SlotOut, - SpeedOption, - StrongFlood, -} - -#[derive(Debug, Deserialize, Clone)] -enum Team { - ArizonaState, - Colorado, - Iowa, - Nebraska, - SouthCarolina, - Syracuse, - TexasAnM, -} diff --git a/src/gamelog/file.rs b/src/gamelog/file.rs new file mode 100644 index 0000000..5264a26 --- /dev/null +++ b/src/gamelog/file.rs @@ -0,0 +1,64 @@ +use crate::error; +use serde::Deserialize; +use std::{fs::File, path::PathBuf}; + +#[derive(Debug, Deserialize, Clone)] +pub struct LogFile(Vec); + +impl TryFrom for LogFile { + type Error = ron::error::SpannedError; + + fn try_from(file: File) -> Result { + ron::de::from_reader(file) + } +} + +impl TryFrom for LogFile { + type Error = error::LogFileError; + + fn try_from(path: PathBuf) -> Result { + match Self::try_from( + match std::fs::OpenOptions::new() // Defaults to setting all options false. + .read(true) // Only need ensure that reading is possible. + .open(path.as_path()) + { + Ok(f) => f, + Err(err) => return Err(error::LogFileError::FailedToOpen(err)), + }, + ) { + Ok(f) => Ok(f), + Err(err) => Err(error::LogFileError::RonSpannedError(err)), + } + } +} + +impl LogFile { + pub fn get_min_ver(self) -> semver::Version { + let mut lowest = semver::Version::new(u64::MAX, u64::MAX, u64::MAX); + + self.0.iter().for_each(|x| { + if x.version.cmp_precedence(&lowest).is_lt() { + lowest = x.version.clone() + } + }); + + lowest + } + + /// Returns if the LogFile min version is compatible. + fn is_compatible(&self) -> bool { + self.clone() + .get_min_ver() + .cmp_precedence(&super::GAMELOG_MIN_VER) + .is_lt() + } + + /// Ensures that the returned gamefile is compatible, else returns Error. + pub fn ensure_compatible(self) -> Result { + if self.is_compatible() { + Ok(self) + } else { + Err(error::LogFileError::CompatibilityCheck(self.get_min_ver())) + } + } +} diff --git a/src/gamelog/mod.rs b/src/gamelog/mod.rs new file mode 100644 index 0000000..58d1ec9 --- /dev/null +++ b/src/gamelog/mod.rs @@ -0,0 +1,11 @@ +mod file; +mod period; +mod play; +mod terrain; + +pub const GAMELOG_MIN_VER: semver::Version = semver::Version::new(0, 2, 0); + +pub use file::LogFile; +pub use period::*; +pub use play::*; +pub use terrain::TerrainState; diff --git a/src/gamelog/period.rs b/src/gamelog/period.rs new file mode 100644 index 0000000..6725d13 --- /dev/null +++ b/src/gamelog/period.rs @@ -0,0 +1,22 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone)] +pub struct Game { + pub version: semver::Version, + periods: Vec>, +} + +#[derive(Debug, Deserialize, Clone)] +pub struct Period { + start: Quarter, + end: Option, + plays: Vec, +} + +#[derive(Debug, Deserialize, Clone)] +pub enum Quarter { + First, + Second, + Third, + Fourth, +} diff --git a/src/gamelog/play.rs b/src/gamelog/play.rs new file mode 100644 index 0000000..11a6ea6 --- /dev/null +++ b/src/gamelog/play.rs @@ -0,0 +1,58 @@ +use crate::error; +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone)] +pub struct Play { + action: Option, + down: Down, + terrain: super::TerrainState, +} + +#[derive(Debug, Deserialize, Clone)] +pub enum Action { + CrackStudentBodyRightTackle, + Curls, + FleaFlicker, + HalfbackSlam, + HalfbackSlipScreen, + HalfbackSweep, + Mesh, + PlayActionBoot, + PlayActionComebacks, + PlayActionPowerZero, + PowerZero, + SlantBubble, + SlotOut, + SpeedOption, + StrongFlood, +} + +#[derive(Debug, Deserialize, Clone)] +pub enum Down { + Kickoff { offence: Team }, + First, + Second, + Third, + Fourth, + PointAfterTouchdown, +} + +impl Down { + fn get_offence(&self) -> Result<&Team, error::DownError> { + match self { + Self::Kickoff { offence } => Ok(offence), + _ => Err(error::DownError::NotKickoff), + } + } +} + +#[derive(Debug, Deserialize, Clone)] +pub enum Team { + ArizonaState, + Colorado, + Iowa, + Nebraska, + SouthCarolina, + Syracuse, + TexasAnM, +} diff --git a/src/gamelog/terrain.rs b/src/gamelog/terrain.rs new file mode 100644 index 0000000..3c00de2 --- /dev/null +++ b/src/gamelog/terrain.rs @@ -0,0 +1,8 @@ +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone)] +pub enum TerrainState { + Yards(u8), + GoalLine, + Inches, +}