use super::types::*;
use crate::state::State;
use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Default)]
pub struct GenerationStateECS {
pub world: hecs::World,
pub generation_events: Vec<GenerationEventECS>,
pub completed_queue: Vec<hecs::Entity>,
pub metrics: GenerationMetrics,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GenerationEventECS {
#[serde(skip)] pub entity: Option<hecs::Entity>,
pub old_generation: f32,
pub new_generation: f32,
pub progress_amount: f32,
pub timestamp: SystemTime,
pub status_changed: bool,
}
impl Clone for GenerationStateECS {
fn clone(&self) -> Self {
Self::default()
}
}
impl State for GenerationStateECS {}
impl GenerationStateECS {
pub fn new() -> Self {
Self::default()
}
pub fn spawn_entity(
&mut self,
generation: Generation,
environment: GenerationEnvironment,
) -> hecs::Entity {
self.world.spawn((
generation,
environment,
GenerationConditions::default(),
GenerationHistory::default(),
EntityTimestamp::new(),
))
}
pub fn spawn_entity_with_conditions(
&mut self,
generation: Generation,
environment: GenerationEnvironment,
conditions: GenerationConditions,
) -> hecs::Entity {
self.world.spawn((
generation,
environment,
conditions,
GenerationHistory::default(),
EntityTimestamp::new(),
))
}
pub fn entity_count(&self) -> usize {
self.world.len() as usize
}
pub fn cleanup_completed(&mut self) {
for entity in self.completed_queue.drain(..) {
let _ = self.world.despawn(entity);
}
}
pub fn trim_generation_events(&mut self, max_events: usize) {
if self.generation_events.len() > max_events {
let remove_count = self.generation_events.len() - max_events;
self.generation_events.drain(0..remove_count);
}
}
pub fn metrics(&self) -> &GenerationMetrics {
&self.metrics
}
pub fn recent_events(&self, count: usize) -> &[GenerationEventECS] {
let start = self.generation_events.len().saturating_sub(count);
&self.generation_events[start..]
}
pub fn entities_with_status(&self, status: GenerationStatus) -> Vec<hecs::Entity> {
self.world
.query::<&Generation>()
.iter()
.filter_map(|(entity, generation)| {
if generation.status == status {
Some(entity)
} else {
None
}
})
.collect()
}
pub fn paused_entities(&self) -> Vec<hecs::Entity> {
self.world
.query::<&Generation>()
.iter()
.filter_map(|(entity, generation)| {
if generation.paused {
Some(entity)
} else {
None
}
})
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_spawn_entity() {
let mut state = GenerationStateECS::new();
let entity = state.spawn_entity(
Generation::new(100.0, 1.0, GenerationType::Organic),
GenerationEnvironment::default(),
);
assert_eq!(state.entity_count(), 1);
let generation = state.world.get::<&Generation>(entity).unwrap();
assert_eq!(generation.max, 100.0);
}
#[test]
fn test_spawn_with_conditions() {
let mut state = GenerationStateECS::new();
let conditions = GenerationConditions::new().with_resource("wood".to_string(), 10);
let entity = state.spawn_entity_with_conditions(
Generation::new(100.0, 1.0, GenerationType::Construction),
GenerationEnvironment::default(),
conditions,
);
let cond = state.world.get::<&GenerationConditions>(entity).unwrap();
assert_eq!(cond.required_resources.len(), 1);
}
#[test]
fn test_cleanup_completed() {
let mut state = GenerationStateECS::new();
let entity1 = state.spawn_entity(
Generation::new(100.0, 1.0, GenerationType::Production),
GenerationEnvironment::default(),
);
let entity2 = state.spawn_entity(
Generation::new(100.0, 1.0, GenerationType::Recovery),
GenerationEnvironment::default(),
);
assert_eq!(state.entity_count(), 2);
state.completed_queue.push(entity1);
state.cleanup_completed();
assert_eq!(state.entity_count(), 1);
assert!(state.world.get::<&Generation>(entity1).is_err());
assert!(state.world.get::<&Generation>(entity2).is_ok());
}
#[test]
fn test_trim_events() {
let mut state = GenerationStateECS::new();
for i in 0..10 {
state.generation_events.push(GenerationEventECS {
entity: None,
old_generation: i as f32,
new_generation: (i + 1) as f32,
progress_amount: 1.0,
timestamp: SystemTime::now(),
status_changed: false,
});
}
assert_eq!(state.generation_events.len(), 10);
state.trim_generation_events(5);
assert_eq!(state.generation_events.len(), 5);
assert_eq!(state.generation_events[0].old_generation, 5.0);
}
#[test]
fn test_entities_with_status() {
let mut state = GenerationStateECS::new();
state.spawn_entity(
Generation::with_current(10.0, 100.0, 1.0, GenerationType::Organic),
GenerationEnvironment::default(),
);
state.spawn_entity(
Generation::with_current(50.0, 100.0, 1.0, GenerationType::Organic),
GenerationEnvironment::default(),
);
state.spawn_entity(
Generation::with_current(100.0, 100.0, 1.0, GenerationType::Organic),
GenerationEnvironment::default(),
);
let seed_entities = state.entities_with_status(GenerationStatus::Seed);
assert_eq!(seed_entities.len(), 1);
let generating_entities = state.entities_with_status(GenerationStatus::Generating);
assert_eq!(generating_entities.len(), 1);
let completed_entities = state.entities_with_status(GenerationStatus::Completed);
assert_eq!(completed_entities.len(), 1);
}
#[test]
fn test_paused_entities() {
let mut state = GenerationStateECS::new();
let entity1 = state.spawn_entity(
Generation::new(100.0, 1.0, GenerationType::Construction),
GenerationEnvironment::default(),
);
let mut gen = Generation::new(100.0, 1.0, GenerationType::Production);
gen.pause();
state.spawn_entity(gen, GenerationEnvironment::default());
let paused = state.paused_entities();
assert_eq!(paused.len(), 1);
assert!(!paused.contains(&entity1));
}
}