forge/compare_matrix/
mod.rs1mod report;
4mod runner;
5mod types;
6
7use anyhow::{Result, anyhow, ensure};
8use clap::Args;
9use wowlab_types::game::SpecId;
10
11use self::types::MatrixFormat;
12use crate::run::{FightDurationSeconds, IterationCount, RunParameters, RunParametersError};
13
14const DEFAULT_DURATION_SECS: u32 = 300;
15const DEFAULT_ITERATIONS: u32 = 1;
16const DEFAULT_JOBS: usize = 4;
17
18#[derive(Args, Debug)]
19pub(crate) struct CompareMatrixArgs {
20 #[arg(value_name = "SPEC")]
22 pub(crate) specs: Vec<Box<str>>,
23
24 #[arg(long, default_value_t = DEFAULT_DURATION_SECS)]
26 pub(crate) duration: u32,
27
28 #[arg(long, default_value_t = DEFAULT_ITERATIONS)]
30 pub(crate) iterations: u32,
31
32 #[arg(long, short = 'j', default_value_t = DEFAULT_JOBS)]
34 pub(crate) jobs: usize,
35
36 #[arg(long)]
38 pub(crate) race: Option<String>,
39
40 #[arg(long, value_enum, default_value_t = MatrixFormat::Table)]
42 pub(crate) format: MatrixFormat,
43}
44
45impl TryFrom<&CompareMatrixArgs> for RunParameters {
46 type Error = RunParametersError;
47
48 fn try_from(args: &CompareMatrixArgs) -> Result<Self, Self::Error> {
49 let fight_duration = FightDurationSeconds::try_from(args.duration)?;
50 let iterations = IterationCount::try_from(args.iterations)?;
51
52 Ok(Self::new(iterations, fight_duration))
53 }
54}
55
56pub(crate) fn run(args: &CompareMatrixArgs) -> Result<()> {
57 let parameters = RunParameters::try_from(args)?;
58
59 ensure!(args.jobs > 0, "jobs must be greater than zero");
60
61 let filter = args
62 .specs
63 .iter()
64 .map(|slug| {
65 SpecId::from_manifest_slug(slug).ok_or_else(|| anyhow!("unknown spec slug: {slug}"))
66 })
67 .collect::<Result<Vec<_>>>()?;
68 let matrix = runner::run(&filter, parameters, args.jobs, args.race.clone())?;
69
70 report::print(&matrix, args.format)
71}