use crate::domain::niseci::{
AnagraficaNISECI, AreaNISECI, CampionamentoNISECI, RiferimentoNISECI, StatoEcologicoNISECI,
ValoriIntermediNISECI, ValoriIntermediSpecieNISECI,
};
use crate::engines::niseci::x2::MetricheX2;
use std::collections::{hash_map::Entry, HashMap};
use super::x1::calculate_x1;
use super::x2::calculate_x2;
use super::x2::calculate_x2_per_alloctone;
use super::x3::calculate_x3;
#[cfg(feature = "lessclone")]
pub mod lessclone;
const RQE_NISECI_MAGIC_ADDEND: f32 = std::f32::consts::FRAC_2_SQRT_PI;
const RQE_NISECI_MAGIC_QUOTIENT: f32 = 1.0603;
pub fn calculate_niseci(
campionamento: &CampionamentoNISECI,
riferimento: &RiferimentoNISECI,
anagrafica: &AnagraficaNISECI,
) -> Result<(Option<f32>, ValoriIntermediNISECI), Vec<String>> {
let mut errors = Vec::new();
let x1 = calculate_x1(campionamento, riferimento);
let x2 = calculate_x2(campionamento, anagrafica, true);
match x2 {
Ok(_) => {}
Err(x2_errors) => {
for e in x2_errors {
errors.push(format!("Errore durante calcolo x2: {}", e));
}
return Err(errors);
}
}
let (x2, criteri_x2) = x2.expect("calc_niseci() returned earlier on Err match");
let x2_non_attese = calculate_x2(campionamento, anagrafica, false);
match x2_non_attese {
Ok(_) => {}
Err(x2_non_attese_errors) => {
for e in x2_non_attese_errors {
errors.push(format!("Errore durante calcolo x2_non_attese: {}", e));
}
return Err(errors);
}
}
let (_x2_non_attese, criteri_x2_non_attese) =
x2_non_attese.expect("calc_niseci() returned earlier on Err match");
let x2_per_alloctone = calculate_x2_per_alloctone(campionamento, anagrafica);
match x2_per_alloctone {
Ok(_) => {}
Err(x2_per_alloctone_errors) => {
for e in x2_per_alloctone_errors {
errors.push(format!("Errore durante calcolo x2_per_alloctone: {}", e));
}
return Err(errors);
}
}
let (_x2_per_alloctone, criteri_x2_per_alloctone) =
x2_per_alloctone.expect("calc_niseci() returned earlier on Err match");
let mut valori_intermedi_specie: HashMap<String, ValoriIntermediSpecieNISECI> = HashMap::new();
valori_intermedi_specie.extend(get_valori_intermedi_specie(&criteri_x2));
let intermedi_non_attese = get_valori_intermedi_specie(&criteri_x2_non_attese);
valori_intermedi_specie.extend(intermedi_non_attese);
valori_intermedi_specie.extend(get_valori_intermedi_specie(&criteri_x2_per_alloctone));
let x3 = calculate_x3(campionamento);
match x3 {
Ok(_) => {}
Err(x3_errors) => {
for e in x3_errors {
errors.push(format!("Errore durante calcolo x3: {}", e));
}
return Err(errors);
}
}
let (x3, criteri_x3) = x3.expect("calc_niseci() returned earlier on Err match");
if let Some(ref crit) = criteri_x3 {
let submetriche_map_x3 = crit.get_ref_submetriche_map();
for (key, val) in submetriche_map_x3 {
let classi_eta = val.get_ref_classi_eta();
let specie = key.clone();
let densita_stimata = -1.0; let subvalue_a = val.get_criterio_a();
let subvalue_b = val.get_criterio_b();
let val = ValoriIntermediSpecieNISECI {
#[expect(deprecated)]
classi_eta: classi_eta.clone(),
#[expect(deprecated)]
densita_stimata,
#[expect(deprecated)]
quantita_stimata: 0,
#[expect(deprecated)]
x2_b: 0.0,
#[expect(deprecated)]
rapporto_ad_juv: val.get_rapporto_ad_juv(),
#[expect(deprecated)]
x2_a_a: subvalue_a,
#[expect(deprecated)]
x2_a_b: subvalue_b,
};
match valori_intermedi_specie.entry(specie) {
Entry::Occupied(_) => {}
Entry::Vacant(vacant_entry) => {
vacant_entry.insert(val);
}
}
}
}
let mut x1_x2_errors = Vec::new();
if x1 < 0.0 {
x1_x2_errors.push(format!("Errore risultato x1: valore negativo: {}", x1));
}
if let Some(val) = x2 {
if val < 0.0 {
x1_x2_errors.push(format!("Errore risultato x2: valore negativo: {}", val));
}
}
if !x1_x2_errors.is_empty() {
return Err(x1_x2_errors);
}
let intermediates = ValoriIntermediNISECI {
#[expect(deprecated)]
x1,
#[expect(deprecated)]
x2,
#[expect(deprecated)]
x3,
#[expect(deprecated)]
specie_specifici: valori_intermedi_specie,
#[expect(deprecated)]
x2_a: criteri_x2.get_criterio_a(),
#[expect(deprecated)]
x2_b: criteri_x2.get_criterio_b(),
#[expect(deprecated)]
x3_a: criteri_x3.as_ref().map(|v| v.get_criterio_a()),
#[expect(deprecated)]
x3_b: criteri_x3.as_ref().map(|v| v.get_criterio_b()),
};
match x2 {
Some(x2_val) => {
let niseci = (0.1 * x1.sqrt()) + (0.1 * x2_val.sqrt()) + (0.8 * (x1 * x2_val))
- ((0.1 * (1.0 - x3))
* ((0.1 * x1.sqrt()) + (0.1 * x2_val.sqrt()) + (0.8 * (x1 * x2_val))));
let rounded_niseci = (1000.0 * niseci).round() / 1000.0;
Ok((Some(rounded_niseci), intermediates))
}
None => {
Ok((None, intermediates))
}
}
}
pub fn calculate_rqe_niseci(niseci: Option<f32>) -> Option<f32> {
let rqe =
niseci.map(|val| (val.log(10.0) + RQE_NISECI_MAGIC_ADDEND) / RQE_NISECI_MAGIC_QUOTIENT);
if let Some(r) = rqe {
let rounded_rqe = (100.0 * r).round() / 100.0;
Some(rounded_rqe)
} else {
rqe
}
}
pub fn calculate_stato_ecologico_niseci(
niseci: Option<f32>,
area: &AreaNISECI,
) -> Option<StatoEcologicoNISECI> {
let rqe_niseci = calculate_rqe_niseci(niseci);
rqe_niseci.map(|val| StatoEcologicoNISECI::from((val, area)))
}
fn get_valori_intermedi_specie(
criteri: &MetricheX2,
) -> HashMap<String, ValoriIntermediSpecieNISECI> {
let mut valori_intermedi_specie: HashMap<String, ValoriIntermediSpecieNISECI> = HashMap::new();
let submetriche_map = criteri.get_ref_submetriche_map();
for (key, val) in submetriche_map.iter() {
let criteri_x2_a = val.get_metriche_x2_a();
let classi_eta = val.get_ref_classi_eta();
let specie = key.clone();
let densita_stimata = val.get_ref_metriche_x2_b().get_densita_stimata();
let quantita_stimata = val.get_ref_metriche_x2_b().get_quantita_stimata();
let x2_b = val.get_ref_metriche_x2_b().get_x2_b();
let val = ValoriIntermediSpecieNISECI {
#[expect(deprecated)]
classi_eta: classi_eta.clone(),
#[expect(deprecated)]
densita_stimata,
#[expect(deprecated)]
quantita_stimata,
#[expect(deprecated)]
x2_b,
#[expect(deprecated)]
x2_a_a: criteri_x2_a.get_criterio_a(),
#[expect(deprecated)]
x2_a_b: criteri_x2_a.get_criterio_b(),
#[expect(deprecated)]
rapporto_ad_juv: criteri_x2_a.get_rapporto_ad_juv(),
};
match valori_intermedi_specie.entry(specie) {
Entry::Occupied(_) => {}
Entry::Vacant(vacant_entry) => {
vacant_entry.insert(val);
}
}
}
valori_intermedi_specie
}