use perfgate_types::{
CHECK_ID_BUDGET, CompareReceipt, FINDING_CODE_METRIC_FAIL, FINDING_CODE_METRIC_WARN,
MetricStatus, VerdictStatus,
};
use super::metric_to_string;
#[derive(Debug, Clone, PartialEq)]
pub struct FindingData {
pub metric_name: String,
pub bench_name: String,
pub baseline: f64,
pub current: f64,
pub regression_pct: f64,
pub threshold: f64,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Finding {
pub code: String,
pub check_id: String,
pub data: FindingData,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Report {
pub verdict: VerdictStatus,
pub findings: Vec<Finding>,
}
#[must_use = "pure computation; call site should use the returned Report"]
pub fn derive_report(receipt: &CompareReceipt) -> Report {
let mut findings = Vec::new();
for (metric, delta) in &receipt.deltas {
match delta.status {
MetricStatus::Pass | MetricStatus::Skip => continue,
MetricStatus::Warn | MetricStatus::Fail => {
let code = match delta.status {
MetricStatus::Warn => FINDING_CODE_METRIC_WARN.to_string(),
MetricStatus::Fail => FINDING_CODE_METRIC_FAIL.to_string(),
_ => unreachable!(),
};
let threshold = receipt
.budgets
.get(metric)
.map(|b| b.threshold)
.unwrap_or(0.0);
findings.push(Finding {
code,
check_id: CHECK_ID_BUDGET.to_string(),
data: FindingData {
metric_name: metric_to_string(*metric),
bench_name: receipt.bench.name.clone(),
baseline: delta.baseline,
current: delta.current,
regression_pct: delta.regression,
threshold,
},
});
}
}
}
Report {
verdict: receipt.verdict.status,
findings,
}
}