//! How often does posing at the SCREEN's settle instant catch an element //! mid-ramp? The adversarial census of my own proposal. //! //! The port agent found `ptmsg` — the main menu's footer — at alpha **127.5 of //! 255** at that screen's settle instant, because the longest keyframe-free //! interval ends exactly as the footer starts to arrive. `screen render --settle` //! already prints "⚠️ narrow — this bundle may never settle" there: the window is //! **12 units**. //! //! ⚠️ **And my `rest_vs_settle` filter was too permissive**: it dropped bundles //! with a window under 10 units, so a 12-unit window passed while the tool itself //! was flagging it. This splits by width instead of picking one cutoff. //! //! "Mid-ramp" = at the settle instant the element sits strictly inside an interval //! whose two endpoint poses DIFFER — it is interpolating, not held. //! //! cargo run -p sylpheed-formats --example settle_midramp_census use sylpheed_formats::{pak::PakArchive, ui_layout}; use std::path::PathBuf; fn main() { let root = PathBuf::from(std::env::var("SYLPHEED_DISC").expect("SYLPHEED_DISC")); let mut paks: Vec = std::fs::read_dir(root.join("dat")).expect("dat/") .filter_map(|e| e.ok().map(|e| e.path())) .filter(|p| p.extension().is_some_and(|x| x == "pak")).collect(); paks.sort(); // buckets by settle-window width let edges = [0u32, 10, 20, 30, 60, u32::MAX]; let names = ["< 10", "10–19", "20–29", "30–59", ">= 60"]; let mut els = [0usize; 5]; let mut mid = [0usize; 5]; let mut bundles = [0usize; 5]; for pak in &paks { let Ok(ar) = PakArchive::open(pak) else { continue }; for e in ar.entries() { let Ok(by) = ar.read(e) else { continue }; let Some(b) = ui_layout::parse_build(&by) else { continue }; let Some((lo, hi)) = b.settle_window() else { continue }; let w = hi - lo; let bi = edges.windows(2).position(|p| w >= p[0] && w < p[1]).unwrap_or(4); bundles[bi] += 1; let st = lo + w / 2; for el in &b.elements { let k = &el.keyframes; if k.len() < 2 { continue } els[bi] += 1; // the interval containing the settle instant let mut interpolating = false; for pair in k.windows(2) { if let (Some(t0), Some(t1)) = (pair[0].time, pair[1].time) { if t0 <= st && st <= t1 && t0 != t1 { let same = pair[0].fade == pair[1].fade && pair[0].x == pair[1].x && pair[0].y == pair[1].y && pair[0].scale_x == pair[1].scale_x && pair[0].scale_y == pair[1].scale_y; if !same && st != t0 && st != t1 { interpolating = true } break; } } } if interpolating { mid[bi] += 1 } } } } println!("{:8}{:>10}{:>10}{:>12}{:>10}", "window", "bundles", "elements", "mid-ramp", "share"); for i in 0..5 { if els[i] == 0 { continue } println!("{:8}{:>10}{:>10}{:>12}{:>9.1}%", names[i], bundles[i], els[i], mid[i], 100.0 * mid[i] as f64 / els[i] as f64); } let te: usize = els.iter().sum(); let tm: usize = mid.iter().sum(); println!("{:8}{:>10}{:>10}{:>12}{:>9.1}%", "ALL", bundles.iter().sum::(), te, tm, 100.0 * tm as f64 / te as f64); println!("\n--- END (if this line is missing, the run did not finish) ---"); }