""" 点名相关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 }