use std::time::Duration;
#[inline]
pub fn clamp01(t: f32) -> f32 {
t.clamp(0.0, 1.0)
}
#[inline]
pub fn progress_from_elapsed(elapsed: Duration, duration: Duration) -> f32 {
if duration.is_zero() {
return 1.0;
}
let elapsed_secs = elapsed.as_secs_f32();
let duration_secs = duration.as_secs_f32();
if duration_secs <= 0.0 {
return 1.0;
}
clamp01(elapsed_secs / duration_secs)
}
pub fn sequence_progress(durations: &[Duration], total_progress: f32) -> (usize, f32) {
if durations.is_empty() {
return (0, 1.0);
}
let total_ms: u128 = durations.iter().map(|d| d.as_millis()).sum();
if total_ms == 0 {
return (durations.len() - 1, 1.0);
}
let total_progress = clamp01(total_progress);
let current_ms = (total_progress * (total_ms as f32)).max(0.0);
let mut accumulated_ms = 0f32;
for (index, duration) in durations.iter().enumerate() {
let duration_ms = duration.as_millis() as f32;
if duration_ms <= 0.0 {
continue;
}
if current_ms < accumulated_ms + duration_ms {
let item_progress = (current_ms - accumulated_ms) / duration_ms;
return (index, clamp01(item_progress));
}
accumulated_ms += duration_ms;
}
(durations.len(), 1.0)
}
pub fn parallel_progress(durations: &[Duration], total_progress: f32, index: usize) -> f32 {
if durations.is_empty() || index >= durations.len() {
return 1.0;
}
let max_ms = durations.iter().map(|d| d.as_millis()).max().unwrap_or(0);
if max_ms == 0 {
return 1.0;
}
let item_ms = durations[index].as_millis();
if item_ms == 0 {
return 1.0;
}
let ratio = (item_ms as f32) / (max_ms as f32);
if ratio <= 0.0 {
return 1.0;
}
let total_progress = clamp01(total_progress);
clamp01(total_progress / ratio)
}