mod korean_telemetry; mod exporter; use rand::Rng; use korean_telemetry::TelemetryReporter; use exporter::StateExporter; // 1. 8대 물리/생물학적 위상 준위 #[derive(Copy, Clone, Debug, PartialEq)] pub enum PhaseState { HyperInhibition, // -2.0 StandardInhibition,// -1.0 SubInhibition, // -0.5 NegQuiescent, // -0.0 PosQuiescent, // +0.0 SubExcitation, // +0.5 StandardExcitation,// +1.0 HyperExcitation, // +2.0 } impl PhaseState { pub fn value(&self) -> f32 { match self { PhaseState::HyperInhibition => -2.0, PhaseState::StandardInhibition => -1.0, PhaseState::SubInhibition => -0.5, PhaseState::NegQuiescent => -0.01, PhaseState::PosQuiescent => 0.01, PhaseState::SubExcitation => 0.5, PhaseState::StandardExcitation => 1.0, PhaseState::HyperExcitation => 2.0, } } pub fn from_energy(e: f32) -> Self { if e <= -1.5 { PhaseState::HyperInhibition } else if e <= -0.75 { PhaseState::StandardInhibition } else if e <= -0.25 { PhaseState::SubInhibition } else if e <= 0.0 { PhaseState::NegQuiescent } else if e <= 0.25 { PhaseState::PosQuiescent } else if e <= 0.75 { PhaseState::SubExcitation } else if e <= 1.5 { PhaseState::StandardExcitation } else { PhaseState::HyperExcitation } } } // 2. 통합 복잡계 동역학 행성 엔진 pub struct BioPhysEngine { pub size: usize, pub bedrock: Vec, pub topsoil: Vec, pub mutation_rate: f32, pub energy_history: Vec<(usize, f32)>, } impl BioPhysEngine { pub fn new(size: usize, mutation_rate: f32) -> Self { let mut rng = rand::thread_rng(); let bedrock: Vec = (0..size * size) .map(|i| { let x = (i % size) as f32; let y = (i / size) as f32; ((x * 0.3).sin() + (y * 0.3).cos()) * 0.5 }) .collect(); let topsoil: Vec = (0..size * size) .map(|_| PhaseState::from_energy(rng.gen_range(-2.0..2.0))) .collect(); BioPhysEngine { size, bedrock, topsoil, mutation_rate, energy_history: Vec::new(), } } // 1 스텝 동역학 전이 연산 pub fn step(&mut self, tick: usize) -> f32 { let mut rng = rand::thread_rng(); let mut next_topsoil = self.topsoil.clone(); let mut total_energy = 0.0f32; let s = self.size as i32; for y in 0..s { for x in 0..s { let idx = (y * s + x) as usize; let neighbors = [ ((y - 1 + s) % s * s + x) as usize, ((y + 1) % s * s + x) as usize, (y * s + (x - 1 + s) % s) as usize, (y * s + (x + 1) % s) as usize, ]; let neighbor_energy: f32 = neighbors.iter() .map(|&n_idx| self.topsoil[n_idx].value()) .sum::() * 0.25; let mut local_field = neighbor_energy + self.bedrock[idx]; if rng.gen_bool(self.mutation_rate as f64) { local_field += rng.gen_range(-0.5..0.5); } let new_phase = PhaseState::from_energy(local_field); next_topsoil[idx] = new_phase; total_energy += local_field.abs(); } } self.topsoil = next_topsoil; let avg_energy = total_energy / (self.size * self.size) as f32; self.energy_history.push((tick, avg_energy)); avg_energy } pub fn get_phase_values(&self) -> Vec { self.topsoil.iter().map(|p| p.value()).collect() } } fn main() { println!("============================================================"); println!(" 🌌 BioPhys 복잡계 동역학 통합 시스템 구동"); println!("============================================================\n"); let grid_size = 16; let mutation_rate = 0.05; let mut engine = BioPhysEngine::new(grid_size, mutation_rate); println!("⚙️ 시스템 초기화 완료 (16x16 격자, 8대 위상 체계, 5% 변이율)\n"); // 10회 동역학 상태 전이 및 실시간 한국어 텔레메트리 실행 for tick in 1..=6 { let avg_energy = engine.step(tick); let phases = engine.get_phase_values(); let report = TelemetryReporter::analyze(&phases, avg_energy, tick); println!("{}", report); } // 결과 로그 파일 저장 if let Err(e) = StateExporter::save_energy_log("energy_log.csv", &engine.energy_history) { eprintln!("로그 저장 오류: {}", e); } else { println!("📁 동역학 수렴 데이터가 'energy_log.csv'에 정상 저장되었습니다."); } println!("\n============================================================"); println!(" ✅ 전체 파이프라인(동역학 + 텔레메트리 + 데이터 로깅) 실행 완료"); println!("============================================================"); } // 🧪 BioPhys 엔진 단위 테스트 스위트 (tests/engine_tests.rs) #[cfg(test)] mod tests { use super::*; // 1. 위상 전이 수치 매핑 테스트 #[test] fn test_phase_state_thresholds() { assert_eq!(PhaseState::from_energy(2.5), PhaseState::HyperExcitation); assert_eq!(PhaseState::from_energy(1.0), PhaseState::StandardExcitation); assert_eq!(PhaseState::from_energy(0.0), PhaseState::NegQuiescent); assert_eq!(PhaseState::from_energy(-1.0), PhaseState::StandardInhibition); assert_eq!(PhaseState::from_energy(-2.5), PhaseState::HyperInhibition); } // 2. 엔진 초기화 및 크기 검증 테스트 #[test] fn test_engine_initialization() { let size = 8; let engine = BioPhysEngine::new(size, 0.0); assert_eq!(engine.bedrock.len(), size * size); assert_eq!(engine.topsoil.len(), size * size); } // 3. 동역학 스텝 및 에너지 로그 누적 테스트 #[test] fn test_engine_step_and_energy() { let size = 8; let mut engine = BioPhysEngine::new(size, 0.05); let e1 = engine.step(1); let e2 = engine.step(2); assert!(e1 > 0.0); assert!(e2 > 0.0); assert_eq!(engine.energy_history.len(), 2); } // 4. 한국어 텔레메트리 백분율 정합성 테스트 #[test] fn test_telemetry_reporter() { let phases = vec![2.0, 1.0, 0.0, -1.0]; // 25% each approximately let report = TelemetryReporter::analyze(&phases, 1.0, 1); assert!(report.contains("분석 리포트")); assert!(report.contains("평균 계면 에너지")); } }