aboutsummaryrefslogtreecommitdiff
path: root/src/analyzers/mod.rs
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2020-07-24 14:23:53 +0200
committerDaniel Schadt <kingdread@gmx.de>2020-07-24 14:23:53 +0200
commit71528905ed228750559a41144a2e0a95db3e6805 (patch)
tree4e46c6cbd3a3e83ab707e7156b345fbe7f3048ea /src/analyzers/mod.rs
parent01354b0934409c355831bb4202f998fe5dbdc335 (diff)
parent9d27ec7034f9ad07d8a1d74ab30fdc470de4e02d (diff)
downloadevtclib-71528905ed228750559a41144a2e0a95db3e6805.tar.gz
evtclib-71528905ed228750559a41144a2e0a95db3e6805.tar.bz2
evtclib-71528905ed228750559a41144a2e0a95db3e6805.zip
Merge branch 'analyzers'
This brings in proper fight outcome detection, which is nice and needed for downstream applications (raidgrep/ezau). Furthermore, this cleans up the CM detection a bit by moving away from the "descriptive" trigger way to just having dynamically dispatched methods for every log.
Diffstat (limited to 'src/analyzers/mod.rs')
-rw-r--r--src/analyzers/mod.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/analyzers/mod.rs b/src/analyzers/mod.rs
new file mode 100644
index 0000000..d6315f3
--- /dev/null
+++ b/src/analyzers/mod.rs
@@ -0,0 +1,121 @@
+//! Traits and structures to analyze fights.
+//!
+//! Fights need different logic in order to determine specific data, for example each fight has a
+//! different way to determine whether or not the Challenge Mote was activated, whether or not the
+//! fight was successful, ...
+//!
+//! This module aims to unify that logic by providing the [`Analyzer`][Analyzer] trait, which
+//! provides a unified interface to query this information. You can use
+//! [`Log::analyzer`][Log::analyzer] or [`for_log`][for_log] to obtain an analyzer fitting for the
+//! encounter that is represented by the log.
+//!
+//! Most of the time, you will be dealing with a dynamically dispatched version of
+//! [`Analyzer`][Analyzer], that is either `&dyn Analyzer` or `Box<dyn Analyzer>`. Also keep in
+//! mind that an analyzer keeps a reference to the log that it is analyzing, which can be accessed
+//! through [`Analyzer::log`][Analyzer::log].
+//!
+//! The implementation of the different analyzers is split off in different submodules:
+//! * [`raids`][raids] for the raid-related encounters.
+//! * [`fractals`][fractals] for the fractal-specific encounters.
+//! * [`strikes`][strikes] for the strike-mission specific encounters.
+//!
+//! Note that you should not create concrete analyzers on your own, as the behaviour is not
+//! specified when you use a wrong analyzer for the given log. Rely only on
+//! [`Log::analyzer`][Log::analyzer] (or [`for_log`][for_log]) and the methods defined in
+//! [`Analyzer`][Analyzer].
+
+use crate::{Boss, Log};
+
+pub mod fractals;
+pub mod helpers;
+pub mod raids;
+pub mod strikes;
+
+/// The outcome of a fight.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum Outcome {
+ /// The fight succeeded.
+ Success,
+ /// The fight failed, i.e. the group wiped.
+ Failure,
+}
+
+impl Outcome {
+ /// A function that turns a boolean into an [`Outcome`][Outcome].
+ ///
+ /// This is a convenience function that can help implementing
+ /// [`Analyzer::outcome`][Analyzer::outcome], which is also why this function returns an Option
+ /// instead of the outcome directly.
+ ///
+ /// This turns `true` into [`Outcome::Success`][Outcome::Success] and `false` into
+ /// [`Outcome::Failure`][Outcome::Failure].
+ pub fn from_bool(b: bool) -> Option<Outcome> {
+ if b {
+ Some(Outcome::Success)
+ } else {
+ Some(Outcome::Failure)
+ }
+ }
+}
+
+/// An [`Analyzer`][Analyzer] is something that implements fight-dependent analyzing of the log.
+///
+/// For more information and explanations, see the [module level documentation][self].
+pub trait Analyzer {
+ /// Returns a reference to the log being analyzed.
+ fn log(&self) -> &Log;
+
+ /// Checks whether the fight was done with the challenge mote activated.
+ fn is_cm(&self) -> bool;
+
+ /// Returns the outcome of the fight.
+ ///
+ /// Note that not all logs need to have an outcome, e.g. WvW or Golem logs may return `None`
+ /// here.
+ fn outcome(&self) -> Option<Outcome>;
+}
+
+/// Returns the correct [`Analyzer`][Analyzer] for the given log file.
+///
+/// See also [`Log::analyzer`][Log::analyzer].
+pub fn for_log<'l>(log: &'l Log) -> Option<Box<dyn Analyzer + 'l>> {
+ let boss = log.encounter()?;
+
+ match boss {
+ Boss::ValeGuardian | Boss::Gorseval | Boss::Sabetha => {
+ Some(Box::new(raids::GenericRaid::new(log)))
+ }
+
+ Boss::Slothasor | Boss::Matthias => Some(Box::new(raids::GenericRaid::new(log))),
+
+ Boss::KeepConstruct => Some(Box::new(raids::GenericRaid::new(log))),
+ Boss::Xera => Some(Box::new(raids::Xera::new(log))),
+
+ Boss::Cairn => Some(Box::new(raids::Cairn::new(log))),
+ Boss::MursaatOverseer => Some(Box::new(raids::MursaatOverseer::new(log))),
+ Boss::Samarog => Some(Box::new(raids::Samarog::new(log))),
+ Boss::Deimos => Some(Box::new(raids::Deimos::new(log))),
+
+ Boss::SoullessHorror => Some(Box::new(raids::SoullessHorror::new(log))),
+ Boss::Dhuum => Some(Box::new(raids::Dhuum::new(log))),
+
+ Boss::ConjuredAmalgamate => Some(Box::new(raids::ConjuredAmalgamate::new(log))),
+ Boss::LargosTwins => Some(Box::new(raids::LargosTwins::new(log))),
+ Boss::Qadim => Some(Box::new(raids::Qadim::new(log))),
+
+ Boss::CardinalAdina => Some(Box::new(raids::CardinalAdina::new(log))),
+ Boss::CardinalSabir => Some(Box::new(raids::CardinalSabir::new(log))),
+ Boss::QadimThePeerless => Some(Box::new(raids::QadimThePeerless::new(log))),
+
+ Boss::Skorvald => Some(Box::new(fractals::Skorvald::new(log))),
+ Boss::Artsariiv | Boss::Arkk | Boss::MAMA | Boss::Siax | Boss::Ensolyss => {
+ Some(Box::new(fractals::GenericFractal::new(log)))
+ }
+
+ Boss::IcebroodConstruct
+ | Boss::VoiceOfTheFallen
+ | Boss::FraenirOfJormag
+ | Boss::Boneskinner
+ | Boss::WhisperOfJormag => Some(Box::new(strikes::GenericStrike::new(log))),
+ }
+}