v1?
This commit is contained in:
31
README.adoc
31
README.adoc
@@ -14,7 +14,38 @@ I figured, that since I already had to digitize every note, that I was required
|
|||||||
|
|
||||||
== Goals
|
== Goals
|
||||||
|
|
||||||
|
=== Gamelog
|
||||||
* [*] Data Format
|
* [*] Data Format
|
||||||
|
** [*] Support recording multiple games
|
||||||
|
** [*] Periods
|
||||||
|
*** Quarters
|
||||||
|
*** Overtime
|
||||||
|
** [*] Teams
|
||||||
|
*** Iowa
|
||||||
|
*** Syracuse
|
||||||
|
*** Texas A&M
|
||||||
|
*** Colorado
|
||||||
|
*** Nebraska
|
||||||
|
*** Boise State [deprecated]
|
||||||
|
*** Arizona State
|
||||||
|
*** South Carolina
|
||||||
|
** [*] Downs
|
||||||
|
*** First - Fourth
|
||||||
|
*** Kickoff
|
||||||
|
*** PAT (Point After Touchdown)
|
||||||
|
**** One
|
||||||
|
**** Two
|
||||||
|
**** Failed
|
||||||
|
** [*] Score
|
||||||
|
** [*] Terrain Position
|
||||||
|
*** [*] Yards
|
||||||
|
*** [*] In (Inches)
|
||||||
|
*** [*] GL (Goal Line)
|
||||||
|
** [*] Penalty
|
||||||
|
** Out?
|
||||||
|
** [*] Plays
|
||||||
|
|
||||||
|
=== Miller:
|
||||||
* [ ] Mathematics
|
* [ ] Mathematics
|
||||||
** [ ] Avg. Terrain Gain
|
** [ ] Avg. Terrain Gain
|
||||||
** [ ] Avg. Terrain Loss
|
** [ ] Avg. Terrain Loss
|
||||||
|
|||||||
35
gamelog/Cargo.lock
generated
35
gamelog/Cargo.lock
generated
@@ -24,8 +24,15 @@ dependencies = [
|
|||||||
"ron",
|
"ron",
|
||||||
"semver",
|
"semver",
|
||||||
"serde",
|
"serde",
|
||||||
|
"strum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.94"
|
version = "1.0.94"
|
||||||
@@ -57,6 +64,12 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.26"
|
version = "1.0.26"
|
||||||
@@ -86,6 +99,28 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum"
|
||||||
|
version = "0.27.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
|
||||||
|
dependencies = [
|
||||||
|
"strum_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strum_macros"
|
||||||
|
version = "0.27.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"rustversion",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.100"
|
version = "2.0.100"
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
ron = "0.9"
|
ron = "0.9"
|
||||||
|
|
||||||
|
[dependencies.strum]
|
||||||
|
version = "0.27"
|
||||||
|
features = ["derive"]
|
||||||
|
|
||||||
[dependencies.semver]
|
[dependencies.semver]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
features = ["serde"]
|
features = ["serde"]
|
||||||
|
|||||||
138
gamelog/src/action.rs
Normal file
138
gamelog/src/action.rs
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
|
||||||
|
pub enum Action {
|
||||||
|
CrackStudentBodyRightTackle,
|
||||||
|
Curls,
|
||||||
|
FleaFlicker,
|
||||||
|
HalfbackSlam,
|
||||||
|
HalfbackSlipScreen,
|
||||||
|
HalfbackSweep,
|
||||||
|
Mesh,
|
||||||
|
PlayActionBoot,
|
||||||
|
PlayActionComebacks,
|
||||||
|
PlayActionPowerZero,
|
||||||
|
PowerZero,
|
||||||
|
SlantBubble,
|
||||||
|
SlotOut,
|
||||||
|
SpeedOption,
|
||||||
|
StrongFlood,
|
||||||
|
#[default]
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Action {
|
||||||
|
// I'd love a better way of doing these
|
||||||
|
// Attributes are probably the way to go,
|
||||||
|
// but I'm not about to write procedural macros for this project.
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is a play action.
|
||||||
|
pub fn is_play_action(&self) -> bool {
|
||||||
|
if let Self::PlayActionBoot | Self::PlayActionComebacks | Self::PlayActionPowerZero = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is a halfback.
|
||||||
|
pub fn is_halfback(&self) -> bool {
|
||||||
|
if let Self::HalfbackSlam | Self::HalfbackSlipScreen | Self::HalfbackSweep = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is a running play.
|
||||||
|
pub fn is_run(&self) -> bool {
|
||||||
|
if let Self::HalfbackSlam
|
||||||
|
| Self::SpeedOption
|
||||||
|
| Self::HalfbackSweep
|
||||||
|
| Self::PowerZero
|
||||||
|
| Self::CrackStudentBodyRightTackle = self
|
||||||
|
{
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is a passing play.
|
||||||
|
pub fn is_pass(&self) -> bool {
|
||||||
|
!self.is_run()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if `self` is `Event::Unknown`.
|
||||||
|
pub fn is_unknown(&self) -> bool {
|
||||||
|
if let Self::Unknown = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `Playset` that this action belongs to.
|
||||||
|
/// Returns `None` if `Event::Unknown`
|
||||||
|
pub fn playset(&self) -> Option<Playset> {
|
||||||
|
if self.is_unknown() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(match self {
|
||||||
|
Self::SlantBubble | Self::HalfbackSlam | Self::PlayActionBoot => Playset::PistolSpread,
|
||||||
|
Self::StrongFlood | Self::SpeedOption | Self::HalfbackSlipScreen => {
|
||||||
|
Playset::ShotgunTripleWingsOffset
|
||||||
|
}
|
||||||
|
Self::SlotOut | Self::HalfbackSweep | Self::PlayActionComebacks => {
|
||||||
|
Playset::ShotgunDoubleFlex
|
||||||
|
}
|
||||||
|
Self::Curls | Self::PowerZero | Self::PlayActionPowerZero => Playset::IFormNormal,
|
||||||
|
Self::Mesh | Self::CrackStudentBodyRightTackle | Self::FleaFlicker => {
|
||||||
|
Playset::IFormTight
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the `Key` that this action belongs to.
|
||||||
|
/// Returns `None` if `Event::Unknown`
|
||||||
|
pub fn key(&self) -> Option<Key> {
|
||||||
|
if self.is_unknown() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All running plays are on `Key::X`
|
||||||
|
if self.is_run() {
|
||||||
|
return Some(Key::X);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(match self {
|
||||||
|
Self::SlantBubble | Self::StrongFlood | Self::SlotOut | Self::Curls | Self::Mesh => {
|
||||||
|
Key::Square
|
||||||
|
}
|
||||||
|
Self::PlayActionBoot
|
||||||
|
| Self::HalfbackSlipScreen
|
||||||
|
| Self::PlayActionComebacks
|
||||||
|
| Self::PlayActionPowerZero
|
||||||
|
| Self::FleaFlicker => Key::Triangle,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Playset {
|
||||||
|
PistolSpread,
|
||||||
|
ShotgunTripleWingsOffset,
|
||||||
|
ShotgunDoubleFlex,
|
||||||
|
IFormNormal,
|
||||||
|
IFormTight,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Key {
|
||||||
|
Square,
|
||||||
|
X,
|
||||||
|
Triangle,
|
||||||
|
}
|
||||||
@@ -4,32 +4,26 @@ use std::{fmt, io};
|
|||||||
pub enum LogFileError {
|
pub enum LogFileError {
|
||||||
FailedToOpen(io::Error),
|
FailedToOpen(io::Error),
|
||||||
RonSpannedError(ron::error::SpannedError),
|
RonSpannedError(ron::error::SpannedError),
|
||||||
CompatibilityCheck(semver::Version),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for LogFileError {
|
impl fmt::Display for LogFileError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::FailedToOpen(err) => write!(f, "{}", err),
|
Self::FailedToOpen(err) => write!(f, "{}", err),
|
||||||
Self::CompatibilityCheck(ver) => write!(
|
|
||||||
f,
|
|
||||||
"GameLogs cannot be older than {}, but {} was found in logfile.",
|
|
||||||
crate::MIN_VER.to_string(),
|
|
||||||
ver.to_string()
|
|
||||||
),
|
|
||||||
Self::RonSpannedError(err) => write!(f, "{}", err),
|
Self::RonSpannedError(err) => write!(f, "{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DownError {
|
#[derive(Debug)]
|
||||||
NotKickoff,
|
pub enum TeamsError {
|
||||||
|
NumberFound(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for DownError {
|
impl fmt::Display for TeamsError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match self {
|
||||||
Self::NotKickoff => write!(f, "Variant was not Down::Kickoff."),
|
Self::NumberFound(err) => write!(f, "Expected two, found: {:?}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
14
gamelog/src/event.rs
Normal file
14
gamelog/src/event.rs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
use crate::{Play, ScoreChange, Team, TerrainState};
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
type Offence = Team;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
pub enum Event {
|
||||||
|
Play(Play),
|
||||||
|
Kickoff(Offence),
|
||||||
|
Turnover(Offence),
|
||||||
|
Penalty(TerrainState),
|
||||||
|
ScoreChange(ScoreChange),
|
||||||
|
}
|
||||||
@@ -5,6 +5,25 @@ use std::{fs::File, path::PathBuf};
|
|||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct LogFile(Vec<super::Game>);
|
pub struct LogFile(Vec<super::Game>);
|
||||||
|
|
||||||
|
impl LogFile {
|
||||||
|
pub fn 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.
|
||||||
|
pub fn is_compatible(&self) -> bool {
|
||||||
|
self.min_ver().cmp_precedence(&super::MIN_VER).is_lt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<File> for LogFile {
|
impl TryFrom<File> for LogFile {
|
||||||
type Error = ron::error::SpannedError;
|
type Error = ron::error::SpannedError;
|
||||||
|
|
||||||
@@ -31,34 +50,3 @@ impl TryFrom<PathBuf> for LogFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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::MIN_VER)
|
|
||||||
.is_lt()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ensures that the returned gamefile is compatible, else returns Error.
|
|
||||||
pub fn ensure_compatible(self) -> Result<Self, error::LogFileError> {
|
|
||||||
if self.is_compatible() {
|
|
||||||
Ok(self)
|
|
||||||
} else {
|
|
||||||
Err(error::LogFileError::CompatibilityCheck(self.get_min_ver()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
44
gamelog/src/game.rs
Normal file
44
gamelog/src/game.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use crate::{Event, Period, Play, PlayHandle, Team, error};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[deprecated(since = "0.2.0", note = "Migrated to Game")]
|
||||||
|
pub type GameRecord = Game;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
pub struct Game {
|
||||||
|
pub version: semver::Version,
|
||||||
|
pub periods: Vec<Period>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Game {
|
||||||
|
/// Returns the teams of this game.
|
||||||
|
pub fn teams(&self) -> Result<Vec<Team>, error::TeamsError> {
|
||||||
|
let mut teams = vec![];
|
||||||
|
|
||||||
|
self.periods.iter().for_each(|period| {
|
||||||
|
period.events.iter().for_each(|event| {
|
||||||
|
if let Event::Kickoff(t) | Event::Turnover(t) = event {
|
||||||
|
if teams.contains(t) {
|
||||||
|
teams.push(t.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if teams.len() == 2 {
|
||||||
|
Ok(teams)
|
||||||
|
} else {
|
||||||
|
Err(error::TeamsError::NumberFound(teams.len()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlayHandle for Game {
|
||||||
|
fn plays(&self) -> Vec<Play> {
|
||||||
|
self.periods
|
||||||
|
.iter()
|
||||||
|
.map(|period| period.plays())
|
||||||
|
.collect::<Vec<Vec<Play>>>() // Make compiler happy with turbofish.
|
||||||
|
.concat()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,23 @@
|
|||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
|
mod action;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod event;
|
||||||
mod file;
|
mod file;
|
||||||
|
mod game;
|
||||||
mod period;
|
mod period;
|
||||||
mod play;
|
mod play;
|
||||||
|
mod score;
|
||||||
mod terrain;
|
mod terrain;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub const MIN_VER: semver::Version = semver::Version::new(0, 3, 0);
|
pub const MIN_VER: semver::Version = semver::Version::new(0, 3, 0);
|
||||||
|
|
||||||
|
pub use action::*;
|
||||||
|
pub use event::Event;
|
||||||
pub use file::LogFile;
|
pub use file::LogFile;
|
||||||
|
pub use game::{Game, GameRecord};
|
||||||
pub use period::*;
|
pub use period::*;
|
||||||
pub use play::*;
|
pub use play::*;
|
||||||
|
pub use score::ScoreChange;
|
||||||
pub use terrain::TerrainState;
|
pub use terrain::TerrainState;
|
||||||
|
|||||||
@@ -1,22 +1,29 @@
|
|||||||
|
use crate::{Event, PlayHandle};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[deprecated(since = "0.2.0", note = "Migrated to Game")]
|
|
||||||
type GameRecord = Game;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
|
||||||
pub struct Game {
|
|
||||||
pub version: semver::Version,
|
|
||||||
periods: Vec<Option<Period>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct Period {
|
pub struct Period {
|
||||||
start: Quarter,
|
pub start: Quarter,
|
||||||
end: Option<Quarter>,
|
pub end: Option<Quarter>,
|
||||||
plays: Vec<super::Play>,
|
pub events: Vec<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
impl PlayHandle for Period {
|
||||||
|
fn plays(&self) -> Vec<crate::Play> {
|
||||||
|
self.events
|
||||||
|
.iter()
|
||||||
|
.filter_map(|event| {
|
||||||
|
if let Event::Play(play) = event {
|
||||||
|
Some(play.to_owned())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone, PartialEq)]
|
||||||
pub enum Quarter {
|
pub enum Quarter {
|
||||||
First,
|
First,
|
||||||
Second,
|
Second,
|
||||||
|
|||||||
@@ -1,57 +1,35 @@
|
|||||||
use crate::{TerrainState, error};
|
use crate::{Action, TerrainState};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
pub trait PlayHandle {
|
||||||
|
/// Returns all plays within object's scope.
|
||||||
|
fn plays(&self) -> Vec<Play>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
|
||||||
pub struct Play {
|
pub struct Play {
|
||||||
down: Down,
|
pub action: Action,
|
||||||
terrain: TerrainState,
|
pub down: Down,
|
||||||
|
pub terrain: TerrainState,
|
||||||
}
|
}
|
||||||
|
|
||||||
type Offence = Team;
|
impl PlayHandle for Play {
|
||||||
impl Offence {}
|
fn plays(&self) -> Vec<Play> {
|
||||||
|
vec![self.to_owned()]
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
}
|
||||||
pub enum Event {
|
|
||||||
CrackStudentBodyRightTackle(Play),
|
|
||||||
Curls(Play),
|
|
||||||
FleaFlicker(Play),
|
|
||||||
HalfbackSlam(Play),
|
|
||||||
HalfbackSlipScreen(Play),
|
|
||||||
HalfbackSweep(Play),
|
|
||||||
Mesh(Play),
|
|
||||||
PlayActionBoot(Play),
|
|
||||||
PlayActionComebacks(Play),
|
|
||||||
PlayActionPowerZero(Play),
|
|
||||||
PowerZero(Play),
|
|
||||||
SlantBubble(Play),
|
|
||||||
SlotOut(Play),
|
|
||||||
SpeedOption(Play),
|
|
||||||
StrongFlood(Play),
|
|
||||||
Unknown(Play),
|
|
||||||
Kickoff { offence: Team },
|
|
||||||
Turnover { offence: Team },
|
|
||||||
Penalty { terrain: TerrainState },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
|
||||||
pub enum Down {
|
pub enum Down {
|
||||||
|
#[default]
|
||||||
First,
|
First,
|
||||||
Second,
|
Second,
|
||||||
Third,
|
Third,
|
||||||
Fourth,
|
Fourth,
|
||||||
PointAfterTouchdown,
|
PointAfterTouchdown(Option<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Down {
|
#[derive(Debug, Deserialize, Clone, PartialEq)]
|
||||||
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 {
|
pub enum Team {
|
||||||
ArizonaState,
|
ArizonaState,
|
||||||
#[deprecated(since = "0.2.0", note = "Team left the project.")]
|
#[deprecated(since = "0.2.0", note = "Team left the project.")]
|
||||||
|
|||||||
8
gamelog/src/score.rs
Normal file
8
gamelog/src/score.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use crate::Team;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone, PartialEq)]
|
||||||
|
pub struct ScoreChange {
|
||||||
|
pub team: Team,
|
||||||
|
pub score: u8,
|
||||||
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone)]
|
#[derive(Debug, Deserialize, Clone, Default, PartialEq)]
|
||||||
pub enum TerrainState {
|
pub enum TerrainState {
|
||||||
#[deprecated(since = "0.2.0", note = "Replaced in favour of TerrainState::Yards")]
|
#[deprecated(since = "0.2.0", note = "Replaced in favour of TerrainState::Yards")]
|
||||||
Distance(u8),
|
Distance(u8),
|
||||||
Yards(u8),
|
Yards(u8),
|
||||||
GoalLine,
|
GoalLine,
|
||||||
Inches,
|
Inches,
|
||||||
|
#[default]
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,5 @@ fn main() {
|
|||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(err) => panic!("Error: Failed to open logfile: {:?}", err),
|
Err(err) => panic!("Error: Failed to open logfile: {:?}", err),
|
||||||
};
|
};
|
||||||
|
|
||||||
match file.ensure_compatible() {
|
|
||||||
Ok(f) => f,
|
|
||||||
Err(err) => panic!("Error: Failed to ensure logfile compatibility: {:?}", err),
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user