diff options
Diffstat (limited to 'src/filters/log.rs')
-rw-r--r-- | src/filters/log.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/filters/log.rs b/src/filters/log.rs new file mode 100644 index 0000000..8d4e0b5 --- /dev/null +++ b/src/filters/log.rs @@ -0,0 +1,130 @@ +//! 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<PartialEvtc, LogResult>; + +#[derive(Debug, Clone)] +struct BossFilter(HashSet<Boss>); + +impl Filter<PartialEvtc, LogResult> 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) + } +} + +/// A `LogFilter` that only accepts logs with one of the given bosses. +pub fn boss(bosses: HashSet<Boss>) -> Box<dyn LogFilter> { + Box::new(BossFilter(bosses)) +} + + +#[derive(Debug, Clone)] +struct OutcomeFilter(HashSet<FightOutcome>); + +impl Filter<PartialEvtc, LogResult> for OutcomeFilter { + fn filter(&self, log: &LogResult) -> bool { + self.0.contains(&log.outcome) + } +} + +/// A `LogFilter` that only accepts logs with one of the given outcomes. +/// +/// See also [`success`][success] and [`wipe`][wipe]. +pub fn outcome(outcomes: HashSet<FightOutcome>) -> Box<dyn LogFilter> { + Box::new(OutcomeFilter(outcomes)) +} + +/// A `LogFilter` that only accepts successful logs. +/// +/// See also [`outcome`][outcome] and [`wipe`][wipe]. +pub fn success() -> Box<dyn LogFilter> { + 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<dyn LogFilter> { + let mut outcomes = HashSet::new(); + outcomes.insert(FightOutcome::Wipe); + outcome(outcomes) +} + +#[derive(Debug, Clone)] +struct WeekdayFilter(HashSet<Weekday>); + +impl Filter<PartialEvtc, LogResult> for WeekdayFilter { + fn filter(&self, log: &LogResult) -> bool { + self.0.contains(&log.time.weekday()) + } +} + +/// A `LogFilter` that only accepts logs if they were done on one of the given weekdays. +pub fn weekday(weekdays: HashSet<Weekday>) -> Box<dyn LogFilter> { + Box::new(WeekdayFilter(weekdays)) +} + + +#[derive(Debug, Clone)] +struct TimeFilter(Option<NaiveDateTime>, Option<NaiveDateTime>); + +impl Filter<PartialEvtc, LogResult> 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 + } +} + +/// 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<NaiveDateTime>, upper: Option<NaiveDateTime>) -> Box<dyn LogFilter> { + 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<dyn LogFilter> { + 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<dyn LogFilter> { + time(None, Some(when)) +} |