diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2018-07-07 03:23:25 +0200 | 
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2018-07-07 03:23:25 +0200 | 
| commit | 22051473844bddb60c8c062f511fd4b1f90d48bd (patch) | |
| tree | 8001a9ff97ae7d065c2e6c56cf5fe5a98d44e6b4 | |
| parent | 4ea1d4f3e5082925874a271d14cc143ebf80912f (diff) | |
| download | evtclib-22051473844bddb60c8c062f511fd4b1f90d48bd.tar.gz evtclib-22051473844bddb60c8c062f511fd4b1f90d48bd.tar.bz2 evtclib-22051473844bddb60c8c062f511fd4b1f90d48bd.zip | |
base for mechanic tracking
| -rw-r--r-- | src/lib.rs | 27 | ||||
| -rw-r--r-- | src/main.rs | 24 | ||||
| -rw-r--r-- | src/statistics/gamedata.rs | 20 | ||||
| -rw-r--r-- | src/statistics/mechanics.rs | 42 | ||||
| -rw-r--r-- | src/statistics/mod.rs | 11 | ||||
| -rw-r--r-- | src/statistics/trackers.rs | 38 | 
6 files changed, 122 insertions, 40 deletions
| @@ -95,27 +95,27 @@ pub enum AgentName {  /// An agent.  #[derive(Debug, Clone, Getters)]  pub struct Agent { -    #[get="pub"] +    #[get = "pub"]      addr: u64, -    #[get="pub"] +    #[get = "pub"]      kind: AgentKind, -    #[get="pub"] +    #[get = "pub"]      toughness: i16, -    #[get="pub"] +    #[get = "pub"]      concentration: i16, -    #[get="pub"] +    #[get = "pub"]      healing: i16, -    #[get="pub"] +    #[get = "pub"]      condition: i16, -    #[get="pub"] +    #[get = "pub"]      name: AgentName, -    #[get="pub"] +    #[get = "pub"]      instance_id: u16, -    #[get="pub"] +    #[get = "pub"]      first_aware: u64, -    #[get="pub"] +    #[get = "pub"]      last_aware: u64, -    #[get="pub"] +    #[get = "pub"]      master_agent: Option<u64>,  } @@ -196,6 +196,11 @@ impl Log {          self.boss_agents().into_iter().any(|a| *a.addr() == addr)      } +    /// Returns the boss/encounter id. +    pub fn boss_id(&self) -> u16 { +        self.boss_id +    } +      /// Return all events present in this log.      pub fn events(&self) -> &[Event] {          &self.events diff --git a/src/main.rs b/src/main.rs index c4f4e0a..81ab36c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -143,11 +143,16 @@ pub fn main() -> Result<(), evtclib::raw::parser::ParseError> {      let my_addr = me(&processed);      let mine = stats.agent_stats.get(&my_addr).expect("My stats not found"); -    let my_damage = stats.damage_log.damage(|m| m.source == my_addr && processed.is_boss(m.target)); +    let my_damage = stats +        .damage_log +        .damage(|m| m.source == my_addr && processed.is_boss(m.target)); -    let combat_time = (mine.exit_combat - mine.enter_combat) as f32/ 1000.; +    let combat_time = (mine.exit_combat - mine.enter_combat) as f32 / 1000.;      println!("Damages: {:?}", stats.damage_log); -    println!("Combat time: {} ({} till {})", combat_time, mine.enter_combat, mine.exit_combat); +    println!( +        "Combat time: {} ({} till {})", +        combat_time, mine.enter_combat, mine.exit_combat +    );      println!("My boss dps: {:?}", my_damage.0 as f32 / combat_time);      for boon in evtclib::statistics::gamedata::BOONS { @@ -157,6 +162,19 @@ pub fn main() -> Result<(), evtclib::raw::parser::ParseError> {          println!("{}: {}", boon.1, avg);      } +    for agent in processed.players() { +        println!("{:?}", agent.name()); +        for mechanic in evtclib::statistics::gamedata::get_mechanics(processed.boss_id()) { +            println!( +                "{}: {}", +                mechanic.2, +                stats +                    .mechanic_log +                    .count(|m, a| m == mechanic && a == *agent.addr()) +            ); +        } +    } +      //println!("NPCs: {:#?}", processed.npcs().collect::<Vec<_>>());      println!("Bosses: {:#?}", processed.boss_agents()); 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<u64, (&'static Mechanic, u64), Counter>, +} + +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<F: FnMut(&'static Mechanic, u64) -> 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<T> = Result<T, StatError>; @@ -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<u64, AgentStats>,  } @@ -90,6 +94,10 @@ pub fn calculate(log: &Log) -> StatResult<Statistics> {      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<Statistics> {              &mut log_start_tracker,              &mut combat_time_tracker,              &mut boon_tracker, +            &mut mechanic_tracker,          ],      )?; @@ -131,9 +140,11 @@ pub fn calculate(log: &Log) -> StatResult<Statistics> {      }      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<u64>,  }  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<u64>, 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<Self::Stat, Self::Error> { -        Ok(self.mechanics) +        Ok(self.log)      }  } | 
