Skip to main content

hpr_validate/
metrics.rs

1//! References and measured values: what an oracle said, and what hpr said.
2
3use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6
7/// One reference value and where it comes from.
8///
9/// [Loft lesson L77][l77]: Loft shipped "stored results" that were hand-written, one set
10/// internally inconsistent. A value without a source is not a reference, so `source` is required.
11///
12/// [l77]: https://nrdptel.github.io/hpr-sim/decisions-and-roadmap.html#l77
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14#[serde(deny_unknown_fields)]
15pub struct ReferenceValue {
16    /// The value, in the metric's own unit.
17    pub value: f64,
18    /// Where it came from: the oracle's own field, a printed page, or a closed form.
19    pub source: String,
20}
21
22/// An oracle's answers for one case, with the provenance of the run that produced them.
23#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
24pub struct Reference {
25    /// What produced it, as the generator records it (for example `rocketpy 1.13.0`).
26    pub oracle: String,
27    /// The generator script, relative to the repository root.
28    pub generator: String,
29    /// The command that regenerates it.
30    pub command: String,
31    /// What the oracle modeled, in the generator's words.
32    pub model: String,
33    /// What the generator overrode to make the comparison like-for-like.
34    pub overrides: String,
35    /// The reference's own case id.
36    pub case: String,
37    /// The file it was read from, relative to the repository root.
38    pub file: String,
39    /// That file's SHA-256, so an edited reference shows up in the report itself.
40    pub sha256: String,
41    /// The values, by metric name.
42    pub values: BTreeMap<String, ReferenceValue>,
43}
44
45impl Reference {
46    /// The metrics that carry no source, which is what [Loft lesson L77][l77] refuses: a value
47    /// without a source is not a reference.
48    ///
49    /// [l77]: https://nrdptel.github.io/hpr-sim/decisions-and-roadmap.html#l77
50    #[must_use]
51    pub fn without_provenance(&self) -> Vec<String> {
52        self.values
53            .iter()
54            .filter(|(_, value)| value.source.trim().is_empty())
55            .map(|(name, _)| name.clone())
56            .collect()
57    }
58}
59
60/// What hpr measured for one case, by metric name.
61#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
62pub struct Measured {
63    /// The values, by metric name, in the same units as the reference's.
64    pub values: BTreeMap<String, f64>,
65}
66
67impl Measured {
68    /// Records `value` for `name`.
69    pub fn insert(&mut self, name: &str, value: f64) {
70        self.values.insert(name.to_owned(), value);
71    }
72}