use clap::{Args, Parser}; use std::path::PathBuf; /// Tidepool is a program that simulates cheese race games for Blockfish to play and /// outputs the result in a machine-readable format. Tidepool is useful for benchmarking, /// analyzing, testing reproducibility, and other tasks for improving Blockfish's /// algorithms. #[derive(Parser)] #[clap(version)] #[command(group = clap::ArgGroup::new("single").conflicts_with("multi"))] #[command(group = clap::ArgGroup::new("multi").conflicts_with("single"))] pub struct CliArgs { /// Path to file containing configuration for running Blockfish. pub config_file: PathBuf, // single-run /// Specify the game seed for the run (single-run mode only). #[arg(short = 's', long, group = "single")] pub seed: Option, /// Output the run to the specified file (single-run mode only). #[arg(short = 'o', long = "outfile", group = "single")] pub output_file: Option, // multi-run /// Path to directory to generate runs to. If set, activates multi-run mode and will /// run multiple times in parallel. #[arg(group = "multi")] pub output_dir: Option, /// Stop after this many runs (multi-run mode only). #[arg(short = 'n', long, group = "multi")] pub count: Option, /// Run this many jobs in parallel (multi-run mode only). #[arg(short = 'j', long, group = "multi")] pub jobs: Option, // global #[command(flatten)] pub data: OutputDataArgs, #[command(flatten)] pub io: IoArgs, } #[derive(Debug, Args)] pub struct OutputDataArgs { /// Generate profiling data in the output. #[arg(short = 'P', long)] pub profile: bool, /// Generate the full list of moves in the output. #[arg(short = 'L', long)] pub list_moves: bool, } #[derive(Debug, Args)] pub struct IoArgs { /// Disable printing extraneous text like a progress bar. #[arg(short = 'q', long)] pub quiet: bool, /// Never prompt the user for input, and immediately exit on interrupt. #[arg(short = 'f', long)] pub noninteractive: bool, } #[derive(Debug)] pub enum Mode { Single(SingleRun), Multi(MultiRun), } #[derive(Debug)] pub struct SingleRun { pub config_file: PathBuf, pub output_file: Option, pub seed: Option, pub data: OutputDataArgs, pub io: IoArgs, } #[derive(Debug)] pub struct MultiRun { pub config_file: PathBuf, pub output_dir: PathBuf, pub count: Option, pub jobs: Option, pub data: OutputDataArgs, pub io: IoArgs, } impl From for Mode { fn from(args: CliArgs) -> Self { match args.output_dir { Some(output_dir) => Mode::Multi(MultiRun { config_file: args.config_file, output_dir, count: args.count, jobs: args.jobs, data: args.data, io: args.io, }), None => Mode::Single(SingleRun { config_file: args.config_file, output_file: args.output_file, seed: args.seed, data: args.data, io: args.io, }), } } } pub fn parse() -> Mode { CliArgs::parse().into() }