use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnergyProfile {
pub idle_cost_per_tick: f64,
pub move_cost_per_tick: f64,
pub weight_factor: f64,
pub regen_factor: f64,
}
impl EnergyProfile {
#[must_use]
pub const fn new(
idle_cost_per_tick: f64,
move_cost_per_tick: f64,
weight_factor: f64,
regen_factor: f64,
) -> Self {
Self {
idle_cost_per_tick,
move_cost_per_tick,
weight_factor,
regen_factor,
}
}
#[must_use]
pub const fn idle_cost_per_tick(&self) -> f64 {
self.idle_cost_per_tick
}
#[must_use]
pub const fn move_cost_per_tick(&self) -> f64 {
self.move_cost_per_tick
}
#[must_use]
pub const fn weight_factor(&self) -> f64 {
self.weight_factor
}
#[must_use]
pub const fn regen_factor(&self) -> f64 {
self.regen_factor
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EnergyMetrics {
pub(crate) total_consumed: f64,
pub(crate) total_regenerated: f64,
pub(crate) ticks_tracked: u32,
}
impl EnergyMetrics {
#[must_use]
pub const fn total_consumed(&self) -> f64 {
self.total_consumed
}
#[must_use]
pub const fn total_regenerated(&self) -> f64 {
self.total_regenerated
}
#[must_use]
pub const fn ticks_tracked(&self) -> u32 {
self.ticks_tracked
}
#[must_use]
pub const fn net_energy(&self) -> f64 {
self.total_consumed - self.total_regenerated
}
pub(crate) fn record(&mut self, consumed: f64, regenerated: f64) {
self.total_consumed += consumed;
self.total_regenerated += regenerated;
self.ticks_tracked += 1;
}
}
#[must_use]
pub(crate) fn compute_tick_energy(
profile: &EnergyProfile,
is_moving: bool,
current_load: f64,
velocity: f64,
) -> (f64, f64) {
if !is_moving {
return (profile.idle_cost_per_tick, 0.0);
}
let consumed = profile
.weight_factor
.mul_add(current_load, profile.move_cost_per_tick);
let regenerated = if velocity < 0.0 {
consumed * profile.regen_factor
} else {
0.0
};
(consumed, regenerated)
}