|
|
|
|
from fastapi import FastAPI, File, UploadFile, HTTPException, Body
|
|
|
|
|
from fastapi.responses import HTMLResponse
|
|
|
|
|
from starlette.middleware.cors import CORSMiddleware
|
|
|
|
|
from starlette.staticfiles import StaticFiles
|
|
|
|
|
from typing import Union, Dict, List
|
|
|
|
|
from io import BytesIO
|
|
|
|
|
import pandas as pd
|
|
|
|
|
import random
|
|
|
|
|
|
|
|
|
|
app = FastAPI()
|
|
|
|
|
|
|
|
|
|
# 假设你的静态文件存放在名为 'static' 的文件夹中
|
|
|
|
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
|
|
|
|
|
|
|
|
data: List[Dict[str, Union[str, int]]] = []
|
|
|
|
|
students_scores = {}
|
|
|
|
|
|
|
|
|
|
app.add_middleware(
|
|
|
|
|
CORSMiddleware,
|
|
|
|
|
allow_origins=["*"],
|
|
|
|
|
allow_credentials=True,
|
|
|
|
|
allow_methods=["*"],
|
|
|
|
|
allow_headers=["*"],
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/", response_class=HTMLResponse)
|
|
|
|
|
async def read_root():
|
|
|
|
|
# 返回 stu_roll.html 页面
|
|
|
|
|
with open("stu_roll.html", "r", encoding="utf-8") as f:
|
|
|
|
|
return f.read()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.post("/upload")
|
|
|
|
|
async def list_upload(file: UploadFile = File(...)):
|
|
|
|
|
global data, students_scores
|
|
|
|
|
if file.content_type != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
|
|
|
|
|
return {"message": "错误的文件格式,请重新上传!"}
|
|
|
|
|
file_content = await file.read()
|
|
|
|
|
|
|
|
|
|
# 使用 openpyxl 作为引擎读取 .xlsx 文件
|
|
|
|
|
df = pd.read_excel(BytesIO(file_content), engine='openpyxl')
|
|
|
|
|
|
|
|
|
|
if "学号" not in df.columns or "姓名" not in df.columns:
|
|
|
|
|
return {"message": "文件中缺少学号或姓名列!"}
|
|
|
|
|
data = [{"学号": str(row["学号"]).strip(), "姓名": row["姓名"], "积分": 0, "被点名次数": 0} for row in
|
|
|
|
|
df.to_dict(orient='records')]
|
|
|
|
|
students_scores = {student["学号"]: 0 for student in data}
|
|
|
|
|
print(f"Uploaded students: {students_scores}")
|
|
|
|
|
return {"message": "名单上传成功!", "students": data} # 返回学生数据
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/roll")
|
|
|
|
|
def list_roll(enable_random_events: bool = False):
|
|
|
|
|
if not data:
|
|
|
|
|
return {"message": "还未上传学生名单,暂无任何数据!"}
|
|
|
|
|
total_score = sum(students_scores.values()) # 计算所有学生的总积分
|
|
|
|
|
# 如果总积分为零,给所有学生相同的权重
|
|
|
|
|
if total_score <= 0:
|
|
|
|
|
weights = [1] * len(data) # 所有学生的权重相同
|
|
|
|
|
else:
|
|
|
|
|
# 计算权重
|
|
|
|
|
weights = [total_score - students_scores[student["学号"]] for student in data]
|
|
|
|
|
# 使用权重进行随机选择
|
|
|
|
|
chosen_student = random.choices(data, weights=weights, k=1)[0]
|
|
|
|
|
# 更新被点名次数
|
|
|
|
|
chosen_student["被点名次数"] += 1
|
|
|
|
|
print(f"Chosen student: {chosen_student['姓名']} - 被点名次数: {chosen_student['被点名次数']}")
|
|
|
|
|
# 打印调试信息
|
|
|
|
|
print(f"Chosen student: {chosen_student}")
|
|
|
|
|
# 检查是否有转移权
|
|
|
|
|
if chosen_student["被点名次数"] >= 3:
|
|
|
|
|
chosen_student["被点名次数"] = 0
|
|
|
|
|
return {"学号": chosen_student["学号"], "姓名": chosen_student["姓名"], "转移权": True}
|
|
|
|
|
# 处理随机事件
|
|
|
|
|
if enable_random_events:
|
|
|
|
|
random_event_result = handle_random_events(chosen_student)
|
|
|
|
|
return {"学号": chosen_student["学号"], "姓名": chosen_student["姓名"], "转移权": False,
|
|
|
|
|
"随机事件": random_event_result}
|
|
|
|
|
return {"学号": chosen_student["学号"], "姓名": chosen_student["姓名"], "转移权": False}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/rank")
|
|
|
|
|
def list_rank():
|
|
|
|
|
if not data:
|
|
|
|
|
return {"message": "请先上传学生名单!"}
|
|
|
|
|
sorted_data = sorted(data, key=lambda x: x["积分"], reverse=True)
|
|
|
|
|
return sorted_data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@app.post("/evaluate-answer")
|
|
|
|
|
async def evaluate_answer(
|
|
|
|
|
student_id: str = Body(...),
|
|
|
|
|
is_come: bool = Body(...),
|
|
|
|
|
can_repeat: bool = Body(...),
|
|
|
|
|
answer_correct: str = Body(...)
|
|
|
|
|
):
|
|
|
|
|
global students_scores, data
|
|
|
|
|
score_delta = 0
|
|
|
|
|
print(
|
|
|
|
|
f"Received student_id: {student_id}, is_come: {is_come}, can_repeat: {can_repeat}, answer_correct: {answer_correct}")
|
|
|
|
|
# 检查学生 ID 是否存在
|
|
|
|
|
if student_id not in students_scores:
|
|
|
|
|
print(f"Student ID {student_id} not found in scores.")
|
|
|
|
|
raise HTTPException(status_code=404, detail="Student not found.")
|
|
|
|
|
# 根据回答情况计算积分变化
|
|
|
|
|
if is_come:
|
|
|
|
|
score_delta += 1
|
|
|
|
|
if can_repeat:
|
|
|
|
|
score_delta += 0.5
|
|
|
|
|
else:
|
|
|
|
|
score_delta -= 0.5
|
|
|
|
|
if answer_correct == "完全正确":
|
|
|
|
|
score_delta += 3
|
|
|
|
|
elif answer_correct == "部分正确":
|
|
|
|
|
score_delta += 1.5
|
|
|
|
|
else:
|
|
|
|
|
score_delta -= 1
|
|
|
|
|
# 更新 students_scores 字典
|
|
|
|
|
students_scores[student_id] += score_delta
|
|
|
|
|
# 更新 data 列表中的积分
|
|
|
|
|
for student in data:
|
|
|
|
|
if student["学号"] == student_id:
|
|
|
|
|
student["积分"] += score_delta
|
|
|
|
|
break
|
|
|
|
|
print(f"Score updated for student_id: {student_id}, new score: {students_scores[student_id]}")
|
|
|
|
|
return {"success": True}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def handle_random_events(chosen_student):
|
|
|
|
|
event = random.choice(["mdfucker", "士多啤梨", "吖食啦嘞", "abandon", "疯狂星期四V你50"])
|
|
|
|
|
event_description = ""
|
|
|
|
|
if event == "surprise mdfucker":
|
|
|
|
|
print(f"{chosen_student['姓名']} surprise mdfucker!")
|
|
|
|
|
students_scores[chosen_student["学号"]] += 2
|
|
|
|
|
chosen_student["积分"] += 2
|
|
|
|
|
event_description = "surprise mdfucker"
|
|
|
|
|
elif event == "士多啤梨":
|
|
|
|
|
print(f"{chosen_student['姓名']} 士多啤梨!")
|
|
|
|
|
students_scores[chosen_student["学号"]] += 1
|
|
|
|
|
chosen_student["积分"] += 1
|
|
|
|
|
event_description = "士多啤梨"
|
|
|
|
|
if event == "吖食啦嘞":
|
|
|
|
|
print(f"{chosen_student['姓名']} 吖食啦嘞!")
|
|
|
|
|
students_scores[chosen_student["学号"]] -= 2
|
|
|
|
|
chosen_student["积分"] -= 2
|
|
|
|
|
event_description = "吖食啦嘞"
|
|
|
|
|
if event == "abandon":
|
|
|
|
|
print(f"{chosen_student['姓名']} abandon!")
|
|
|
|
|
students_scores[chosen_student["学号"]] -= 1
|
|
|
|
|
chosen_student["积分"] -= 1
|
|
|
|
|
event_description = "abandon"
|
|
|
|
|
elif event == "疯狂星期四V你50":
|
|
|
|
|
if chosen_student["积分"] % 50 == 0: # 积分是50的因数
|
|
|
|
|
print(f"{chosen_student['姓名']} 疯狂星期四V你50!")
|
|
|
|
|
students_scores[chosen_student["学号"]] += 1.5
|
|
|
|
|
chosen_student["积分"] += 1.5
|
|
|
|
|
event_description = "疯狂星期四V你50"
|
|
|
|
|
return event_description
|