use std::fmt; use std::fmt::{Debug, Formatter}; use hashbrown::HashMap; use crate::defines::LevelInt; use crate::static_data::GrowthRate; use crate::{StringKey, ValueIdentifiable, ValueIdentifier}; /// A library to store all growth rates. pub trait GrowthRateLibrary: Debug + ValueIdentifiable { /// Calculates the level for a given growth key name and a certain experience. fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt; /// Calculates the experience for a given growth key name and a certain level. fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32; /// Adds a new growth rate with a name and value. fn add_growth_rate(&mut self, key: &StringKey, value: Box); } /// A library to store all growth rates. pub struct GrowthRateLibraryImpl { /// A unique identifier so we know what value this is. identifier: ValueIdentifier, /// The underlying data structure. growth_rates: HashMap>, } impl GrowthRateLibraryImpl { /// Instantiates a new growth rate library with a capacity. pub fn new(capacity: usize) -> Self { Self { identifier: Default::default(), growth_rates: HashMap::with_capacity(capacity), } } } impl GrowthRateLibrary for GrowthRateLibraryImpl { /// Calculates the level for a given growth key name and a certain experience. fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt { self.growth_rates[growth_rate].calculate_level(experience) } /// Calculates the experience for a given growth key name and a certain level. fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32 { self.growth_rates[growth_rate].calculate_experience(level) } /// Adds a new growth rate with a name and value. fn add_growth_rate(&mut self, key: &StringKey, value: Box) { self.growth_rates.insert(key.clone(), value); } } impl ValueIdentifiable for GrowthRateLibraryImpl { fn value_identifier(&self) -> ValueIdentifier { self.identifier } } impl Debug for GrowthRateLibraryImpl { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("GrowthRateLibrary").finish() } } #[cfg(test)] pub mod tests { use super::*; use crate::static_data::growth_rates::LookupGrowthRate; use crate::static_data::libraries::growth_rate_library::GrowthRateLibrary; use crate::static_data::GrowthRateLibraryImpl; pub fn build() -> GrowthRateLibraryImpl { let mut lib = GrowthRateLibraryImpl::new(1); // Borrow as mut so we can insert let w = &mut lib; w.add_growth_rate( &"test_growthrate".into(), Box::new(LookupGrowthRate::new(vec![0, 5, 10, 100])), ); // Drops borrow as mut lib } mockall::mock! { #[derive(Debug)] pub GrowthRateLibrary{} impl GrowthRateLibrary for GrowthRateLibrary { fn calculate_level(&self, growth_rate: &StringKey, experience: u32) -> LevelInt; fn calculate_experience(&self, growth_rate: &StringKey, level: LevelInt) -> u32; fn add_growth_rate(&mut self, key: &StringKey, value: Box); } impl ValueIdentifiable for GrowthRateLibrary { fn value_identifier(&self) -> ValueIdentifier{ ValueIdentifier::new(0) } } } #[test] fn add_growth_rate_to_library_and_calculate_level() { let lib = build(); assert_eq!(lib.calculate_level(&"test_growthrate".into(), 3), 1); assert_eq!(lib.calculate_level(&"test_growthrate".into(), 50), 3); } #[test] fn add_growth_rate_to_library_and_calculate_experience() { let lib = build(); assert_eq!(lib.calculate_experience(&"test_growthrate".into(), 1), 0); assert_eq!(lib.calculate_experience(&"test_growthrate".into(), 3), 10); } }