You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
6.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
点名相关API路由
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from datetime import datetime
from backend.database import get_db
from backend.models import Student, RollCallRecord, ScoreRecord
from backend.schemas import (
RollCallRequest, RollCallResult, RollCallRecordCreate,
RollCallRecordResponse
)
from backend.utils.probability import get_random_student, get_next_order_student
from backend.utils.events import trigger_random_event
from typing import Optional, List
router = APIRouter(prefix="/api/rollcall", tags=["rollcall"])
# 存储当前顺序点名的学生ID简单实现生产环境应使用Redis等
current_order_student_id: Optional[int] = None
@router.post("/start", response_model=RollCallResult)
def start_rollcall(request: RollCallRequest, db: Session = Depends(get_db)):
"""开始点名"""
global current_order_student_id
try:
if request.rollcall_type == "random":
# 随机点名
student = get_random_student(db)
student.random_rollcall_count += 1
elif request.rollcall_type == "order":
# 顺序点名
student = get_next_order_student(db, current_order_student_id)
current_order_student_id = student.id
student.order_rollcall_count += 1
else:
raise HTTPException(status_code=400, detail="无效的点名类型")
db.commit()
return RollCallResult(
student_id=student.id,
student_code=student.student_id,
name=student.name,
major=student.major,
total_score=student.total_score,
random_rollcall_count=student.random_rollcall_count
)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail=f"点名失败: {str(e)}")
@router.post("/record", response_model=RollCallRecordResponse)
def record_rollcall(record: RollCallRecordCreate, db: Session = Depends(get_db)):
"""记录点名结果并更新积分"""
student = db.query(Student).filter(Student.id == record.student_id).first()
if not student:
raise HTTPException(status_code=404, detail="学生不存在")
# 触发随机事件
event = trigger_random_event()
event_multiplier = event["multiplier"]
# 计算积分变化
attendance_score = 1.0 if record.is_present else 0.0
question_repeat_score = record.question_repeat_score # -1, 0, 0.5
answer_score: float = record.answer_score # 0-3
# 应用事件倍数
total_score_change = (
(attendance_score + question_repeat_score + answer_score) * event_multiplier
)
# 更新学生积分
student.total_score += total_score_change
# 检查转移权(被点名两次后获得一次转移权)
total_rollcall_count = student.random_rollcall_count + student.order_rollcall_count
if total_rollcall_count % 2 == 0 and total_rollcall_count > 0:
student.transfer_right_count += 1
# 创建点名记录
rollcall_record = RollCallRecord(
student_id=record.student_id,
rollcall_type=record.rollcall_type,
is_present=record.is_present,
question_repeat_score=question_repeat_score,
answer_score=answer_score,
attendance_score=attendance_score,
total_score_change=total_score_change,
event_type=event["type"]
)
db.add(rollcall_record)
# 创建积分记录
score_record = ScoreRecord(
student_id=record.student_id,
score_change=total_score_change,
reason=f"点名记录: {event['name']}"
)
db.add(score_record)
db.commit()
db.refresh(rollcall_record)
tmp = RollCallRecordResponse(
id=rollcall_record.id,
student_id=student.id,
student_code=student.student_id,
student_name=student.name,
rollcall_type=rollcall_record.rollcall_type,
is_present=rollcall_record.is_present,
total_score_change=rollcall_record.total_score_change,
created_at=rollcall_record.created_at
)
print(tmp.model_dump_json())
return RollCallRecordResponse(
id=rollcall_record.id,
student_id=student.id,
student_code=student.student_id,
student_name=student.name,
rollcall_type=rollcall_record.rollcall_type,
is_present=rollcall_record.is_present,
total_score_change=rollcall_record.total_score_change,
created_at=rollcall_record.created_at
)
@router.get("/records", response_model=List[RollCallRecordResponse])
def get_rollcall_records(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
"""获取点名记录列表"""
records = (
db.query(RollCallRecord)
.join(Student)
.offset(skip)
.limit(limit)
.order_by(RollCallRecord.created_at.desc())
.all()
)
result = []
for record in records:
result.append(RollCallRecordResponse(
id=record.id,
student_id=record.student_id,
student_code=record.student.student_id,
student_name=record.student.name,
rollcall_type=record.rollcall_type,
is_present=record.is_present,
total_score_change=record.total_score_change,
created_at=record.created_at
))
return result
@router.post("/transfer")
def transfer_rollcall(request_data: dict, db: Session = Depends(get_db)):
"""转移点名(使用转移权)"""
from_student_id = request_data.get("from_student_id")
to_student_id = request_data.get("to_student_id")
if not from_student_id or not to_student_id:
raise HTTPException(status_code=400, detail="缺少必要参数")
from_student = db.query(Student).filter(Student.id == from_student_id).first()
to_student = db.query(Student).filter(Student.id == to_student_id).first()
if not from_student or not to_student:
raise HTTPException(status_code=404, detail="学生不存在")
if from_student.transfer_right_count <= 0:
raise HTTPException(status_code=400, detail="没有可用的转移权")
# 使用转移权
from_student.transfer_right_count -= 1
db.commit()
return {
"message": "转移成功",
"from_student": from_student.name,
"to_student": to_student.name,
"remaining_transfer_rights": from_student.transfer_right_count
}