use serde::{Deserialize, Serialize};
use crate::types::Element;
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
pub struct Stats {
pub hp: f64,
pub atk: f64,
pub def: f64,
pub elemental_mastery: f64,
pub crit_rate: f64,
pub crit_dmg: f64,
pub energy_recharge: f64,
pub dmg_bonus: f64,
#[serde(default)]
pub pyro_dmg_bonus: f64,
#[serde(default)]
pub hydro_dmg_bonus: f64,
#[serde(default)]
pub electro_dmg_bonus: f64,
#[serde(default)]
pub cryo_dmg_bonus: f64,
#[serde(default)]
pub dendro_dmg_bonus: f64,
#[serde(default)]
pub anemo_dmg_bonus: f64,
#[serde(default)]
pub geo_dmg_bonus: f64,
#[serde(default)]
pub physical_dmg_bonus: f64,
}
impl Stats {
pub fn total_dmg_bonus(&self, element: Option<Element>) -> f64 {
self.dmg_bonus
+ match element {
Some(Element::Pyro) => self.pyro_dmg_bonus,
Some(Element::Hydro) => self.hydro_dmg_bonus,
Some(Element::Electro) => self.electro_dmg_bonus,
Some(Element::Cryo) => self.cryo_dmg_bonus,
Some(Element::Dendro) => self.dendro_dmg_bonus,
Some(Element::Anemo) => self.anemo_dmg_bonus,
Some(Element::Geo) => self.geo_dmg_bonus,
None => self.physical_dmg_bonus,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::Element;
#[test]
fn total_dmg_bonus_pyro() {
let stats = Stats {
dmg_bonus: 0.10,
pyro_dmg_bonus: 0.466,
..Default::default()
};
let result = stats.total_dmg_bonus(Some(Element::Pyro));
assert!((result - 0.566).abs() < 1e-10);
}
#[test]
fn total_dmg_bonus_physical() {
let stats = Stats {
dmg_bonus: 0.10,
physical_dmg_bonus: 0.583,
..Default::default()
};
let result = stats.total_dmg_bonus(None);
assert!((result - 0.683).abs() < 1e-10);
}
#[test]
fn total_dmg_bonus_no_element_bonus() {
let stats = Stats {
dmg_bonus: 0.15,
pyro_dmg_bonus: 0.466,
..Default::default()
};
let result = stats.total_dmg_bonus(Some(Element::Hydro));
assert!((result - 0.15).abs() < 1e-10);
}
}