nex_math/backend/routers/overview.py

71 lines
2.1 KiB
Python

"""学习总览。"""
from __future__ import annotations
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from database import get_db
from dependencies import require_learning_user
from models import AttemptSession, User
from schemas import KnowledgeOut, MetricItem, OverviewOut, PlanOut
from services.mastery_engine import snapshot, status_for
from services.recommendation import build_plan
router = APIRouter(tags=["overview"])
@router.get("/overview", response_model=OverviewOut)
def get_overview(
db: Session = Depends(get_db),
user: User = Depends(require_learning_user),
):
total_questions = (
db.query(AttemptSession.total)
.filter(AttemptSession.user_id == user.id)
.all()
)
total_answers = sum(row.total for row in total_questions)
total_correct = (
db.query(AttemptSession.correct)
.filter(AttemptSession.user_id == user.id)
.all()
)
correct_answers = sum(row.correct for row in total_correct)
accuracy = correct_answers / total_answers * 100 if total_answers else 0.0
knowledge = snapshot(db, user.id)
weak_count = sum(1 for k in knowledge if k.mastery < 60)
metrics = [
MetricItem(label="累计题目", value=str(total_answers)),
MetricItem(
label="累计正确率",
value=f"{accuracy:.1f}%" if total_answers else "0%",
),
MetricItem(label="薄弱知识点", value=str(weak_count)),
MetricItem(label="当前阶段", value="L2 基础应用"),
]
plan = build_plan(db, user.id)
return OverviewOut(
metrics=metrics,
knowledge=[
KnowledgeOut(
id=k.id,
knowledge_id=k.knowledge_id,
name=k.name,
mastery=k.mastery,
position=k.position,
status=status_for(k.mastery),
domain=k.domain,
category=k.category,
)
for k in knowledge
],
plan=PlanOut(
notice=plan["notice"],
focus_names=plan["focus_names"],
steps=plan["steps"],
),
)