From 08465ea1b8c1b9f90057bcc10fb8887ee57cac8c Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Mon, 27 Apr 2020 14:39:36 +0200 Subject: remove statistics submodule The way the trackers worked was rather... "adventurous", and while there were some good ideas and it mostly worked, the implementation and interface could do better. Additionally, it was incomplete, for example there were a lot of mechanics just missing. While I'm not against having this functionality provided by evtclib, I think it would be more worthwile with a better designed implementation & API, so this "proof of concept" implementation is gone until there is a better way of doing things. gamedata is being kept, as the boss identifiers are useful and applications shouldn't have to deal with keeping this low-level list themselves. --- src/statistics/mod.rs | 145 -------------------------------------------------- 1 file changed, 145 deletions(-) delete mode 100644 src/statistics/mod.rs (limited to 'src/statistics/mod.rs') diff --git a/src/statistics/mod.rs b/src/statistics/mod.rs deleted file mode 100644 index 3e42d9c..0000000 --- a/src/statistics/mod.rs +++ /dev/null @@ -1,145 +0,0 @@ -//! This module aids in the creation of actual boss statistics. -use super::*; -use std::collections::HashMap; -use thiserror::Error; - -pub mod boon; -pub mod damage; -pub mod gamedata; -pub mod math; -pub mod mechanics; -pub mod trackers; - -use self::boon::BoonLog; -use self::damage::DamageLog; -use self::mechanics::MechanicLog; -use self::trackers::{RunnableTracker, Tracker}; - -pub type StatResult = Result; - -#[derive(Error, Debug)] -pub enum StatError { - #[error("tracker returned an error: {0}")] - TrackerError(#[from] Box), -} - -macro_rules! try_tracker { - ($expr:expr) => { - #[allow(unreachable_code)] - match $expr { - Ok(e) => e, - Err(e) => return Err(StatError::TrackerError(e)), - } - }; -} - -/// A struct containing the calculated statistics for the log. -#[derive(Clone, Debug)] -pub struct Statistics { - /// The complete damage log. - pub damage_log: DamageLog, - /// The complete mechanics log. - pub mechanic_log: MechanicLog, - /// A map mapping agent addresses to their stats. - pub agent_stats: HashMap, -} - -/// A struct describing the agent statistics. -#[derive(Clone, Debug, Default)] -pub struct AgentStats { - /// Average stacks of boons. - /// - /// This also includes conditions. - /// - /// For duration-based boons, the average amount of stacks is the same as - /// the uptime. - pub boon_log: BoonLog, - /// Time when the agent has entered combat (millseconds since log start). - pub enter_combat: u64, - /// Time when the agent has left combat (millseconds since log start). - pub exit_combat: u64, -} - -impl AgentStats { - /// Returns the combat time of this agent in milliseconds. - pub fn combat_time(&self) -> u64 { - self.exit_combat - self.enter_combat - } -} - -/// Takes a bunch of trackers and runs them on the given log. -/// -/// This method returns "nothing", as the statistics are saved in the trackers. -/// It's the job of the caller to extract them appropriately. -pub fn run_trackers(log: &Log, trackers: &mut [&mut dyn RunnableTracker]) -> StatResult<()> { - for event in log.events() { - for tracker in trackers.iter_mut() { - try_tracker!((*tracker).run_feed(event)); - } - } - Ok(()) -} - -/// Calculate the statistics for the given log. -pub fn calculate(log: &Log) -> StatResult { - let mut agent_stats = HashMap::::new(); - - let mut damage_tracker = trackers::DamageTracker::new(log); - let mut log_start_tracker = trackers::LogStartTracker::new(); - let mut combat_time_tracker = trackers::CombatTimeTracker::new(); - let mut boon_tracker = trackers::BoonTracker::new(); - - let mechanics = gamedata::get_mechanics(log.boss_id); - let boss_addr = log.boss_agents().into_iter().map(|x| *x.addr()).collect(); - let mut mechanic_tracker = trackers::MechanicTracker::new(boss_addr, mechanics); - - run_trackers( - log, - &mut [ - &mut damage_tracker, - &mut log_start_tracker, - &mut combat_time_tracker, - &mut boon_tracker, - &mut mechanic_tracker, - ], - )?; - - let log_start_time = try_tracker!(log_start_tracker.finalize()); - - let combat_times = try_tracker!(combat_time_tracker.finalize()); - for (agent_addr, &(enter_time, exit_time)) in &combat_times { - let agent = agent_stats - .entry(*agent_addr) - .or_insert_with(Default::default); - // XXX: This used to be enter_time - log_start_time, as it makes more - // sense to have the time relative to the log start instead of the - // Windows boot time. However, this also means that we need to modify - // all event times before we do any tracking, as many trackers rely on - // event.time to track information related to time. - if enter_time != 0 { - agent.enter_combat = enter_time; - } else { - agent.enter_combat = log_start_time; - } - if exit_time != 0 { - agent.exit_combat = exit_time; - } - } - - let boon_logs = try_tracker!(boon_tracker.finalize()); - for (agent_addr, boon_log) in boon_logs { - let agent = agent_stats - .entry(agent_addr) - .or_insert_with(Default::default); - agent.boon_log = boon_log; - } - - let damage_log = try_tracker!(damage_tracker.finalize()); - let mechanic_log = try_tracker!(mechanic_tracker.finalize()); - - Ok(Statistics { - damage_log, - mechanic_log, - agent_stats, - }) -} -- cgit v1.2.3