104 lines
3.5 KiB
Rust
Executable File
104 lines
3.5 KiB
Rust
Executable File
use anyhow_ext::Result;
|
|
use indexmap::IndexSet;
|
|
use parking_lot::RwLock;
|
|
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(&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(Debug)]
|
|
pub struct LearnableMovesImpl {
|
|
/// A map of the moves a Pokemon can learn per level.
|
|
learned_by_level: RwLock<Vec<Vec<StringKey>>>,
|
|
/// A list of the distinct moves a Pokemon can learn through leveling up.
|
|
distinct_level_moves: RwLock<IndexSet<StringKey>>,
|
|
}
|
|
|
|
impl LearnableMovesImpl {
|
|
/// Instantiates a new object to store the moves a Pokemon can learn.
|
|
pub fn new(max_level: LevelInt) -> Self {
|
|
Self {
|
|
learned_by_level: RwLock::new(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(&self, level: LevelInt, m: &StringKey) -> Result<()> {
|
|
self.learned_by_level
|
|
.write()
|
|
.get_mut_res(level as usize)?
|
|
.push(m.clone());
|
|
self.distinct_level_moves.write().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.read().get(level as usize).cloned()
|
|
}
|
|
|
|
/// Gets the distinct moves a Pokemon can learn through leveling up.
|
|
fn get_distinct_level_moves(&self) -> IndexSet<StringKey> {
|
|
self.distinct_level_moves.read().clone()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[allow(clippy::indexing_slicing)]
|
|
#[allow(clippy::unwrap_used)]
|
|
pub(crate) mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn adds_level_moves() {
|
|
let 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 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>;
|
|
}
|
|
}
|
|
}
|