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:
33
classes/open.go
Normal file
33
classes/open.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package classes
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"git.golem15.com/golem15/sm-quizzes-plugin/models"
|
||||
)
|
||||
|
||||
// MaxLength is the longest answer an open question accepts, in characters:
|
||||
// its MaxLength when set and positive, else models.DefaultMaxLength.
|
||||
func MaxLength(q models.Question) int {
|
||||
if q.MaxLength != nil && *q.MaxLength > 0 {
|
||||
return *q.MaxLength
|
||||
}
|
||||
return models.DefaultMaxLength
|
||||
}
|
||||
|
||||
// CheckOpenText cleans a student's answer to an open question (D-04): it
|
||||
// removes every NUL character (Postgres text refuses them) and the
|
||||
// surrounding whitespace. A blank text is a FieldError text_required and a
|
||||
// text longer than MaxLength(q) characters (runes, not bytes) is a
|
||||
// FieldError text_too_long.
|
||||
func CheckOpenText(text string, q models.Question) (string, error) {
|
||||
text = strings.TrimSpace(strings.ReplaceAll(text, "\x00", ""))
|
||||
if text == "" {
|
||||
return "", &FieldError{Field: "text", Key: "text_required"}
|
||||
}
|
||||
if utf8.RuneCountInString(text) > MaxLength(q) {
|
||||
return "", &FieldError{Field: "text", Key: "text_too_long"}
|
||||
}
|
||||
return text, nil
|
||||
}
|
||||
Reference in New Issue
Block a user