- Fully decouple course quizzes from main quiz system (hidden from dashboard stats, history, search, results page) - Course quiz results show "Back to Course" instead of retake/delete - Add allow_review toggle for course creators to control answer review - Show quiz title on course page, hide pool size from students - Add course thumbnails to browse cards - Replace passlib with bcrypt directly (compatible with existing hashes) - Add HIBP breached password warnings on register/reset/change password - Add CLI management tools (reset-password, set-role, stats, etc.) - Fix quiz PATCH endpoint: ownership check instead of moderator-only - Add max_length validation on course/module/lesson titles - Fix score display bug on results page (0 of N when review disabled) - Fix question count on course quiz start (show per-attempt, not pool) - Improve suspend warning for timed course quizzes with max attempts - Clean up validation error messages (show "Invalid email" not Pydantic dump) - Add DDL migration for allow_review column Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63 lines
1.2 KiB
Python
63 lines
1.2 KiB
Python
from datetime import datetime
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class AnswerSubmission(BaseModel):
|
|
question_id: int
|
|
user_answer: str
|
|
|
|
|
|
class AttemptSubmit(BaseModel):
|
|
answers: list[AnswerSubmission]
|
|
|
|
|
|
class AnswerDetail(BaseModel):
|
|
question_id: int
|
|
question_text: str
|
|
question_type: str
|
|
options: list[str] | None = None
|
|
user_answer: str
|
|
correct_answer: str
|
|
is_correct: bool
|
|
explanation: str | None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class AttemptResponse(BaseModel):
|
|
id: int
|
|
quiz_id: int
|
|
score: int
|
|
total_questions: int
|
|
percentage: float
|
|
started_at: datetime
|
|
completed_at: datetime | None
|
|
course_id: int | None = None
|
|
allow_review: bool = True
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class AttemptDetail(AttemptResponse):
|
|
answers: list[AnswerDetail] = []
|
|
|
|
|
|
# Stats schemas
|
|
class QuizStats(BaseModel):
|
|
quiz_id: int
|
|
quiz_title: str
|
|
attempts_count: int
|
|
best_score: float
|
|
latest_score: float
|
|
average_score: float
|
|
|
|
|
|
class DashboardStats(BaseModel):
|
|
total_documents: int
|
|
total_quizzes: int
|
|
total_attempts: int
|
|
average_score: float
|
|
quiz_stats: list[QuizStats] = []
|