From ba491c8a5f6c8c2fa86b12dacf9d80f92da9168a Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 17 Apr 2020 15:18:20 +0200 Subject: split off player filters and log filters As it turns out, we can easily re-use the existing Filter machinery to generalize over LogFilters (which operate on LogResults) and PlayerFilters (which operate on Players). The feature trait_aliases is not strictly needed but makes the function signatures a bit nicer and easier to read, and it reduces the chances of an error (e.g. by using Filter<&PartialEvtc, ...>). --- src/filters/log.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/filters/log.rs (limited to 'src/filters/log.rs') diff --git a/src/filters/log.rs b/src/filters/log.rs new file mode 100644 index 0000000..ded4c44 --- /dev/null +++ b/src/filters/log.rs @@ -0,0 +1,95 @@ +//! This module contains specific filters that operate on log files. +//! +//! This is the "base unit", as each file corresponds to one log. Filters on other items (such as +//! players) have to be lifted into log filters first. +use super::{ + super::{FightOutcome, LogResult, Weekday}, + Filter, Inclusion, +}; + +use std::collections::HashSet; + +use evtclib::raw::parser::PartialEvtc; +use evtclib::statistics::gamedata::Boss; + +use chrono::{Datelike, NaiveDateTime}; +use num_traits::FromPrimitive as _; + +/// Filter trait used for filters that operate on complete logs. +pub trait LogFilter = Filter; + +#[derive(Debug, Clone)] +pub struct BossFilter(HashSet); + +impl BossFilter { + pub fn new(bosses: HashSet) -> Box { + Box::new(BossFilter(bosses)) + } +} + +impl Filter for BossFilter { + fn filter_early(&self, partial_evtc: &PartialEvtc) -> Inclusion { + let boss = Boss::from_u16(partial_evtc.header.combat_id); + boss.map(|b| self.0.contains(&b).into()) + .unwrap_or(Inclusion::Include) + } + + fn filter(&self, log: &LogResult) -> bool { + let boss = Boss::from_u16(log.boss_id); + boss.map(|b| self.0.contains(&b)).unwrap_or(false) + } +} + +#[derive(Debug, Clone)] +pub struct OutcomeFilter(HashSet); + +impl OutcomeFilter { + pub fn new(outcomes: HashSet) -> Box { + Box::new(OutcomeFilter(outcomes)) + } +} + +impl Filter for OutcomeFilter { + fn filter(&self, log: &LogResult) -> bool { + self.0.contains(&log.outcome) + } +} + +#[derive(Debug, Clone)] +pub struct WeekdayFilter(HashSet); + +impl WeekdayFilter { + pub fn new(weekdays: HashSet) -> Box { + Box::new(WeekdayFilter(weekdays)) + } +} + +impl Filter for WeekdayFilter { + fn filter(&self, log: &LogResult) -> bool { + self.0.contains(&log.time.weekday()) + } +} + +#[derive(Debug, Clone)] +pub struct TimeFilter(Option, Option); + +impl TimeFilter { + pub fn new(after: Option, before: Option) -> Box { + Box::new(TimeFilter(after, before)) + } +} + +impl Filter for TimeFilter { + fn filter(&self, log: &LogResult) -> bool { + let after_ok = match self.0 { + Some(time) => time <= log.time, + None => true, + }; + let before_ok = match self.1 { + Some(time) => time >= log.time, + None => true, + }; + + after_ok && before_ok + } +} -- cgit v1.2.3 From 7030224fd2a97b3551fdd47c43249e3a42341238 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 18 Apr 2020 15:10:59 +0200 Subject: make filters Debug It's nice if you can print out the filter tree for debugging, so we're requireing filters to be Debug now. --- src/filters/log.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/filters/log.rs') diff --git a/src/filters/log.rs b/src/filters/log.rs index ded4c44..8b84bf3 100644 --- a/src/filters/log.rs +++ b/src/filters/log.rs @@ -47,6 +47,18 @@ impl OutcomeFilter { pub fn new(outcomes: HashSet) -> Box { Box::new(OutcomeFilter(outcomes)) } + + pub fn success() -> Box { + let mut outcomes = HashSet::new(); + outcomes.insert(FightOutcome::Success); + Self::new(outcomes) + } + + pub fn wipe() -> Box { + let mut outcomes = HashSet::new(); + outcomes.insert(FightOutcome::Wipe); + Self::new(outcomes) + } } impl Filter for OutcomeFilter { -- cgit v1.2.3 From 5dbea93266c3a30dac5ec6f5a7915d73a440f573 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 25 Apr 2020 13:14:30 +0200 Subject: use free functions instead of Filter::new Having a ::new on each of the filter types was a bit weird, especially because we returned Box instead of Self (and clippy rightfully complained). With this patch, we now have a bunch of normal functions, and we don't show to the outside how a filter is actually implemented (or what struct is behind it). --- src/filters/log.rs | 99 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 38 deletions(-) (limited to 'src/filters/log.rs') diff --git a/src/filters/log.rs b/src/filters/log.rs index 8b84bf3..8d4e0b5 100644 --- a/src/filters/log.rs +++ b/src/filters/log.rs @@ -19,13 +19,7 @@ use num_traits::FromPrimitive as _; pub trait LogFilter = Filter; #[derive(Debug, Clone)] -pub struct BossFilter(HashSet); - -impl BossFilter { - pub fn new(bosses: HashSet) -> Box { - Box::new(BossFilter(bosses)) - } -} +struct BossFilter(HashSet); impl Filter for BossFilter { fn filter_early(&self, partial_evtc: &PartialEvtc) -> Inclusion { @@ -40,26 +34,14 @@ impl Filter for BossFilter { } } -#[derive(Debug, Clone)] -pub struct OutcomeFilter(HashSet); - -impl OutcomeFilter { - pub fn new(outcomes: HashSet) -> Box { - Box::new(OutcomeFilter(outcomes)) - } +/// A `LogFilter` that only accepts logs with one of the given bosses. +pub fn boss(bosses: HashSet) -> Box { + Box::new(BossFilter(bosses)) +} - pub fn success() -> Box { - let mut outcomes = HashSet::new(); - outcomes.insert(FightOutcome::Success); - Self::new(outcomes) - } - pub fn wipe() -> Box { - let mut outcomes = HashSet::new(); - outcomes.insert(FightOutcome::Wipe); - Self::new(outcomes) - } -} +#[derive(Debug, Clone)] +struct OutcomeFilter(HashSet); impl Filter for OutcomeFilter { fn filter(&self, log: &LogResult) -> bool { @@ -67,30 +49,49 @@ impl Filter for OutcomeFilter { } } -#[derive(Debug, Clone)] -pub struct WeekdayFilter(HashSet); +/// A `LogFilter` that only accepts logs with one of the given outcomes. +/// +/// See also [`success`][success] and [`wipe`][wipe]. +pub fn outcome(outcomes: HashSet) -> Box { + Box::new(OutcomeFilter(outcomes)) +} -impl WeekdayFilter { - pub fn new(weekdays: HashSet) -> Box { - Box::new(WeekdayFilter(weekdays)) - } +/// A `LogFilter` that only accepts successful logs. +/// +/// See also [`outcome`][outcome] and [`wipe`][wipe]. +pub fn success() -> Box { + let mut outcomes = HashSet::new(); + outcomes.insert(FightOutcome::Success); + outcome(outcomes) +} + +/// A `LogFilter` that only accepts failed logs. +/// +/// See also [`outcome`][outcome] and [`success`][wipe]. +pub fn wipe() -> Box { + let mut outcomes = HashSet::new(); + outcomes.insert(FightOutcome::Wipe); + outcome(outcomes) } +#[derive(Debug, Clone)] +struct WeekdayFilter(HashSet); + impl Filter for WeekdayFilter { fn filter(&self, log: &LogResult) -> bool { self.0.contains(&log.time.weekday()) } } -#[derive(Debug, Clone)] -pub struct TimeFilter(Option, Option); - -impl TimeFilter { - pub fn new(after: Option, before: Option) -> Box { - Box::new(TimeFilter(after, before)) - } +/// A `LogFilter` that only accepts logs if they were done on one of the given weekdays. +pub fn weekday(weekdays: HashSet) -> Box { + Box::new(WeekdayFilter(weekdays)) } + +#[derive(Debug, Clone)] +struct TimeFilter(Option, Option); + impl Filter for TimeFilter { fn filter(&self, log: &LogResult) -> bool { let after_ok = match self.0 { @@ -105,3 +106,25 @@ impl Filter for TimeFilter { after_ok && before_ok } } + +/// A `LogFilter` that only accepts logs in the given time frame. +/// +/// If a bound is not given, -Infinity is assumed for the lower bound, and Infinity for the upper +/// bound. +pub fn time(lower: Option, upper: Option) -> Box { + Box::new(TimeFilter(lower, upper)) +} + +/// A `LogFilter` that only accepts logs after the given date. +/// +/// Also see [`time`][time] and [`before`][before]. +pub fn after(when: NaiveDateTime) -> Box { + time(Some(when), None) +} + +/// A `LogFilter` that only accepts logs before the given date. +/// +/// Also see [`time`][time] and [`after`][after]. +pub fn before(when: NaiveDateTime) -> Box { + time(None, Some(when)) +} -- cgit v1.2.3