mecha10_sim/services/
simulation.rs1#![allow(dead_code)]
2
3use crate::paths;
9use crate::sim::{EnvironmentSelector, RobotGenerator, RobotProfile};
10use anyhow::Result;
11use std::path::{Path, PathBuf};
12
13pub struct SimulationService {
35 base_path: PathBuf,
37}
38
39impl SimulationService {
40 pub fn new() -> Self {
42 Self {
43 base_path: PathBuf::from(paths::project::SIMULATION_OUTPUT_DIR),
44 }
45 }
46
47 pub fn with_base_path(base_path: impl Into<PathBuf>) -> Self {
53 Self {
54 base_path: base_path.into(),
55 }
56 }
57
58 pub fn generate(
67 &self,
68 config_path: &Path,
69 output_path: &Path,
70 max_envs: usize,
71 min_score: i32,
72 ) -> Result<GenerationResult> {
73 let profile = RobotProfile::from_config_file(config_path)?;
75
76 let robot_output = output_path.join("robot.tscn");
78 let robot_generator = RobotGenerator::from_config_file(config_path)?;
79 robot_generator.generate(&robot_output)?;
80
81 let selector = EnvironmentSelector::new()?;
83 let matches = selector.select_environments(&profile, max_envs)?;
84
85 let filtered_matches: Vec<_> = matches.into_iter().filter(|m| m.score >= min_score).collect();
86
87 if filtered_matches.is_empty() {
88 return Err(anyhow::anyhow!(
89 "No matching environments found (min score: {})",
90 min_score
91 ));
92 }
93
94 let _catalog_path = PathBuf::from(paths::framework::ROBOT_TASKS_CATALOG);
96 let base_path = PathBuf::from(paths::framework::ROBOT_TASKS_DIR);
97 let mut available_count = 0;
98
99 for env_match in &filtered_matches {
100 let env_path = base_path.join(&env_match.environment.path);
101 if env_path.exists() {
102 available_count += 1;
103 }
104 }
105
106 Ok(GenerationResult {
107 robot_scene: robot_output,
108 environments: filtered_matches.iter().map(|m| m.environment.id.clone()).collect(),
109 available_count,
110 })
111 }
112
113 pub fn generate_robot(&self, config_path: &Path, output_path: &Path) -> Result<()> {
120 let robot_generator = RobotGenerator::from_config_file(config_path)?;
121 robot_generator.generate(output_path)
122 }
123
124 pub fn list_environments(&self, config_path: &Path, verbose: bool) -> Result<Vec<EnvironmentInfo>> {
131 let profile = RobotProfile::from_config_file(config_path)?;
132 let selector = EnvironmentSelector::new()?;
133 let matches = selector.select_environments(&profile, 100)?; let base_path = PathBuf::from(paths::framework::ROBOT_TASKS_DIR);
136 let mut environments = Vec::new();
137
138 for env_match in matches {
139 let env_path = base_path.join(&env_match.environment.path);
140 let available = env_path.exists();
141
142 if verbose || available {
143 environments.push(EnvironmentInfo {
144 id: env_match.environment.id.clone(),
145 name: env_match.environment.name.clone(),
146 description: env_match.environment.description.clone(),
147 score: env_match.score,
148 available,
149 });
150 }
151 }
152
153 Ok(environments)
154 }
155
156 pub fn validate_config(&self, config_path: &Path) -> Result<ValidationResult> {
162 let profile = RobotProfile::from_config_file(config_path)?;
163
164 let mut errors = Vec::new();
165 let mut warnings = Vec::new();
166
167 if profile.platform.is_empty() {
169 errors.push("Platform not specified".to_string());
170 }
171
172 if profile.sensors.is_empty() {
174 warnings.push("No sensors configured".to_string());
175 }
176
177 if profile.task_nodes.is_empty() {
179 warnings.push("No task nodes configured".to_string());
180 }
181
182 let is_valid = errors.is_empty();
183
184 Ok(ValidationResult {
185 is_valid,
186 errors,
187 warnings,
188 platform: profile.platform,
189 sensor_count: profile.sensors.len(),
190 node_count: profile.task_nodes.len(),
191 })
192 }
193
194 pub fn is_setup(&self) -> bool {
196 self.base_path.exists() && self.base_path.join("robot.tscn").exists()
197 }
198
199 pub fn base_path(&self) -> &Path {
201 &self.base_path
202 }
203}
204
205impl Default for SimulationService {
206 fn default() -> Self {
207 Self::new()
208 }
209}
210
211#[derive(Debug)]
213pub struct GenerationResult {
214 pub robot_scene: PathBuf,
215 pub environments: Vec<String>,
216 pub available_count: usize,
217}
218
219#[derive(Debug, Clone)]
221pub struct EnvironmentInfo {
222 pub id: String,
223 pub name: String,
224 pub description: String,
225 pub score: i32,
226 pub available: bool,
227}
228
229#[derive(Debug)]
231pub struct ValidationResult {
232 pub is_valid: bool,
233 pub errors: Vec<String>,
234 pub warnings: Vec<String>,
235 pub platform: String,
236 pub sensor_count: usize,
237 pub node_count: usize,
238}