Skip to content

Commit

Permalink
Merge pull request #82 from Virv12/st0-for-att
Browse files Browse the repository at this point in the history
  • Loading branch information
edomora97 authored Sep 24, 2022
2 parents 123dba9 + a0a81f2 commit 5688e00
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/tools/find_bad_case/dag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub fn patch_task_for_batch(
let testcase = TestcaseInfo {
id: testcase_id,
input_generator,
input_validator: task.input_validator.clone(),
input_validator: task.input_validator_generator.generate(Some(0)),
output_generator: testcase_template.output_generator.clone(),
};

Expand Down
2 changes: 1 addition & 1 deletion task-maker-format/src/ioi/dag/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ mod tests {
infile: None,
outfile: None,
subtasks: Default::default(),
input_validator: InputValidator::AssumeValid,
input_validator_generator: Default::default(),
testcase_score_aggregator: TestcaseScoreAggregator::Min,
grader_map: Arc::new(GraderMap::new(Vec::<PathBuf>::new())),
booklets: vec![],
Expand Down
8 changes: 4 additions & 4 deletions task-maker-format/src/ioi/format/italian_yaml/gen_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub(crate) fn parse_gen_gen<P: AsRef<Path>, V, O>(
get_output_gen: O,
) -> Result<Vec<TaskInputEntry>, Error>
where
V: Fn(SubtaskId) -> InputValidator,
V: Fn(Option<SubtaskId>) -> InputValidator,
O: Fn(TestcaseId) -> OutputGenerator,
{
let path = path.as_ref();
Expand Down Expand Up @@ -146,7 +146,7 @@ where
entries.push(TaskInputEntry::Testcase(TestcaseInfo {
id: testcase_count,
input_generator: InputGenerator::StaticFile(task_dir.join(what)),
input_validator: get_validator(subtask_id - 1),
input_validator: get_validator(Some(subtask_id - 1)),
output_generator: get_output_gen(testcase_count),
}));
testcase_count += 1;
Expand All @@ -165,7 +165,7 @@ where
entries.push(TaskInputEntry::Testcase(TestcaseInfo {
id: testcase_count,
input_generator: InputGenerator::Custom(generator.clone(), cmd),
input_validator: get_validator(subtask_id - 1),
input_validator: get_validator(Some(subtask_id - 1)),
output_generator,
}));
testcase_count += 1;
Expand Down Expand Up @@ -218,7 +218,7 @@ mod tests {
dir
}

fn get_validator(_subtask: SubtaskId) -> InputValidator {
fn get_validator(_subtask: Option<SubtaskId>) -> InputValidator {
InputValidator::AssumeValid
}

Expand Down
18 changes: 12 additions & 6 deletions task-maker-format/src/ioi/format/italian_yaml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,12 @@ pub(crate) use cases_gen::{is_gen_gen_deletable, TM_ALLOW_DELETE_COOKIE};
use task_maker_lang::GraderMap;

use crate::ioi::sanity_checks::get_sanity_checks;
use crate::ioi::TM_VALIDATION_FILE_NAME;
use crate::ioi::{
make_task_booklets, Checker, IOITask, InputValidator, OutputGenerator, SubtaskId, SubtaskInfo,
TaskType, TestcaseId, TestcaseInfo, TestcaseScoreAggregator,
};
use crate::ioi::{BatchTypeData, CommunicationTypeData, UserIo};
use crate::ioi::{InputValidatorGenerator, TM_VALIDATION_FILE_NAME};
use crate::{find_source_file, list_files, EvaluationConfig, WriteBinTo};

mod cases_gen;
Expand Down Expand Up @@ -508,8 +508,9 @@ pub fn parse_task<P: AsRef<Path>>(
difficulty: yaml.difficulty,
syllabus_level: yaml.syllabuslevel,
sanity_checks: Arc::new(get_sanity_checks(&eval_config.disabled_sanity_checks)),
input_validator: detect_validator(task_dir.to_path_buf())
.context("Failed to detect validator")?(0),
input_validator_generator: InputValidatorGenerator::new(
detect_validator(task_dir.to_path_buf()).context("Failed to detect validator")?,
),
};
// split the creation of the task because make_booklets need an instance of Task
if !eval_config.no_statement {
Expand All @@ -522,7 +523,9 @@ pub fn parse_task<P: AsRef<Path>>(
/// Search for a valid input validator inside the task directory. Will return a function that, given
/// a subtask id, returns an `InputValidator` using that validator. If no validator is found,
/// `InputValidator::AssumeValid` is used.
fn detect_validator(task_dir: PathBuf) -> Result<impl Fn(SubtaskId) -> InputValidator, Error> {
fn detect_validator(
task_dir: PathBuf,
) -> Result<impl Fn(Option<SubtaskId>) -> InputValidator, Error> {
let mut validators = find_source_file(
&task_dir,
vec![
Expand All @@ -541,12 +544,15 @@ fn detect_validator(task_dir: PathBuf) -> Result<impl Fn(SubtaskId) -> InputVali
}
let validator = validators.pop().map(Arc::new);
debug!("Detected input validator: {:?}", validator);
Ok(move |st: SubtaskId| -> InputValidator {
Ok(move |st: Option<SubtaskId>| -> InputValidator {
if let Some(validator) = validator.as_ref() {
InputValidator::Custom(
validator.clone(),
// for legacy support reasons the subtask is passed 1-based
vec![TM_VALIDATION_FILE_NAME.to_string(), (st + 1).to_string()],
vec![
TM_VALIDATION_FILE_NAME.to_string(),
st.map(|x| x + 1).unwrap_or(0).to_string(),
],
)
} else {
InputValidator::AssumeValid
Expand Down
10 changes: 5 additions & 5 deletions task-maker-format/src/ioi/format/italian_yaml/static_inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::ioi::{
/// generator.
struct StaticInputIter<V, O>
where
V: Fn(SubtaskId) -> InputValidator,
V: Fn(Option<SubtaskId>) -> InputValidator,
O: Fn(TestcaseId) -> OutputGenerator,
{
/// The path to the input files directory.
Expand All @@ -27,7 +27,7 @@ where

impl<V, O> Iterator for StaticInputIter<V, O>
where
V: Fn(SubtaskId) -> InputValidator,
V: Fn(Option<SubtaskId>) -> InputValidator,
O: Fn(TestcaseId) -> OutputGenerator,
{
type Item = TaskInputEntry;
Expand All @@ -52,7 +52,7 @@ where
Some(TaskInputEntry::Testcase(TestcaseInfo {
id,
input_generator: InputGenerator::StaticFile(path),
input_validator: (self.get_validator)(0),
input_validator: (self.get_validator)(Some(0)),
output_generator: (self.get_output_gen)(id),
}))
} else {
Expand All @@ -72,7 +72,7 @@ pub(crate) fn static_inputs<P: Into<PathBuf>, V, O>(
get_output_gen: O,
) -> Box<dyn Iterator<Item = TaskInputEntry>>
where
V: Fn(SubtaskId) -> InputValidator + 'static,
V: Fn(Option<SubtaskId>) -> InputValidator + 'static,
O: Fn(TestcaseId) -> OutputGenerator + 'static,
{
Box::new(StaticInputIter {
Expand All @@ -96,7 +96,7 @@ mod tests {

use super::*;

fn get_validator(_subtask: SubtaskId) -> InputValidator {
fn get_validator(_subtask: Option<SubtaskId>) -> InputValidator {
InputValidator::AssumeValid
}

Expand Down
39 changes: 34 additions & 5 deletions task-maker-format/src/ioi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//! file and the _correct_ output file (the one produced by the jury).
use std::collections::HashMap;
use std::fmt::Debug;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -72,6 +73,34 @@ pub struct ScoreManager {
aggregator: TestcaseScoreAggregator,
}

/// A simple struct that generates input validators for a given subtask.
#[derive(Clone)]
pub struct InputValidatorGenerator(Arc<dyn Fn(Option<SubtaskId>) -> InputValidator + Send + Sync>);

impl Debug for InputValidatorGenerator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("InputValidatorGenerator").finish()
}
}

impl Default for InputValidatorGenerator {
fn default() -> Self {
InputValidatorGenerator(Arc::new(|_| InputValidator::AssumeValid))
}
}

impl InputValidatorGenerator {
/// Build a generator based on a generating function.
pub fn new<F: Fn(Option<SubtaskId>) -> InputValidator + Send + Sync + 'static>(f: F) -> Self {
InputValidatorGenerator(Arc::new(f))
}

/// Obtain a validator for the given subtask.
pub fn generate(&self, subtask: Option<SubtaskId>) -> InputValidator {
(self.0)(subtask)
}
}

/// Information about a generic IOI task.
#[derive(Debug, Clone, Serialize, Deserialize, TypeScriptify)]
pub struct IOITask {
Expand All @@ -93,9 +122,9 @@ pub struct IOITask {
pub outfile: Option<PathBuf>,
/// The list of the subtasks.
pub subtasks: HashMap<SubtaskId, SubtaskInfo>,
/// The default input validator for this task, if any.
#[serde(skip_serializing)]
pub input_validator: InputValidator,
/// The generator of validators for the various subtasks.
#[serde(skip_serializing, skip_deserializing)]
pub input_validator_generator: InputValidatorGenerator,
/// The aggregator to use to compute the score of the subtask based on the score of the
/// testcases.
pub testcase_score_aggregator: TestcaseScoreAggregator,
Expand Down Expand Up @@ -160,7 +189,7 @@ impl IOITask {
/// Create a "fake" `IOITask` that will not contain any data.
///
/// This can be used to setup executions that are not related to tasks (e.g. booklet
/// compilations).
/// compilations).
pub fn fake() -> IOITask {
IOITask {
path: Default::default(),
Expand All @@ -172,7 +201,7 @@ impl IOITask {
infile: None,
outfile: None,
subtasks: Default::default(),
input_validator: InputValidator::AssumeValid,
input_validator_generator: Default::default(),
testcase_score_aggregator: TestcaseScoreAggregator::Min,
grader_map: Arc::new(GraderMap::new::<&Path>(vec![])),
booklets: vec![],
Expand Down
5 changes: 3 additions & 2 deletions task-maker-format/src/ioi/sanity_checks/att.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ impl SanityCheck<IOITask> for AttSampleFilesValid {
}

fn pre_hook(&mut self, task: &IOITask, eval: &mut EvaluationData) -> Result<(), Error> {
let validator = &task.input_validator;
let validator = &task.input_validator_generator;
let task_type = if let TaskType::Batch(data) = &task.task_type {
data
} else {
Expand All @@ -183,11 +183,12 @@ impl SanityCheck<IOITask> for AttSampleFilesValid {

// validate the input file
let (val_handle, val) = validator
.generate(None)
.validate(
eval,
format!("Validation of sample case {}", input_name.display()),
0,
None,
Some("att"),
0,
input_uuid,
)
Expand Down
2 changes: 1 addition & 1 deletion task-maker-format/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn new_task_with_context(path: &Path) -> IOITask {
infile: None,
outfile: None,
subtasks: HashMap::new(),
input_validator: InputValidator::AssumeValid,
input_validator_generator: Default::default(),
testcase_score_aggregator: TestcaseScoreAggregator::Min,
grader_map: Arc::new(GraderMap::new(Vec::<PathBuf>::new())),
booklets: vec![],
Expand Down

0 comments on commit 5688e00

Please sign in to comment.