This branch predates CI on `main`. `cargo fmt --all` only; no behaviour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
134 lines
5.4 KiB
Rust
134 lines
5.4 KiB
Rust
//! When an element has MORE THAN ONE plateau, does `rest_plateau()` pick the
|
|
//! wrong one — and is that the 21.9 % residual?
|
|
//!
|
|
//! `rest_vs_settle` found that among elements holding a pose ACROSS the screen's
|
|
//! settle instant, `pose_at(settle)` and `rest()` still disagree 21.9 % of the
|
|
//! time. I hypothesised that `rest_plateau()` picks the **longest** run (it does —
|
|
//! `len >= any_len`), which need not be the run covering the settle instant.
|
|
//!
|
|
//! ⚠️ **Control**: on elements with exactly ONE plateau that covers the settle
|
|
//! instant, the two MUST agree. If they do not, the hypothesis is not the
|
|
//! explanation and something else is wrong.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example plateau_choice
|
|
use std::path::PathBuf;
|
|
use sylpheed_formats::{pak::PakArchive, ui_layout};
|
|
|
|
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();
|
|
let (mut one_cov, mut one_agree) = (0usize, 0usize); // control
|
|
let (mut multi_cov, mut multi_agree, mut multi_wrongrun) = (0usize, 0usize, 0usize);
|
|
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;
|
|
};
|
|
if hi - lo < 10 {
|
|
continue;
|
|
}
|
|
let st = lo + (hi - lo) / 2;
|
|
for el in &b.elements {
|
|
let k = &el.keyframes;
|
|
if k.len() < 2 {
|
|
continue;
|
|
}
|
|
let same = |a: &ui_layout::Keyframe, c: &ui_layout::Keyframe| {
|
|
a.fade == c.fade
|
|
&& a.scale_x == c.scale_x
|
|
&& a.scale_y == c.scale_y
|
|
&& a.tint == c.tint
|
|
&& a.x == c.x
|
|
&& a.y == c.y
|
|
};
|
|
// enumerate maximal runs of length >= 2, with their time spans
|
|
let mut runs: Vec<(usize, usize)> = Vec::new();
|
|
let mut i = 0usize;
|
|
while i < k.len() {
|
|
let mut j = i;
|
|
while j + 1 < k.len() && same(&k[j], &k[j + 1]) {
|
|
j += 1
|
|
}
|
|
if j - i + 1 >= 2 {
|
|
runs.push((i, j))
|
|
}
|
|
i = j + 1;
|
|
}
|
|
if runs.is_empty() {
|
|
continue;
|
|
}
|
|
let covers = |&(a, c): &(usize, usize)| match (k[a].time, k[c].time) {
|
|
(Some(t0), Some(t1)) => t0 <= st && st <= t1,
|
|
_ => false,
|
|
};
|
|
let covering: Vec<_> = runs.iter().filter(|r| covers(r)).collect();
|
|
if covering.is_empty() {
|
|
continue;
|
|
}
|
|
let (Some(r), Some(s)) = (el.rest(), el.pose_at(st)) else {
|
|
continue;
|
|
};
|
|
let agree = r.fade == s.fade
|
|
&& r.x == s.x
|
|
&& r.y == s.y
|
|
&& r.scale_x == s.scale_x
|
|
&& r.scale_y == s.scale_y;
|
|
if runs.len() == 1 {
|
|
one_cov += 1;
|
|
if agree {
|
|
one_agree += 1
|
|
}
|
|
} else {
|
|
multi_cov += 1;
|
|
if agree {
|
|
multi_agree += 1
|
|
} else {
|
|
// did rest() land on a run that does NOT cover settle?
|
|
let on_covering = covering.iter().any(|&&(a, c)| {
|
|
(a..=c).any(|idx| {
|
|
let kk = &k[idx];
|
|
kk.fade == r.fade
|
|
&& kk.x == r.x
|
|
&& kk.y == r.y
|
|
&& kk.scale_x == r.scale_x
|
|
&& kk.scale_y == r.scale_y
|
|
})
|
|
});
|
|
if !on_covering {
|
|
multi_wrongrun += 1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!("CONTROL — exactly ONE plateau, and it covers the settle instant:");
|
|
println!(
|
|
" {one_cov} elements, rest() and pose_at(settle) agree on {one_agree} ({:.1} %)",
|
|
100.0 * one_agree as f64 / one_cov.max(1) as f64
|
|
);
|
|
println!("\nTEST — MORE THAN ONE plateau, at least one covering the settle instant:");
|
|
println!(
|
|
" {multi_cov} elements, agree on {multi_agree} ({:.1} %)",
|
|
100.0 * multi_agree as f64 / multi_cov.max(1) as f64
|
|
);
|
|
println!(
|
|
" of the {} disagreements, rest() landed on a run that does NOT cover",
|
|
multi_cov - multi_agree
|
|
);
|
|
println!(" the settle instant: {multi_wrongrun}");
|
|
println!("\n--- END (if this line is missing, the run did not finish) ---");
|
|
}
|