//! Which focus records have a VARYING alpha — disc-wide, not export-wide? //! //! `rest()` returns an element's last hold keyframe. For a constant-alpha //! element that is harmless. For one that pulses it returns the PEAK, which is //! the `ui-settle-time.md` pathology: the plate's `ptbtn00f` ramps 0→80→0 and //! `rest()` reports 80, its maximum. //! //! The port censused this over its own export (34 records, 2 varying) and //! concluded there is nothing to fix. That conclusion is only as wide as the //! export. This asks the same question of the whole disc. use sylpheed_formats::{pak, ratc, ui_layout}; fn main() { let root = std::env::var("SYLPHEED_DISC").expect("set SYLPHEED_DISC to the extracted disc root"); let mut paks: Vec<_> = std::fs::read_dir(format!("{root}/dat")) .expect("dat/") .flatten() .map(|e| e.path()) .filter(|p| p.extension().and_then(|s| s.to_str()) == Some("pak")) .collect(); paks.sort(); let (mut n_rec, mut n_elem, mut varying) = (0usize, 0usize, 0usize); let (mut at_peak, mut mid_ramp) = (0usize, 0usize); let mut by_pak: std::collections::BTreeMap = Default::default(); let mut hits: Vec = Vec::new(); for p in &paks { let pn = p.file_name().unwrap().to_string_lossy().to_string(); let Ok(ar) = pak::PakArchive::open(p) else { continue; }; for (ei, e) in ar.entries().iter().enumerate() { let Ok(by) = ar.read(e) else { continue }; if !ratc::is_ratc(&by) { continue; } let Some(b) = ui_layout::parse_build(&by) else { continue; }; for (rn, &(o, s)) in &b.records { // A focus record is one whose name is another record's plus `f`. let Some(stem) = rn.strip_suffix("f.rat") else { continue; }; if !b.records.contains_key(&format!("{stem}.rat")) { continue; } if o + s > by.len() { continue; } let Some(lb) = ui_layout::parse_build(&by[o..o + s]) else { continue; }; n_rec += 1; for el in &lb.elements { if el.keyframes.is_empty() { continue; } n_elem += 1; let a: Vec = el.keyframes.iter().map(|k| k.fade >> 24).collect(); let (lo, hi) = (*a.iter().min().unwrap(), *a.iter().max().unwrap()); if lo == hi { continue; } varying += 1; let rest = el.rest().map(|k| k.fade >> 24).unwrap_or(0); if rest == hi { at_peak += 1 } else { mid_ramp += 1 } *by_pak.entry(pn.clone()).or_default() += 1; hits.push(format!( "{pn} [{ei}] {rn}::{} alpha {lo}..{hi} rest()={rest}{}", el.name, if rest == hi { " 🔴 == PEAK" } else { "" } )); } } } } println!("focus records disc-wide : {n_rec}"); println!(" their timed elements : {n_elem}"); println!(" with a VARYING alpha : {varying}"); println!(" of which rest() == the PEAK : {at_peak} <- burns bright forever"); println!(" of which rest() is MID-RAMP : {mid_ramp} <- neither extreme; looks plausible"); println!("\nby pak:"); for (k, v) in &by_pak { println!(" {k:<34} {v}") } println!("\nevery varying one:"); hits.sort(); hits.dedup(); for h in &hits { println!(" {h}") } println!("\n({} distinct)", hits.len()); }