Skip to main content

mecha10_sim/sim/
validator.rs

1//! Simulation validation
2//!
3//! Functions for validating simulation configurations and catalogs.
4
5use crate::sim::{EnvironmentCatalog, RobotProfile};
6use anyhow::Result;
7use std::path::Path;
8
9/// Validate mecha10.json for simulation generation
10pub fn validate_config(config_path: &Path) -> Result<()> {
11    println!("šŸ” Validating configuration...\n");
12
13    let profile = RobotProfile::from_config_file(config_path)?;
14
15    println!("āœ… Configuration is valid!\n");
16    println!("Robot Profile:");
17    println!("  Platform: {}", profile.platform);
18    println!("  Sensors: {} configured", profile.sensors.len());
19    println!("  Task Nodes: {} configured", profile.task_nodes.len());
20    println!("  Capabilities: {}", profile.capabilities.join(", "));
21
22    Ok(())
23}
24
25/// Validate environment catalog integrity
26///
27/// `robot_tasks_dir` is `configs/simulation/environments/robot-tasks` under a freshly-fetched
28/// `mecha10-assets` extraction (see `EnvironmentSelector::new`).
29pub fn validate_catalog(robot_tasks_dir: &Path, verbose: bool, missing_only: bool) -> Result<()> {
30    println!("šŸ” Validating environment catalog...\n");
31
32    let catalog_path = robot_tasks_dir.join("catalog.json");
33    let catalog = EnvironmentCatalog::load(&catalog_path)?;
34    let base_path = robot_tasks_dir;
35
36    let mut total = 0;
37    let mut implemented = 0;
38    let mut missing = 0;
39    let mut missing_envs = Vec::new();
40
41    for env in &catalog.environments {
42        total += 1;
43
44        let full_path = base_path.join(&env.path);
45        let exists = full_path.exists();
46
47        if exists {
48            implemented += 1;
49            if !missing_only {
50                if verbose {
51                    println!("āœ… {} ({}):", env.name, env.id);
52                    println!("   Path: {}", env.path);
53                    println!("   Difficulty: {}", env.difficulty);
54                    println!("   Stage: {}", env.curriculum_stage);
55                    println!();
56                } else {
57                    println!("āœ… {}", env.name);
58                }
59            }
60        } else {
61            missing += 1;
62            missing_envs.push(env);
63
64            if verbose {
65                println!("āŒ {} ({}):", env.name, env.id);
66                println!("   Expected path: {}", env.path);
67                println!("   Full path: {}", full_path.display());
68                println!("   Difficulty: {}", env.difficulty);
69                println!("   Stage: {}", env.curriculum_stage);
70                println!();
71            } else {
72                println!("āŒ {} - MISSING", env.name);
73            }
74        }
75    }
76
77    println!("\nšŸ“Š Summary:");
78    println!("   Total environments: {}", total);
79    println!(
80        "   āœ… Implemented: {} ({:.1}%)",
81        implemented,
82        (implemented as f64 / total as f64) * 100.0
83    );
84    println!(
85        "   āŒ Missing: {} ({:.1}%)",
86        missing,
87        (missing as f64 / total as f64) * 100.0
88    );
89
90    if missing > 0 {
91        println!("\nāš ļø  Missing Environments:");
92        for env in &missing_envs {
93            println!("   • {} ({})", env.name, env.id);
94            if verbose {
95                println!("     Path: {}", env.path);
96                println!("     Tags: {}", env.tags.join(", "));
97            }
98        }
99
100        println!("\nšŸ’” To implement missing environments:");
101        println!("   1. Create directory: configs/simulation/environments/robot-tasks/<path> in mecha10-assets");
102        println!("   2. Add .tscn scene file");
103        println!("   3. Add .gd script with environment logic");
104        println!("   4. Add README.md documentation");
105    } else {
106        println!("\n✨ All catalog environments are implemented!");
107    }
108
109    Ok(())
110}