aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gamedata.rs62
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)] = &[