use chrono::NaiveDate;
use serde::{Deserialize, Serialize};
use crate::ruleset::{Effectivity, RegulatoryBasis, Ruleset, RulesetId, RulesetVersion};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IndexWeights {
pub disassembly_depth: f64,
pub fasteners: f64,
pub tools: f64,
pub spare_parts: f64,
pub software_updates: f64,
pub repair_information: f64,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PartWeights {
pub battery: f64,
pub display_assembly: f64,
pub back_cover: f64,
pub minor_part: f64,
pub folding_mechanism: Option<f64>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct IndexClassBoundaries {
pub a: f64,
pub b: f64,
pub c: f64,
pub d: f64,
}
pub trait RepairabilityIndexRuleset: Ruleset {
fn weights(&self) -> &IndexWeights;
fn part_weights(&self, foldable: bool) -> &PartWeights;
fn class_boundaries(&self) -> &IndexClassBoundaries;
}
static WEIGHTS: IndexWeights = IndexWeights {
disassembly_depth: 0.25,
fasteners: 0.15,
tools: 0.15,
spare_parts: 0.15,
software_updates: 0.15,
repair_information: 0.15,
};
static PART_WEIGHTS_RIGID: PartWeights = PartWeights {
battery: 0.30,
display_assembly: 0.30,
back_cover: 0.10,
minor_part: 0.05,
folding_mechanism: None,
};
static PART_WEIGHTS_FOLDABLE: PartWeights = PartWeights {
battery: 0.25,
display_assembly: 0.25,
back_cover: 0.09,
minor_part: 0.04,
folding_mechanism: Some(0.17),
};
static CLASS_BOUNDARIES: IndexClassBoundaries = IndexClassBoundaries {
a: 4.00,
b: 3.35,
c: 2.55,
d: 1.75,
};
static BASIS: RegulatoryBasis = RegulatoryBasis {
regulation: "EU 2023/1669",
article: "Annex IV point 5 (calculation method); Annex II Table 4 (class boundaries)",
standard: Some("EN 45554:2020"),
technical_study: Some("JRC128672"),
source_url: Some("https://eur-lex.europa.eu/eli/reg_del/2023/1669/oj/eng"),
superseded_by: None,
};
static ID: RulesetId = RulesetId("eu-2023-1669-repairability-index");
static VERSION: RulesetVersion = RulesetVersion("1.0.0");
static EFFECTIVE: std::sync::OnceLock<Effectivity> = std::sync::OnceLock::new();
pub struct Eu2023_1669Ruleset;
impl Ruleset for Eu2023_1669Ruleset {
fn id(&self) -> &RulesetId {
&ID
}
fn version(&self) -> &RulesetVersion {
&VERSION
}
fn effectivity(&self) -> &Effectivity {
EFFECTIVE.get_or_init(|| {
Effectivity::open(NaiveDate::from_ymd_opt(2025, 6, 20).expect("valid date"))
})
}
fn regulatory_basis(&self) -> &RegulatoryBasis {
&BASIS
}
}
impl RepairabilityIndexRuleset for Eu2023_1669Ruleset {
fn weights(&self) -> &IndexWeights {
&WEIGHTS
}
fn part_weights(&self, foldable: bool) -> &PartWeights {
if foldable {
&PART_WEIGHTS_FOLDABLE
} else {
&PART_WEIGHTS_RIGID
}
}
fn class_boundaries(&self) -> &IndexClassBoundaries {
&CLASS_BOUNDARIES
}
}