From 22051473844bddb60c8c062f511fd4b1f90d48bd Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Sat, 7 Jul 2018 03:23:25 +0200 Subject: base for mechanic tracking --- src/statistics/gamedata.rs | 20 +++++++++++++++----- src/statistics/mechanics.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/statistics/mod.rs | 11 +++++++++++ src/statistics/trackers.rs | 38 +++++++++++++++++--------------------- 4 files changed, 85 insertions(+), 26 deletions(-) create mode 100644 src/statistics/mechanics.rs (limited to 'src/statistics') diff --git a/src/statistics/gamedata.rs b/src/statistics/gamedata.rs index 1b5fec6..3bd895e 100644 --- a/src/statistics/gamedata.rs +++ b/src/statistics/gamedata.rs @@ -13,6 +13,8 @@ pub enum Boss { /// second phase. This agent will have another ID, see /// [`XERA_PHASE2_ID`](constant.XERA_PHASE2_ID.html). Xera = 0x3F76, + + Samarog = 0x4324, } /// ID for Xera in the second phase. @@ -112,15 +114,23 @@ pub enum Trigger { pub struct Mechanic(pub u16, pub Trigger, pub &'static str); macro_rules! mechanics { - ($boss_id:expr => [ $($name:expr => $trigger:expr,)* ]) => { - $(Mechanic($boss_id as u16, $trigger, $name)),* + ( $( $boss_id:expr => [ $($name:expr => $trigger:expr,)* ], )* ) => { + &[ + $( $(Mechanic($boss_id as u16, $trigger, $name)),* ),* + ] } } /// A slice of all mechanics that we know about. -pub static MECHANICS: &[Mechanic] = &[mechanics! { Boss::ValeGuardian => [ - "Unstable Magic Spike" => Trigger::SkillOnPlayer(31860), -]}]; +pub static MECHANICS: &[Mechanic] = mechanics! { + Boss::ValeGuardian => [ + "Unstable Magic Spike" => Trigger::SkillOnPlayer(31860), + ], + Boss::Samarog => [ + "Prisoner Sweep" => Trigger::SkillOnPlayer(38168), + "Shockwave" => Trigger::SkillOnPlayer(37996), + ], +}; /// Get all mechanics that belong to the given boss. pub fn get_mechanics(boss_id: u16) -> Vec<&'static Mechanic> { diff --git a/src/statistics/mechanics.rs b/src/statistics/mechanics.rs new file mode 100644 index 0000000..5a16204 --- /dev/null +++ b/src/statistics/mechanics.rs @@ -0,0 +1,42 @@ +use super::gamedata::Mechanic; +use super::math::{Monoid, RecordFunc, Semigroup}; + +use std::fmt; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Counter(u32); + +impl Semigroup for Counter { + #[inline] + fn combine(&self, other: &Counter) -> Counter { + Counter(self.0 + other.0) + } +} + +impl Monoid for Counter { + #[inline] + fn mempty() -> Counter { + Counter(0) + } +} + +#[derive(Clone, Default)] +pub struct MechanicLog { + inner: RecordFunc, +} + +impl MechanicLog { + pub fn increase(&mut self, time: u64, mechanic: &'static Mechanic, agent: u64) { + self.inner.insert(time, (mechanic, agent), Counter(1)); + } + + pub fn count bool>(&self, mut filter: F) -> u32 { + self.inner.tally_only(|(a, b)| filter(a, *b)).0 + } +} + +impl fmt::Debug for MechanicLog { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "MechanicLog {{ ... }}") + } +} diff --git a/src/statistics/mod.rs b/src/statistics/mod.rs index a46fc27..f46f778 100644 --- a/src/statistics/mod.rs +++ b/src/statistics/mod.rs @@ -7,10 +7,12 @@ 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; @@ -41,6 +43,8 @@ macro_rules! try_tracker { 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, } @@ -90,6 +94,10 @@ pub fn calculate(log: &Log) -> StatResult { 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 [ @@ -97,6 +105,7 @@ pub fn calculate(log: &Log) -> StatResult { &mut log_start_tracker, &mut combat_time_tracker, &mut boon_tracker, + &mut mechanic_tracker, ], )?; @@ -131,9 +140,11 @@ pub fn calculate(log: &Log) -> StatResult { } let damage_log = try_tracker!(damage_tracker.finalize()); + let mechanic_log = try_tracker!(mechanic_tracker.finalize()); Ok(Statistics { damage_log, + mechanic_log, agent_stats, }) } diff --git a/src/statistics/trackers.rs b/src/statistics/trackers.rs index d18e9c5..93c7f49 100644 --- a/src/statistics/trackers.rs +++ b/src/statistics/trackers.rs @@ -23,6 +23,7 @@ use super::super::{Event, EventKind, Log}; use super::boon::{BoonLog, BoonQueue}; use super::damage::{DamageLog, DamageType}; use super::gamedata::{self, Mechanic, Trigger}; +use super::mechanics::MechanicLog; use fnv::FnvHashMap; @@ -354,37 +355,33 @@ impl Tracker for BoonTracker { /// A tracker that tracks boss mechanics for each player. pub struct MechanicTracker { - mechanics: HashMap<&'static Mechanic, u32>, + log: MechanicLog, available_mechanics: Vec<&'static Mechanic>, - boss_address: u64, - agent_address: u64, + boss_addresses: Vec, } impl MechanicTracker { /// Create a new mechanic tracker that watches over the given mechanics. - pub fn new( - agent_address: u64, - boss_address: u64, - mechanics: Vec<&'static Mechanic>, - ) -> MechanicTracker { + pub fn new(boss_addresses: Vec, mechanics: Vec<&'static Mechanic>) -> MechanicTracker { MechanicTracker { - mechanics: HashMap::new(), + log: MechanicLog::default(), available_mechanics: mechanics, - boss_address, - agent_address, + boss_addresses, } } } +impl MechanicTracker { + fn is_boss(&self, addr: u64) -> bool { + self.boss_addresses.contains(&addr) + } +} + impl Tracker for MechanicTracker { - type Stat = HashMap<&'static Mechanic, u32>; + type Stat = MechanicLog; type Error = !; fn feed(&mut self, event: &Event) -> Result<(), Self::Error> { - fn increase(map: &mut HashMap<&'static Mechanic, u32>, entry: &'static Mechanic) { - *map.entry(entry).or_insert(0) += 1; - } - for mechanic in &self.available_mechanics { match (&event.kind, &mechanic.1) { ( @@ -395,11 +392,10 @@ impl Tracker for MechanicTracker { .. }, Trigger::SkillOnPlayer(trigger_id), - ) if skill_id == trigger_id - && *source_agent_addr == self.boss_address - && *destination_agent_addr == self.agent_address => + ) if skill_id == trigger_id && self.is_boss(*source_agent_addr) => { - increase(&mut self.mechanics, mechanic); + self.log + .increase(event.time, mechanic, *destination_agent_addr); } _ => (), } @@ -408,6 +404,6 @@ impl Tracker for MechanicTracker { } fn finalize(self) -> Result { - Ok(self.mechanics) + Ok(self.log) } } -- cgit v1.2.3