|
|
|
|
@ -356,3 +356,75 @@ def score_student():
|
|
|
|
|
"random_called_count": student.random_called_count,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@main_bp.route("/api/stats/top_students_timeline")
|
|
|
|
|
@login_required
|
|
|
|
|
def top_students_timeline():
|
|
|
|
|
# 选取当前账号积分前5名学生
|
|
|
|
|
top_students = (
|
|
|
|
|
Student.query.filter_by(user_id=current_user.id)
|
|
|
|
|
.order_by(
|
|
|
|
|
Student.total_score.desc(),
|
|
|
|
|
Student.attendance_count.desc(),
|
|
|
|
|
Student.student_no.asc(),
|
|
|
|
|
)
|
|
|
|
|
.limit(5)
|
|
|
|
|
.all()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if not top_students:
|
|
|
|
|
return jsonify({"labels": [], "series": []})
|
|
|
|
|
|
|
|
|
|
student_ids = [s.id for s in top_students]
|
|
|
|
|
|
|
|
|
|
# 取这些学生的所有点名记录,按时间排序
|
|
|
|
|
records = (
|
|
|
|
|
RollCall.query.filter(
|
|
|
|
|
RollCall.user_id == current_user.id,
|
|
|
|
|
RollCall.student_id.in_(student_ids),
|
|
|
|
|
)
|
|
|
|
|
.order_by(RollCall.call_time.asc())
|
|
|
|
|
.all()
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if not records:
|
|
|
|
|
return jsonify({"labels": [], "series": []})
|
|
|
|
|
|
|
|
|
|
# 构造全局时间轴(去重后的时间点)
|
|
|
|
|
time_points = []
|
|
|
|
|
for rc in records:
|
|
|
|
|
local_time = utc_to_local(rc.call_time)
|
|
|
|
|
label = local_time.strftime("%m-%d %H:%M")
|
|
|
|
|
if label not in time_points:
|
|
|
|
|
time_points.append(label)
|
|
|
|
|
|
|
|
|
|
# 为每个学生按时间累积分数
|
|
|
|
|
series = []
|
|
|
|
|
for s in top_students:
|
|
|
|
|
cumulative = 0.0
|
|
|
|
|
# 取该学生记录
|
|
|
|
|
s_records = [rc for rc in records if rc.student_id == s.id]
|
|
|
|
|
idx = 0
|
|
|
|
|
points = []
|
|
|
|
|
for label in time_points:
|
|
|
|
|
# 把该时间点及之前所有还未计入的记录加入累计
|
|
|
|
|
while idx < len(s_records):
|
|
|
|
|
rc = s_records[idx]
|
|
|
|
|
local_time = utc_to_local(rc.call_time)
|
|
|
|
|
rc_label = local_time.strftime("%m-%d %H:%M")
|
|
|
|
|
if rc_label <= label:
|
|
|
|
|
cumulative += rc.score_change
|
|
|
|
|
idx += 1
|
|
|
|
|
else:
|
|
|
|
|
break
|
|
|
|
|
points.append(round(cumulative, 2))
|
|
|
|
|
|
|
|
|
|
series.append(
|
|
|
|
|
{
|
|
|
|
|
"name": f"{s.name}({s.student_no})",
|
|
|
|
|
"data": points,
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return jsonify({"labels": time_points, "series": series})
|
|
|
|
|
|