use rand::Rng;
use std::env;
use crate::constants::DST_SIMULATION_STEPS_MAX;
#[derive(Debug, Clone, Copy)]
pub struct SimConfig {
seed: u64,
steps_max: u64,
}
impl SimConfig {
#[must_use]
pub fn with_seed(seed: u64) -> Self {
let config = Self {
seed,
steps_max: DST_SIMULATION_STEPS_MAX,
};
assert_eq!(config.seed, seed, "seed must be stored correctly");
assert!(config.steps_max > 0, "steps_max must be positive");
config
}
#[must_use]
pub fn from_env_or_random() -> Self {
let seed = match env::var("DST_SEED") {
Ok(seed_str) => {
seed_str.parse::<u64>().unwrap_or_else(|_| {
panic!("DST_SEED must be a valid u64, got: {}", seed_str);
})
}
Err(_) => {
let seed = rand::thread_rng().gen::<u64>();
eprintln!("DST: Generated random seed (replay with DST_SEED={})", seed);
seed
}
};
Self::with_seed(seed)
}
#[must_use]
pub fn seed(&self) -> u64 {
self.seed
}
#[must_use]
pub fn steps_max(&self) -> u64 {
self.steps_max
}
#[must_use]
pub fn with_steps_max(self, steps_max: u64) -> Self {
assert!(steps_max > 0, "steps_max must be positive");
Self {
seed: self.seed,
steps_max,
}
}
}
impl Default for SimConfig {
fn default() -> Self {
Self::from_env_or_random()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_with_seed() {
let config = SimConfig::with_seed(12345);
assert_eq!(config.seed(), 12345);
assert_eq!(config.steps_max(), DST_SIMULATION_STEPS_MAX);
}
#[test]
fn test_with_seed_zero() {
let config = SimConfig::with_seed(0);
assert_eq!(config.seed(), 0);
}
#[test]
fn test_with_seed_max() {
let config = SimConfig::with_seed(u64::MAX);
assert_eq!(config.seed(), u64::MAX);
}
#[test]
fn test_with_steps_max() {
let config = SimConfig::with_seed(42).with_steps_max(100);
assert_eq!(config.seed(), 42);
assert_eq!(config.steps_max(), 100);
}
#[test]
#[should_panic(expected = "steps_max must be positive")]
fn test_with_steps_max_zero_panics() {
let _ = SimConfig::with_seed(42).with_steps_max(0);
}
#[test]
fn test_random_seed_generation() {
let _ = env::remove_var("DST_SEED");
let config = SimConfig::from_env_or_random();
assert!(config.seed() > 0 || config.seed() == 0); assert!(config.steps_max() > 0);
}
}