Initial commit: secondary school grade archive system.
Add FastAPI/React app with Docker deployment, Ubuntu one-click install, and docs for junior/senior high score tracking and mistake bank. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
|
||||
from app.core.config import settings
|
||||
from app.models.user import ExamRecord, Subject, SubjectScore
|
||||
from app.schemas import ExamTypeEnum, TrendPoint, TrendResponse
|
||||
|
||||
|
||||
def build_trend(db: Session, student_id, subject_id: int) -> TrendResponse:
|
||||
subject = db.get(Subject, subject_id)
|
||||
if subject is None:
|
||||
raise ValueError("科目不存在")
|
||||
|
||||
scores = (
|
||||
db.query(SubjectScore)
|
||||
.join(ExamRecord)
|
||||
.options(joinedload(SubjectScore.exam_record))
|
||||
.filter(
|
||||
ExamRecord.student_id == student_id,
|
||||
SubjectScore.subject_id == subject_id,
|
||||
)
|
||||
.order_by(ExamRecord.exam_date.asc(), ExamRecord.created_at.asc())
|
||||
.all()
|
||||
)
|
||||
|
||||
threshold = settings.FLUCTUATION_THRESHOLD
|
||||
points: list[TrendPoint] = []
|
||||
prev_ratio: float | None = None
|
||||
|
||||
for score in scores:
|
||||
exam = score.exam_record
|
||||
ratio = float(score.ratio)
|
||||
delta = None if prev_ratio is None else ratio - prev_ratio
|
||||
direction = None
|
||||
is_volatile = False
|
||||
|
||||
if delta is not None:
|
||||
if delta > 0:
|
||||
direction = "up"
|
||||
elif delta < 0:
|
||||
direction = "down"
|
||||
else:
|
||||
direction = "flat"
|
||||
is_volatile = abs(delta) >= threshold
|
||||
|
||||
points.append(
|
||||
TrendPoint(
|
||||
exam_id=exam.id,
|
||||
exam_type=ExamTypeEnum(exam.exam_type.value),
|
||||
exam_date=exam.exam_date,
|
||||
title=exam.title,
|
||||
ratio=ratio,
|
||||
ratio_percent=round(ratio * 100, 2),
|
||||
delta=delta,
|
||||
delta_percent=round(delta * 100, 2) if delta is not None else None,
|
||||
is_volatile=is_volatile,
|
||||
direction=direction,
|
||||
)
|
||||
)
|
||||
prev_ratio = ratio
|
||||
|
||||
return TrendResponse(
|
||||
subject_id=subject_id,
|
||||
subject_name=subject.name,
|
||||
threshold=threshold,
|
||||
points=points,
|
||||
)
|
||||
Reference in New Issue
Block a user