Automated Action 1754fec627 Create Bible Quiz App API with FastAPI and SQLite
- Set up project structure with FastAPI and SQLite
- Create models for users, questions, and quizzes
- Implement Alembic migrations with seed data
- Add user authentication with JWT
- Implement question management endpoints
- Implement quiz creation and management
- Add quiz-taking and scoring functionality
- Set up API documentation and health check endpoint
- Update README with comprehensive documentation
2025-06-03 15:46:44 +00:00

158 lines
3.4 KiB
Python

from datetime import datetime
from enum import Enum
from typing import List, Optional
from pydantic import BaseModel, Field, validator
from app.schemas.question import Question
from app.schemas.user import User
class QuizQuestionBase(BaseModel):
question_id: int
position: int = 0
class QuizQuestionCreate(QuizQuestionBase):
pass
class QuizQuestionUpdate(QuizQuestionBase):
question_id: Optional[int] = None
position: Optional[int] = None
class QuizQuestionInDBBase(QuizQuestionBase):
id: int
quiz_id: int
class Config:
orm_mode = True
class QuizQuestion(QuizQuestionInDBBase):
question: Optional[Question] = None
class QuizBase(BaseModel):
title: str
description: Optional[str] = None
is_public: bool = False
time_limit_minutes: int = 10
pass_percentage: float = 70.0
class QuizCreate(QuizBase):
questions: List[QuizQuestionCreate] = Field(..., min_items=1)
@validator("questions")
def validate_unique_questions(cls, v):
question_ids = [q.question_id for q in v]
if len(question_ids) != len(set(question_ids)):
raise ValueError("Quiz cannot contain duplicate questions")
return v
class QuizUpdate(QuizBase):
title: Optional[str] = None
description: Optional[str] = None
is_public: Optional[bool] = None
time_limit_minutes: Optional[int] = None
pass_percentage: Optional[float] = None
questions: Optional[List[QuizQuestionCreate]] = None
@validator("questions")
def validate_unique_questions(cls, v):
if v is not None:
question_ids = [q.question_id for q in v]
if len(question_ids) != len(set(question_ids)):
raise ValueError("Quiz cannot contain duplicate questions")
return v
class QuizInDBBase(QuizBase):
id: int
user_id: int
created_at: datetime
updated_at: datetime
class Config:
orm_mode = True
class Quiz(QuizInDBBase):
user: Optional[User] = None
questions: List[QuizQuestion] = []
class QuizWithoutDetails(QuizInDBBase):
user: Optional[User] = None
question_count: int
class AttemptStatus(str, Enum):
started = "started"
completed = "completed"
abandoned = "abandoned"
class QuizAnswerBase(BaseModel):
quiz_question_id: int
selected_option_id: Optional[int] = None
class QuizAnswerCreate(QuizAnswerBase):
pass
class QuizAnswerUpdate(QuizAnswerBase):
selected_option_id: Optional[int] = None
class QuizAnswerInDBBase(QuizAnswerBase):
id: int
quiz_attempt_id: int
is_correct: Optional[bool] = None
answered_at: datetime
class Config:
orm_mode = True
class QuizAnswer(QuizAnswerInDBBase):
pass
class QuizAttemptBase(BaseModel):
quiz_id: int
status: AttemptStatus = AttemptStatus.started
score: Optional[float] = None
started_at: datetime = Field(default_factory=datetime.utcnow)
completed_at: Optional[datetime] = None
class QuizAttemptCreate(QuizAttemptBase):
pass
class QuizAttemptUpdate(QuizAttemptBase):
status: Optional[AttemptStatus] = None
score: Optional[float] = None
completed_at: Optional[datetime] = None
class QuizAttemptInDBBase(QuizAttemptBase):
id: int
user_id: int
class Config:
orm_mode = True
class QuizAttempt(QuizAttemptInDBBase):
quiz: Optional[Quiz] = None
answers: List[QuizAnswer] = []
class QuizSubmitAnswer(BaseModel):
selected_option_id: int