Improved most_frequent_action method; Introduced LogFile check for improper composition where games have more than two teams.
This commit is contained in:
@@ -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 {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
impl From<io::Error> for LogFileError {
|
||||||
match self {
|
fn from(value: io::Error) -> Self {
|
||||||
Self::NumberFound(err) => write!(f, "Expected two, found: {:?}", err),
|
Self::IOError(value)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user