use ordered_float::NotNan;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use crate::node::NodeID;
#[derive(
Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Serialize, Deserialize, ToSchema,
)]
pub struct GID(pub u64);
impl GID {
pub fn get_then_increase(&mut self) -> GID {
let rtn = self.clone();
self.0 += 1;
rtn
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, ToSchema)]
pub struct Guest {
pub id: GID,
pub node: NodeID,
pub energy: u64,
pub walk_cost: u64,
temperature: u8,
#[schema(value_type = f32)]
engine_efficiency: NotNan<f32>,
}
impl Guest {
pub(crate) fn new(id: GID, node: NodeID) -> Guest {
Guest {
id,
node,
temperature: 128,
energy: 100u64,
engine_efficiency: NotNan::new(0.8).unwrap(),
walk_cost: 1u64,
}
}
pub(crate) fn is_energy_enough(&self, cost: u64) -> bool {
self.energy >= cost
}
pub(crate) fn carnot_efficiency(&self, cell: &u8) -> f32 {
let s = unsafe { NotNan::new_unchecked(self.temperature as f32) };
let o = unsafe { NotNan::new_unchecked(*cell as f32) };
let (h, c) = if s > o { (*s, *o) } else { (*o, *s) };
1f32 - c / h
}
pub(crate) fn total_efficiency(&self, cell: &u8) -> f32 {
*self.engine_efficiency * self.carnot_efficiency(cell)
}
pub(crate) fn generate_energy(&mut self, cell: &mut u8) -> u8 {
let delta = self.temperature.abs_diff(*cell);
let delta = (self.total_efficiency(cell) * delta as f32).floor() as u8;
if self.temperature > *cell {
self.temperature -= delta;
*cell += delta;
} else if self.temperature < *cell {
self.temperature += delta;
*cell -= delta;
} else {
()
};
self.energy += delta as u64;
delta
}
}