use num_enum::{IntoPrimitive, TryFromPrimitive}; use serde::{Deserialize, Serialize}; use strum::IntoEnumIterator; use strum_macros::{AsRefStr, Display, EnumString, IntoStaticStr}; /// LoL and TFT ranked tiers, such as gold, diamond, challenger, etc. /// /// Sorts from lowest rank to highest rank. /// /// Repr'd as arbitrary `u8` values. /// /// Implements [IntoEnumIterator](super::IntoEnumIterator). #[derive( Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord, IntoPrimitive, TryFromPrimitive, EnumString, Display, AsRefStr, IntoStaticStr, Serialize, Deserialize, )] #[repr(u8)] pub enum Tier { /// Challenger, the highest tier, an apex tier. Repr: `220_u8`. CHALLENGER = 220, /// Grand Master, an apex tier. Repr: `200_u8`. GRANDMASTER = 200, /// Master, an apex tier. Repr: `180_u8`. MASTER = 180, /// Diamond, the higest non-apex tier. Repr: `140_u8`. DIAMOND = 140, /// Emerald. Added in 2023. Repr: `130_u8`. EMERALD = 130, /// Platinum. Repr: `120_u8`. PLATINUM = 120, /// Gold. Repr: `100_u8`. GOLD = 100, /// Silver. Repr: `80_u8`. SILVER = 80, /// Bronze. Repr: `60_u8`. BRONZE = 60, /// Iron, the lowest tier. Repr: `40_u8`. IRON = 40, /// Unranked, no tier. Repr: `0_u8`. /// Also deserializes from "NONE" returned by `lol-challenges-v1.getChallengePercentiles`. #[serde(alias = "NONE")] UNRANKED = 0, } impl Tier { /// If this tier is an apex tier: [`Self::MASTER`], [`Self::GRANDMASTER`], /// or [`Self::CHALLENGER`]. Returns false for [`Self::UNRANKED`]. /// /// These tiers are NOT queryable by LeagueV4Endpoints::get_league_entries(...). pub const fn is_apex(self) -> bool { // Casts needed for const. (Self::MASTER as u8) <= (self as u8) } /// If this tier is a "standard" tier: iron through diamond. /// Returns false for unranked. /// /// ONLY these tiers are queryable by [`LeagueV4::get_league_entries(...)`](crate::endpoints::LeagueV4::get_league_entries). pub fn is_standard(self) -> bool { // Casts needed for const. ((Self::UNRANKED as u8) < (self as u8)) && ((self as u8) < (Self::MASTER as u8)) } /// If this tier is ranked. Returns true for iron through challenger, false for unranked. pub const fn is_ranked(self) -> bool { // Casts needed for const. (Self::UNRANKED as u8) < (self as u8) } /// If this tier is unranked (`Tier::UNRANKED`). /// /// UNRANKED is returned by `Participant.highest_achieved_season_tier`. pub const fn is_unranked(self) -> bool { // Casts needed for const. (self as u8) <= (Self::UNRANKED as u8) } /// Converts UNRANKED to None and all ranked tiers to Some(...). pub fn to_ranked(self) -> Option<Self> { if self.is_unranked() { None } else { Some(self) } } } /// Returns a DoubleEndedIterator of I, II, III, IV. /// Ordered from high rank (I) to low (IV). /// Excludes V, which is deprecated. impl IntoEnumIterator for Tier { type Iterator = std::iter::Copied<std::slice::Iter<'static, Self>>; fn iter() -> Self::Iterator { [ Self::CHALLENGER, Self::GRANDMASTER, Self::MASTER, Self::DIAMOND, Self::EMERALD, Self::PLATINUM, Self::GOLD, Self::SILVER, Self::BRONZE, Self::IRON, ] .iter() .copied() } } #[cfg(test)] mod tests { use super::*; #[test] fn ord() { assert!(Tier::GOLD < Tier::DIAMOND); assert!(Tier::UNRANKED < Tier::IRON); } #[test] fn is_apex() { assert!(Tier::GRANDMASTER.is_apex()); assert!(!Tier::DIAMOND.is_apex()); assert!(!Tier::UNRANKED.is_apex()); } #[test] fn is_ranked() { assert!(Tier::GRANDMASTER.is_ranked()); assert!(Tier::DIAMOND.is_ranked()); assert!(!Tier::UNRANKED.is_ranked()); } #[test] fn is_unranked() { assert!(!Tier::GRANDMASTER.is_unranked()); assert!(!Tier::DIAMOND.is_unranked()); assert!(Tier::UNRANKED.is_unranked()); } #[test] fn to_ranked() { assert_eq!(Some(Tier::GRANDMASTER), Tier::GRANDMASTER.to_ranked()); assert_eq!(Some(Tier::DIAMOND), Tier::DIAMOND.to_ranked()); assert_eq!(None, Tier::UNRANKED.to_ranked()); } #[test] fn is_standard() { assert!(!Tier::GRANDMASTER.is_standard()); assert!(Tier::DIAMOND.is_standard()); assert!(!Tier::UNRANKED.is_standard()); } #[test] fn to_string() { assert_eq!("GRANDMASTER", Tier::GRANDMASTER.as_ref()); assert_eq!("GRANDMASTER", Tier::GRANDMASTER.to_string()); assert_eq!("UNRANKED", Tier::UNRANKED.as_ref()); assert_eq!("UNRANKED", Tier::UNRANKED.to_string()); } #[test] fn from_string() { assert_eq!(Ok(Tier::GRANDMASTER), "GRANDMASTER".parse()); assert_eq!(Ok(Tier::UNRANKED), "UNRANKED".parse()); } #[test] fn iter() { use strum::IntoEnumIterator; let mut iter = Tier::iter(); assert_eq!(Some(Tier::CHALLENGER), iter.next()); iter.next(); iter.next(); assert_eq!(Some(Tier::DIAMOND), iter.next()); assert_eq!(Some(Tier::EMERALD), iter.next()); iter.next(); iter.next(); iter.next(); iter.next(); assert_eq!(Some(Tier::IRON), iter.next()); assert_eq!(None, iter.next()); assert_eq!(None, iter.next_back()); let mut iter = Tier::iter().rev(); assert_eq!(Some(Tier::IRON), iter.next()); iter.next(); iter.next(); iter.next(); iter.next(); assert_eq!(Some(Tier::EMERALD), iter.next()); assert_eq!(Some(Tier::DIAMOND), iter.next()); iter.next(); iter.next(); assert_eq!(Some(Tier::CHALLENGER), iter.next()); assert_eq!(None, iter.next()); assert_eq!(None, iter.next_back()); let mut iter = Tier::iter(); assert_eq!(Some(Tier::CHALLENGER), iter.next()); assert_eq!(Some(Tier::IRON), iter.next_back()); } }