use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum MaterialType {
Organic,
Metal,
Plastic,
Stone,
Electronic,
Custom(String),
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum DurabilityStatus {
Intact,
Worn,
Damaged,
Critical,
Destroyed,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Durability {
pub current: f32,
pub max: f32,
pub decay_rate: f32,
pub material: MaterialType,
pub status: DurabilityStatus,
}
impl Durability {
pub fn new(max: f32, decay_rate: f32, material: MaterialType) -> Self {
Self {
current: max,
max,
decay_rate,
material,
status: DurabilityStatus::Intact,
}
}
pub fn current_ratio(&self) -> f32 {
if self.max <= 0.0 {
0.0
} else {
(self.current / self.max).clamp(0.0, 1.0)
}
}
pub fn update_status(&mut self) {
let ratio = self.current_ratio();
self.status = if ratio >= 0.8 {
DurabilityStatus::Intact
} else if ratio >= 0.5 {
DurabilityStatus::Worn
} else if ratio >= 0.2 {
DurabilityStatus::Damaged
} else if ratio > 0.0 {
DurabilityStatus::Critical
} else {
DurabilityStatus::Destroyed
};
}
pub fn is_destroyed(&self) -> bool {
self.status == DurabilityStatus::Destroyed
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EnvironmentalExposure {
pub humidity: f32,
pub pollution: f32,
pub temperature: f32,
pub sunlight_exposure: f32,
}
impl Default for EnvironmentalExposure {
fn default() -> Self {
Self {
humidity: 0.5,
pollution: 0.0,
temperature: 20.0,
sunlight_exposure: 0.5,
}
}
}
impl EnvironmentalExposure {
pub fn new() -> Self {
Self::default()
}
pub fn with_values(humidity: f32, pollution: f32, temperature: f32, sunlight: f32) -> Self {
Self {
humidity: humidity.clamp(0.0, 1.0),
pollution: pollution.clamp(0.0, 1.0),
temperature,
sunlight_exposure: sunlight.clamp(0.0, 1.0),
}
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct MaintenanceHistory {
pub last_maintained: Option<SystemTime>,
pub maintenance_count: u32,
pub total_repair_cost: f32,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EntityTimestamp {
pub created_at: SystemTime,
pub last_updated: SystemTime,
}
impl EntityTimestamp {
pub fn new() -> Self {
let now = SystemTime::now();
Self {
created_at: now,
last_updated: now,
}
}
pub fn touch(&mut self) {
self.last_updated = SystemTime::now();
}
}
impl Default for EntityTimestamp {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug)]
pub struct DurabilityChange {
pub old_value: f32,
pub new_value: f32,
pub decay_amount: f32,
pub status_changed: bool,
pub destroyed: bool,
}
#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct EntropyMetrics {
pub entities_processed: usize,
pub entities_destroyed: usize,
pub last_update_duration_us: u64,
pub total_decay_applied: f32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_durability_ratio() {
let dur = Durability::new(100.0, 0.01, MaterialType::Metal);
assert_eq!(dur.current_ratio(), 1.0);
let mut dur = Durability {
current: 50.0,
max: 100.0,
decay_rate: 0.01,
material: MaterialType::Metal,
status: DurabilityStatus::Intact,
};
assert_eq!(dur.current_ratio(), 0.5);
dur.update_status();
assert_eq!(dur.status, DurabilityStatus::Worn);
}
#[test]
fn test_status_transitions() {
let mut dur = Durability::new(100.0, 0.01, MaterialType::Organic);
dur.current = 85.0;
dur.update_status();
assert_eq!(dur.status, DurabilityStatus::Intact);
dur.current = 60.0;
dur.update_status();
assert_eq!(dur.status, DurabilityStatus::Worn);
dur.current = 30.0;
dur.update_status();
assert_eq!(dur.status, DurabilityStatus::Damaged);
dur.current = 10.0;
dur.update_status();
assert_eq!(dur.status, DurabilityStatus::Critical);
dur.current = 0.0;
dur.update_status();
assert_eq!(dur.status, DurabilityStatus::Destroyed);
assert!(dur.is_destroyed());
}
#[test]
fn test_environmental_exposure_clamping() {
let env = EnvironmentalExposure::with_values(1.5, -0.5, 25.0, 0.8);
assert_eq!(env.humidity, 1.0);
assert_eq!(env.pollution, 0.0);
assert_eq!(env.sunlight_exposure, 0.8);
}
}