aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs43
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),