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:
@@ -9,13 +9,25 @@ const (
|
||||
TypeSingle = "single"
|
||||
TypeMultiple = "multiple"
|
||||
TypeSelfCheck = "self_check"
|
||||
TypeOpen = "open"
|
||||
)
|
||||
|
||||
// QuestionTypes lists the valid values of Question.Type.
|
||||
var QuestionTypes = []string{TypeSingle, TypeMultiple, TypeSelfCheck}
|
||||
var QuestionTypes = []string{TypeSingle, TypeMultiple, TypeSelfCheck, TypeOpen}
|
||||
|
||||
// Limits of the answer length of an open question, in characters.
|
||||
const (
|
||||
// DefaultMaxLength applies when MaxLength is nil.
|
||||
DefaultMaxLength = 2000
|
||||
// MaxMaxLength is the largest MaxLength the column accepts.
|
||||
MaxMaxLength = 20000
|
||||
)
|
||||
|
||||
// Question is one question of a quiz. A self_check question is a flashcard:
|
||||
// the user reveals AnswerText and marks whether they knew it.
|
||||
// the user reveals AnswerText and marks whether they knew it. An open
|
||||
// question is answered in free text and graded against AnswerText (the
|
||||
// model answer) and the owner-only Rubric; MaxLength caps the answer
|
||||
// (DefaultMaxLength when nil).
|
||||
type Question struct {
|
||||
ID uint `gorm:"column:id;primaryKey"`
|
||||
QuizID uint `gorm:"column:quiz_id"`
|
||||
@@ -24,6 +36,8 @@ type Question struct {
|
||||
Category *string `gorm:"column:category"`
|
||||
AnswerText *string `gorm:"column:answer_text"`
|
||||
Explanation *string `gorm:"column:explanation"`
|
||||
Rubric *string `gorm:"column:rubric"`
|
||||
MaxLength *int `gorm:"column:max_length"`
|
||||
SortOrder int `gorm:"column:sort_order"`
|
||||
Points int `gorm:"column:points"`
|
||||
CreatedAt time.Time `gorm:"column:created_at"`
|
||||
@@ -37,7 +51,7 @@ func (Question) TableName() string { return "golem15_quizzes_questions" }
|
||||
|
||||
// Fillable lists the columns mass assignment may set.
|
||||
func (Question) Fillable() []string {
|
||||
return []string{"quiz_id", "text", "type", "category", "answer_text", "explanation", "sort_order", "points"}
|
||||
return []string{"quiz_id", "text", "type", "category", "answer_text", "explanation", "sort_order", "points", "rubric", "max_length"}
|
||||
}
|
||||
|
||||
// Rules are checked by the admin API on every save.
|
||||
@@ -45,9 +59,10 @@ func (Question) Rules() map[string]string {
|
||||
return map[string]string{
|
||||
"quiz_id": "required|integer|min:1",
|
||||
"text": "required",
|
||||
"type": "required|in:single,multiple,self_check",
|
||||
"type": "required|in:single,multiple,self_check,open",
|
||||
"category": "nullable|max:255",
|
||||
"sort_order": "nullable|integer",
|
||||
"points": "required|integer|min:0",
|
||||
"max_length": "nullable|integer|between:1,20000",
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user