feat: quiz and rbac
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// Quiz target kinds.
|
||||
const (
|
||||
QuizChapter = "chapter"
|
||||
QuizLecture = "lecture"
|
||||
QuizConversation = "conversation"
|
||||
QuizStandalone = "standalone"
|
||||
)
|
||||
|
||||
// Attempt states, as seen by the person taking the quiz.
|
||||
const (
|
||||
QuizNotStarted = "not_started"
|
||||
QuizInProgress = "in_progress"
|
||||
QuizCompleted = "completed"
|
||||
)
|
||||
|
||||
// Quiz is a set of multiple-choice questions, optionally tied to a page.
|
||||
type Quiz struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
TargetKind string `json:"target_kind"`
|
||||
TargetPath *string `json:"target_path,omitempty"`
|
||||
TargetTitle string `json:"target_title"`
|
||||
PublishedAt *time.Time `json:"published_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
QuestionCount int `json:"question_count"`
|
||||
// Admin-only counters.
|
||||
AttemptCount int `json:"attempt_count,omitempty"`
|
||||
CompletedCount int `json:"completed_count,omitempty"`
|
||||
|
||||
Questions []QuizQuestion `json:"questions,omitempty"`
|
||||
}
|
||||
|
||||
// QuizQuestion is one question. Prompt and option bodies carry the same
|
||||
// formatting markers as the rest of the admin text.
|
||||
type QuizQuestion struct {
|
||||
ID string `json:"id"`
|
||||
Ord int `json:"ord"`
|
||||
Prompt string `json:"prompt"`
|
||||
Explanation string `json:"explanation,omitempty"`
|
||||
// Multi questions ask for every correct option ("select all that apply").
|
||||
Multi bool `json:"multi"`
|
||||
Options []QuizOption `json:"options"`
|
||||
}
|
||||
|
||||
// QuizOption is one choice. IsCorrect is nil whenever the reader must not
|
||||
// know it yet — every response to someone mid-attempt.
|
||||
type QuizOption struct {
|
||||
ID string `json:"id"`
|
||||
Ord int `json:"ord"`
|
||||
Body string `json:"body"`
|
||||
IsCorrect *bool `json:"is_correct,omitempty"`
|
||||
}
|
||||
|
||||
// QuizStatus is the caller's progress on a quiz.
|
||||
type QuizStatus struct {
|
||||
State string `json:"state"`
|
||||
Answered int `json:"answered"`
|
||||
Total int `json:"total"`
|
||||
Score *int `json:"score,omitempty"`
|
||||
}
|
||||
|
||||
// QuizCard is a quiz plus the caller's progress, for buttons and lists.
|
||||
type QuizCard struct {
|
||||
Quiz
|
||||
My QuizStatus `json:"my"`
|
||||
}
|
||||
|
||||
// QuizPlay is the next step of an attempt: the current question, or Done.
|
||||
type QuizPlay struct {
|
||||
QuizID string `json:"quiz_id"`
|
||||
Title string `json:"title"`
|
||||
Answered int `json:"answered"`
|
||||
Total int `json:"total"`
|
||||
Done bool `json:"done"`
|
||||
Question *QuizQuestion `json:"question,omitempty"`
|
||||
}
|
||||
|
||||
// QuizResultItem is one question on a results screen.
|
||||
type QuizResultItem struct {
|
||||
QuizQuestion
|
||||
ChosenOptionIDs []string `json:"chosen_option_ids"`
|
||||
IsCorrect bool `json:"is_correct"`
|
||||
ResponseMs *int `json:"response_ms,omitempty"`
|
||||
}
|
||||
|
||||
// QuizResult is a finished attempt.
|
||||
type QuizResult struct {
|
||||
Quiz Quiz `json:"quiz"`
|
||||
Score int `json:"score"`
|
||||
Total int `json:"total"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
TotalMs int `json:"total_ms"`
|
||||
Items []QuizResultItem `json:"items"`
|
||||
}
|
||||
|
||||
// QuizParticipant is one person's attempt, for the admin participants list.
|
||||
type QuizParticipant struct {
|
||||
UserID string `json:"user_id"`
|
||||
Handle string `json:"handle"`
|
||||
Name string `json:"name"`
|
||||
AvatarURL *string `json:"avatar_url,omitempty"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
Answered int `json:"answered"`
|
||||
Score int `json:"score"`
|
||||
Total int `json:"total"`
|
||||
TotalMs int `json:"total_ms"`
|
||||
}
|
||||
|
||||
// QuizOptionStat is how often one option was chosen.
|
||||
type QuizOptionStat struct {
|
||||
QuizOption
|
||||
Picks int `json:"picks"`
|
||||
}
|
||||
|
||||
// QuizQuestionStat aggregates every response to one question.
|
||||
type QuizQuestionStat struct {
|
||||
ID string `json:"id"`
|
||||
Ord int `json:"ord"`
|
||||
Prompt string `json:"prompt"`
|
||||
Multi bool `json:"multi"`
|
||||
Answered int `json:"answered"`
|
||||
Correct int `json:"correct"`
|
||||
AvgMs int `json:"avg_ms"`
|
||||
MedianMs int `json:"median_ms"`
|
||||
Options []QuizOptionStat `json:"options"`
|
||||
}
|
||||
Reference in New Issue
Block a user