feat: add learning objective targets
This commit is contained in:
+24
-26
@@ -509,12 +509,9 @@ pub fn student(
|
||||
.objectives
|
||||
.iter()
|
||||
.map(|mastery| ObjectiveRow {
|
||||
id: mastery.objective.clone(),
|
||||
id: mastery.id.clone(),
|
||||
text: mastery.text.clone(),
|
||||
unit: course
|
||||
.learning_objectives
|
||||
.get(&mastery.objective)
|
||||
.and_then(|o| o.unit.clone()),
|
||||
unit: course.objective_unit(&mastery.id).map(str::to_string),
|
||||
n_items: mastery.n_items,
|
||||
credit: mastery.credit,
|
||||
rate: mastery.rate,
|
||||
@@ -700,11 +697,11 @@ fn question_row(
|
||||
number: row.item_number,
|
||||
position: row.form_position.filter(|p| *p != row.item_number),
|
||||
level: row.level.map(|l| l.code()),
|
||||
objectives: row.learning_objectives.clone(),
|
||||
objectives: row.learning_targets.clone(),
|
||||
objective_texts: if missed {
|
||||
row.learning_objectives
|
||||
row.learning_targets
|
||||
.iter()
|
||||
.map(|id| catalog.course.objective_text(id))
|
||||
.map(|id| catalog.course.text_for(id))
|
||||
.collect()
|
||||
} else {
|
||||
// Only where it earns its space. Every question already carries its
|
||||
@@ -830,15 +827,13 @@ fn lecture_focus(catalog: &Catalog, rows: &[&Response], opts: &Options) -> Vec<L
|
||||
.extend(source.slides.iter().copied());
|
||||
}
|
||||
}
|
||||
for objective in &row.learning_objectives {
|
||||
if let Some(entry) = course.learning_objectives.get(objective) {
|
||||
lectures.extend(entry.lectures.iter().cloned());
|
||||
}
|
||||
for target in &row.learning_targets {
|
||||
lectures.extend(course.lectures_for(target).iter().cloned());
|
||||
}
|
||||
|
||||
for lecture in lectures {
|
||||
let tally = tallies.entry(lecture.clone()).or_default();
|
||||
tally.objectives.extend(row.learning_objectives.clone());
|
||||
tally.objectives.extend(row.learning_targets.clone());
|
||||
tally.questions.insert(row.item_number);
|
||||
if let Some(numbers) = slides.get(&lecture) {
|
||||
tally.slides.extend(numbers.iter().copied());
|
||||
@@ -866,7 +861,7 @@ fn lecture_focus(catalog: &Catalog, rows: &[&Response], opts: &Options) -> Vec<L
|
||||
objectives: tally
|
||||
.objectives
|
||||
.iter()
|
||||
.map(|id| course.objective_text(id))
|
||||
.map(|id| course.text_for(id))
|
||||
.collect(),
|
||||
lecture,
|
||||
}
|
||||
@@ -1390,17 +1385,22 @@ pub fn cohort(
|
||||
.collect();
|
||||
|
||||
// Objective counts come from the responses so that an objective assessed by
|
||||
// two items is not reported as if it had one.
|
||||
// two items is not reported as if it had one. Counted per objective, and by
|
||||
// item number, so a question tagged with two of that objective's targets is
|
||||
// one item here.
|
||||
let mut objective_items: BTreeMap<String, BTreeSet<u32>> = BTreeMap::new();
|
||||
for row in set.rows.iter().filter(|r| r.counts()) {
|
||||
for objective in &row.learning_objectives {
|
||||
for objective in &row.learning_targets {
|
||||
objective_items
|
||||
.entry(objective.clone())
|
||||
.entry(course.objective_for(objective).to_string())
|
||||
.or_default()
|
||||
.insert(row.item_number);
|
||||
}
|
||||
}
|
||||
|
||||
// Objectives, not targets: this table is the reteaching queue, and it is
|
||||
// only usable if it is short enough to read and each row rests on enough
|
||||
// items to believe.
|
||||
let mut objectives: Vec<CohortObjectiveRow> = cohort
|
||||
.objective_rates
|
||||
.iter()
|
||||
@@ -1410,7 +1410,7 @@ pub fn cohort(
|
||||
let mut not_yet = 0;
|
||||
let mut thin = 0;
|
||||
for student in &cohort.students {
|
||||
if let Some(row) = student.objectives.iter().find(|o| &o.objective == id) {
|
||||
if let Some(row) = student.objectives.iter().find(|o| &o.id == id) {
|
||||
match row.status {
|
||||
Mastery::Meeting => meeting += 1,
|
||||
Mastery::Developing => developing += 1,
|
||||
@@ -1421,7 +1421,7 @@ pub fn cohort(
|
||||
}
|
||||
CohortObjectiveRow {
|
||||
id: id.clone(),
|
||||
text: course.objective_text(id),
|
||||
text: course.text_for(id),
|
||||
n_items: objective_items.get(id).map(|s| s.len()).unwrap_or(0),
|
||||
rate: *rate,
|
||||
meeting,
|
||||
@@ -1451,7 +1451,7 @@ pub fn cohort(
|
||||
.map(|p| {
|
||||
(
|
||||
p.number,
|
||||
(p.level.map(|l| l.code()), p.learning_objectives.clone()),
|
||||
(p.level.map(|l| l.code()), p.learning_targets.clone()),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
@@ -1467,7 +1467,7 @@ pub fn cohort(
|
||||
level: meta.and_then(|m| m.0),
|
||||
objectives: meta.map(|m| m.1.clone()).unwrap_or_default(),
|
||||
objective_texts: meta
|
||||
.map(|m| m.1.iter().map(|id| course.objective_text(id)).collect())
|
||||
.map(|m| m.1.iter().map(|id| course.text_for(id)).collect())
|
||||
.unwrap_or_default(),
|
||||
taught_in: item
|
||||
.item_ref
|
||||
@@ -1564,7 +1564,7 @@ pub fn cohort(
|
||||
questions,
|
||||
revise,
|
||||
forms: form_rows(set, cohort),
|
||||
blueprint: crate::select::check_blueprint(record),
|
||||
blueprint: crate::select::check_blueprint(record, course),
|
||||
patterns: cohort
|
||||
.archetypes
|
||||
.iter()
|
||||
@@ -1739,10 +1739,8 @@ fn lecture_rows(
|
||||
lectures.insert(source.lecture.clone());
|
||||
}
|
||||
}
|
||||
for objective in &question.objectives {
|
||||
if let Some(entry) = course.learning_objectives.get(objective) {
|
||||
lectures.extend(entry.lectures.iter().cloned());
|
||||
}
|
||||
for target in &question.objectives {
|
||||
lectures.extend(course.lectures_for(target).iter().cloned());
|
||||
}
|
||||
for lecture in lectures {
|
||||
items.entry(lecture.clone()).or_default().push(question);
|
||||
|
||||
Reference in New Issue
Block a user