From 352df776454c44418b034d0e1df676d885a72b46 Mon Sep 17 00:00:00 2001 From: Cutieguwu Date: Sat, 26 Apr 2025 14:45:25 -0400 Subject: [PATCH] Improved most_frequent_action method; Introduced LogFile check for improper composition where games have more than two teams. --- gamelog/src/error.rs | 31 +++++++++--------- gamelog/src/file.rs | 75 +++++++++++++++++++++----------------------- gamelog/src/game.rs | 4 +-- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/gamelog/src/error.rs b/gamelog/src/error.rs index c3e135f..a599914 100644 --- a/gamelog/src/error.rs +++ b/gamelog/src/error.rs @@ -1,29 +1,32 @@ use std::{fmt, io}; +use ron::de::SpannedError; + #[derive(Debug)] pub enum LogFileError { - FailedToOpen(io::Error), - RonSpannedError(ron::error::SpannedError), + IOError(io::Error), + RonSpanned(ron::error::SpannedError), + TooManyTeams(usize), } impl fmt::Display for LogFileError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::FailedToOpen(err) => write!(f, "{}", err), - Self::RonSpannedError(err) => write!(f, "{}", err), + Self::IOError(err) => write!(f, "{}", err), + Self::RonSpanned(err) => write!(f, "{}", err), + Self::TooManyTeams(err) => write!(f, "Expected two, found: {:?}", err), } } } -#[derive(Debug)] -pub enum TeamsError { - NumberFound(usize), -} - -impl fmt::Display for TeamsError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::NumberFound(err) => write!(f, "Expected two, found: {:?}", err), - } +impl From for LogFileError { + fn from(value: SpannedError) -> Self { + Self::RonSpanned(value) + } +} + +impl From for LogFileError { + fn from(value: io::Error) -> Self { + Self::IOError(value) } } diff --git a/gamelog/src/file.rs b/gamelog/src/file.rs index e74930e..bb611dd 100644 --- a/gamelog/src/file.rs +++ b/gamelog/src/file.rs @@ -1,4 +1,4 @@ -use crate::{Action, Team, error}; +use crate::{Action, Play, Team, error}; use serde::Deserialize; use std::{fs::File, path::PathBuf}; use strum::IntoEnumIterator; @@ -9,53 +9,57 @@ pub struct LogFile(pub Vec); impl LogFile { /// Returns the most common action for a given team. 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 team_actions = self + .0 + .iter() + .filter_map(|game| Some(game.team_plays(team.to_owned()).0)) + .collect::>>() + .concat() + .iter() + .filter_map(|play| Some(play.action.to_owned())) + .collect::>() + .into_iter(); + for action in Action::iter() { if action == Action::Unknown { continue; } // Clean this up? - let found = self - .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::>() - .len(), - ) - }) - .sum::(); + let found: usize = team_actions.clone().filter(|a| *a == action).count(); if found > frequency { 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 { + for game in &self.0 { + if let Err(err) = game.teams() { + return Err(err); + } + } + + Ok(self) } } impl TryFrom for LogFile { - type Error = ron::error::SpannedError; + type Error = error::LogFileError; - fn try_from(file: File) -> Result { - ron::Options::default() + fn try_from(file: File) -> Result { + let file: LogFile = ron::Options::default() .with_default_extension(ron::extensions::Extensions::EXPLICIT_STRUCT_NAMES) - .from_reader(file) + .from_reader(file)?; + + file.check_teams() } } @@ -63,17 +67,10 @@ 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. + Self::try_from( + 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)), - } + .open(path.as_path())?, + ) } } diff --git a/gamelog/src/game.rs b/gamelog/src/game.rs index 6da7012..54cdd7c 100644 --- a/gamelog/src/game.rs +++ b/gamelog/src/game.rs @@ -11,7 +11,7 @@ pub struct Game { impl Game { /// Returns the teams that played. - pub fn teams(&self) -> Result, error::TeamsError> { + pub fn teams(&self) -> Result, error::LogFileError> { let ignore: Vec = self .flags .iter() @@ -37,7 +37,7 @@ impl Game { if teams.len() == 2 || ignore.len() != 0 { Ok(teams) } else { - Err(error::TeamsError::NumberFound(teams.len())) + Err(error::LogFileError::TooManyTeams(teams.len())) } }