Skip to content

Commit

Permalink
Merge pull request #204 from Virv12/merge-subtask-name-description
Browse files Browse the repository at this point in the history
Merge subtask_description and subtask_name
  • Loading branch information
dp1 authored Dec 6, 2023
2 parents 74508d3 + 49503f7 commit 49e3c06
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 78 deletions.
3 changes: 1 addition & 2 deletions src/tools/find_bad_case/dag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,10 @@ pub fn patch_task_for_batch(
let subtask = SubtaskInfo {
id: 0,
name: Some(format!("batch-{}", batch_index)),
description: None,
max_score: 100.0,
testcases,
span: None,
is_default: false,
..Default::default()
};
task.subtasks.insert(0, subtask);
}
Expand Down
8 changes: 4 additions & 4 deletions task-maker-format/src/ioi/finish_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ impl FinishUI {
cwriteln!(self, BLUE, "Generations");
for (st_num, subtask) in state.generations.iter().sorted_by_key(|(n, _)| *n) {
cwrite!(self, BOLD, "Subtask {}", st_num);
if let Some(description) = &state.task.subtasks[st_num].description {
print!(" [{}]", description);
if let Some(name) = &state.task.subtasks[st_num].name {
print!(" [{}]", name);
}
println!(": {} points", state.task.subtasks[st_num].max_score);
for (tc_num, testcase) in subtask.testcases.iter().sorted_by_key(|(n, _)| *n) {
Expand Down Expand Up @@ -232,8 +232,8 @@ impl FinishUI {

for (st_num, subtask) in eval.subtasks.iter().sorted_by_key(|(n, _)| *n) {
cwrite!(self, BOLD, "Subtask #{}", st_num);
if let Some(description) = &state.task.subtasks[st_num].description {
print!(" [{}]", description);
if let Some(name) = &state.task.subtasks[st_num].name {
print!(" [{}]", name);
}
print!(": ");
let max_score = state.task.subtasks[st_num].max_score;
Expand Down
103 changes: 62 additions & 41 deletions task-maker-format/src/ioi/format/italian_yaml/cases_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ where
current_validator: Option<String>,
/// The identifier of the next subtask to process.
subtask_id: SubtaskId,
/// The description of the last subtask added, if any.
subtask_description: Option<String>,
/// The name of the last subtask added, if any.
subtask_name: Option<String>,
/// The identifier of the next testcase to process.
testcase_id: TestcaseId,
}
Expand Down Expand Up @@ -166,7 +166,7 @@ where
current_generator: None,
current_validator: None,
subtask_id: 0,
subtask_description: None,
subtask_name: None,
testcase_id: 0,
};

Expand Down Expand Up @@ -227,12 +227,11 @@ where
for entry in &self.result {
match entry {
TaskInputEntry::Subtask(subtask) => {
if let Some(descr) = &subtask.description {
let _ = writeln!(gen, "\n# Subtask {}: {}", subtask.id, descr);
} else {
let _ = writeln!(gen, "\n# Subtask {}", subtask.id);
}
let _ = writeln!(gen, "\n# Subtask {}", subtask.id);
let _ = writeln!(gen, "#ST: {}", subtask.max_score);
if let Some(name) = &subtask.name {
let _ = writeln!(gen, "#STNAME: {}", name);
}
if let Some(constraints) = self.subtask_constraints.get(subtask.id as usize) {
for constr in constraints {
let _ = writeln!(gen, "# {:?}", constr);
Expand Down Expand Up @@ -526,23 +525,29 @@ where
} else {
None
};
self.subtask_description = description.clone();
// FIXME: the cases.gen format does not yet support giving the subtasks a name.
self.result.push(TaskInputEntry::Subtask(SubtaskInfo {
id: self.subtask_id,
name: None,
description,
max_score: score,
testcases: HashMap::new(),
span: CodeSpan::from_str(
&self.file_path,
&self.file_content,
span.start(),
span.end() - span.start(),
)
.ok(),
is_default: false,
}));
// Remove whitespaces for retrocompatibility with descriptions
let name = description
.as_deref()
.map(|s| s.chars().filter(|&c| c != ' ' && c != '\t').collect());
self.subtask_name = name.clone();
self.result.push(TaskInputEntry::Subtask(
#[allow(deprecated)]
SubtaskInfo {
id: self.subtask_id,
name,
description,
max_score: score,
span: CodeSpan::from_str(
&self.file_path,
&self.file_content,
span.start(),
span.end() - span.start(),
)
.ok(),
is_default: false,
..Default::default()
},
));
self.subtask_id += 1;
Ok(())
}
Expand Down Expand Up @@ -637,8 +642,8 @@ where
vars.insert("INPUT".to_string(), TM_VALIDATION_FILE_NAME.to_string());
vars.insert("ST_NUM".to_string(), (self.subtask_id - 1).to_string());
vars.insert("TC_NUM".to_string(), self.testcase_id.to_string());
if let Some(descr) = &self.subtask_description {
vars.insert("ST_DESCRIPTION".to_string(), descr.clone());
if let Some(name) = &self.subtask_name {
vars.insert("ST_NAME".to_string(), name.clone());
}
vars
}
Expand Down Expand Up @@ -833,11 +838,12 @@ mod tests {
.split('\n')
.filter(|s| !s.is_empty() && !s.starts_with("# ") && !s.starts_with("#COPY"))
.collect();
assert_eq!(res.len(), 4);
assert_eq!(res.len(), 5);
assert_eq!(res[0], "#ST: 42");
assert!(res[1].contains("12 34"));
assert_eq!(res[2], "#ST: 24");
assert!(res[3].contains("21 21"));
assert_eq!(res[1], "#STNAME: lol");
assert!(res[2].contains("12 34"));
assert_eq!(res[3], "#ST: 24");
assert!(res[4].contains("21 21"));
}

#[test]
Expand All @@ -850,11 +856,11 @@ mod tests {
assert_eq!(vars["INPUT"], TM_VALIDATION_FILE_NAME);
assert_eq!(vars["ST_NUM"], "0");
assert_eq!(vars["TC_NUM"], "1");
assert_eq!(vars["ST_DESCRIPTION"], "lol");
assert_eq!(vars["ST_NAME"], "lol");
}

#[test]
fn test_auto_variables_no_descr() {
fn test_auto_variables_no_name() {
let gen = TestHelper::new()
.add_file("gen/generator.py")
.cases_gen(":GEN gen gen/generator.py\n:SUBTASK 42 lol\n12 34\n: SUBTASK 43")
Expand All @@ -863,7 +869,7 @@ mod tests {
assert_eq!(vars["INPUT"], TM_VALIDATION_FILE_NAME);
assert_eq!(vars["ST_NUM"], "1");
assert_eq!(vars["TC_NUM"], "1");
assert!(!vars.contains_key("ST_DESCRIPTION"));
assert!(!vars.contains_key("ST_NAME"));
}

#[test]
Expand Down Expand Up @@ -1223,25 +1229,40 @@ mod tests {
let subtask = &gen.result[0];
if let TaskInputEntry::Subtask(subtask) = subtask {
assert_eq!(subtask.id, 0);
assert_eq!(subtask.description, None);
assert_eq!(subtask.name, None);
assert_abs_diff_eq!(subtask.max_score, 42.0);
} else {
panic!("Expecting a subtask, got: {:?}", subtask);
}
}

#[test]
fn test_add_subtask_name() {
let gen = TestHelper::new().cases_gen(":SUBTASK 42 the-name").unwrap();
assert_eq!(gen.subtask_id, 1);
assert_eq!(gen.result.len(), 1);
let subtask = &gen.result[0];
if let TaskInputEntry::Subtask(subtask) = subtask {
assert_eq!(subtask.id, 0);
assert_eq!(subtask.name, Some("the-name".into()));
assert_abs_diff_eq!(subtask.max_score, 42.0);
} else {
panic!("Expecting a subtask, got: {:?}", subtask);
}
}

#[test]
fn test_add_subtask_description() {
fn test_add_subtask_space_in_name() {
let gen = TestHelper::new()
.cases_gen(":SUBTASK 42 the description")
.cases_gen(":SUBTASK 42.42 the name")
.unwrap();
assert_eq!(gen.subtask_id, 1);
assert_eq!(gen.result.len(), 1);
let subtask = &gen.result[0];
if let TaskInputEntry::Subtask(subtask) = subtask {
assert_eq!(subtask.id, 0);
assert_eq!(subtask.description, Some("the description".into()));
assert_abs_diff_eq!(subtask.max_score, 42.0);
assert_eq!(subtask.name, Some("thename".into()));
assert_abs_diff_eq!(subtask.max_score, 42.42);
} else {
panic!("Expecting a subtask, got: {:?}", subtask);
}
Expand All @@ -1250,14 +1271,14 @@ mod tests {
#[test]
fn test_add_subtask_float_score() {
let gen = TestHelper::new()
.cases_gen(":SUBTASK 42.42 the description")
.cases_gen(":SUBTASK 42.42 the-name")
.unwrap();
assert_eq!(gen.subtask_id, 1);
assert_eq!(gen.result.len(), 1);
let subtask = &gen.result[0];
if let TaskInputEntry::Subtask(subtask) = subtask {
assert_eq!(subtask.id, 0);
assert_eq!(subtask.description, Some("the description".into()));
assert_eq!(subtask.name, Some("the-name".into()));
assert_abs_diff_eq!(subtask.max_score, 42.42);
} else {
panic!("Expecting a subtask, got: {:?}", subtask);
Expand Down
10 changes: 2 additions & 8 deletions task-maker-format/src/ioi/format/italian_yaml/gen_gen.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;

Expand Down Expand Up @@ -51,12 +50,9 @@ where

let mut default_subtask = Some(SubtaskInfo {
id: 0,
name: None,
description: None,
max_score: 100.0,
testcases: HashMap::new(),
span: None,
is_default: true,
..Default::default()
});

let mut generators = find_source_file(
Expand Down Expand Up @@ -100,10 +96,7 @@ where
let path = path.strip_prefix(task_dir).unwrap_or(path);
entries.push(TaskInputEntry::Subtask(SubtaskInfo {
id: subtask_id,
name: None,
description: None,
max_score: score.parse::<f64>().context("Invalid subtask score")?,
testcases: HashMap::new(),
span: CodeSpan::from_str(
path,
&content,
Expand All @@ -112,6 +105,7 @@ where
)
.ok(),
is_default: false,
..Default::default()
}));
subtask_id += 1;
}
Expand Down
16 changes: 8 additions & 8 deletions task-maker-format/src/ioi/format/italian_yaml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,15 +161,15 @@
//! Example: `:CONSTRAINT 0 <= $N < $M <= 1000000` will check that the variables `$N` and `$M` are
//! between 0 and 1000000 and `$N` is smaller than `$M`.
//!
//! ### `: SUBTASK score [description]`
//! ### `: SUBTASK score [name]`
//! This command marks the start of a new subtask, just like how `#ST` in `gen/GEN` did. The score
//! can be a simple floating point number (either an integer or an integer.integer). The description
//! can be a simple floating point number (either an integer or an integer.integer). The name
//! that follows is optional and will be included in the subtask metadata.
//!
//! When a new subtask is started the generator and validator will be reset to the default ones.
//!
//! Example: `: SUBTASK 40 All the nodes are in a line` defines a new subtask worth 40 points, with
//! the provided description.
//! Example: `: SUBTASK 40 all-the-nodes-are-in-a-line` defines a new subtask worth 40 points, with
//! the provided name.
//!
//! ### `: COPY path`
//! This command creates a new testcase coping the input file from the specified path, relative to
Expand Down Expand Up @@ -200,7 +200,7 @@
//! obtained from the parsing of the generator's arguments will be available. Also some automatic
//! variables will be available:
//! - `$ST_NUM`: the 0-based index of the subtask
//! - `$ST_DESCRIPTION`: the description of the subtask
//! - `$ST_NAME`: the name of the subtask
//! - `$TC_NUM`: the 0-based index of the testcase
//! - `$INPUT` _(only for validators)_: the name of the file to validate
//!
Expand All @@ -216,11 +216,11 @@
//! : CONSTRAINT 1 <= $N <= 1000
//! : CONSTRAINT 1 <= $M <= 1000000
//!
//! : SUBTASK 0 Examples
//! : SUBTASK 0 examples
//! : COPY gen/example1.in
//! : COPY gen/example2.in
//!
//! : SUBTASK 30 Nodes are in a line
//! : SUBTASK 30 nodes-are-in-a-line
//! : GEN line
//! : VAL line
//! : CONSTRAINT $N <= 500
Expand Down Expand Up @@ -254,7 +254,7 @@
//! which will use the `hard` one. Note that since the `hard` generator does not have the argument
//! specification, its parameters won't be checked. Also note that the constraint `$N <= 500` won't
//! be checked because it was scoped only to the second subtask.
//! The subtask also does not have a description, the default one (`Subtask 2`) will be used.
//! The subtask also does not have a name, the default one (`subtask2`) will be used.
use std::collections::HashMap;
use std::fs;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::collections::HashMap;
use std::path::PathBuf;

use crate::ioi::format::italian_yaml::TaskInputEntry;
Expand Down Expand Up @@ -38,12 +37,10 @@ where
self.index = 1;
return Some(TaskInputEntry::Subtask(SubtaskInfo {
id: 0,
name: None,
description: Some("Static testcases".into()),
name: Some("static-testcases".into()),
max_score: 100.0,
testcases: HashMap::new(),
span: None,
is_default: true,
..Default::default()
}));
}
let id = self.index - 1; // offset caused by the first iteration
Expand Down
5 changes: 3 additions & 2 deletions task-maker-format/src/ioi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,16 @@ pub struct IOITask {
}

/// A subtask of a IOI task.
#[derive(Debug, Clone, Serialize, Deserialize, TypeScriptify)]
#[derive(Debug, Clone, Serialize, Deserialize, TypeScriptify, Default)]
pub struct SubtaskInfo {
/// The id of the subtask.
pub id: SubtaskId,
/// The name of the subtask.
///
/// This is what is used for running the solutions' checks.
pub name: Option<String>,
/// Textual description of the subtask.
/// Textual description of the subtask. (deprecated)
#[deprecated(note = "Use the `name` field instead")]
pub description: Option<String>,
/// The maximum score of the subtask, must be >= 0.
pub max_score: f64,
Expand Down
Loading

0 comments on commit 49e3c06

Please sign in to comment.