//! 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 log::{error, info}; use std::error::Error as StdError; use std::fs; use std::path::PathBuf; #[tokio::main] async fn main() -> Result<(), Box> { 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 = 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); } }; // 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(()) }