use chrono::NaiveDate;
use crate::assessability::Assessability;
use crate::co2e::CradleToGateRuleset;
use crate::repairability::thresholds::{
DisplaysRuleset, LaptopRuleset, RepairabilityRuleset, SimplifiedRepairabilityHeuristic,
WashingMachineRuleset,
};
use crate::repairability_index::{Eu2023_1669Ruleset, RepairabilityIndexRuleset};
use crate::ruleset::{Effectivity, Ruleset};
pub fn all_rulesets() -> &'static [&'static dyn Ruleset] {
&[
&SimplifiedRepairabilityHeuristic,
&LaptopRuleset,
&DisplaysRuleset,
&WashingMachineRuleset,
&CradleToGateRuleset,
&Eu2023_1669Ruleset,
]
}
pub fn resolve_repairability(
product_category: &str,
law_in_force_on: NaiveDate,
) -> Assessability<&'static dyn RepairabilityRuleset> {
let all: &[(&str, &'static dyn RepairabilityRuleset)] = &[
("smartphone-tablet", &SimplifiedRepairabilityHeuristic),
("laptop", &LaptopRuleset),
("displays", &DisplaysRuleset),
("washing-machine", &WashingMachineRuleset),
];
let rows = || all.iter().filter(|(cat, _)| *cat == product_category);
if let Some((_, r)) = rows().find(|(_, r)| r.effectivity().is_active_on(law_in_force_on)) {
return Assessability::Assessed(*r);
}
let mut not_yet: Option<(&'static str, NaiveDate)> = None;
let mut undetermined: Option<(&'static str, &'static str)> = None;
let mut expired: Option<(&'static str, NaiveDate, Option<&'static str>)> = None;
for (_, r) in rows() {
let id = r.id().0;
match r.effectivity() {
Effectivity::Pending { empowerment, .. } => {
undetermined.get_or_insert((id, empowerment));
}
Effectivity::InForce { from, until } => {
if law_in_force_on < *from {
match not_yet {
Some((_, best)) if best <= *from => {}
_ => not_yet = Some((id, *from)),
}
} else if let Some(until) = until {
match expired {
Some((_, best, _)) if best >= *until => {}
_ => expired = Some((id, *until, r.regulatory_basis().superseded_by)),
}
}
}
}
}
if let Some((ruleset_id, applies_from)) = not_yet {
Assessability::NotYetInForce {
ruleset_id,
applies_from,
}
} else if let Some((ruleset_id, empowerment)) = undetermined {
Assessability::Undetermined {
ruleset_id,
empowerment,
}
} else if let Some((ruleset_id, until, superseded_by)) = expired {
Assessability::Expired {
ruleset_id,
until,
superseded_by,
}
} else {
Assessability::OutOfScope
}
}
pub fn resolve_repairability_index(
product_category: &str,
law_in_force_on: NaiveDate,
) -> Assessability<&'static dyn RepairabilityIndexRuleset> {
let all: &[(&str, &'static dyn RepairabilityIndexRuleset)] =
&[("smartphone-tablet", &Eu2023_1669Ruleset)];
let rows = || all.iter().filter(|(cat, _)| *cat == product_category);
if let Some((_, r)) = rows().find(|(_, r)| r.effectivity().is_active_on(law_in_force_on)) {
return Assessability::Assessed(*r);
}
match rows().next() {
None => Assessability::OutOfScope,
Some((_, r)) => match r.effectivity() {
Effectivity::Pending { empowerment, .. } => Assessability::Undetermined {
ruleset_id: r.id().0,
empowerment,
},
Effectivity::InForce { from, .. } => Assessability::NotYetInForce {
ruleset_id: r.id().0,
applies_from: *from,
},
},
}
}