The port found ptmsg, the main menu's footer, at alpha 127.5 at that screen's settle instant. Verified: build 5's window is [44,56] = 12 units and screen render --settle already prints 'narrow -- this bundle may never settle'. Disc-wide, elements caught mid-ramp at their screen's settle instant: 25.5 % overall, 40.9 % on windows under 10 units, 45.1 % on 10-19, falling to 11.7 % and 15.0 % on wide ones. The obvious reading of that table -- narrow window means the settle pose is bad -- is REFUTED by the screens that motivated the proposal, and I nearly published it. The two splashes have an 8-unit window, narrower than the main menu's 12, and the settle pose beats rest() there by 75x and 33x. Width does not predict quality. The predictor is the port's own statement: the settle pose wins decisively where rest() lands on a transient's peak, and loses slightly where rest() is already sound and an element arrives after the window closes. And my own rest_vs_settle filter was wrong in both directions: dropping bundles under 10 units admitted the 10-19 bucket, the worst at 45.1 %, and excluded both splashes at width 8 -- the strongest evidence FOR the proposal. A threshold taken from a documented rule of thumb and applied without checking which screens it admitted and which it threw away. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
76 lines
3.6 KiB
Rust
76 lines
3.6 KiB
Rust
//! 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<PathBuf> = 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::<usize>(), te, tm,
|
||
100.0 * tm as f64 / te as f64);
|
||
println!("\n--- END (if this line is missing, the run did not finish) ---");
|
||
}
|