use evtclib::{Encounter, GameMode, Log}; // There is no canonical order of "categories", so we'll do // * WvW // * Raid wings ascending // * Strike // * Fractals descending // * Training area // * Unknown // Subject to change, it's only used to sort the message (if enabled). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)] pub enum Category { WvW, Wing1, Wing2, Wing3, Wing4, Wing5, Wing6, Wing7, Strike, SunquaPeak, ShatteredObservatory, Nightmare, SpecialForcesTrainingArea, #[default] Unknown, } macro_rules! category_strings { ($(($item:path, $str:literal),)*) => { impl std::fmt::Display for Category { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let repr = match *self { $($item => $str),* }; write!(f, "{}", repr) } } impl std::str::FromStr for Category { type Err = (); fn from_str(s: &str) -> Result { match s { $($str => Ok($item),)* _ => Err(()), } } } } } category_strings! { (Category::WvW, "World versus World"), (Category::Wing1, "Wing 1 (Spirit Vale)"), (Category::Wing2, "Wing 2 (Salvation Pass)"), (Category::Wing3, "Wing 3 (Stronghold of the Faithful)"), (Category::Wing4, "Wing 4 (Bastion of the Penitent)"), (Category::Wing5, "Wing 5 (Hall of Chains)"), (Category::Wing6, "Wing 6 (Mythwright Gambit)"), (Category::Wing7, "Wing 7 (Key of Ahdashim)"), (Category::SunquaPeak, "100 CM (Sunqua Peak)"), (Category::ShatteredObservatory, "99 CM (Shattered Observatory)"), (Category::Nightmare, "98 CM (Nightmare)"), (Category::Strike, "Strike Mission"), (Category::SpecialForcesTrainingArea, "Special Forces Training Area"), (Category::Unknown, "Unknown"), } pub trait Categorizable { fn category(&self) -> Category; } impl Categorizable for Log { fn category(&self) -> Category { if self.game_mode() == Some(GameMode::WvW) { return Category::WvW; } if let Some(encounter) = self.encounter() { match encounter { Encounter::ValeGuardian | Encounter::Gorseval | Encounter::Sabetha => { Category::Wing1 } Encounter::Slothasor | Encounter::BanditTrio | Encounter::Matthias => { Category::Wing2 } Encounter::KeepConstruct | Encounter::TwistedCastle | Encounter::Xera => { Category::Wing3 } Encounter::Cairn | Encounter::MursaatOverseer | Encounter::Samarog | Encounter::Deimos => Category::Wing4, Encounter::SoullessHorror | Encounter::RiverOfSouls | Encounter::BrokenKing | Encounter::EaterOfSouls | Encounter::StatueOfDarkness | Encounter::VoiceInTheVoid => Category::Wing5, Encounter::ConjuredAmalgamate | Encounter::TwinLargos | Encounter::Qadim => { Category::Wing6 } Encounter::CardinalAdina | Encounter::CardinalSabir | Encounter::QadimThePeerless => Category::Wing7, Encounter::Ai => Category::SunquaPeak, Encounter::Skorvald | Encounter::Artsariiv | Encounter::Arkk => { Category::ShatteredObservatory } Encounter::MAMA | Encounter::Siax | Encounter::Ensolyss => Category::Nightmare, Encounter::IcebroodConstruct | Encounter::SuperKodanBrothers | Encounter::FraenirOfJormag | Encounter::Boneskinner | Encounter::WhisperOfJormag | Encounter::CaptainMaiTrin | Encounter::Ankka | Encounter::MinisterLi | Encounter::Dragonvoid => Category::Strike, Encounter::StandardKittyGolem | Encounter::MediumKittyGolem | Encounter::LargeKittyGolem => Category::SpecialForcesTrainingArea, _ => Category::Unknown, } } else { Category::Unknown } } }