80 findings, not the 14 the first run showed -- clippy stops at the first failing compilation unit, so `--keep-going` is what makes the list complete. 60 were machine-applicable (`cargo clippy --fix`). The rest by hand: * five descending `sort_by` -> `sort_by_key(Reverse(..))` * `chunks_exact(4)` on both sides of four zips, so the compared items stay `[u8; 4]` rather than one array against one slice * three `type` aliases for the census maps and the captured-quad tuple * `&PathBuf` -> `&Path` in two disc tests * two range loops; one of them keeps `#[allow(needless_range_loop)]` with the reason -- the index is into a map's value, which changes each iteration * the module doc list in `invert_capture` re-indented to markdown's rules * `blit`'s eight arguments get `#[allow(too_many_arguments)]`, not a struct One dead `let off = b.len();` in a `ratc` test is dropped rather than renamed. The sibling test at :162 is the one that asserts an offset; if this one was meant to as well, that is a test change and not a lint fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
92 lines
4.0 KiB
Rust
92 lines
4.0 KiB
Rust
//! When the resting-pose DWELL FALLBACK actually runs, does it pick a visible pose?
|
|
//!
|
|
//! `ui-resting-pose.md` argues the fallback is structurally unsound — the gap it
|
|
//! maximises is time spent *interpolating*, so neither endpoint is held. Its one
|
|
//! worked example, `GP_TITLE` build 7's `ptlogo_eff3.t32`, **no longer
|
|
//! discriminates**: under the corrected keyframe-record layout the longest gap
|
|
//! moved from `61→103` to `0→46`, and both ends of that are `a = 0`. The page's
|
|
//! listing still shows the stale parser's trailing `-`.
|
|
//!
|
|
//! Losing the example is not the same as closing the question, so: disc-wide, how
|
|
//! often does the fallback fire, and when it does, does it return something the
|
|
//! player would see? An element resting at `a = 0` is harmless whichever end the
|
|
//! rule lands on.
|
|
//!
|
|
//! cargo run -p sylpheed-formats --example rest_fallback_census
|
|
|
|
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 elements, mut plateau, mut fallback, mut fb_visible) = (0usize, 0, 0, 0);
|
|
let mut worst: Vec<(u32, String, String)> = Vec::new();
|
|
let mut per_pak: std::collections::BTreeMap<String, (usize, usize)> = Default::default();
|
|
for pak in &paks {
|
|
let Ok(ar) = PakArchive::open(pak) else {
|
|
continue;
|
|
};
|
|
let name = pak.file_name().unwrap().to_string_lossy().to_string();
|
|
for (i, e) in ar.entries().iter().enumerate() {
|
|
let Ok(by) = ar.read(e) else { continue };
|
|
let Some(b) = ui_layout::parse_build(&by) else {
|
|
continue;
|
|
};
|
|
for el in &b.elements {
|
|
if el.keyframes.len() < 2 {
|
|
continue;
|
|
}
|
|
elements += 1;
|
|
// a plateau is two ADJACENT poses that are equal — the same test
|
|
// the plateau path makes before the fallback can run
|
|
let has_plateau = el.keyframes.windows(2).any(|w| {
|
|
w[0].x == w[1].x
|
|
&& w[0].y == w[1].y
|
|
&& w[0].scale_x == w[1].scale_x
|
|
&& w[0].scale_y == w[1].scale_y
|
|
&& w[0].fade == w[1].fade
|
|
});
|
|
if has_plateau {
|
|
plateau += 1;
|
|
continue;
|
|
}
|
|
fallback += 1;
|
|
per_pak.entry(name.clone()).or_default().0 += 1;
|
|
let Some(r) = el.rest() else { continue };
|
|
let a = (r.fade >> 24) & 0xff;
|
|
if a > 0 {
|
|
fb_visible += 1;
|
|
per_pak.entry(name.clone()).or_default().1 += 1;
|
|
worst.push((a, name.clone(), format!("e{i}/{}", el.name)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
println!(
|
|
"POPULATION: {elements} elements with >= 2 keyframes, over {} archives",
|
|
paks.len()
|
|
);
|
|
println!("COVERAGE: {plateau} have a plateau (fallback never runs)");
|
|
println!(" {fallback} have NONE -> the dwell fallback decides");
|
|
println!(" {fb_visible} of those rest at alpha > 0 -- i.e. VISIBLE\n");
|
|
println!("PER ARCHIVE — fallback fires / of those, rests VISIBLE:");
|
|
let mut rows: Vec<_> = per_pak.into_iter().collect();
|
|
rows.sort_by_key(|a| std::cmp::Reverse(a.1 .1));
|
|
for (pak, (fires, vis)) in &rows {
|
|
println!(" {pak:34} {fires:5} fires {vis:5} visible");
|
|
}
|
|
println!();
|
|
worst.sort_by_key(|a| std::cmp::Reverse(a.0));
|
|
for (a, pak, el) in worst.iter().take(6) {
|
|
println!(" a={a:3} {pak} {el}");
|
|
}
|
|
println!("\n--- END OF CENSUS (if this line is missing, the run did not finish) ---");
|
|
}
|