report.rs

3.0 kB · rust · 103 lines

1use crate::ledger::Book;2use crate::registry::Verdict;3use std::collections::HashSet;45pub struct Run {6    pub key: &'static str,7    pub outcome: Option<Result<(), String>>,8}910#[derive(Default)]11pub struct Sheet {12    rows: usize,13    parts: usize,14    untagged: usize,15    witnessless: usize,16    tags: [usize; 4],17    counts: [usize; 5],18    failures: Vec<(String, String)>,19    orphans: Vec<String>,20    missing: Vec<String>,21}2223impl Sheet {24    pub fn count(&self, verdict: Verdict) -> usize {25        self.counts[verdict as usize]26    }2728    fn record(&mut self, verdict: Verdict, key: &str, why: &str) {29        self.counts[verdict as usize] += 1;30        match verdict {31            Verdict::Failed => self.failures.push((key.to_string(), why.to_string())),32            Verdict::Orphan => self.orphans.push(key.to_string()),33            Verdict::Unchecked => self.missing.push(key.to_string()),34            _ => {}35        }36    }37}3839// TALLY4041pub fn tally(book: &Book, runs: &[Run]) -> Sheet {42    let mut sheet = Sheet {43        rows: book.rows.len(),44        parts: book.parts,45        untagged: book.untagged,46        witnessless: book47            .rows48            .iter()49            .filter(|row| row.witnesses.is_empty())50            .count(),51        ..Sheet::default()52    };53    for row in &book.rows {54        sheet.tags[row.tag as usize] += 1;55    }56    let claimed: HashSet<&str> = book.rows.iter().map(|row| row.key.as_str()).collect();57    let run: HashSet<&str> = runs.iter().map(|entry| entry.key).collect();58    for entry in runs {59        let (verdict, why) = match (claimed.contains(entry.key), &entry.outcome) {60            (false, _) => (Verdict::Orphan, String::new()),61            (true, None) => (Verdict::Skipped, String::new()),62            (true, Some(Ok(()))) => (Verdict::Checked, String::new()),63            (true, Some(Err(why))) => (Verdict::Failed, why.clone()),64        };65        sheet.record(verdict, entry.key, &why);66    }67    for row in &book.rows {68        if !run.contains(row.key.as_str()) {69            sheet.record(Verdict::Unchecked, &row.key, "");70        }71    }72    sheet73}7475// DASHBOARD7677pub fn print(sheet: &Sheet) {78    println!(79        "LEDGER {} rows in {} parts, {} untagged, {} witnessless",80        sheet.rows, sheet.parts, sheet.untagged, sheet.witnessless81    );82    println!(83        "TAGS {} proved, {} verified, {} conjecture, {} refuted",84        sheet.tags[0], sheet.tags[1], sheet.tags[2], sheet.tags[3]85    );86    println!(87        "CLAIMS {} checked, {} failed, {} unchecked, {} skipped, {} orphan",88        sheet.count(Verdict::Checked),89        sheet.count(Verdict::Failed),90        sheet.count(Verdict::Unchecked),91        sheet.count(Verdict::Skipped),92        sheet.count(Verdict::Orphan)93    );94    for (key, why) in &sheet.failures {95        println!("FAILED {key}: {why}");96    }97    for key in &sheet.orphans {98        println!("ORPHAN {key}");99    }100    for key in sheet.missing.iter().take(10) {101        println!("UNCHECKED {key}");102    }103}