feat: add open questions with a pending grading state
- migration: open question type, rubric, max_length, quiz grader and the grading and review columns of attempt answers - open answers are checked, stored as pending and never scored on answer; a changed text resets the grading state - student JSON gains text, grading_status, grader_feedback, review_comment, max_length, needs_review and open_answers; the rubric is never serialized
This commit is contained in:
@@ -152,6 +152,27 @@ func Totals(points []float64, maxPoints int) (score, percent float64) {
|
||||
return score, round(score / float64(maxPoints) * 100)
|
||||
}
|
||||
|
||||
// ClampOpenPoints keeps a grader's score of an open question in
|
||||
// 0..points (a negative points value counts as 0), rounded to the nearest
|
||||
// 0.5 (D-02). NaN and ±Inf are not a score: it returns 0, false.
|
||||
func ClampOpenPoints(p float64, points int) (float64, bool) {
|
||||
if math.IsNaN(p) || math.IsInf(p, 0) {
|
||||
return 0, false
|
||||
}
|
||||
full := float64(max(points, 0))
|
||||
p = math.Round(math.Min(math.Max(p, 0), full)*2) / 2
|
||||
if p == 0 {
|
||||
return 0, true // no negative zero in JSON
|
||||
}
|
||||
return p, true
|
||||
}
|
||||
|
||||
// OpenCorrect reports whether an open answer scored p earns full marks: a
|
||||
// question with points earns is_correct only with all of them (D-02).
|
||||
func OpenCorrect(p float64, points int) bool {
|
||||
return points > 0 && p == float64(points)
|
||||
}
|
||||
|
||||
// round keeps two decimals.
|
||||
func round(f float64) float64 {
|
||||
r := math.Round(f*100) / 100
|
||||
|
||||
Reference in New Issue
Block a user