LCOV - code coverage report
Current view: top level - src/src - attack_type.rs (source / functions) Coverage Total Hit
Test: lcov Lines: 74.1 % 58 43
Test Date: 2025-06-05 00:12:56 Functions: 80.0 % 5 4
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : use anyhow::{anyhow, Result};
       2                 :             : use indexmap::IndexMap;
       3                 :             : use std::{path::Path, vec};
       4                 :             : 
       5                 :             : use serde::{Deserialize, Serialize};
       6                 :             : 
       7                 :             : use crate::{
       8                 :             :     common::{
       9                 :             :         all_target_const::{TARGET_ALLY, TARGET_ENNEMY},
      10                 :             :         reach_const::INDIVIDUAL,
      11                 :             :         stats_const::HP,
      12                 :             :     },
      13                 :             :     effect::EffectParam,
      14                 :             :     utils,
      15                 :             : };
      16                 :             : 
      17                 :             : #[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq)]
      18                 :             : pub struct AtksInfo {
      19                 :             :     pub atk_name: String,
      20                 :             :     pub nb_use: i64,
      21                 :             :     pub all_damages_by_target: IndexMap<String, i64>, // key target, i64 dmg or heal accumulated
      22                 :             : }
      23                 :             : 
      24                 :             : /// Defines the parameters of an attack.
      25                 :             : #[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
      26                 :             : #[serde(default)]
      27                 :             : pub struct AttackType {
      28                 :             :     /// Name of the attack
      29                 :             :     #[serde(rename = "Nom")]
      30                 :             :     pub name: String,
      31                 :             :     #[serde(rename = "Niveau")]
      32                 :             :     pub level: u8,
      33                 :             :     #[serde(rename = "Coût de mana")]
      34                 :             :     pub mana_cost: u64,
      35                 :             :     #[serde(rename = "Coût de vigueur")]
      36                 :             :     pub vigor_cost: u64,
      37                 :             :     #[serde(rename = "Coût de rage")]
      38                 :             :     pub berseck_cost: u64,
      39                 :             :     #[serde(rename = "Cible")]
      40                 :             :     pub target: String,
      41                 :             :     #[serde(rename = "Portée")]
      42                 :             :     pub reach: String,
      43                 :             :     #[serde(rename = "Photo")]
      44                 :             :     pub name_photo: String,
      45                 :             :     #[serde(rename = "Effet")]
      46                 :             :     pub all_effects: Vec<EffectParam>,
      47                 :             :     #[serde(rename = "Forme")]
      48                 :             :     pub form: String,
      49                 :             :     #[serde(rename = "Aggro")]
      50                 :             :     pub aggro: i64,
      51                 :             :     #[serde(rename = "Durée")]
      52                 :             :     pub turns_duration: i64,
      53                 :             : }
      54                 :             : 
      55                 :             : impl Default for AttackType {
      56                 :         249 :     fn default() -> Self {
      57                 :         249 :         AttackType {
      58                 :         249 :             name: "".to_owned(),
      59                 :         249 :             level: 0,
      60                 :         249 :             mana_cost: 0,
      61                 :         249 :             vigor_cost: 0,
      62                 :         249 :             berseck_cost: 0,
      63                 :         249 :             target: TARGET_ALLY.to_owned(),
      64                 :         249 :             reach: INDIVIDUAL.to_owned(),
      65                 :         249 :             name_photo: "".to_owned(),
      66                 :         249 :             all_effects: vec![],
      67                 :         249 :             form: "".to_owned(),
      68                 :         249 :             aggro: 0,
      69                 :         249 :             turns_duration: 0,
      70                 :         249 :         }
      71                 :         249 :     }
      72                 :             : }
      73                 :             : 
      74                 :             : impl AttackType {
      75                 :         218 :     pub fn try_new_from_json<P: AsRef<Path>>(path: P) -> Result<AttackType> {
      76                 :         218 :         if let Ok(value) = utils::read_from_json::<_, AttackType>(&path) {
      77                 :         218 :             Ok(value)
      78                 :             :         } else {
      79                 :           0 :             Err(anyhow!("Unknown file: {:?}", path.as_ref()))
      80                 :             :         }
      81                 :         218 :     }
      82                 :             : 
      83                 :           0 :     pub fn has_only_heal_effect(&self) -> bool {
      84                 :           0 :         let mut is_only_heal_effect = false;
      85                 :           0 :         for e in &self.all_effects {
      86                 :           0 :             if e.stats_name == HP && e.value < 0 {
      87                 :           0 :                 return false;
      88                 :           0 :             }
      89                 :           0 :             if e.stats_name == HP && e.value > 0 {
      90                 :           0 :                 is_only_heal_effect = true;
      91                 :           0 :             }
      92                 :             :         }
      93                 :           0 :         if self.target != TARGET_ENNEMY && is_only_heal_effect {
      94                 :           0 :             return true;
      95                 :           0 :         }
      96                 :           0 :         false
      97                 :           0 :     }
      98                 :             : }
      99                 :             : 
     100                 :             : #[cfg(test)]
     101                 :             : mod tests {
     102                 :             :     use crate::{
     103                 :             :         attack_type::AttackType,
     104                 :             :         common::{
     105                 :             :             all_target_const::TARGET_ENNEMY, character_json_key::STANDARD_CLASS,
     106                 :             :             effect_const::EFFECT_VALUE_CHANGE, reach_const::INDIVIDUAL, stats_const::HP,
     107                 :             :         },
     108                 :             :     };
     109                 :             : 
     110                 :             :     #[test]
     111                 :           1 :     fn unit_try_new_from_json() {
     112                 :           1 :         let file_path = "./tests/offlines/attack/test/SimpleAtk.json"; // Path to the JSON file
     113                 :           1 :         let atk_type = AttackType::try_new_from_json(file_path);
     114                 :           1 :         assert!(atk_type.is_ok());
     115                 :           1 :         let atk_type: AttackType = atk_type.unwrap();
     116                 :           1 :         assert_eq!(atk_type.name, "SimpleAtk");
     117                 :           1 :         assert_eq!(atk_type.level, 1);
     118                 :           1 :         assert_eq!(atk_type.mana_cost, 9);
     119                 :           1 :         assert_eq!(atk_type.vigor_cost, 0);
     120                 :           1 :         assert_eq!(atk_type.berseck_cost, 0);
     121                 :           1 :         assert_eq!(atk_type.target, TARGET_ENNEMY);
     122                 :           1 :         assert_eq!(atk_type.reach, INDIVIDUAL);
     123                 :           1 :         assert_eq!(atk_type.name_photo, "SimpleAtk.png");
     124                 :           1 :         assert_eq!(atk_type.form, STANDARD_CLASS);
     125                 :           1 :         assert_eq!(atk_type.aggro, 0);
     126                 :             :         // decode the effect
     127                 :           1 :         assert_eq!(atk_type.all_effects.len(), 1);
     128                 :           1 :         assert_eq!(atk_type.all_effects[0].stats_name, HP);
     129                 :           1 :         assert_eq!(atk_type.all_effects[0].value, -35);
     130                 :           1 :         assert_eq!(atk_type.all_effects[0].target, TARGET_ENNEMY);
     131                 :           1 :         assert_eq!(atk_type.all_effects[0].reach, INDIVIDUAL);
     132                 :           1 :         assert_eq!(atk_type.all_effects[0].effect_type, EFFECT_VALUE_CHANGE);
     133                 :           1 :         assert_eq!(atk_type.all_effects[0].sub_value_effect, 0);
     134                 :           1 :     }
     135                 :             : }
        

Generated by: LCOV version 2.0-1