diff options
-rw-r--r-- | src/analyzers/mod.rs | 4 | ||||
-rw-r--r-- | src/analyzers/strikes.rs | 77 |
2 files changed, 79 insertions, 2 deletions
diff --git a/src/analyzers/mod.rs b/src/analyzers/mod.rs index 8f9b1ff..c27fefa 100644 --- a/src/analyzers/mod.rs +++ b/src/analyzers/mod.rs @@ -131,11 +131,11 @@ pub fn for_log<'l>(log: &'l Log) -> Option<Box<dyn Analyzer + 'l>> { | Encounter::SuperKodanBrothers | Encounter::FraenirOfJormag | Encounter::Boneskinner - | Encounter::WhisperOfJormag - | Encounter::Dragonvoid => Some(Box::new(strikes::GenericStrike::new(log))), + | Encounter::WhisperOfJormag => Some(Box::new(strikes::GenericStrike::new(log))), Encounter::CaptainMaiTrin => Some(Box::new(strikes::CaptainMaiTrin::new(log))), Encounter::Ankka => Some(Box::new(strikes::Ankka::new(log))), Encounter::MinisterLi => Some(Box::new(strikes::MinisterLi::new(log))), + Encounter::Dragonvoid => Some(Box::new(strikes::Dragonvoid::new(log))), } } diff --git a/src/analyzers/strikes.rs b/src/analyzers/strikes.rs index 4c43016..9244124 100644 --- a/src/analyzers/strikes.rs +++ b/src/analyzers/strikes.rs @@ -241,3 +241,80 @@ impl<'log> Analyzer for MinisterLi<'log> { Outcome::from_bool(phase_change_count >= Self::MINIMUM_PHASE_COUNT) } } + +/// Analyzer for the Dragonvoid/Harvest Temple strike. +#[derive(Debug, Clone, Copy)] +pub struct Dragonvoid<'log> { + log: &'log Log, +} + +impl<'log> Dragonvoid<'log> { + pub const EXPECTED_TARGET_OFF_COUNT: usize = 2; + + /// Create a new [`Dragonvoid`] analyzer for the given log. + /// + /// **Do not** use this method unless you know what you are doing. Instead, rely on + /// [`Log::analyzer`]! + pub fn new(log: &'log Log) -> Self { + Dragonvoid { log } + } +} + +impl<'log> Analyzer for Dragonvoid<'log> { + fn log(&self) -> &Log { + self.log + } + + fn is_cm(&self) -> bool { + // EoD strike CMs are not implemented yet as of 2022-03-31 + false + } + + fn outcome(&self) -> Option<Outcome> { + // check_reward is pointless because the reward is delayed. + + // First, we find the right agent_addr + let mut first_voids = None; + for event in self.log.events() { + if let EventKind::AttackTarget { + agent_addr, + parent_agent_addr, + .. + } = event.kind() + { + if first_voids.is_none() { + first_voids = Some(parent_agent_addr); + } else if first_voids != Some(parent_agent_addr) { + // We find the amount of target off switches that occurred after a target on + // switch. + let mut is_on = false; + let mut target_off_count = 0; + + // The nested loop over events is not ideal, but it is currently the easiest + // way to implement this logic without trying to cram it into a single loop. + for e in self.log.events() { + if let EventKind::Targetable { + agent_addr: taa, + targetable, + } = e.kind() + { + if *taa != *agent_addr { + continue; + } + if *targetable { + is_on = true; + } else if !targetable && is_on { + target_off_count += 1; + } + } + } + + if target_off_count == Self::EXPECTED_TARGET_OFF_COUNT { + return Some(Outcome::Success); + } + } + } + } + Some(Outcome::Failure) + } +} |