refactor: improve student report

This commit is contained in:
2026-09-19 21:30:04 -04:00
parent 994e9065e8
commit c06d5caa8c
5 changed files with 1074 additions and 270 deletions
+90 -6
View File
@@ -148,6 +148,10 @@ impl Meta {
out.insert("assessment", assessment);
out.insert("generator", generator);
out.insert("policy", policy);
// `students-tested` is the honest name: it is how many people sat this
// assessment, which is not the enrolment. `class-size` stays as an alias
// so a template forked before this change keeps working.
out.insert("students-tested", Value::Int(self.n_students as i64));
out.insert("class-size", Value::Int(self.n_students as i64));
out.insert("extra", extra_value(config));
out
@@ -180,6 +184,7 @@ pub fn student_value(diagnostic: &StudentDiagnostic, config: &RenderConfig) -> V
out.insert("student-key", Value::str(&diagnostic.student_key));
out.insert_some("name", diagnostic.name.as_ref().map(Value::str));
out.insert_some("sid", diagnostic.sid.as_ref().map(Value::str));
out.insert_some("email", diagnostic.email.as_ref().map(Value::str));
out.insert_some("form", diagnostic.form.as_ref().map(Value::str));
let mut score = Value::dict();
@@ -296,17 +301,96 @@ pub fn student_value(diagnostic: &StudentDiagnostic, config: &RenderConfig) -> V
value.insert("bonus", Value::Bool(question.bonus));
value.insert("blank", Value::Bool(question.blank));
value.insert_some("class-rate", question.class_rate.map(Value::Float));
value.insert_some(
"feedback",
question
.feedback
.as_ref()
.map(|text| markup_value(text, content)),
value.insert(
"objective-texts",
Value::Array(
question
.objective_texts
.iter()
.map(|text| markup_value(text, content))
.collect(),
),
);
for (key, text) in [
("feedback", question.feedback.as_ref()),
("hint", question.hint.as_ref()),
("misconception", question.misconception.as_ref()),
("worked", question.worked.as_ref()),
] {
value.insert_some(key, text.map(|t| markup_value(t, content)));
}
value.insert(
"taught-in",
Value::Array(question.taught_in.iter().map(|s| Value::str(s)).collect()),
);
value.insert(
"review",
Value::Array(
question
.review
.iter()
.map(|reading| {
let mut entry = Value::dict();
entry.insert("citation", Value::str(&reading.citation));
entry.insert_some(
"title",
reading.title.as_ref().map(Value::str),
);
entry.insert_some("url", reading.url.as_ref().map(Value::str));
entry
})
.collect(),
),
);
value
})
.collect(),
),
);
out.insert(
"review-lectures",
Value::Array(
diagnostic
.review_lectures
.iter()
.map(|lecture| {
let mut value = Value::dict();
value.insert("lecture", Value::str(&lecture.lecture));
value.insert("title", Value::str(&lecture.title));
value.insert_some("url", lecture.url.as_ref().map(Value::str));
value.insert("objectives-missed", Value::Int(lecture.n_objectives as i64));
value.insert("questions-missed", Value::Int(lecture.n_questions as i64));
value.insert(
"questions",
Value::Array(
lecture
.questions
.iter()
.map(|n| Value::Int(*n as i64))
.collect(),
),
);
value.insert(
"slides",
Value::Array(
lecture
.slides
.iter()
.map(|n| Value::Int(*n as i64))
.collect(),
),
);
value.insert(
"objectives",
Value::Array(
lecture
.objectives
.iter()
.map(|text| markup_value(text, content))
.collect(),
),
);
value
})
.collect(),