PkmnLib_rs/src/static_data/species_data/learnable_moves.rs

100 lines
3.4 KiB
Rust
Executable File

use anyhow_ext::Result;
use indexmap::IndexSet;
use std::fmt::Debug;
use crate::defines::LevelInt;
use crate::{StringKey, VecExt};
/// 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) -> Result<()>;
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<StringKey>>;
/// Gets the distinct moves a Pokemon can learn through leveling up.
fn get_distinct_level_moves(&self) -> &IndexSet<StringKey>;
}
/// 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<Vec<StringKey>>,
/// A list of the distinct moves a Pokemon can learn through leveling up.
distinct_level_moves: IndexSet<StringKey>,
}
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) -> Result<()> {
self.learned_by_level.get_mut_res(level as usize)?.push(m.clone());
self.distinct_level_moves.insert(m.clone());
Ok(())
}
/// Gets all moves a Pokemon can learn when leveling up to a specific level.
fn get_learned_by_level(&self, level: LevelInt) -> Option<&Vec<StringKey>> {
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<StringKey> {
&self.distinct_level_moves
}
}
#[cfg(test)]
#[allow(clippy::indexing_slicing)]
#[allow(clippy::unwrap_used)]
pub(crate) mod tests {
use super::*;
#[test]
fn adds_level_moves() {
let mut moves = LearnableMovesImpl::new(100);
moves.add_level_move(1, &"foo".into()).unwrap();
moves.add_level_move(1, &"bar".into()).unwrap();
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()).unwrap();
moves.add_level_move(5, &"foo".into()).unwrap();
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<StringKey>>;
fn get_distinct_level_moves(&self) -> &Vec<StringKey>;
}
}
}