use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum GenerationType {
Organic,
Construction,
Production,
Recovery,
Custom(String),
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum GenerationStatus {
Seed,
Generating,
Maturing,
Mature,
Completed,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Generation {
pub current: f32,
pub max: f32,
pub generation_rate: f32,
pub generation_type: GenerationType,
pub status: GenerationStatus,
pub paused: bool,
}
impl Generation {
pub fn new(max: f32, generation_rate: f32, generation_type: GenerationType) -> Self {
Self {
current: 0.0,
max,
generation_rate,
generation_type,
status: GenerationStatus::Seed,
paused: false,
}
}
pub fn with_current(
current: f32,
max: f32,
generation_rate: f32,
generation_type: GenerationType,
) -> Self {
let mut gen = Self::new(max, generation_rate, generation_type);
gen.current = current.clamp(0.0, max);
gen.update_status();
gen
}
pub fn progress_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.progress_ratio();
self.status = if ratio >= 1.0 {
GenerationStatus::Completed
} else if ratio >= 0.9 {
GenerationStatus::Mature
} else if ratio >= 0.6 {
GenerationStatus::Maturing
} else if ratio >= 0.2 {
GenerationStatus::Generating
} else {
GenerationStatus::Seed
};
}
pub fn is_completed(&self) -> bool {
self.status == GenerationStatus::Completed
}
pub fn pause(&mut self) {
self.paused = true;
}
pub fn resume(&mut self) {
self.paused = false;
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct GenerationConditions {
pub required_resources: Vec<(String, u32)>,
pub min_temperature: Option<f32>,
pub max_temperature: Option<f32>,
pub required_building: Option<String>,
}
impl GenerationConditions {
pub fn new() -> Self {
Self::default()
}
pub fn with_resource(mut self, resource_id: String, amount: u32) -> Self {
self.required_resources.push((resource_id, amount));
self
}
pub fn with_temperature_range(mut self, min: f32, max: f32) -> Self {
self.min_temperature = Some(min);
self.max_temperature = Some(max);
self
}
pub fn with_building(mut self, building_id: String) -> Self {
self.required_building = Some(building_id);
self
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct GenerationEnvironment {
pub temperature: f32,
pub fertility: f32,
pub resource_availability: f32,
pub light_exposure: f32,
}
impl Default for GenerationEnvironment {
fn default() -> Self {
Self {
temperature: 20.0,
fertility: 0.7,
resource_availability: 1.0,
light_exposure: 0.8,
}
}
}
impl GenerationEnvironment {
pub fn new() -> Self {
Self::default()
}
pub fn with_values(temperature: f32, fertility: f32, resources: f32, light: f32) -> Self {
Self {
temperature,
fertility: fertility.clamp(0.0, 1.0),
resource_availability: resources.clamp(0.0, 1.0),
light_exposure: light.clamp(0.0, 1.0),
}
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct GenerationHistory {
pub started_at: Option<SystemTime>,
pub completed_at: Option<SystemTime>,
pub cycle_count: u32,
pub total_resources_consumed: 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 GenerationChange {
pub old_value: f32,
pub new_value: f32,
pub progress_amount: f32,
pub status_changed: bool,
pub completed: bool,
}
#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct GenerationMetrics {
pub entities_processed: usize,
pub entities_completed: usize,
pub last_update_duration_us: u64,
pub total_progress_applied: f32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generation_progress_ratio() {
let gen = Generation::new(100.0, 1.0, GenerationType::Organic);
assert_eq!(gen.progress_ratio(), 0.0);
let mut gen = Generation::with_current(50.0, 100.0, 1.0, GenerationType::Construction);
assert_eq!(gen.progress_ratio(), 0.5);
gen.update_status();
assert_eq!(gen.status, GenerationStatus::Generating);
}
#[test]
fn test_status_transitions() {
let mut gen = Generation::new(100.0, 1.0, GenerationType::Production);
gen.current = 10.0;
gen.update_status();
assert_eq!(gen.status, GenerationStatus::Seed);
gen.current = 30.0;
gen.update_status();
assert_eq!(gen.status, GenerationStatus::Generating);
gen.current = 70.0;
gen.update_status();
assert_eq!(gen.status, GenerationStatus::Maturing);
gen.current = 95.0;
gen.update_status();
assert_eq!(gen.status, GenerationStatus::Mature);
gen.current = 100.0;
gen.update_status();
assert_eq!(gen.status, GenerationStatus::Completed);
assert!(gen.is_completed());
}
#[test]
fn test_pause_resume() {
let mut gen = Generation::new(100.0, 1.0, GenerationType::Organic);
assert!(!gen.paused);
gen.pause();
assert!(gen.paused);
gen.resume();
assert!(!gen.paused);
}
#[test]
fn test_generation_conditions_builder() {
let conditions = GenerationConditions::new()
.with_resource("wood".to_string(), 10)
.with_resource("stone".to_string(), 5)
.with_temperature_range(15.0, 25.0)
.with_building("farm".to_string());
assert_eq!(conditions.required_resources.len(), 2);
assert_eq!(conditions.min_temperature, Some(15.0));
assert_eq!(conditions.max_temperature, Some(25.0));
assert_eq!(conditions.required_building, Some("farm".to_string()));
}
#[test]
fn test_environment_clamping() {
let env = GenerationEnvironment::with_values(25.0, 1.5, -0.5, 0.5);
assert_eq!(env.fertility, 1.0);
assert_eq!(env.resource_availability, 0.0);
assert_eq!(env.light_exposure, 0.5);
}
}