aboutsummaryrefslogtreecommitdiff
path: root/src/analyzers/helpers.rs
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2020-06-28 17:22:43 +0200
committerDaniel Schadt <kingdread@gmx.de>2020-06-28 17:22:43 +0200
commit0978345648cf9cdad6222f583dd21497b409d07e (patch)
tree9470f87a879e36c68104ef067c6657eb94cd98e5 /src/analyzers/helpers.rs
parentacdc4d977e573d54c73530f77ba210efd2184cf0 (diff)
downloadevtclib-0978345648cf9cdad6222f583dd21497b409d07e.tar.gz
evtclib-0978345648cf9cdad6222f583dd21497b409d07e.tar.bz2
evtclib-0978345648cf9cdad6222f583dd21497b409d07e.zip
start implementing analyzers
It turns out that the different encounters do require quite some encounter-specific logic, not only to determine whether the CM was activated, but also to determine whether the fight was successful, the duration of the fight, later the phases, ... Wrapping all of this in pre-defined "triggers" (like CmTrigger) feels like it will be a bit unfitting, so with this patch we have introduced the evtclib::Analyzer, which can be used to analyze the fights. Currently, the whole CM detection logic has been moved to this new interface, and soon we also want the success-detection logic in there. The tests pass and the interface of Log::is_cm is unchanged.
Diffstat (limited to 'src/analyzers/helpers.rs')
-rw-r--r--src/analyzers/helpers.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/analyzers/helpers.rs b/src/analyzers/helpers.rs
new file mode 100644
index 0000000..ec09355
--- /dev/null
+++ b/src/analyzers/helpers.rs
@@ -0,0 +1,70 @@
+//! This module contains helper methods that are used in different analyzers.
+use std::collections::HashMap;
+
+use crate::{EventKind, Log};
+
+/// Returns the maximum health of the boss agent.
+///
+/// If the health cannot be determined, this function returns `None`.
+///
+/// The boss agent is determined by using [`Log::is_boss`][Log::is_boss].
+pub fn boss_health(log: &Log) -> Option<u64> {
+ let mut health: Option<u64> = None;
+ for event in log.events() {
+ if let EventKind::MaxHealthUpdate {
+ agent_addr,
+ max_health,
+ } = *event.kind()
+ {
+ if log.is_boss(agent_addr) {
+ health = health.map(|h| h.max(max_health)).or(Some(max_health));
+ }
+ }
+ }
+ health
+}
+
+/// Checks if the given buff is present in the log.
+pub fn buff_present(log: &Log, wanted_buff_id: u32) -> bool {
+ for event in log.events() {
+ if let EventKind::BuffApplication { buff_id, .. } = *event.kind() {
+ if buff_id == wanted_buff_id {
+ return true;
+ }
+ }
+ }
+ false
+}
+
+/// Returns the (minimum) time between applications of the given buff in milliseconds.
+pub fn time_between_buffs(log: &Log, wanted_buff_id: u32) -> u64 {
+ let mut time_maps: HashMap<u64, Vec<u64>> = HashMap::new();
+ for event in log.events() {
+ if let EventKind::BuffApplication {
+ destination_agent_addr,
+ buff_id,
+ ..
+ } = event.kind()
+ {
+ if *buff_id == wanted_buff_id {
+ time_maps
+ .entry(*destination_agent_addr)
+ .or_default()
+ .push(event.time());
+ }
+ }
+ }
+ let timestamps = if let Some(ts) = time_maps.values().max_by_key(|v| v.len()) {
+ ts
+ } else {
+ return 0;
+ };
+ timestamps
+ .iter()
+ .zip(timestamps.iter().skip(1))
+ .map(|(a, b)| b - a)
+ // Arbitrary limit to filter out duplicated buff application events
+ .filter(|x| *x > 50)
+ .min()
+ .unwrap_or(0)
+}