use comfy_table::{Cell, CellAlignment, Color, Table};
use crate::attestation::Record;
use crate::scoring::{self, ScoreReport};
pub fn format_score(score: i32) -> String {
if score > 0 {
format!("[+{}]", score)
} else if score < 0 {
format!("[{}]", score)
} else {
"[ 0]".into()
}
}
pub fn score_color(score: i32) -> Color {
if score >= 60 {
Color::Green
} else if score >= 0 {
Color::Yellow
} else {
Color::Red
}
}
pub fn score_table(reports: &[(String, ScoreReport)]) -> Table {
let mut table = Table::new();
table.set_header(vec!["SUBJECT", "RAW", "EFF", "", "STATUS"]);
for (subject, report) in reports {
let status = scoring::score_status(report);
let bar = scoring::score_bar(report.effective, 10);
let status_text = if let Some(ref path) = report.limiting_path {
format!("limited by {}", path.join(" -> "))
} else {
status.to_string()
};
let color = score_color(report.effective);
table.add_row(vec![
Cell::new(subject),
Cell::new(report.raw).set_alignment(CellAlignment::Right),
Cell::new(report.effective)
.set_alignment(CellAlignment::Right)
.fg(color),
Cell::new(&bar),
Cell::new(&status_text).fg(color),
]);
}
table
}
pub fn scores_json(reports: &[(String, ScoreReport)]) -> String {
let entries: Vec<serde_json::Value> = reports
.iter()
.map(|(subject, report)| {
serde_json::json!({
"subject": subject,
"raw_score": report.raw,
"effective_score": report.effective,
"status": scoring::score_status(report),
"limiting_path": report.limiting_path,
})
})
.collect();
serde_json::to_string_pretty(&entries).unwrap_or_default()
}
pub fn show_json(subject: &str, report: &ScoreReport, records: &[Record]) -> String {
serde_json::to_string_pretty(&serde_json::json!({
"subject": subject,
"raw_score": report.raw,
"effective_score": report.effective,
"limiting_path": report.limiting_path,
"records": records,
}))
.unwrap_or_default()
}