Skip to content

Commit

Permalink
limit total-points to flat task arrays, remove filter parameter in fa…
Browse files Browse the repository at this point in the history
…vor of regular array filtering
  • Loading branch information
SillyFreak committed Oct 11, 2024
1 parent 55e4f69 commit 0711bf8
Show file tree
Hide file tree
Showing 6 changed files with 16 additions and 24 deletions.
Binary file modified docs/manual.pdf
Binary file not shown.
8 changes: 4 additions & 4 deletions docs/manual.typ
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ In this example, #ref-fn("task.current()") is used in conjunction with #ref-fn("

The next puzzle piece is grading. There are many different possibilities to grade an exam; Scrutinize tries not to be tied to specific grading strategies, but it does assume that each task gets assigned points and that the grade results from looking at some kinds of sums of these points. If your test does not fit that schema, you can simply ignore the related features.

The first step in creating a typical grading scheme is determining how many points can be achieved in total, using #ref-fn("grading.total-points()"). We also need to use #ref-fn("task.all()") to get access to the task metadata distributed throughout the document:
The first step in creating a typical grading scheme is determining how many points can be achieved in total, using #ref-fn("grading.total-points()"). We also need to use #ref-fn("task.all()") (with the `flatten` parameter) to get access to the task metadata distributed throughout the document:

#example(lines: "12-", ```typ
// you usually want to alias this, as you'll need it often
Expand All @@ -185,9 +185,9 @@ The first step in creating a typical grading scheme is determining how many poin
}
#context [
#let ts = task.all()
#let ts = task.all(flatten: true)
#let total = grading.total-points(ts)
#let hard = grading.total-points(ts, filter: t => t.data.points >= 5)
#let hard = grading.total-points(ts.filter(t => t.data.points >= 5))
Total points: #total \ Points from hard tasks: #hard
]
Expand All @@ -214,7 +214,7 @@ Once we have the total points of the exam figured out, we need to define the gra
}
#context [
#let total = grading.total-points(task.all())
#let total = grading.total-points(task.all(flatten: true))
#grading.grades(
[bad],
total * 2/4, [okay],
Expand Down
5 changes: 2 additions & 3 deletions gallery/gk-ek-austria.typ
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,10 @@
set text(size: 10pt)

let points(category, extended) = {
grading.total-points(ts, filter: t => {
grading.total-points(ts.filter(t => {
t.data.category == category and t.data.at("extended", default: false) == extended
})
}))
}
let category-points(category) = grading.total-points(ts, filter: t => t.data.category == category)

let categories = categories.map((category) => {
let gk = points(category.id, false)
Expand Down
2 changes: 1 addition & 1 deletion gallery/small-example.typ
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#set table(stroke: 0.5pt)

#context {
let ts = task.all()
let ts = task.all(flatten: true)
let total = grading.total-points(ts)

[The candidate achieved #h(3em) out of #total points.]
Expand Down
5 changes: 2 additions & 3 deletions gallery/test.typ
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@

// for grading, we need to consider all questions
#context {
let ts = task.all()
let ts = task.all(flatten: true)
let total = grading.total-points(ts)
// the total-points function can also accept a filter function
let hard = grading.total-points(ts, filter: t => t.data.points >= 5)
let hard = grading.total-points(ts.filter(t => t.data.points >= 5))

// create a grading key
let grades = grading.grades([bad], total * 2/4, [okay], total * 3/4, [good])
Expand Down
20 changes: 7 additions & 13 deletions src/grading.typ
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
/// Takes an array of task metadata and returns the sum of their points, recursivly including
/// subtasks. Tasks without points count as zero points.
/// Takes an array of _flattened_ task metadata and returns the sum of their points. Tasks without points count as zero points.
///
/// - tasks (array): an array of task metadata dictionaries
/// - filter (function): an optional filter function for determining which tasks to sum up. Subtasks
/// of tasks that didn't match are ignored.
/// - tasks (array): a flat array of task metadata dictionaries
/// - field (string): the field in the metadata over which to calculate the sum
/// -> integer, float
#let total-points(tasks, filter: none, field: "points") = {
#let total-points(tasks, field: "points") = {
tasks.map(t => {
let points = 0
if filter == none or filter(t) {
if t.data != none {
points += t.data.at(field, default: 0)
}
points += total-points(t.at("subtasks", default: ()))
if t.data != none {
t.data.at(field, default: 0)
} else {
0
}
points
}).sum(default: 0)
}

Expand Down

0 comments on commit 0711bf8

Please sign in to comment.