Improved most_frequent_action method; Introduced LogFile check for improper composition where games have more than two teams.

This commit is contained in:
Cutieguwu
2025-04-26 14:45:25 -04:00
parent fd5d7951f9
commit 352df77645
3 changed files with 55 additions and 55 deletions

View File

@@ -1,29 +1,32 @@
use std::{fmt, io}; use std::{fmt, io};
use ron::de::SpannedError;
#[derive(Debug)] #[derive(Debug)]
pub enum LogFileError { pub enum LogFileError {
FailedToOpen(io::Error), IOError(io::Error),
RonSpannedError(ron::error::SpannedError), RonSpanned(ron::error::SpannedError),
TooManyTeams(usize),
} }
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::IOError(err) => write!(f, "{}", err),
Self::RonSpannedError(err) => write!(f, "{}", err), Self::RonSpanned(err) => write!(f, "{}", err),
Self::TooManyTeams(err) => write!(f, "Expected two, found: {:?}", err),
} }
} }
} }
#[derive(Debug)] impl From<SpannedError> for LogFileError {
pub enum TeamsError { fn from(value: SpannedError) -> Self {
NumberFound(usize), Self::RonSpanned(value)
}
} }
impl fmt::Display for TeamsError { impl From<io::Error> for LogFileError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn from(value: io::Error) -> Self {
match self { Self::IOError(value)
Self::NumberFound(err) => write!(f, "Expected two, found: {:?}", err),
}
} }
} }

View File

@@ -1,4 +1,4 @@
use crate::{Action, Team, error}; use crate::{Action, Play, Team, error};
use serde::Deserialize; use serde::Deserialize;
use std::{fs::File, path::PathBuf}; use std::{fs::File, path::PathBuf};
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
@@ -9,53 +9,57 @@ pub struct LogFile(pub Vec<super::Game>);
impl LogFile { impl LogFile {
/// Returns the most common action for a given team. /// Returns the most common action for a given team.
pub fn most_frequent_action(&self, team: Team) -> Action { pub fn most_frequent_action(&self, team: Team) -> Action {
let mut most_common_action = Action::Unknown; let mut most_freq_action = Action::Unknown;
let mut frequency = 0; let mut frequency = 0;
let team_actions = self
.0
.iter()
.filter_map(|game| Some(game.team_plays(team.to_owned()).0))
.collect::<Vec<Vec<Play>>>()
.concat()
.iter()
.filter_map(|play| Some(play.action.to_owned()))
.collect::<Vec<Action>>()
.into_iter();
for action in Action::iter() { for action in Action::iter() {
if action == Action::Unknown { if action == Action::Unknown {
continue; continue;
} }
// Clean this up? // Clean this up?
let found = self let found: usize = team_actions.clone().filter(|a| *a == action).count();
.0
.iter()
.filter_map(|game| {
Some(
game.team_plays(team.to_owned())
.0
.iter()
.filter_map(|play| {
if play.action == action {
Some(())
} else {
None
}
})
.collect::<Vec<()>>()
.len(),
)
})
.sum::<usize>();
if found > frequency { if found > frequency {
frequency = found; frequency = found;
most_common_action = action.to_owned(); most_freq_action = action.to_owned();
} }
} }
most_common_action most_freq_action
}
pub fn check_teams(self) -> Result<LogFile, error::LogFileError> {
for game in &self.0 {
if let Err(err) = game.teams() {
return Err(err);
}
}
Ok(self)
} }
} }
impl TryFrom<File> for LogFile { impl TryFrom<File> for LogFile {
type Error = ron::error::SpannedError; type Error = error::LogFileError;
fn try_from(file: File) -> Result<Self, Self::Error> { fn try_from(file: File) -> Result<LogFile, Self::Error> {
ron::Options::default() let file: LogFile = ron::Options::default()
.with_default_extension(ron::extensions::Extensions::EXPLICIT_STRUCT_NAMES) .with_default_extension(ron::extensions::Extensions::EXPLICIT_STRUCT_NAMES)
.from_reader(file) .from_reader(file)?;
file.check_teams()
} }
} }
@@ -63,17 +67,10 @@ impl TryFrom<PathBuf> for LogFile {
type Error = error::LogFileError; type Error = error::LogFileError;
fn try_from(path: PathBuf) -> Result<Self, Self::Error> { fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
match Self::try_from( Self::try_from(
match std::fs::OpenOptions::new() // Defaults to setting all options false. std::fs::OpenOptions::new() // Defaults to setting all options false.
.read(true) // Only need ensure that reading is possible. .read(true) // Only need ensure that reading is possible.
.open(path.as_path()) .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)),
}
} }
} }

View File

@@ -11,7 +11,7 @@ pub struct Game {
impl Game { impl Game {
/// Returns the teams that played. /// Returns the teams that played.
pub fn teams(&self) -> Result<Vec<Team>, error::TeamsError> { pub fn teams(&self) -> Result<Vec<Team>, error::LogFileError> {
let ignore: Vec<Team> = self let ignore: Vec<Team> = self
.flags .flags
.iter() .iter()
@@ -37,7 +37,7 @@ impl Game {
if teams.len() == 2 || ignore.len() != 0 { if teams.len() == 2 || ignore.len() != 0 {
Ok(teams) Ok(teams)
} else { } else {
Err(error::TeamsError::NumberFound(teams.len())) Err(error::LogFileError::TooManyTeams(teams.len()))
} }
} }