diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gamedata.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/gamedata.rs b/src/gamedata.rs index f880ba6..9f0f9d4 100644 --- a/src/gamedata.rs +++ b/src/gamedata.rs @@ -345,6 +345,53 @@ impl Display for Encounter { } } +macro_rules! ordering_group { + ($self:expr, $other:expr ; $($group:expr;)*) => { + $( + let group = &$group; + if let Some(pos_a) = group.iter().position(|x| *x == $self) { + if let Some(pos_b) = group.iter().position(|x| *x == $other) { + return Some(pos_a.cmp(&pos_b)); + } + } + )* + } +} + +// We could implement (or even derive) PartialOrd for all bosses, but there is no "canonical" order +// (do fractal bosses come before raid bosses or after?). This implements a conservative order, +// such that at least the bosses that appear in a single raid wing/fractal are ordered relative to +// each other, but there is no order between different wings. This still allows some useful cases +// (like sorting bosses within a wing). +// +// There are some edge cases, like the Wing 5 events (Eater/Eyes/Broken King) and Adina/Sabir, +// which technically happen at the same time, but we're just defining a fixed order for those here. +// +// In the future, this implementation might be expanded to a total order, but by keeping it a +// partial order for now we can implement the cases that are clear (bosses within a wing) while +// allowing future extensions in a backwards-compatible way (once we figured out how we want to +// order the different wings/strikes/fractals). +impl PartialOrd for Encounter { + fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { + use Encounter::*; + ordering_group!(*self, *other; + // Raids + [ValeGuardian, Gorseval, Sabetha]; + [Slothasor, BanditTrio, Matthias]; + [KeepConstruct, TwistedCastle, Xera]; + [Cairn, MursaatOverseer, Samarog, Deimos]; + [SoullessHorror, RiverOfSouls, BrokenKing, EaterOfSouls, StatueOfDarkness, VoiceInTheVoid]; + [ConjuredAmalgamate, TwinLargos, Qadim]; + [CardinalAdina, CardinalSabir, QadimThePeerless]; + // Shattered Observatory CM + [Skorvald, Artsariiv, Arkk]; + // Nightmare CM + [MAMA, Siax, Ensolyss]; + ); + None + } +} + /// Enum containing all boss IDs. /// /// For a high-level event categorization, take a look at the [`Encounter`] enum. The IDs listed @@ -1142,6 +1189,21 @@ mod tests { } #[test] + fn test_encounter_partial_cmp() { + // Just a few example cases + use Encounter::*; + assert!(ValeGuardian < Gorseval); + assert!(ValeGuardian < Sabetha); + assert!(Gorseval < Sabetha); + assert!(ValeGuardian.partial_cmp(&Slothasor).is_none()); + + assert!(VoiceInTheVoid > SoullessHorror); + assert!(Qadim > TwinLargos); + + assert!(Ankka.partial_cmp(&Dragonvoid).is_none()); + } + + #[test] fn test_boss_parsing_ok() { use Boss::*; let tests: &[(&'static str, Boss)] = &[ |