diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2018-06-10 11:55:59 +0200 | 
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2018-06-10 12:04:58 +0200 | 
| commit | 812a3d3d42aea4b1f53bfa47982fd35a070a4612 (patch) | |
| tree | cfbfb038e24a4040d503c6bdc6c2e071798be203 /src | |
| parent | 877549baca100d534c1272000b2af7a8b364cd35 (diff) | |
| download | evtclib-812a3d3d42aea4b1f53bfa47982fd35a070a4612.tar.gz evtclib-812a3d3d42aea4b1f53bfa47982fd35a070a4612.tar.bz2 evtclib-812a3d3d42aea4b1f53bfa47982fd35a070a4612.zip | |
first iteration of multiplexer
Diffstat (limited to 'src')
| -rw-r--r-- | src/event.rs | 67 | ||||
| -rw-r--r-- | src/statistics/trackers.rs | 86 | 
2 files changed, 153 insertions, 0 deletions
| diff --git a/src/event.rs b/src/event.rs index 02f4686..f87688e 100644 --- a/src/event.rs +++ b/src/event.rs @@ -104,6 +104,73 @@ pub enum EventKind {      },  } +impl EventKind { +    /// Returns the source agent address for this event, if one exists. +    pub fn source_agent_addr(&self) -> Option<u64> { +        use EventKind::*; +        match *self { +            EnterCombat { agent_addr, .. } => return Some(agent_addr), +            ExitCombat { agent_addr } => return Some(agent_addr), +            ChangeUp { agent_addr } => return Some(agent_addr), +            ChangeDown { agent_addr } => return Some(agent_addr), +            ChangeDead { agent_addr } => return Some(agent_addr), +            Spawn { agent_addr } => return Some(agent_addr), +            Despawn { agent_addr } => return Some(agent_addr), +            HealthUpdate { agent_addr, .. } => return Some(agent_addr), +            WeaponSwap { agent_addr, .. } => return Some(agent_addr), +            MaxHealthUpdate { agent_addr, .. } => return Some(agent_addr), +            PointOfView { agent_addr } => return Some(agent_addr), +            SkillUse { +                source_agent_addr, .. +            } => return Some(source_agent_addr), +            ConditionTick { +                source_agent_addr, .. +            } => return Some(source_agent_addr), +            InvulnTick { +                source_agent_addr, .. +            } => return Some(source_agent_addr), +            Physical { +                source_agent_addr, .. +            } => return Some(source_agent_addr), +            BuffApplication { +                source_agent_addr, .. +            } => return Some(source_agent_addr), +            BuffRemove { +                source_agent_addr, .. +            } => return Some(source_agent_addr), +            _ => return None, +        } +    } + +    /// Returns the destination agent address for this event, if one exists. +    pub fn destination_agent_addr(&self) -> Option<u64> { +        use EventKind::*; +        match *self { +            ConditionTick { +                destination_agent_addr, +                .. +            } => return Some(destination_agent_addr), +            InvulnTick { +                destination_agent_addr, +                .. +            } => return Some(destination_agent_addr), +            Physical { +                destination_agent_addr, +                .. +            } => return Some(destination_agent_addr), +            BuffApplication { +                destination_agent_addr, +                .. +            } => return Some(destination_agent_addr), +            BuffRemove { +                destination_agent_addr, +                .. +            } => return Some(destination_agent_addr), +            _ => return None, +        } +    } +} +  /// A higher-level representation of a combat event.  #[derive(Clone, Debug, PartialEq, Eq)]  pub struct Event { diff --git a/src/statistics/trackers.rs b/src/statistics/trackers.rs index bcf5e90..8381a43 100644 --- a/src/statistics/trackers.rs +++ b/src/statistics/trackers.rs @@ -13,6 +13,7 @@  //! trackers on the same log.  use std::collections::HashMap;  use std::error::Error; +use std::hash::Hash;  use super::super::{Event, EventKind, Log};  use super::boon::BoonQueue; @@ -76,6 +77,91 @@ impl<S, E: Error + 'static, T: Tracker<Stat = S, Error = E>> RunnableTracker for      }  } +/// A trait that allows a tracker to be multiplexed. +/// +/// Basically, this is a factory that allows new trackers to be created. Each +/// tracker can be given a key that it should listen on, which is expressed by +/// the `K` type parameter and the `key` parameter to `create`. +pub trait Multiplexable<K> { +    /// The type of tracker that this multiplexable/factory creates. +    type T: Tracker; + +    /// Create a new tracker, listening for the given key. +    fn create(&mut self, key: K) -> Self::T; +} + +/// A helper that wraps (decorates) another tracker and separates the results +/// based on the given criteria. +/// +/// Instead of outputting a single statistic, it outputs a `HashMap`, mapping +/// the criteria to its own tracker. +/// +/// This can be used for example to count damage per player: The damage tracker +/// itself only counts damage for a single player, and together with a +/// multiplexer, it will count the damage per player. +/// +/// Type parameters: +/// * `K` Key that is used to distinguish criteria. For example, `u64` for a +///   multiplexer that separates based on agents. +/// * `F` Factory that creates new trackers for each key. +/// * `T` Inner tracker type. Usually determined by the factory. +/// * `S` Selection function type. Takes an event and outputs a key. +pub struct Multiplexer<K, F, T, S> { +    factory: F, +    trackers: HashMap<K, T>, +    selector: S, +} + +impl<K, F, T, S> Multiplexer<K, F, T, S> { +    /// Create a new multiplexer that multiplexes on the source agent. +    pub fn multiplex_on_source<Factory: Multiplexable<u64>>( +        factory: Factory, +    ) -> Multiplexer<u64, Factory, Factory::T, impl Fn(&Event) -> Option<u64>> { +        Multiplexer { +            factory, +            trackers: HashMap::new(), +            selector: |event: &Event| event.kind.source_agent_addr(), +        } +    } + +    /// Create a new multiplexer that multiplexes on the destination agent. +    pub fn multiplex_on_destination<Factory: Multiplexable<u64>>( +        factory: Factory, +    ) -> Multiplexer<u64, Factory, Factory::T, impl Fn(&Event) -> Option<u64>> { +        Multiplexer { +            factory, +            trackers: HashMap::new(), +            selector: |event: &Event| event.kind.destination_agent_addr(), +        } +    } +} + +impl<K: Hash + Eq + Clone, F: Multiplexable<K>, S: FnMut(&Event) -> Option<K>> Tracker +    for Multiplexer<K, F, F::T, S> +{ +    type Stat = HashMap<K, <F::T as Tracker>::Stat>; +    type Error = <F::T as Tracker>::Error; + +    fn feed(&mut self, event: &Event) -> Result<(), Self::Error> { +        if let Some(key) = (self.selector)(event) { +            let factory = &mut self.factory; +            let entry = self +                .trackers +                .entry(key.clone()) +                .or_insert_with(|| factory.create(key)); +            entry.feed(event)?; +        } +        Ok(()) +    } + +    fn finalize(self) -> Result<Self::Stat, Self::Error> { +        self.trackers +            .into_iter() +            .map(|(k, v)| v.finalize().map(|inner| (k, inner))) +            .collect() +    } +} +  /// A tracker that tracks per-target damage of all agents.  pub struct DamageTracker<'l> {      log: &'l Log, | 
