pub const SYMBOL: &str = "Ag";
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Time {
Hours(f64),
Seconds(f64),
Millis(f64),
}
impl Time {
#[inline]
pub fn hours(self) -> f64 {
match self {
Time::Hours(h) => h,
Time::Seconds(s) => s / 3600.0,
Time::Millis(ms) => ms / 3_600_000.0,
}
}
}
#[inline]
pub fn agentron(tokens: f64, time: Time) -> f64 {
time.hours() * (tokens / 1_000_000.0)
}
pub fn agentron_total(runs: &[(f64, f64)]) -> f64 {
let mut tokens = 0.0;
let mut hours = 0.0;
for &(t, h) in runs {
tokens += t;
hours += h;
}
hours * (tokens / 1_000_000.0)
}
#[inline]
pub fn compute_agentron(duration_ms: f64, tokens: f64) -> f64 {
agentron(tokens, Time::Millis(duration_ms))
}
pub fn format_ag(value: f64) -> String {
let s = if value >= 1.0 {
format!("{value:.1}")
} else {
format!("{value:.2}")
};
format!("{s} {SYMBOL}")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic() {
assert_eq!(agentron(1_500_000.0, Time::Hours(2.0)), 3.0);
}
#[test]
fn time_units_equivalent() {
assert_eq!(agentron(1_000_000.0, Time::Seconds(3600.0)), 1.0);
assert_eq!(agentron(1_000_000.0, Time::Millis(3_600_000.0)), 1.0);
assert_eq!(compute_agentron(3_600_000.0, 1_000_000.0), 1.0);
}
#[test]
fn multi_agent_multiplies() {
assert_eq!(agentron_total(&[(1_000_000.0, 1.0), (1_000_000.0, 1.0)]), 4.0);
}
#[test]
fn formatting() {
assert_eq!(format_ag(3.0), "3.0 Ag");
assert_eq!(format_ag(0.0845), "0.08 Ag");
assert_eq!(SYMBOL, "Ag");
}
}