use crate::resources::Resource;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ContagionConfig {
pub global_propagation_rate: f32,
pub default_mutation_rate: f32,
pub lifetime_turns: u64,
pub min_credibility: f32,
}
impl Default for ContagionConfig {
fn default() -> Self {
Self {
global_propagation_rate: 0.5,
default_mutation_rate: 0.1,
lifetime_turns: 10,
min_credibility: 0.1,
}
}
}
impl Resource for ContagionConfig {}
impl ContagionConfig {
pub fn new() -> Self {
Self::default()
}
pub fn with_propagation_rate(mut self, rate: f32) -> Self {
self.global_propagation_rate = rate.clamp(0.0, 1.0);
self
}
pub fn with_mutation_rate(mut self, rate: f32) -> Self {
self.default_mutation_rate = rate.clamp(0.0, 1.0);
self
}
pub fn with_lifetime_turns(mut self, turns: u64) -> Self {
self.lifetime_turns = turns;
self
}
pub fn with_min_credibility(mut self, credibility: f32) -> Self {
self.min_credibility = credibility.clamp(0.0, 1.0);
self
}
pub fn validate(&self) -> Result<(), String> {
if self.global_propagation_rate < 0.0 || self.global_propagation_rate > 1.0 {
return Err("global_propagation_rate must be between 0.0 and 1.0".to_string());
}
if self.default_mutation_rate < 0.0 || self.default_mutation_rate > 1.0 {
return Err("default_mutation_rate must be between 0.0 and 1.0".to_string());
}
if self.min_credibility < 0.0 || self.min_credibility > 1.0 {
return Err("min_credibility must be between 0.0 and 1.0".to_string());
}
if self.lifetime_turns == 0 {
return Err("lifetime_turns must be greater than 0".to_string());
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = ContagionConfig::default();
assert_eq!(config.global_propagation_rate, 0.5);
assert_eq!(config.default_mutation_rate, 0.1);
assert_eq!(config.lifetime_turns, 10);
assert_eq!(config.min_credibility, 0.1);
}
#[test]
fn test_builder_pattern() {
let config = ContagionConfig::new()
.with_propagation_rate(0.8)
.with_mutation_rate(0.2)
.with_lifetime_turns(15)
.with_min_credibility(0.2);
assert_eq!(config.global_propagation_rate, 0.8);
assert_eq!(config.default_mutation_rate, 0.2);
assert_eq!(config.lifetime_turns, 15);
assert_eq!(config.min_credibility, 0.2);
}
#[test]
fn test_value_clamping() {
let config = ContagionConfig::new()
.with_propagation_rate(1.5) .with_mutation_rate(-0.5) .with_min_credibility(2.0);
assert_eq!(config.global_propagation_rate, 1.0);
assert_eq!(config.default_mutation_rate, 0.0);
assert_eq!(config.min_credibility, 1.0);
}
#[test]
fn test_validation_success() {
let config = ContagionConfig::default();
assert!(config.validate().is_ok());
}
#[test]
fn test_validation_invalid_propagation_rate() {
let config = ContagionConfig {
global_propagation_rate: 1.5,
..Default::default()
};
assert!(config.validate().is_err());
}
#[test]
fn test_validation_invalid_mutation_rate() {
let config = ContagionConfig {
default_mutation_rate: -0.1,
..Default::default()
};
assert!(config.validate().is_err());
}
#[test]
fn test_validation_zero_lifetime() {
let config = ContagionConfig {
lifetime_turns: 0,
..Default::default()
};
assert!(config.validate().is_err());
}
#[test]
fn test_serialization() {
let config = ContagionConfig::default();
let json = serde_json::to_string(&config).unwrap();
let deserialized: ContagionConfig = serde_json::from_str(&json).unwrap();
assert_eq!(
config.global_propagation_rate,
deserialized.global_propagation_rate
);
assert_eq!(
config.default_mutation_rate,
deserialized.default_mutation_rate
);
}
}