use sva_formula::Lane;
use super::Horizon;
pub(super) fn nonzero(lane: &Lane, horizon: Horizon, rate: u32, len: usize) -> Vec<(usize, usize)> {
windows(lane, horizon.start_secs, rate, len as f64).unwrap_or_else(|| vec![(0, len)])
}
pub(super) fn windows(
lane: &Lane,
start_secs: f64,
rate: u32,
cap: f64,
) -> Option<Vec<(usize, usize)>> {
if !lane.is_finite_sum() || lane.atoms.iter().any(|a| a.ind.is_none()) {
return None;
}
let edge =
|secs: f64| (((secs - start_secs) * f64::from(rate)).ceil()).clamp(0.0, cap) as usize;
let mut spans: Vec<(usize, usize)> = lane
.atoms
.iter()
.filter_map(|a| {
let window = a.ind?;
let (from, to) = (edge(window.l.value()), edge(window.r.value()));
(from < to).then_some((from, to))
})
.collect();
spans.sort_unstable();
let mut merged: Vec<(usize, usize)> = Vec::with_capacity(spans.len());
for (from, to) in spans {
match merged.last_mut() {
Some(held) if from <= held.1 => held.1 = held.1.max(to),
_ => merged.push((from, to)),
}
}
Some(merged)
}