diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 43 |
1 files changed, 31 insertions, 12 deletions
diff --git a/src/main.rs b/src/main.rs index 6b67875..41df732 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,15 +6,16 @@ use std::str::FromStr; use anyhow::{anyhow, Result}; use chrono::{Duration, NaiveDateTime, Weekday}; +use log::debug; use num_traits::cast::FromPrimitive; use regex::Regex; use structopt::StructOpt; use walkdir::{DirEntry, WalkDir}; -use log::debug; use evtclib::{AgentKind, AgentName, EventKind, Log}; mod filters; +use filters::{Filter, Inclusion}; mod guilds; mod logger; mod output; @@ -32,7 +33,6 @@ macro_rules! unwrap { }; } - /// A program that allows you to search through all your evtc logs for specific /// people. #[derive(StructOpt, Debug)] @@ -106,7 +106,7 @@ pub struct Opt { /// A flag indicating which fields should be searched. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -enum SearchField { +pub enum SearchField { /// Only search the account name. Account, /// Only search the character name. @@ -135,6 +135,8 @@ pub struct LogResult { log_file: PathBuf, /// The time of the recording. time: NaiveDateTime, + /// The numeric ID of the boss. + boss_id: u16, /// The name of the boss. boss_name: String, /// A vector of all participating players. @@ -258,16 +260,36 @@ fn is_log_file(entry: &DirEntry) -> bool { .unwrap_or(false) } +fn build_filter(opt: &Opt) -> Box<dyn Filter> { + let mut filter = filters::Const::new(false); + for field in opt.field.values() { + filter = filter | filters::NameFilter::new(*field, opt.expression.clone()); + } + + if opt.invert { + filter = !filter; + } + + filter = filter + & filters::BossFilter::new(opt.bosses.values().clone()) + & filters::OutcomeFilter::new(opt.outcome.values().clone()) + & filters::WeekdayFilter::new(opt.weekdays.values().clone()) + & filters::TimeFilter::new(opt.after, opt.before); + + filter +} + /// Run the grep search with the given options. fn grep(opt: &Opt) -> Result<()> { let pipeline = &output::build_pipeline(opt); + let filter: &dyn Filter = &*build_filter(opt); rayon::scope(|s| { let walker = WalkDir::new(&opt.path); for entry in walker { let entry = entry?; s.spawn(move |_| { if is_log_file(&entry) { - let search = search_log(&entry, opt); + let search = search_log(&entry, filter); match search { Ok(None) => (), Ok(Some(result)) => pipeline.push_item(&result), @@ -287,7 +309,7 @@ fn grep(opt: &Opt) -> Result<()> { /// If the log matches, returns `Ok(Some(..))`. /// If the log doesn't match, returns `Ok(None)`. /// If there was a fatal error, returns `Err(..)`. -fn search_log(entry: &DirEntry, opt: &Opt) -> Result<Option<LogResult>> { +fn search_log(entry: &DirEntry, filter: &dyn Filter) -> Result<Option<LogResult>> { let file_stream = BufReader::new(File::open(entry.path())?); let is_zip = entry .file_name() @@ -302,10 +324,9 @@ fn search_log(entry: &DirEntry, opt: &Opt) -> Result<Option<LogResult>> { let mut stream = wrapper.get_stream(); let partial = evtclib::raw::parser::parse_partial_file(&mut stream)?; - let early_ok = - filters::filter_name(&partial, opt) != opt.invert && filters::filter_boss(&partial, opt); + let early_ok = filter.filter_early(&partial); - if !early_ok { + if early_ok == Inclusion::Exclude { return Ok(None); } @@ -320,10 +341,7 @@ fn search_log(entry: &DirEntry, opt: &Opt) -> Result<Option<LogResult>> { let info = extract_info(entry, &log); - let take_log = filters::filter_outcome(&info, opt) - && filters::filter_weekday(&info, opt) - && filters::filter_time(&info, opt) - && filters::filter_guilds(&info, opt); + let take_log = filter.filter(&info); if take_log { Ok(Some(info)) @@ -372,6 +390,7 @@ fn extract_info(entry: &DirEntry, log: &Log) -> LogResult { LogResult { log_file: entry.path().to_path_buf(), time: NaiveDateTime::from_timestamp(i64::from(get_start_timestamp(log)), 0), + boss_id: log.boss_id(), boss_name, players, outcome: get_fight_outcome(log), |