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 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<SpannedError> for LogFileError {
fn from(value: SpannedError) -> Self {
Self::RonSpanned(value)
}
}
impl From<io::Error> for LogFileError {
fn from(value: io::Error) -> Self {
Self::IOError(value)
}
}

View File

@@ -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<super::Game>);
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::<Vec<Vec<Play>>>()
.concat()
.iter()
.filter_map(|play| Some(play.action.to_owned()))
.collect::<Vec<Action>>()
.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::<Vec<()>>()
.len(),
)
})
.sum::<usize>();
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<LogFile, error::LogFileError> {
for game in &self.0 {
if let Err(err) = game.teams() {
return Err(err);
}
}
Ok(self)
}
}
impl TryFrom<File> for LogFile {
type Error = ron::error::SpannedError;
type Error = error::LogFileError;
fn try_from(file: File) -> Result<Self, Self::Error> {
ron::Options::default()
fn try_from(file: File) -> Result<LogFile, Self::Error> {
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<PathBuf> for LogFile {
type Error = error::LogFileError;
fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
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())?,
)
}
}

View File

@@ -11,7 +11,7 @@ pub struct Game {
impl Game {
/// 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
.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()))
}
}