Skip to content

Commit a6902a4

Browse files
committed
Allow to specify a generator with find-bad-case.
1 parent f2bb5bb commit a6902a4

5 files changed

Lines changed: 42 additions & 23 deletions

File tree

src/tools/find_bad_case/dag.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use std::collections::HashMap;
22
use std::path::{Path, PathBuf};
3+
use std::sync::Arc;
34

45
use anyhow::{anyhow, bail, Context, Error};
56

67
use task_maker_format::ioi::{
78
InputGenerator, SubtaskInfo, TestcaseId, TestcaseInfo, GENERATION_PRIORITY,
89
};
9-
use task_maker_format::{EvaluationData, TaskFormat};
10+
use task_maker_format::{EvaluationData, SourceFile, TaskFormat};
1011

1112
/// The information about a testcase to generate.
1213
#[derive(Debug, Clone, Default)]
@@ -33,6 +34,7 @@ pub struct Batch {
3334
/// testcases instead of the normal ones.
3435
pub fn patch_task_for_batch(
3536
task: &mut TaskFormat,
37+
generator: &Option<Arc<SourceFile>>,
3638
generator_args: &[String],
3739
batch_size: usize,
3840
batch_index: usize,
@@ -66,8 +68,11 @@ pub fn patch_task_for_batch(
6668
InputGenerator::StaticFile(_) => {
6769
unreachable!("The generator cannot be StaticFile")
6870
}
69-
InputGenerator::Custom(_, args) => {
71+
InputGenerator::Custom(g, args) => {
7072
args.clone_from(&generator_args);
73+
if let Some(generator) = generator {
74+
*g = generator.clone();
75+
}
7176
}
7277
}
7378

src/tools/find_bad_case/mod.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use clap::{Parser, ValueHint};
77
use task_maker_exec::ductile::ChannelSender;
88
use task_maker_exec::proto::ExecutorClientMessage;
99
use task_maker_exec::ExecutorClient;
10+
use task_maker_format::ioi::get_generator;
1011
use task_maker_format::ui::{CursesUI, StdoutPrinter, UIMessage, BLUE, BOLD, RED, UI, YELLOW};
1112
use task_maker_format::{cwrite, cwriteln, get_sanity_check_list, EvaluationConfig};
1213

@@ -38,6 +39,10 @@ pub struct FindBadCaseOpt {
3839
#[clap(long, short, default_value = "100")]
3940
pub batch_size: usize,
4041

42+
/// Name of the generator to use.
43+
#[clap(long, short)]
44+
pub generator: Option<String>,
45+
4146
/// Path to the solution to check against the official solution of the task.
4247
#[clap(value_hint = ValueHint::FilePath)]
4348
pub solution: PathBuf,
@@ -81,6 +86,11 @@ pub fn main_find_bad_case(opt: FindBadCaseOpt) -> Result<(), Error> {
8186

8287
let task = opt.find_task.find_task(&eval_config)?;
8388
let task_path = task.path().to_path_buf();
89+
let generator = opt
90+
.generator
91+
.as_ref()
92+
.map(|x| get_generator(&format!("gen_{x}"), &task_path))
93+
.transpose()?;
8494

8595
// Create a single UI for all the batches.
8696
let ui_state = UIState::new(&opt, stop_evaluation);
@@ -120,6 +130,7 @@ pub fn main_find_bad_case(opt: FindBadCaseOpt) -> Result<(), Error> {
120130
let mut task = opt.find_task.find_task(&eval_config)?;
121131
let batch = patch_task_for_batch(
122132
&mut task,
133+
&generator,
123134
&opt.generator_args,
124135
opt.batch_size,
125136
batch_index,

task-maker-format/src/ioi/format/italian_toml/gen_toml.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,26 @@ fn detect_validator(task_dir: &Path, validator: &str) -> Result<Arc<SourceFile>>
234234
Ok(validators.pop().map(Arc::new).unwrap())
235235
}
236236

237-
pub fn parse(
237+
/// Finds a generator with the specified name.
238+
pub fn get_generator(generator: &str, task_dir: &Path) -> Result<Arc<SourceFile>> {
239+
let mut generators = find_source_file(
240+
task_dir,
241+
vec![&format!("gen/{generator}.*")],
242+
task_dir,
243+
"Input file generator at",
244+
None,
245+
WriteBinTo::None,
246+
);
247+
if generators.len() > 1 {
248+
let paths = generators.iter().map(|s| s.name()).collect::<Vec<_>>();
249+
bail!("Multiple generators found: {:?}", paths);
250+
} else if generators.is_empty() {
251+
bail!("No generator `{generator}` found");
252+
}
253+
Ok(generators.pop().map(Arc::new).unwrap())
254+
}
255+
256+
pub(super) fn parse(
238257
task_dir: &Path,
239258
config: &TaskYAML,
240259
grader_map: Arc<GraderMap>,
@@ -298,24 +317,6 @@ pub fn parse(
298317
}
299318
}
300319

301-
let get_generator = |generator: &str| {
302-
let mut generators = find_source_file(
303-
task_dir,
304-
vec![&format!("gen/{generator}.*")],
305-
task_dir,
306-
"Input file generator at",
307-
None,
308-
WriteBinTo::None,
309-
);
310-
if generators.len() > 1 {
311-
let paths = generators.iter().map(|s| s.name()).collect::<Vec<_>>();
312-
bail!("Multiple generators found: {:?}", paths);
313-
} else if generators.is_empty() {
314-
bail!("No generator `{generator}` found");
315-
}
316-
Ok(generators.pop().map(Arc::new).unwrap())
317-
};
318-
319320
let mut process_group = |name: &str, group: &mut GroupConfig| -> Result<()> {
320321
group.resolve_repeats();
321322
let mut constants = constants.clone();
@@ -361,7 +362,7 @@ pub fn parse(
361362
.push(id);
362363
}
363364
let generator = testcase.generator().unwrap_or(generator);
364-
let generator = get_generator(generator)?;
365+
let generator = get_generator(generator, task_dir)?;
365366
let input_generator =
366367
InputGenerator::Custom(generator, testcase.args().instantiate(&constants)?);
367368
testcases.insert(

task-maker-format/src/ioi/format/italian_toml/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::ioi::{
1616
};
1717
use crate::{find_source_file, list_files, EvaluationConfig, WriteBinTo};
1818

19-
mod gen_toml;
19+
pub(in crate::ioi) mod gen_toml;
2020

2121
pub fn parse_task<P: AsRef<Path>>(
2222
task_dir: P,

task-maker-format/src/ioi/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ mod statement;
5252
pub(crate) mod task_info;
5353
pub(crate) mod ui_state;
5454

55+
pub use format::italian_toml::gen_toml::get_generator;
56+
5557
/// In IOI tasks the subtask numbers are non-negative 0-based integers.
5658
pub type SubtaskId = u32;
5759
/// In IOI tasks the testcase numbers are non-negative 0-based integers.

0 commit comments

Comments
 (0)