Automated Action 53d9909fb6 Create gamified kids learning API with FastAPI and SQLite
- Set up project structure with FastAPI and SQLite
- Implement user authentication with JWT
- Create models for learning content (subjects, lessons, quizzes)
- Add progress tracking and gamification features
- Implement comprehensive API documentation
- Add error handling and validation
- Set up proper logging and health check endpoint
2025-06-17 18:25:16 +00:00

121 lines
4.6 KiB
Python

from __future__ import annotations
import enum
from datetime import datetime
from sqlalchemy import Boolean, Column, DateTime, Enum, ForeignKey, Integer, String, Text
from sqlalchemy.orm import relationship
from app.db.base_class import Base
class DifficultyLevel(enum.Enum):
EASY = "easy"
MEDIUM = "medium"
HARD = "hard"
class Subject(Base):
"""
Subject model representing a learning area (e.g., Math, Science, Language).
"""
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True, nullable=False)
description = Column(Text, nullable=True)
image_url = Column(String, nullable=True)
order = Column(Integer, default=0)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
lessons = relationship("Lesson", back_populates="subject", cascade="all, delete-orphan")
class Lesson(Base):
"""
Lesson model representing a specific learning unit within a subject.
"""
id = Column(Integer, primary_key=True, index=True)
subject_id = Column(Integer, ForeignKey("subject.id"), nullable=False)
title = Column(String, index=True, nullable=False)
description = Column(Text, nullable=True)
content = Column(Text, nullable=False)
image_url = Column(String, nullable=True)
order = Column(Integer, default=0)
difficulty = Column(Enum(DifficultyLevel), default=DifficultyLevel.EASY)
points = Column(Integer, default=10) # Points awarded for completing the lesson
duration_minutes = Column(Integer, default=15) # Estimated time to complete the lesson
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
subject = relationship("Subject", back_populates="lessons")
quizzes = relationship("Quiz", back_populates="lesson", cascade="all, delete-orphan")
progress = relationship("UserProgress", back_populates="lesson")
class Quiz(Base):
"""
Quiz model representing a set of questions related to a lesson.
"""
id = Column(Integer, primary_key=True, index=True)
lesson_id = Column(Integer, ForeignKey("lesson.id"), nullable=False)
title = Column(String, index=True, nullable=False)
description = Column(Text, nullable=True)
time_limit_minutes = Column(Integer, default=10) # Time limit to complete the quiz
pass_percentage = Column(Integer, default=70) # Percentage required to pass
points = Column(Integer, default=20) # Points awarded for passing the quiz
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
lesson = relationship("Lesson", back_populates="quizzes")
questions = relationship("Question", back_populates="quiz", cascade="all, delete-orphan")
class Question(Base):
"""
Question model representing a single quiz question.
"""
id = Column(Integer, primary_key=True, index=True)
quiz_id = Column(Integer, ForeignKey("quiz.id"), nullable=False)
text = Column(Text, nullable=False)
image_url = Column(String, nullable=True)
explanation = Column(Text, nullable=True) # Explanation of the correct answer
points = Column(Integer, default=5) # Points for this question
order = Column(Integer, default=0)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
quiz = relationship("Quiz", back_populates="questions")
answers = relationship("Answer", back_populates="question", cascade="all, delete-orphan")
user_answers = relationship("UserAnswer", back_populates="question")
class Answer(Base):
"""
Answer model representing a possible answer to a question.
"""
id = Column(Integer, primary_key=True, index=True)
question_id = Column(Integer, ForeignKey("question.id"), nullable=False)
text = Column(Text, nullable=False)
is_correct = Column(Boolean, default=False)
explanation = Column(Text, nullable=True)
order = Column(Integer, default=0)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
question = relationship("Question", back_populates="answers")
user_answers = relationship("UserAnswer", back_populates="answer")