71 lines
2.1 KiB
Python
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"],
|
|
),
|
|
)
|