re: coverage is 96.4% (6069/6294) -- and the 225 misses get a gate breakdown
undecoded.rs supplies the denominator the coverage numbers never had; the disc holds 6294 XBG7 resources, 6069 decode, 225 are searched and missed, 0 lack a descriptor. gate_histogram.rs attributes each miss to the furthest gate its best candidate reached: 120 connectivity, 74 grouped-pool (different path), 15 degenerate/extent, 9 winding, 7 buffer-not-covered. Recorded as a work-list, not a verdict -- a wrong candidate can pass more gates than the true block. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
60
crates/sylpheed-formats/examples/gate_histogram.rs
Normal file
60
crates/sylpheed-formats/examples/gate_histogram.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
//! Which gate stops the resources that never decode?
|
||||
//! Usage: gate_histogram <resource3d_dir> [max_resources]
|
||||
use sylpheed_formats::mesh::{debug_best_rejection, xbg7_resource_names, Xbg7Model};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
fn main() {
|
||||
let dir = std::env::args().nth(1).expect("resource3d dir");
|
||||
let cap: usize = std::env::args().nth(2).and_then(|s| s.parse().ok()).unwrap_or(usize::MAX);
|
||||
let mut files: Vec<_> = std::fs::read_dir(&dir)
|
||||
.unwrap()
|
||||
.flatten()
|
||||
.map(|e| e.path())
|
||||
.filter(|p| p.extension().and_then(|s| s.to_str()) == Some("xpr"))
|
||||
.collect();
|
||||
files.sort();
|
||||
|
||||
let mut hist: BTreeMap<usize, (usize, String)> = BTreeMap::new();
|
||||
let mut done = 0usize;
|
||||
for f in &files {
|
||||
if done >= cap {
|
||||
break;
|
||||
}
|
||||
let Ok(bytes) = std::fs::read(f) else { continue };
|
||||
let names = xbg7_resource_names(&bytes);
|
||||
if names.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let got: HashSet<String> = Xbg7Model::anchor_models_cancellable(&bytes, 0.0, &|| false)
|
||||
.into_iter()
|
||||
.map(|m| m.name)
|
||||
.collect();
|
||||
for n in names.iter().filter(|n| !got.contains(*n)) {
|
||||
if done >= cap {
|
||||
break;
|
||||
}
|
||||
done += 1;
|
||||
if let Some((rank, why)) = debug_best_rejection(&bytes, n) {
|
||||
let e = hist.entry(rank).or_insert((0, String::new()));
|
||||
e.0 += 1;
|
||||
if e.1.is_empty() {
|
||||
e.1 = format!("{n}: {why}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("furthest gate reached, over {done} resources that never decode:");
|
||||
let label = |r: usize| match r {
|
||||
0 => "no gate reached",
|
||||
1 => "index out of range",
|
||||
2 => "buffer not covered by indices",
|
||||
3 => "degenerate / implausible positions",
|
||||
4 => "connectivity (mean edge / diagonal)",
|
||||
5 => "winding consistency",
|
||||
9 => "grouped pool (different path)",
|
||||
_ => "?",
|
||||
};
|
||||
for (r, (n, ex)) in &hist {
|
||||
println!(" {:<38} {n:>5} e.g. {ex}", label(*r));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user