Skip to main content

qualia_core_db/query/
spawn_decay.rs

1//! Continuous spawn/decay α ramps (P3).
2//!
3//! Replaces binary temporal on/off with fade-in/out over valid-time windows.
4
5/// Compute the visibility α ∈ [0, 1] for an asset at `now` given its valid-time
6/// interval and optional ramp durations (seconds).
7///
8/// - Before `valid_from - onset`: α = 0
9/// - During onset ramp: linear 0 → 1
10/// - Between onset end and decay start: α = 1
11/// - During decay ramp: linear 1 → 0
12/// - After `valid_until + decay`: α = 0
13pub fn spawn_decay_alpha(
14    now: u64,
15    valid_from: u64,
16    valid_until: Option<u64>,
17    onset_secs: u64,
18    decay_secs: u64,
19) -> f32 {
20    if now < valid_from.saturating_sub(onset_secs) {
21        return 0.0;
22    }
23    if onset_secs > 0 && now < valid_from {
24        let t = (now - valid_from.saturating_sub(onset_secs)) as f64 / onset_secs as f64;
25        return t.clamp(0.0, 1.0) as f32;
26    }
27    if let Some(until) = valid_until {
28        if now > until.saturating_add(decay_secs) {
29            return 0.0;
30        }
31        if decay_secs > 0 && now > until {
32            let t = 1.0 - (now - until) as f64 / decay_secs as f64;
33            return t.clamp(0.0, 1.0) as f32;
34        }
35    }
36    1.0
37}
38
39/// Whether an asset should be considered visible at all (α > 0).
40#[inline]
41pub fn temporally_active(
42    now: u64,
43    valid_from: u64,
44    valid_until: Option<u64>,
45    onset_secs: u64,
46    decay_secs: u64,
47) -> bool {
48    spawn_decay_alpha(now, valid_from, valid_until, onset_secs, decay_secs) > 0.0
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn full_lifecycle_ramps() {
57        let vf = 1000u64;
58        let vu = 2000u64;
59        let onset = 100u64;
60        let decay = 100u64;
61
62        assert_eq!(spawn_decay_alpha(899, vf, Some(vu), onset, decay), 0.0);
63        assert!((spawn_decay_alpha(950, vf, Some(vu), onset, decay) - 0.5).abs() < 0.01);
64        assert_eq!(spawn_decay_alpha(1500, vf, Some(vu), onset, decay), 1.0);
65        assert!((spawn_decay_alpha(2050, vf, Some(vu), onset, decay) - 0.5).abs() < 0.01);
66        assert_eq!(spawn_decay_alpha(2101, vf, Some(vu), onset, decay), 0.0);
67    }
68
69    #[test]
70    fn open_ended_validity() {
71        assert_eq!(spawn_decay_alpha(5000, 1000, None, 0, 0), 1.0);
72        assert_eq!(spawn_decay_alpha(500, 1000, None, 0, 0), 0.0);
73    }
74}