feat: grade open answers through a grader registry in the background
- graders registry collected at boot from every HasGraders plugin, manual first; a duplicate or reserved code fails boot - grading job on queue quizzes_grading with three attempts; a stale or reviewed answer is never touched; the last failure marks it failed - learning answers enqueue at once, tests at close; a grade recalculates a finished attempt and fires AnswerGradedEvent after commit
This commit is contained in:
62
events/events.go
Normal file
62
events/events.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// Package events holds the plugin events of golem15.quizzes that other
|
||||
// plugins listen to with app.Events.Listen. Every event fires after the
|
||||
// write it announces has committed, so a listener never sees a score that
|
||||
// was rolled back; a listener error is logged and never undoes the write.
|
||||
// The package imports nothing from golem15.quizzes, so a listener can
|
||||
// depend on it alone.
|
||||
package events
|
||||
|
||||
// Event names, for logs and documentation; the bus itself is keyed by type.
|
||||
const (
|
||||
AnswerGradedEventName = "quizzes.AnswerGraded"
|
||||
AnswerReviewedEventName = "quizzes.AnswerReviewed"
|
||||
AttemptReviewedEventName = "quizzes.AttemptReviewed"
|
||||
)
|
||||
|
||||
// AnswerGradedEvent is fired as *AnswerGradedEvent after a grader's score
|
||||
// of an open answer is stored (grading_status graded). The owner has not
|
||||
// confirmed it yet. MaxPoints is the question's points.
|
||||
type AnswerGradedEvent struct {
|
||||
QuizID uint
|
||||
QuestionID uint
|
||||
AttemptID uint
|
||||
AnswerID uint
|
||||
UserID uint
|
||||
Grader string
|
||||
Points float64
|
||||
MaxPoints int
|
||||
Feedback string
|
||||
}
|
||||
|
||||
// AnswerReviewedEvent is fired as *AnswerReviewedEvent after the owner
|
||||
// confirms or sets the score of an open answer (grading_status reviewed).
|
||||
// GraderPoints is the grader's score when there was one; Comment is the
|
||||
// owner's comment to the student. The reviewer is a frontend user
|
||||
// (ReviewerUserID, over MCP) or a backend administrator (ReviewerAdminID).
|
||||
type AnswerReviewedEvent struct {
|
||||
QuizID uint
|
||||
QuestionID uint
|
||||
AttemptID uint
|
||||
AnswerID uint
|
||||
UserID uint
|
||||
Points float64
|
||||
MaxPoints int
|
||||
GraderPoints *float64
|
||||
Comment *string
|
||||
ReviewerUserID *uint
|
||||
ReviewerAdminID *uint
|
||||
}
|
||||
|
||||
// AttemptReviewedEvent is fired as *AttemptReviewedEvent once every open
|
||||
// answer of a completed attempt is reviewed, with the attempt's final
|
||||
// score. MaxPoints is the attempt's stored maximum; Passed compares
|
||||
// ScorePercent with the quiz's passing score.
|
||||
type AttemptReviewedEvent struct {
|
||||
QuizID uint
|
||||
AttemptID uint
|
||||
UserID uint
|
||||
ScorePoints float64
|
||||
MaxPoints int
|
||||
ScorePercent *float64
|
||||
Passed bool
|
||||
}
|
||||
Reference in New Issue
Block a user