//! 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::Boss; use chrono::{DateTime, Datelike, Utc}; use num_traits::FromPrimitive as _; /// Filter trait used for filters that operate on complete logs. pub trait LogFilter = Filter; #[derive(Debug, Clone)] struct BossFilter(HashSet); 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::Exclude) } 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) -> Box { Box::new(BossFilter(bosses)) } #[derive(Debug, Clone)] struct OutcomeFilter(HashSet); impl Filter 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) -> Box { Box::new(OutcomeFilter(outcomes)) } /// 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()) } } /// 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 { 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>, 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: DateTime) -> 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: DateTime) -> Box { time(None, Some(when)) }