chore: drop zz_scratch_measure.rs, swept into 49a09a9 by accident

It is a throwaway measurement harness I wrote in this session ("TEMPORARY
measurement scratch — not for commit") that a concurrent commit picked up
along with its own files. It asserts nothing and duplicates work that is now
covered by tests/game_data_disc.rs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Sylpheed RE agent
2026-08-26 01:42:28 +00:00
parent 510dcf29d8
commit 62d8264cbb

View File

@@ -1,88 +0,0 @@
//! TEMPORARY measurement scratch — not for commit.
use std::collections::{BTreeMap, BTreeSet};
use sylpheed_formats::idxd::IdxdObject;
use sylpheed_formats::game_data::schema;
use sylpheed_formats::PakArchive;
fn pak(name: &str) -> Option<PakArchive> {
let disc = std::env::var("SYLPHEED_DISC").ok()?;
PakArchive::open(format!("{disc}/dat/{name}")).ok()
}
fn as_f32(v: &str) -> Option<f32> {
let v = v.strip_suffix(['f','F']).unwrap_or(v);
v.parse().ok()
}
/// field lists per loader
fn keys_for(schema_id: u32) -> Vec<&'static str> {
match schema_id {
schema::WEAPON => vec!["Power","Velocity","MinimumVelocity","MaximumVelocity","MinimumRange","MaximumRange","LoadingCount","Interval","TriggerShotCount","Mass","Heating","Cooling","LifeTime","ID","Name","TargetType"],
schema::UNIT => vec!["HP","IsDestructible","Size_X","Size_Y","Size_Z","Size_Radius","RadarRange","FCSRange","CruisingVelocity","MaximumVelocity","Acceleration","Deceleration","ShieldRatio","TurretCount","ScorePoint","ID","Name"],
schema::VESSEL => vec!["HP","Size_X","Size_Y","Size_Z","RadarRange","FCSRange","MaximumVelocity","ShieldRatio","ScorePoint","TurretCount","BridgeCount","HatchCount","ShieldGeneratorCount","ThrusterCount","ID","Name","Model"],
schema::PLAYER => vec!["AirDragFactor","GravityFactor","BulletLimit","LaserLimit","HomingLimit","SpaceSize","SupplyRange","MainMissionBonus","RankScore_S","RankScore_A","RankScore_B","RankScore_C","RankScore_D"],
schema::CHARACTER => vec!["ID","Name","SideID","Unique"],
schema::STAGE => vec!["BackGroundID"],
_ => vec![],
}
}
#[test]
fn measure() {
let Some(pak) = pak("GP_MAIN_GAME_E.pak") else { eprintln!("SKIP"); return };
let schemas = [
("WEAPON", schema::WEAPON), ("UNIT", schema::UNIT), ("VESSEL", schema::VESSEL),
("PLAYER", schema::PLAYER), ("CHARACTER", schema::CHARACTER), ("STAGE", schema::STAGE),
];
let mut tot = [0usize;5]; // reads, ok, miss, flat, wrong
for (label, sid) in schemas {
let mut objs = 0usize;
let mut c = [0usize;5];
let mut recnames: BTreeMap<String, usize> = BTreeMap::new();
let mut fieldspread: BTreeMap<&str, BTreeMap<usize,usize>> = BTreeMap::new();
let mut examples: Vec<String> = Vec::new();
for e in pak.entries() {
let Ok(b) = pak.read(e) else { continue };
let Ok(o) = IdxdObject::parse(&b) else { continue };
if o.schema_hash != sid { continue }
objs += 1;
let Some(recs) = o.records() else { eprintln!("{label}: NO RECORD TABLE"); continue };
for r in recs { *recnames.entry(r.name.clone()).or_default() += 1; }
// flat map, as game_data builds it
let fmap: BTreeMap<String,String> = o.resolved_fields().into_iter().map(|(k,v)|(k.to_string(),v.to_string())).collect();
for key in keys_for(sid) {
let hits: Vec<(&str,&str)> = recs.iter().filter_map(|r| r.get(key).map(|v| (r.name.as_str(), v))).collect();
let flat: Option<&str> = if ["ID","Name","Model","TargetType","SideID","BackGroundID","Unique","IsDestructible"].contains(&key) {
o.get_raw(key)
} else {
fmap.get(key).map(String::as_str)
};
if hits.is_empty() { continue }
c[0]+=1; tot[0]+=1;
let distinct: BTreeSet<&str> = hits.iter().map(|(_,v)| *v).collect();
*fieldspread.entry(key).or_default().entry(hits.len()).or_default() += 1;
if hits.len() > 1 && distinct.len() > 1 {
c[3]+=1; tot[3]+=1;
if examples.len() < 6 { examples.push(format!("FLAT {key}: {} records, {} distinct vals, flat={:?}, e.g. {:?}", hits.len(), distinct.len(), flat, &hits[..hits.len().min(4)])); }
} else {
let truth = hits[0].1;
match flat {
None => { c[2]+=1; tot[2]+=1;
if examples.len()<6 && hits.len()==1 { examples.push(format!("MISS {key} = {truth:?} in record {:?}", hits[0].0)); } }
Some(f) if f == truth || as_f32(f).is_some() && as_f32(f)==as_f32(truth) => { c[1]+=1; tot[1]+=1; }
Some(f) => { c[4]+=1; tot[4]+=1; examples.push(format!("WRONG {key}: flat={f:?} truth={truth:?} rec={:?}", hits[0].0)); }
}
}
}
}
println!("\n=== {label} {sid:#010x}: {objs} objects; reads {} ok {} miss {} flat {} wrong {}", c[0],c[1],c[2],c[3],c[4]);
let mut rn: Vec<_> = recnames.iter().collect();
rn.sort_by_key(|(_,n)| std::cmp::Reverse(**n));
println!(" records ({} distinct): {:?}", recnames.len(), rn.iter().take(25).map(|(k,n)|format!("{k}×{n}")).collect::<Vec<_>>());
for (k, spread) in &fieldspread {
println!(" field {k}: recs-per-object {:?}", spread);
}
for e in &examples { println!(" {e}"); }
}
println!("\n=== TOTAL reads {} ok {} miss {} flat {} wrong {}", tot[0],tot[1],tot[2],tot[3],tot[4]);
}