refactor(stage-4): partition monolithic main.py into modular APIRouters
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.auth import require_user
|
||||
from app.database import get_db
|
||||
from app.cefr import (
|
||||
get_cefr_level_summaries,
|
||||
get_cefr_quiz_batch,
|
||||
process_cefr_answer,
|
||||
reset_user_cefr_level,
|
||||
ingest_cefr_word,
|
||||
)
|
||||
|
||||
router = APIRouter(tags=["CEFR Testing & Mining"])
|
||||
|
||||
|
||||
class CefrAnswerRequest(BaseModel):
|
||||
question_id: int
|
||||
selected_option: str
|
||||
|
||||
|
||||
class CefrResetRequest(BaseModel):
|
||||
level: str
|
||||
|
||||
|
||||
class CefrAddWordRequest(BaseModel):
|
||||
level: str
|
||||
term: str
|
||||
context_sentence: Optional[str] = ""
|
||||
|
||||
|
||||
@router.get("/api/cefr/levels")
|
||||
async def api_cefr_levels(user: dict = Depends(require_user)):
|
||||
"""
|
||||
Returns progress summaries for all CEFR levels (A1, A2, B1, B2).
|
||||
"""
|
||||
with get_db() as conn:
|
||||
summaries = get_cefr_level_summaries(conn, user["id"])
|
||||
return {"levels": summaries}
|
||||
|
||||
|
||||
@router.get("/api/cefr/quiz")
|
||||
async def api_cefr_quiz(
|
||||
level: str = Query("A1"),
|
||||
count: int = Query(10, ge=1, le=30),
|
||||
mode: str = Query("all"),
|
||||
user: dict = Depends(require_user),
|
||||
):
|
||||
"""
|
||||
Returns next batch of Cloze Tap test questions for level (A1..B2).
|
||||
"""
|
||||
with get_db() as conn:
|
||||
quiz_items = get_cefr_quiz_batch(conn, user["id"], level, count, mode)
|
||||
return {"level": level.upper(), "count": len(quiz_items), "quiz": quiz_items}
|
||||
|
||||
|
||||
@router.post("/api/cefr/answer")
|
||||
async def api_cefr_answer(
|
||||
req: CefrAnswerRequest,
|
||||
user: dict = Depends(require_user),
|
||||
):
|
||||
"""
|
||||
Submits an answer for a CEFR question.
|
||||
If wrong, automatically ingests into user's SRS active vocabulary with status 'learning'.
|
||||
"""
|
||||
with get_db() as conn:
|
||||
result = process_cefr_answer(conn, user["id"], req.question_id, req.selected_option)
|
||||
if "error" in result:
|
||||
raise HTTPException(status_code=404, detail=result["error"])
|
||||
return result
|
||||
|
||||
|
||||
@router.post("/api/cefr/reset")
|
||||
async def api_cefr_reset(
|
||||
req: CefrResetRequest,
|
||||
user: dict = Depends(require_user),
|
||||
):
|
||||
"""
|
||||
Resets user testing progress for a given CEFR level.
|
||||
"""
|
||||
with get_db() as conn:
|
||||
deleted = reset_user_cefr_level(conn, user["id"], req.level)
|
||||
return {"status": "ok", "level": req.level.upper(), "reset_count": deleted}
|
||||
|
||||
|
||||
@router.post("/api/cefr/add-word")
|
||||
async def api_cefr_add_word(
|
||||
req: CefrAddWordRequest,
|
||||
user: dict = Depends(require_user),
|
||||
):
|
||||
"""
|
||||
Adds a word from a CEFR test options list directly into user's SRS active vocabulary.
|
||||
"""
|
||||
with get_db() as conn:
|
||||
return ingest_cefr_word(conn, user["id"], req.level, req.term, req.context_sentence)
|
||||
Reference in New Issue
Block a user