use super::types::*;
use crate::state::State;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DecayEventECS {
#[serde(skip)] pub entity: Option<hecs::Entity>,
pub old_durability: f32,
pub new_durability: f32,
pub decay_amount: f32,
pub timestamp: std::time::SystemTime,
pub status_changed: bool,
}
pub struct EntropyStateECS {
pub world: hecs::World,
pub destroyed_queue: Vec<hecs::Entity>,
pub decay_events: Vec<DecayEventECS>,
pub metrics: EntropyMetrics,
}
impl Default for EntropyStateECS {
fn default() -> Self {
Self {
world: hecs::World::new(),
destroyed_queue: Vec::new(),
decay_events: Vec::new(),
metrics: EntropyMetrics::default(),
}
}
}
impl Clone for EntropyStateECS {
fn clone(&self) -> Self {
Self::default()
}
}
impl State for EntropyStateECS {}
impl EntropyStateECS {
pub fn new() -> Self {
Self::default()
}
pub fn spawn_entity(
&mut self,
durability: Durability,
environment: EnvironmentalExposure,
) -> hecs::Entity {
self.world.spawn((
durability,
environment,
MaintenanceHistory::default(),
EntityTimestamp::new(),
))
}
pub fn spawn_entity_full(
&mut self,
durability: Durability,
environment: EnvironmentalExposure,
maintenance: MaintenanceHistory,
timestamp: EntityTimestamp,
) -> hecs::Entity {
self.world
.spawn((durability, environment, maintenance, timestamp))
}
pub fn despawn(&mut self, entity: hecs::Entity) -> Result<(), hecs::ComponentError> {
self.world.despawn(entity)?;
Ok(())
}
pub fn entity_count(&self) -> usize {
self.world.len() as usize
}
pub fn clear_destroyed_queue(&mut self) {
self.destroyed_queue.clear();
}
pub fn cleanup_destroyed(&mut self) {
let entities: Vec<_> = self.destroyed_queue.drain(..).collect();
for entity in entities {
let _ = self.despawn(entity);
}
}
pub fn metrics(&self) -> &EntropyMetrics {
&self.metrics
}
pub fn metrics_mut(&mut self) -> &mut EntropyMetrics {
&mut self.metrics
}
pub fn trim_decay_events(&mut self, max_events: usize) {
if self.decay_events.len() > max_events {
let excess = self.decay_events.len() - max_events;
self.decay_events.drain(0..excess);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_spawn_entity() {
let mut state = EntropyStateECS::new();
let durability = Durability::new(100.0, 0.01, MaterialType::Metal);
let environment = EnvironmentalExposure::default();
let entity = state.spawn_entity(durability.clone(), environment);
assert_eq!(state.entity_count(), 1);
let dur = state.world.get::<&Durability>(entity).unwrap();
assert_eq!(dur.max, 100.0);
assert_eq!(dur.material, MaterialType::Metal);
}
#[test]
fn test_despawn_entity() {
let mut state = EntropyStateECS::new();
let durability = Durability::new(100.0, 0.01, MaterialType::Organic);
let environment = EnvironmentalExposure::default();
let entity = state.spawn_entity(durability, environment);
assert_eq!(state.entity_count(), 1);
state.despawn(entity).unwrap();
assert_eq!(state.entity_count(), 0);
}
#[test]
fn test_destroyed_queue() {
let mut state = EntropyStateECS::new();
let entity1 = state.spawn_entity(
Durability::new(100.0, 0.01, MaterialType::Metal),
EnvironmentalExposure::default(),
);
let entity2 = state.spawn_entity(
Durability::new(100.0, 0.01, MaterialType::Organic),
EnvironmentalExposure::default(),
);
state.destroyed_queue.push(entity1);
state.destroyed_queue.push(entity2);
assert_eq!(state.destroyed_queue.len(), 2);
assert_eq!(state.entity_count(), 2);
state.cleanup_destroyed();
assert_eq!(state.destroyed_queue.len(), 0);
assert_eq!(state.entity_count(), 0);
}
#[test]
fn test_trim_decay_events() {
let mut state = EntropyStateECS::new();
for i in 0..100 {
state.decay_events.push(DecayEventECS {
entity: None,
old_durability: 100.0,
new_durability: 99.0 - i as f32,
decay_amount: 1.0,
timestamp: std::time::SystemTime::now(),
status_changed: false,
});
}
assert_eq!(state.decay_events.len(), 100);
state.trim_decay_events(50);
assert_eq!(state.decay_events.len(), 50);
assert_eq!(state.decay_events[0].new_durability, 49.0);
}
}