diff options
| author | Daniel <kingdread@gmx.de> | 2021-11-19 22:04:50 +0100 | 
|---|---|---|
| committer | Daniel <kingdread@gmx.de> | 2021-11-19 22:04:50 +0100 | 
| commit | 53123d5ab01f2b6ee0282ff067ba39e10b28528e (patch) | |
| tree | 11c616ea7a20be3f7e9f8688c2d5d3134359731d /src | |
| parent | 0c634d3c2d279ef75347ac635b69d396d5bf695a (diff) | |
| parent | a7682465132e4758bd50777f17a7c4b2048b4c8c (diff) | |
| download | raidgrep-53123d5ab01f2b6ee0282ff067ba39e10b28528e.tar.gz raidgrep-53123d5ab01f2b6ee0282ff067ba39e10b28528e.tar.bz2 raidgrep-53123d5ab01f2b6ee0282ff067ba39e10b28528e.zip | |
Merge branch 'gamemode-filters'
Diffstat (limited to 'src')
| -rw-r--r-- | src/fexpr/grammar.lalrpop | 17 | ||||
| -rw-r--r-- | src/fexpr/mod.rs | 2 | ||||
| -rw-r--r-- | src/filters/log.rs | 29 | ||||
| -rw-r--r-- | src/main.rs | 20 | ||||
| -rw-r--r-- | src/output/formats.rs | 59 | ||||
| -rw-r--r-- | src/output/sorting.rs | 7 | 
6 files changed, 105 insertions, 29 deletions
| diff --git a/src/fexpr/grammar.lalrpop b/src/fexpr/grammar.lalrpop index ce78396..bca7691 100644 --- a/src/fexpr/grammar.lalrpop +++ b/src/fexpr/grammar.lalrpop @@ -9,7 +9,7 @@ use super::{      DurationProducer,      CountProducer,  }; -use evtclib::Encounter; +use evtclib::{Encounter, GameMode};  use std::collections::HashSet;  use lalrpop_util::ParseError; @@ -64,6 +64,12 @@ LogPredicate: Box<dyn filters::log::LogFilter> = {      "-boss" <Comma<Encounter>> => filters::log::encounter(<>),      "-cm" => filters::log::challenge_mote(), +    "-raid" => filters::log::game_mode([GameMode::Raid].into()), +    "-fractal" => filters::log::game_mode([GameMode::Fractal].into()), +    "-strike" => filters::log::game_mode([GameMode::Strike].into()), +    "-wvw" => filters::log::game_mode([GameMode::WvW].into()), +    "-gamemode" <Comma<GameMode>> => filters::log::game_mode(<>), +      "-include" => filters::constant(true),      "-exclude" => filters::constant(false), @@ -150,6 +156,15 @@ Encounter: Encounter = {      }),  } +GameMode: GameMode = { +    <l:@L> <w:word> =>? w.parse().map_err(|_| ParseError::User { +        error: FError { +            location: l, +            kind: FErrorKind::GameMode, +        } +    }), +} +  PlayerClass: PlayerClass = {      <l:@L> <w:word> =>? w.parse().map_err(|_| ParseError::User {          error: FError { diff --git a/src/fexpr/mod.rs b/src/fexpr/mod.rs index 0fe2acf..6eeb753 100644 --- a/src/fexpr/mod.rs +++ b/src/fexpr/mod.rs @@ -51,6 +51,8 @@ pub enum FErrorKind {      Boss,      #[error("invalid class name")]      Class, +    #[error("invalid game mode")] +    GameMode,  }  /// Shortcut to create a new parser and parse the given input. diff --git a/src/filters/log.rs b/src/filters/log.rs index ac166e1..c878b78 100644 --- a/src/filters/log.rs +++ b/src/filters/log.rs @@ -9,7 +9,7 @@ use super::{  use std::collections::HashSet; -use evtclib::Encounter; +use evtclib::{Encounter, GameMode};  use chrono::{DateTime, Datelike, Utc, Weekday}; @@ -37,6 +37,33 @@ pub fn encounter(bosses: HashSet<Encounter>) -> Box<dyn LogFilter> {  }  #[derive(Debug, Clone)] +struct GameModeFilter(HashSet<GameMode>); + +impl Filter<EarlyLogResult, LogResult> for GameModeFilter { +    fn filter_early(&self, early_log: &EarlyLogResult) -> Inclusion { +        let encounter_id = early_log.evtc.header.combat_id; +        // Special WvW encounter +        const GENERIC_ENCOUNTER_ID: u16 = 1; +        let mode = if encounter_id == GENERIC_ENCOUNTER_ID { +            Some(GameMode::WvW) +        } else { +            Encounter::from_header_id(encounter_id).map(Encounter::game_mode) +        }; +        mode.map(|m| self.0.contains(&m).into()) +            .unwrap_or(Inclusion::Exclude) +    } + +    fn filter(&self, log: &LogResult) -> bool { +        log.game_mode.map(|m| self.0.contains(&m)).unwrap_or(false) +    } +} + +/// A [`LogFilter`] that only accepts logs with the given game mode. +pub fn game_mode(game_modes: HashSet<GameMode>) -> Box<dyn LogFilter> { +    Box::new(GameModeFilter(game_modes)) +} + +#[derive(Debug, Clone)]  struct OutcomeFilter(HashSet<FightOutcome>);  impl Filter<EarlyLogResult, LogResult> for OutcomeFilter { diff --git a/src/main.rs b/src/main.rs index b35f769..365a400 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ use structopt::StructOpt;  use walkdir::{DirEntry, WalkDir};  use evtclib::raw::parser::PartialEvtc; -use evtclib::{Encounter, EventKind, Log, Outcome}; +use evtclib::{Encounter, EventKind, GameMode, Log, Outcome};  mod fexpr;  mod filters; @@ -61,16 +61,23 @@ const RETCODE_ERROR: i32 = 2;  ///     -after DATE             Only include logs from after the given date.  ///     -boss BOSSES            Only include logs from the given bosses.  ///     -cm                     Only include logs with challenge mote enabled. +///     -gamemode MODE          Only include logs from the given game modes. +///     -raid                   Only include raid logs. +///     -fractal                Only include fractal logs. +///     -strike                 Only include strike mission logs. +///     -golem                  Only include golem logs. +///     -wvw                    Only include WvW logs.  ///     -player REGEX           Shorthand to check if any player in the log has the given name.  ///     -include                Always evaluates to including the log.  ///     -exclude                Always evaluates to excluding the log.  ///  /// BOSS NAMES:  ///     The following names can be used with the -boss filter: -///       vg, gorseval, sabetha, slothasor, matthias, kc, xera, cairn, -///       mo, samarog, deimos, desmina, dhuum, ca, largos, qadim, -///       adina, sabir, qadimp, ai, skorvald, artsariiv, arkk, mama, siax, -///       ensolyss, icebrood, fraenir, kodans, boneskinner, whisper. +///       vg, gorseval, sabetha, slothasor, trio, matthias, kc, xera, cairn, +///       mo, samarog, deimos, desmina, river, broken king, eater, eyes, +///       dhuum, ca, largos, qadim, adina, sabir, qadimp, ai, skorvald, +///       artsariiv, arkk, mama, siax, ensolyss, icebrood, fraenir, kodans, +///       boneskinner, whisper, standard golem, medium golem, large golem.  ///     Names can also be comma separated.  #[derive(StructOpt, Debug)]  #[structopt(verbatim_doc_comment)] @@ -180,6 +187,8 @@ pub struct LogResult {      outcome: FightOutcome,      /// Whether the fight had the Challenge Mote turned on.      is_cm: bool, +    /// The game mode of the fight. +    game_mode: Option<GameMode>,  }  /// A player. @@ -578,6 +587,7 @@ fn extract_info(path: &Path, log: &Log) -> LogResult {          players,          outcome: get_fight_outcome(log),          is_cm: log.is_cm(), +        game_mode: log.game_mode(),      }  } diff --git a/src/output/formats.rs b/src/output/formats.rs index d22ab19..47da57e 100644 --- a/src/output/formats.rs +++ b/src/output/formats.rs @@ -5,6 +5,7 @@ use super::super::guilds;  use super::{FightOutcome, LogResult};  use chrono::Local; +use evtclib::GameMode;  /// An output format  pub trait Format: Sync + Send { @@ -30,27 +31,43 @@ impl Format for HumanReadable {              item.log_file.to_string_lossy()          )          .expect("writing to String failed"); -        let outcome = match item.outcome { -            FightOutcome::Success => "SUCCESS".green(), -            FightOutcome::Wipe => "WIPE".red(), -        }; -        writeln!( -            result, -            "{}: {} - {}: {}{} {} after {}", -            "Date".green(), -            item.time -                .with_timezone(&Local) -                .format("%Y-%m-%d %H:%M:%S %a"), -            "Boss".green(), -            item.encounter -                .map(|x| x.to_string()) -                .unwrap_or_else(|| "unknown".into()), -            if item.is_cm { " CM" } else { "" }, -            outcome, -            humantime::Duration::from(item.duration.to_std().unwrap()), -        ) -        .expect("writing to String failed"); -        for player in &item.players { + +        if item.game_mode != Some(GameMode::WvW) { +            let outcome = match item.outcome { +                FightOutcome::Success => "SUCCESS".green(), +                FightOutcome::Wipe => "WIPE".red(), +            }; +            writeln!( +                result, +                "{}: {} - {}: {}{} {} after {}", +                "Date".green(), +                item.time +                    .with_timezone(&Local) +                    .format("%Y-%m-%d %H:%M:%S %a"), +                "Boss".green(), +                item.encounter +                    .map(|x| x.to_string()) +                    .unwrap_or_else(|| "unknown".into()), +                if item.is_cm { " CM" } else { "" }, +                outcome, +                humantime::Duration::from(item.duration.to_std().unwrap()), +            ) +            .expect("writing to String failed"); +        } else { +            writeln!( +                result, +                "{}: {} - {} ended after {}", +                "Date".green(), +                item.time +                    .with_timezone(&Local) +                    .format("%Y-%m-%d %H:%M:%S %a"), +                "World vs. World".green(), +                humantime::Duration::from(item.duration.to_std().unwrap()), +            ) +            .expect("writing to String failed"); +        } + +        for player in item.players.iter().filter(|p| !p.account_name.is_empty()) {              write!(                  result,                  "  {:2} {:20} {:19} {:12}", diff --git a/src/output/sorting.rs b/src/output/sorting.rs index 234d804..27ea1e1 100644 --- a/src/output/sorting.rs +++ b/src/output/sorting.rs @@ -135,7 +135,7 @@ mod tests {      use super::*;      use chrono::prelude::*; -    use evtclib::Encounter as E; +    use evtclib::{Encounter as E, GameMode};      #[test]      fn test_parse_component() { @@ -179,6 +179,7 @@ mod tests {                  players: vec![],                  outcome: FightOutcome::Success,                  is_cm: false, +                game_mode: Some(GameMode::Raid),              },              &LogResult {                  log_file: "".into(), @@ -188,6 +189,7 @@ mod tests {                  players: vec![],                  outcome: FightOutcome::Success,                  is_cm: false, +                game_mode: Some(GameMode::Raid),              },              &LogResult {                  log_file: "".into(), @@ -197,6 +199,7 @@ mod tests {                  players: vec![],                  outcome: FightOutcome::Success,                  is_cm: false, +                game_mode: Some(GameMode::Raid),              },              &LogResult {                  log_file: "".into(), @@ -206,6 +209,7 @@ mod tests {                  players: vec![],                  outcome: FightOutcome::Success,                  is_cm: false, +                game_mode: Some(GameMode::Raid),              },              &LogResult {                  log_file: "".into(), @@ -215,6 +219,7 @@ mod tests {                  players: vec![],                  outcome: FightOutcome::Success,                  is_cm: false, +                game_mode: Some(GameMode::Raid),              },          ]; | 
