use swarm_engine_core::environment::{DefaultEnvironment, EnvironmentBox};
use crate::environments::{MazeEnvironment, NoneEnvironment};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EnvironmentType {
None,
Maze,
Codebase,
}
impl EnvironmentType {
pub fn parse(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"none" | "" => Some(Self::None),
"maze" => Some(Self::Maze),
"codebase" | "default" => Some(Self::Codebase),
_ => None,
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::None => "none",
Self::Maze => "maze",
Self::Codebase => "codebase",
}
}
}
pub struct EnvironmentRegistry;
impl EnvironmentRegistry {
pub fn create(
env_type: &str,
params: &serde_json::Value,
) -> Result<EnvironmentBox, EnvironmentError> {
let env_type = EnvironmentType::parse(env_type)
.ok_or_else(|| EnvironmentError::UnknownType(env_type.to_string()))?;
match env_type {
EnvironmentType::None => Ok(Box::new(NoneEnvironment)),
EnvironmentType::Maze => {
let map_str = params.get("map").and_then(|v| v.as_str()).ok_or_else(|| {
EnvironmentError::Config("Maze environment requires 'map' parameter".into())
})?;
let worker_count = params
.get("worker_count")
.and_then(|v| v.as_u64())
.unwrap_or(1) as usize;
Ok(Box::new(MazeEnvironment::from_str(map_str, worker_count)))
}
EnvironmentType::Codebase => Ok(Box::new(DefaultEnvironment::new())),
}
}
pub fn supported_types() -> Vec<EnvironmentType> {
vec![
EnvironmentType::None,
EnvironmentType::Maze,
EnvironmentType::Codebase,
]
}
}
#[derive(Debug, Clone)]
pub enum EnvironmentError {
UnknownType(String),
Config(String),
}
impl std::fmt::Display for EnvironmentError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UnknownType(t) => write!(f, "Unknown environment type: {}", t),
Self::Config(e) => write!(f, "Environment config error: {}", e),
}
}
}
impl std::error::Error for EnvironmentError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_environment_type_from_str() {
assert_eq!(EnvironmentType::parse("none"), Some(EnvironmentType::None));
assert_eq!(EnvironmentType::parse("maze"), Some(EnvironmentType::Maze));
assert_eq!(
EnvironmentType::parse("codebase"),
Some(EnvironmentType::Codebase)
);
assert_eq!(EnvironmentType::parse("unknown"), None);
}
#[test]
fn test_create_none_environment() {
let env = EnvironmentRegistry::create("none", &serde_json::Value::Null);
assert!(env.is_ok());
assert_eq!(env.unwrap().name(), "NoneEnvironment");
}
#[test]
fn test_create_codebase_environment() {
let env = EnvironmentRegistry::create("codebase", &serde_json::Value::Null);
assert!(env.is_ok());
assert_eq!(env.unwrap().name(), "DefaultEnvironment");
}
#[test]
fn test_create_maze_environment() {
let params = serde_json::json!({
"map": "#####\n#S.G#\n#####",
"worker_count": 1
});
let env = EnvironmentRegistry::create("maze", ¶ms);
assert!(env.is_ok());
assert_eq!(env.unwrap().name(), "MazeEnvironment");
}
#[test]
fn test_create_maze_without_map() {
let env = EnvironmentRegistry::create("maze", &serde_json::Value::Null);
assert!(env.is_err());
}
}