1use crate::{MetricSet, error::RadiateResult};
2use radiate_error::radiate_bail;
3use radiate_expr::Expr;
4use radiate_utils::SmallStr;
5use smallvec::SmallVec;
6
7const DEFAULT_VALUE: f32 = 1.0;
8
9#[derive(Clone)]
10pub struct RateSet {
11 pub control: Expr,
12 pub internal: Vec<Expr>,
13 pub rate_cache: SmallVec<[f32; 8]>,
14 pub last_update_index: usize,
15 pub has_updated: bool,
16}
17
18impl RateSet {
19 pub fn new(control: impl Into<Expr>) -> Self {
20 Self {
21 control: control.into(),
22 internal: Vec::new(),
23 rate_cache: SmallVec::new(),
24 last_update_index: 0,
25 has_updated: false,
26 }
27 }
28
29 pub fn calculate_rates(
30 &mut self,
31 generation: usize,
32 metrics: &MetricSet,
33 ) -> RadiateResult<&[f32]> {
34 if generation > self.last_update_index || !self.has_updated {
35 self.rate_cache.clear();
36
37 let control_rate = Self::try_eval_rate(metrics, &mut self.control)?;
38 self.rate_cache.push(control_rate);
39
40 for expr in &mut self.internal {
41 let rate = Self::try_eval_rate(metrics, expr)?;
42 self.rate_cache.push(rate);
43 }
44
45 self.last_update_index = generation;
46 self.has_updated = true;
47 }
48
49 Ok(&self.rate_cache)
50 }
51
52 pub fn calculate_control_rate(
53 &mut self,
54 generation: usize,
55 metrics: &MetricSet,
56 ) -> RadiateResult<f32> {
57 self.calculate_rates(generation, metrics)?;
58 Ok(self.rate_cache[0])
59 }
60
61 pub fn rates(&self) -> &[f32] {
62 &self.rate_cache
63 }
64
65 pub fn alias(mut self, name: impl Into<SmallStr>) -> Self {
66 let name = name.into();
67 self.control = self.control.clone().alias(name);
68 self
69 }
70
71 pub fn push(mut self, expr: impl Into<Expr>) -> Self {
72 self.internal.push(expr.into());
73 self
74 }
75
76 fn try_eval_rate(metrics: &MetricSet, expr: &mut Expr) -> RadiateResult<f32> {
77 if let Some(metric) = metrics.get(expr.name()) {
78 return Ok(metric.last_value());
79 }
80
81 let output = expr.evaluate(metrics)?;
82 match output.extract::<f32>() {
83 Some(rate) => Ok(rate),
84 None => {
85 radiate_bail!(Expr:
86 "Failed to evaluate rate expression for alterer: expected f32 value, got {:?}",
87 output
88 );
89 }
90 }
91 }
92}
93
94impl Default for RateSet {
95 fn default() -> Self {
96 Self {
97 control: Expr::lit(DEFAULT_VALUE),
98 internal: Vec::new(),
99 rate_cache: SmallVec::new(),
100 last_update_index: 0,
101 has_updated: false,
102 }
103 }
104}
105
106impl From<Expr> for RateSet {
107 fn from(expr: Expr) -> Self {
108 Self::new(expr)
109 }
110}