circles/examples/ourworld/main.rs
2025-06-19 05:17:14 +03:00

83 lines
3.0 KiB
Rust

//! Example of launching multiple circles and outputting their details to a file.
//!
//! This example demonstrates how to use the launcher library to start circles
//! programmatically, similar to how the `launcher` binary works.
//!
//! # Usage
//!
//! ```sh
//! cargo run --example ourworld
//! ```
//!
//! This will:
//! 1. Read the `circles.json` file in the `examples/ourworld` directory.
//! 2. Launch all 7 circles defined in the config.
//! 3. Create a `ourworld_output.json` file in the same directory with the details.
//! 4. The launcher will run until you stop it with Ctrl+C.
use launcher::{run_launcher, Args, CircleConfig};
use std::fs;
use std::path::PathBuf;
use std::error::Error as StdError;
use log::{error, info};
#[tokio::main]
async fn main() -> Result<(), Box<dyn StdError>> {
println!("--- Launching OurWorld Example Programmatically ---");
// The example is now at the root of the `examples` directory,
// so we can reference its assets directly.
let example_dir = PathBuf::from("./examples/ourworld");
let config_path = example_dir.join("circles.json");
let output_path = example_dir.join("ourworld_output.json");
println!("Using config file: {:?}", config_path);
println!("Output will be written to: {:?}", output_path);
// Manually construct the arguments instead of parsing from command line.
// This is useful when embedding the launcher logic in another application.
let args = Args {
config_path: config_path.clone(),
output: Some(output_path),
debug: true, // Enable debug logging for the example
verbose: 2, // Set verbosity to max
};
if !config_path.exists() {
let msg = format!("Configuration file not found at {:?}", config_path);
error!("{}", msg);
return Err(msg.into());
}
let config_content = fs::read_to_string(&config_path)?;
let mut circle_configs: Vec<CircleConfig> = match serde_json::from_str(&config_content) {
Ok(configs) => configs,
Err(e) => {
error!("Failed to parse {}: {}. Ensure it's a valid JSON array of CircleConfig.", config_path.display(), e);
return Err(Box::new(e) as Box<dyn StdError>);
}
};
// Make script paths relative to the project root by prepending the example directory path.
for config in &mut circle_configs {
if let Some(script_path) = &config.script_path {
let full_script_path = example_dir.join(script_path);
config.script_path = Some(full_script_path.to_string_lossy().into_owned());
}
}
if circle_configs.is_empty() {
info!("No circle configurations found in {}. Exiting.", config_path.display());
return Ok(());
}
println!("Starting launcher... Press Ctrl+C to exit.");
// The run_launcher function will setup logging, spawn circles, print the table,
// and wait for a shutdown signal (Ctrl+C).
run_launcher(args, circle_configs).await?;
println!("--- OurWorld Example Finished ---");
Ok(())
}