use indexmap::IndexSet; use std::fmt::Debug; use crate::defines::LevelInt; use crate::StringKey; /// The storage of the moves a Pokemon can learn. pub trait LearnableMoves: Debug { /// Adds a new level move the Pokemon can learn. fn add_level_move(&mut self, level: LevelInt, m: &StringKey); /// Gets all moves a Pokemon can learn when leveling up to a specific level. fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec>; /// Gets the distinct moves a Pokemon can learn through leveling up. fn get_distinct_level_moves(&self) -> &IndexSet; } /// The storage of the moves a Pokemon can learn. #[derive(PartialEq, Eq, Debug)] pub struct LearnableMovesImpl { /// A map of the moves a Pokemon can learn per level. learned_by_level: Vec>, /// A list of the distinct moves a Pokemon can learn through leveling up. distinct_level_moves: IndexSet, } impl LearnableMovesImpl { /// Instantiates a new Learnable Moves. pub fn new(max_level: LevelInt) -> Self { Self { learned_by_level: vec![Vec::new(); (max_level + 1) as usize], distinct_level_moves: Default::default(), } } } impl LearnableMoves for LearnableMovesImpl { /// Adds a new level move the Pokemon can learn. fn add_level_move(&mut self, level: LevelInt, m: &StringKey) { self.learned_by_level.get_mut(level as usize).unwrap().push(m.clone()); self.distinct_level_moves.insert(m.clone()); } /// Gets all moves a Pokemon can learn when leveling up to a specific level. fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec> { self.learned_by_level.get(level as usize) } /// Gets the distinct moves a Pokemon can learn through leveling up. fn get_distinct_level_moves(&self) -> &IndexSet { &self.distinct_level_moves } } #[cfg(test)] pub(crate) mod tests { use super::*; #[test] fn adds_level_moves() { let mut moves = LearnableMovesImpl::new(100); moves.add_level_move(1, &"foo".into()); moves.add_level_move(1, &"bar".into()); let m = moves.get_learned_by_level(1u8).unwrap(); assert_eq!(m.len(), 2); assert_eq!(m[0], "foo".into()); assert_eq!(m[1], "bar".into()); } #[test] fn adds_two_same_moves_at_different_level() { let mut moves = LearnableMovesImpl::new(100); moves.add_level_move(1, &"foo".into()); moves.add_level_move(5, &"foo".into()); let m = moves.get_learned_by_level(1u8).unwrap(); assert_eq!(m.len(), 1); assert_eq!(m[0], "foo".into()); let m2 = moves.get_learned_by_level(5u8).unwrap(); assert_eq!(m2.len(), 1); assert_eq!(m2[0], "foo".into()); let distinct = moves.get_distinct_level_moves(); assert_eq!(distinct.len(), 1); assert_eq!(distinct[0], "foo".into()); } mockall::mock! { pub LearnableMoves { fn add_level_move(&mut self, level: LevelInt, m: &StringKey); fn get_learned_by_level<'a>(&'a self, level: LevelInt) -> Option<&'a Vec>; fn get_distinct_level_moves(&self) -> &Vec; } } }