//! Identify which stage + ship a capture log came from: match the capture's //! draw vertex counts against every resource (incl. LODs) of every Stage_SNN.xpr. //! cargo run --release --example capture_match -- use sylpheed_formats::mesh::{xbg7_resource_names, Xbg7Model}; use sylpheed_formats::ship_capture::{parse_capture, parse_drawlog}; use std::collections::{BTreeMap, HashSet}; fn main() { let a: Vec = std::env::args().collect(); let text = std::fs::read_to_string(&a[1]).unwrap(); let mut draws = parse_capture(&text); if draws.is_empty() { draws = parse_drawlog(&text); } let caps: HashSet = draws.iter().map(|d| d.vcount).filter(|v| *v >= 100).collect(); eprintln!("{} draws, {} distinct vcounts>=100", draws.len(), caps.len()); let mut entries: Vec<_> = std::fs::read_dir(&a[2]).unwrap().filter_map(|e| e.ok()) .filter(|e| { let n = e.file_name().to_string_lossy().to_string(); n.starts_with("Stage_") && n.ends_with(".xpr") }) .map(|e| e.path()).collect(); entries.sort(); for path in entries { let bytes = std::fs::read(&path).unwrap(); let names = xbg7_resource_names(&bytes); let want: HashSet = names.iter().cloned().collect(); let models = Xbg7Model::models_named(&bytes, &want, &|| false); // resource -> vcount; group hits by ship-id prefix let mut hits: BTreeMap> = BTreeMap::new(); for m in &models { let vc: usize = m.meshes.iter().map(|s| s.positions.len()).sum(); if vc >= 100 && caps.contains(&(vc as u32)) { let id = m.name.get(..4).unwrap_or("?").to_string(); hits.entry(id).or_default().push((m.name.clone(), vc as u32)); } } let total: usize = hits.values().map(|v| v.len()).sum(); if total >= 3 { println!("== {} : {} matching resources ==", path.file_name().unwrap().to_string_lossy(), total); for (id, v) in &hits { let s: Vec = v.iter().map(|(n, c)| format!("{n}({c})")).collect(); println!(" {id}: {}", s.join(" ")); } } } }