Skip to main content

calculate_metrics/
calculate_metrics.rs

1//! Compute a product's CO₂e footprint and simplified repairability heuristic.
2//!
3//! Run with: `cargo run --example calculate_metrics -p dpp-calc`
4
5use chrono::NaiveDate;
6use dpp_calc::clock::AssessmentClock;
7use dpp_calc::co2e::{self, Co2eInputs, CradleToGateRuleset, MaterialFootprint};
8use dpp_calc::repairability::{
9    self, SimplifiedRepairabilityHeuristic, parameters::RepairabilityInputs,
10};
11
12fn main() {
13    // The date the governing law attached to this product. In a real caller this
14    // comes from the passport's placing-on-market date, never from the clock.
15    let clock = AssessmentClock::placed_on(NaiveDate::from_ymd_opt(2026, 1, 1).unwrap());
16
17    // Cradle-to-gate CO₂e for a small battery (materials + manufacturing energy).
18    let footprint = co2e::calculate(
19        &Co2eInputs {
20            materials: vec![
21                MaterialFootprint {
22                    mass_kg: 0.5,
23                    emission_factor_kg_co2e_per_kg: 8.0, // e.g. recycled aluminium
24                },
25                MaterialFootprint {
26                    mass_kg: 0.2,
27                    emission_factor_kg_co2e_per_kg: 3.0,
28                },
29            ],
30            energy_kwh: 1.5,
31            grid_factor_kg_co2e_per_kwh: 0.4,
32        },
33        &CradleToGateRuleset,
34        clock,
35    )
36    .expect("valid inputs");
37
38    println!(
39        "CO₂e: {:.2} kg  (materials {:.2} + energy {:.2})  stages={:?}  receipt={}",
40        footprint.total_co2e_kg,
41        footprint.material_co2e_kg,
42        footprint.energy_co2e_kg,
43        footprint.declared_stages,
44        footprint.receipt.receipt_id,
45    );
46    for (i, line) in footprint.material_breakdown.iter().enumerate() {
47        println!(
48            "  material[{i}]: {:.3} kg × {:.3} kg CO₂e/kg = {:.3} kg CO₂e",
49            line.mass_kg, line.emission_factor_kg_co2e_per_kg, line.co2e_kg
50        );
51    }
52
53    // Simplified repairability heuristic band (A–E) for a smartphone — not the
54    // EU 2023/1669 regulatory class.
55    let rep = repairability::calculate(
56        &RepairabilityInputs {
57            disassembly: 2,
58            spare_parts: 2,
59            repair_info: 1,
60            diagnostic_tools: 1,
61            software_updatability: 2,
62            customer_support: 1,
63        },
64        &SimplifiedRepairabilityHeuristic,
65        clock,
66    )
67    .expect("valid inputs");
68
69    println!(
70        "Repairability: {}  ({:.2}/10)  ruleset={}@{}",
71        rep.class, rep.numeric_score, rep.receipt.ruleset_id, rep.receipt.ruleset_version,
72    );
73    let c = &rep.contributions;
74    println!(
75        "  disassembly={:.2} spare_parts={:.2} repair_info={:.2} \
76         diagnostic={:.2} software={:.2} support={:.2}",
77        c.disassembly,
78        c.spare_parts,
79        c.repair_info,
80        c.diagnostic_tools,
81        c.software_updatability,
82        c.customer_support,
83    );
84}