feat: add more report cli options
Pipeline / check (pull_request) Failing after 21s
Pipeline / docs (pull_request) Skipped
Pipeline / nightly (pull_request) Skipped
Pipeline / release (pull_request) Skipped

This commit is contained in:
2026-09-20 10:54:39 -04:00
parent beec860a2c
commit 9755417899
4 changed files with 188 additions and 18 deletions
+79 -1
View File
@@ -328,6 +328,58 @@ impl Default for Fields {
}
}
/// Which sections of a student diagnostic are emitted.
///
/// Everything defaults on. Each flag corresponds to one block that
/// [`crate::typst::diagnostic::student_value`] would otherwise write
/// unconditionally: turning one off drops it from `cb-data` as an empty array
/// rather than omitting the key, so a template that checks `len() > 0` (the
/// pattern the bundled templates use) simply renders nothing for that section
/// without needing to guard against a missing key.
///
/// This governs whole sections. Which fields survive *within* a question —
/// feedback, hints, misconceptions, worked solutions — is decided when the
/// diagnostic itself is built, not here.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct StudentSections {
/// The per-level ("kinds of thinking") comparison to the class.
#[serde(default = "yes")]
pub levels: bool,
/// The per-objective mastery table.
#[serde(default = "yes")]
pub objectives: bool,
/// Objectives called out as strengths.
#[serde(default = "yes")]
pub strengths: bool,
/// Objectives called out as focus areas.
#[serde(default = "yes")]
pub focus: bool,
/// Which questions were dropped from scoring.
#[serde(default = "yes")]
pub dropped_questions: bool,
/// Lectures to revisit for missed objectives.
#[serde(default = "yes")]
pub review_lectures: bool,
/// Suggested study groups and their readings.
#[serde(default = "yes")]
pub study: bool,
}
impl Default for StudentSections {
fn default() -> StudentSections {
StudentSections {
levels: true,
objectives: true,
strengths: true,
focus: true,
dropped_questions: true,
review_lectures: true,
study: true,
}
}
}
/// The resolved configuration for rendering one variant.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
@@ -378,6 +430,11 @@ pub struct RenderConfig {
#[serde(default = "yes")]
pub number_from_record: bool,
/// Which sections of a student diagnostic are emitted. Ignored by every
/// variant except [`Variant::StudentReport`].
#[serde(default)]
pub student_sections: StudentSections,
/// Anything else you want the template to see, carried through untouched.
///
/// This is the escape hatch that keeps the crate out of your layout
@@ -410,6 +467,7 @@ impl RenderConfig {
stimulus: StimulusMode::Inline,
fields: Fields::default(),
number_from_record: true,
student_sections: StudentSections::default(),
extra: BTreeMap::new(),
};
match variant {
@@ -560,6 +618,9 @@ pub struct Overrides {
/// See [`RenderConfig::fields`].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub fields: Option<Fields>,
/// See [`RenderConfig::student_sections`].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub student_sections: Option<StudentSections>,
/// See [`RenderConfig::number_from_record`].
#[serde(default, skip_serializing_if = "Option::is_none")]
pub number_from_record: Option<bool>,
@@ -603,6 +664,9 @@ impl Overrides {
if let Some(v) = &self.fields {
config.fields = v.clone();
}
if let Some(v) = &self.student_sections {
config.student_sections = v.clone();
}
if let Some(v) = self.number_from_record {
config.number_from_record = v;
}
@@ -668,6 +732,20 @@ variants:
answer-sheet:
reveal: nothing
# Every student-report section defaults on. Uncomment what you don't want;
# the CLI's `--no-levels`, `--no-objectives`, `--no-strengths`, `--no-focus`,
# `--no-dropped-questions`, `--no-review-lectures`, and `--no-study` flags
# set these same fields for a single run without editing this file.
# student-report:
# student_sections:
# levels: false
# objectives: false
# strengths: false
# focus: false
# dropped_questions: false
# review_lectures: false
# study: false
"#;
/// Serde default: `true`.
@@ -791,4 +869,4 @@ mod tests {
assert_eq!(file.resolve(Variant::Exam).reveal, Reveal::Nothing);
assert_eq!(file.resolve(Variant::Key).reveal, Reveal::Everything);
}
}
}