learning.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. from pydantic import BaseModel
  2. from typing import Optional, List, Dict
  3. from enum import Enum
  4. from datetime import datetime
  5. class LearningPath(str, Enum):
  6. FRONTEND = "frontend"
  7. BACKEND = "backend"
  8. FULLSTACK = "fullstack"
  9. class ModuleStatus(str, Enum):
  10. NOT_STARTED = "not_started"
  11. IN_PROGRESS = "in_progress"
  12. COMPLETED = "completed"
  13. LOCKED = "locked"
  14. class UserLevel(str, Enum):
  15. BEGINNER = "beginner"
  16. INTERMEDIATE = "intermediate"
  17. ADVANCED = "advanced"
  18. class LearningModule(BaseModel):
  19. id: str
  20. title: str
  21. description: str
  22. icon: str
  23. order: int
  24. lessons: List["LearningLesson"]
  25. status: ModuleStatus = ModuleStatus.NOT_STARTED
  26. progress: float = 0.0 # 0-100
  27. class LearningLesson(BaseModel):
  28. id: str
  29. title: str
  30. description: str
  31. type: str # "theory", "practice", "quiz", "project"
  32. duration_minutes: int
  33. is_completed: bool = False
  34. content_markdown: Optional[str] = None # Markdown格式的课程内容
  35. class LearningPathData(BaseModel):
  36. path: LearningPath
  37. title: str
  38. description: str
  39. icon: str
  40. modules: List[LearningModule]
  41. total_lessons: int = 0
  42. completed_lessons: int = 0
  43. progress: float = 0.0
  44. class AssessmentResult(BaseModel):
  45. """水平检测结果"""
  46. user_id: str = "default"
  47. path_type: str # LearningPath value
  48. total_questions: int
  49. correct_count: int
  50. score: float # 0-100
  51. level: UserLevel
  52. category_scores: Dict[str, float] # 各分类得分 {"html_css": 80, "javascript": 60, ...}
  53. recommended_start_module: str # 推荐开始的模块ID
  54. completed_at: datetime
  55. is_current: bool = True # 是否为当前有效结果
  56. class UserProgress(BaseModel):
  57. user_id: str = "default"
  58. current_path: Optional[LearningPath] = None
  59. completed_modules: List[str] = []
  60. completed_lessons: List[str] = []
  61. current_module: Optional[str] = None
  62. current_lesson: Optional[str] = None
  63. started_at: Optional[datetime] = None
  64. last_activity_at: Optional[datetime] = None
  65. total_study_minutes: int = 0
  66. assessments: List[AssessmentResult] = [] # 测试结果历史
  67. skill_levels: Dict[str, float] = {} # 各分类水平 0-100
  68. learning_plan: Optional[str] = None # AI生成的个性化学习计划
  69. last_session: Optional[dict] = None # 用户最近的会话数据
  70. class CodeSubmission(BaseModel):
  71. """代码提交记录"""
  72. id: str
  73. user_id: str = "default"
  74. code: str
  75. language: str = "python"
  76. output: str = ""
  77. error: str = ""
  78. success: bool = True
  79. exit_code: int = 0
  80. lesson_id: Optional[str] = None
  81. feedback: str = ""
  82. created_at: datetime
  83. class CoachRecommendation(BaseModel):
  84. type: str # "next_lesson", "review", "practice", "challenge"
  85. title: str
  86. description: str
  87. module_id: Optional[str] = None
  88. lesson_id: Optional[str] = None
  89. priority: int = 1 # 1-5
  90. class GamificationProfile(BaseModel):
  91. """游戏化个人档案"""
  92. user_id: str = "default"
  93. total_xp: int = 0
  94. level: int = 1
  95. streak: int = 0 # 连续学习天数
  96. last_active_date: str = "" # "YYYY-MM-DD"
  97. badges: List[str] = [] # 已获得的徽章ID列表
  98. xp_log: List[dict] = [] # XP变动记录 [{amount, reason, timestamp}]
  99. class CoachResponse(BaseModel):
  100. greeting: str
  101. recommendations: List[CoachRecommendation]
  102. encouragement: str
  103. stats: dict
  104. learning_plan: Optional[str] = None # AI生成的个性化学习计划
  105. # ===== 水平检测相关模型 =====
  106. class AssessmentQuestion(BaseModel):
  107. """检测题目"""
  108. id: str
  109. category: str # "html_css", "javascript", "python", "vue", "system_design"
  110. difficulty: int # 1-5
  111. content: str
  112. question_type: str = "choice" # "choice" | "code_output" | "code_fill" | "bug_fix"
  113. code_snippet: Optional[str] = None # 代码片段(用于代码类题目)
  114. options: List[str] # 选择题选项
  115. correct_answer: str # "A", "B", "C", "D"
  116. explanation: str
  117. class AssessmentStartRequest(BaseModel):
  118. """开始检测请求"""
  119. path_type: str # LearningPath value
  120. user_id: str = "default"
  121. class AssessmentAnswerRequest(BaseModel):
  122. """提交答案请求"""
  123. session_id: str
  124. question_id: str
  125. answer: str # "A", "B", "C", "D"
  126. path_type: str
  127. user_id: str = "default"
  128. class AssessmentCompleteRequest(BaseModel):
  129. """完成检测请求"""
  130. session_id: str
  131. path_type: str
  132. user_id: str = "default"
  133. class AssessmentStartResponse(BaseModel):
  134. """开始检测响应"""
  135. session_id: str
  136. question: AssessmentQuestion
  137. current_index: int
  138. total_questions: int
  139. class AssessmentAnswerResponse(BaseModel):
  140. """提交答案响应"""
  141. is_correct: bool
  142. correct_answer: str
  143. explanation: str
  144. next_question: Optional[AssessmentQuestion]
  145. current_index: int
  146. total_questions: int
  147. is_completed: bool