//! Utilities for working with ranks, represented as `(Tier, Division)` tuples. use std::iter::Peekable; use strum::IntoEnumIterator; use super::{ Tier, Division }; /// (Tier, Division) tuple representing a rank. pub type Rank = ( Tier, Division ); /// Iterator for iterating `(Tier, Division)` rank tuples. pub struct Iter { tier_iter: Peekable<::Iterator>, div_iter: ::Iterator, } impl Iterator for Iter { type Item = Rank; fn next(&mut self) -> Option { // First find the tier (innermost loop). // If none found, we go to next tier (in unwrap_or_else case). let div = self.div_iter.next() .unwrap_or_else(|| { // If no divisions available, go to next tier, reset the divisions, and return I. self.tier_iter.next(); self.div_iter = Division::iter(); self.div_iter.next().unwrap() }); // Then find the tier. let tier = *self.tier_iter.peek()?; // If its an apex tier go to next tier and reset the divisions. if tier.is_apex() { self.tier_iter.next(); self.div_iter = Division::iter(); } Some(( tier, div )) } } /// Returns an iterator over all `(Tier, Division)` pairs, ordered from highest rank to lowest rank. /// /// Apex tiers are all division I, for example: `(Tier::CHALLENGER, Division::I)`. /// This matches how they are represented by Riot. There is no "Challenger II", etc. pub fn iter() -> Iter { Iter { tier_iter: Tier::iter().peekable(), div_iter: Division::iter(), } } /// Returns an iterator over all `(Tier, Division)` pairs, excluding apex (Master+) tiers, /// ordered from highest (Diamond I) to lowest (Iron IV). pub fn non_apex_iter() -> Iter { let mut tier_iter = Tier::iter().peekable(); while tier_iter.peek().unwrap().is_apex() { tier_iter.next(); } Iter { tier_iter: tier_iter, div_iter: Division::iter(), } } #[cfg(test)] mod tests { use super::{ Tier, Division }; #[test] fn iter() { let mut it = super::iter(); assert_eq!(Some(( Tier::CHALLENGER, Division::I )), it.next()); assert_eq!(Some(( Tier::GRANDMASTER, Division::I )), it.next()); assert_eq!(Some(( Tier::MASTER, Division::I )), it.next()); assert_eq!(Some(( Tier::DIAMOND, Division::I )), it.next()); assert_eq!(Some(( Tier::DIAMOND, Division::II )), it.next()); let mut last = None; for next in &mut it { last = Some(next); } assert_eq!(Some(( Tier::IRON, Division::IV )), last); assert_eq!(None, it.next()); } #[test] fn non_apex_iter() { let mut it = super::non_apex_iter(); assert_eq!(Some((Tier::DIAMOND, Division::I)), it.next()); assert_eq!(Some((Tier::DIAMOND, Division::II)), it.next()); assert_eq!(Some((Tier::DIAMOND, Division::III)), it.next()); assert_eq!(Some((Tier::DIAMOND, Division::IV)), it.next()); assert_eq!(Some((Tier::PLATINUM, Division::I)), it.next()); let mut last = None; for next in &mut it { last = Some(next); } assert_eq!(Some((Tier::IRON, Division::IV)), last); assert_eq!(None, it.next()); } }