From d34f7f8caa949ab2a2c293e5702659536f6a9c3f Mon Sep 17 00:00:00 2001
From: xx_mmc <2985005738@qq.com>
Date: Mon, 30 Sep 2024 22:52:54 +0800
Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 back_end/server.py | 201 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 201 insertions(+)
 create mode 100644 back_end/server.py

diff --git a/back_end/server.py b/back_end/server.py
new file mode 100644
index 0000000..8577d76
--- /dev/null
+++ b/back_end/server.py
@@ -0,0 +1,201 @@
+from fastapi import FastAPI, HTTPException
+from pydantic import BaseModel
+from fastapi.middleware.cors import CORSMiddleware
+import random
+import time
+from fastapi import FastAPI, File, UploadFile
+from fastapi.responses import JSONResponse
+import pandas as pd
+# from openpyxl import Workbook, load_workbook
+import math
+import os
+from fastapi import Depends
+
+app = FastAPI()
+
+# CORS 中间件
+app.add_middleware(
+    CORSMiddleware,
+    allow_origins=["*"],  # 允许所有来源
+    allow_credentials=True,
+    allow_methods=["*"],
+    allow_headers=["*"],
+)
+
+# DATA_PATH = os.path.abspath(__file__) + "\\data\\"
+DATA_PATH = "./demo/Data/"
+
+initial_data = {
+    '学号': ['*********'],
+    '姓名': ['BOSS_K'],
+    '积分': [9.9]
+}
+initial_info = {
+    'basicProbability': [1.0],
+    # 'lastRow': [0],
+    'maxPoint': [0.0],
+    'minPoint': [0.0]
+}
+initial_data_df = pd.DataFrame(initial_data)
+initial_info_df = pd.DataFrame(initial_info)
+
+# 定义请求体模型
+class StudentRequest(BaseModel):
+    id: str
+    name: str
+    points: float
+
+# 获取文件路径
+async def get_file_path(class_name: str):
+    file_path = DATA_PATH + class_name + ".xlsx"
+    if not os.path.exists(file_path): 
+        raise HTTPException(status_code=403, detail="Not authenticated")
+    return file_path
+
+
+# 上传excel
+@app.post("/{class_name}/upload")
+async def upload_file(file_path: str = Depends(get_file_path), file: UploadFile = File(...)):
+    # 检查文件类型
+    if not (file.filename.endswith('.xlsx') or file.filename.endswith('.xls')):
+        return JSONResponse(content={"error": "无效的文件类型"}, status_code=400)
+
+    try:
+        # 将 Excel 文件读取为 DataFrame
+        df_data = pd.read_excel(file_path, sheet_name='Data')
+        df_info = pd.read_excel(file_path, sheet_name='Info')
+        df_upload = pd.read_excel(file.file)
+
+        new_rows = []
+
+        # maxPoint = df_info.loc[0, 'maxPoint']
+        # minPoint = df_info.loc[0, 'minPoint']
+
+        for index, row in df_upload.iterrows():
+            id = row['学号']        # 根据列名访问学号
+            name = row['姓名']      # 根据列名访问姓名
+            points = 0.0
+            if '积分' in row:
+                points = row['积分']
+            # maxPoint = math.max(points, maxPoint)
+            # minPoint = math.min(points, minPoint)
+            new_rows.append({'学号': id, '姓名': name, '积分': points})
+
+        df_data = pd.concat([df_data, pd.DataFrame(new_rows)], ignore_index=True)
+
+        # 根据 '积分' 列降序排序
+        df_data = df_data.sort_values(by='积分', ascending=False)
+
+        with pd.ExcelWriter(file_path, mode='a', engine='openpyxl') as writer:
+            del writer.book['Data']  # 删除旧的工作表
+            df_data.to_excel(writer, sheet_name='Data', index=False)
+        
+        
+        df_info.loc[0, 'basicProbability'] = 1.0
+        # df_info.loc[0, 'maxPoint'] = maxPoint
+        # df_info.loc[0, 'minPoint'] = minPoint
+        with pd.ExcelWriter(file_path, mode='a', engine='openpyxl') as writer:
+            del writer.book['Info']  # 删除旧的工作表
+            df_info.to_excel(writer, sheet_name='Info', index=False)
+        
+        return {"message": "文件上传成功"}
+
+    except Exception as e:
+        return JSONResponse(content={"error": str(e)}, status_code=500)
+
+# 创建班级的接口
+@app.get("/create-class/{class_name}")
+async def create_class(class_name: str):
+    # return {"ok":"ok"}
+    file_path = DATA_PATH + class_name + ".xlsx"
+    if os.path.exists(file_path):
+        return {"message": "班级已存在"}
+    
+    # 创建excel
+    initial_data_df.to_excel(file_path, sheet_name='Data', index=False)
+    with pd.ExcelWriter(file_path, mode='a', engine='openpyxl') as writer:
+        initial_info_df.to_excel(writer, sheet_name='Info', index=False)
+
+    return {"message": "班级创建成功"}
+
+# 随机点名的接口
+@app.get("/{class_name}/random-call")
+async def random_call(file_path: str = Depends(get_file_path)):
+    df_data = pd.read_excel(file_path, sheet_name='Data')
+    df_info = pd.read_excel(file_path, sheet_name='Info')
+
+    n = len(df_data)
+    if n <= 0:
+        raise HTTPException(status_code=404, detail="没有学生可供点名")
+    
+    # 进行随机
+    basicProbability = float(df_info.iloc[0]['basicProbability'])
+    # lastRow = int(df_info.iloc[0]['lastRow'])
+    maxPoint = float(df_info.iloc[0]['maxPoint'])
+    minPoint = float(df_info.iloc[0]['minPoint'])
+
+    res = {}
+    basicProbability *= 0.8
+    while (True):
+        # print(basicProbability)
+        # lastRow = (lastRow + 1) % n
+        i = math.floor(random.random() * n)
+        points = df_data.iloc[i]['积分']
+        hit_probability = (maxPoint - points + 1) / (maxPoint - minPoint + 20) * basicProbability
+        if random.random() <= hit_probability: #成功命中倒霉蛋
+            res = {"name": str(df_data.iloc[i]['姓名']), 
+                   "id": str(df_data.iloc[i]['学号']), 
+                   "points": float(points)}
+            break
+        basicProbability *= 1.03
+    
+    # 更新信息
+    df_info.loc[0, 'basicProbability'] = basicProbability
+    # df_info.loc[0, 'lastRow'] = lastRow
+    with pd.ExcelWriter(file_path, mode='a', engine='openpyxl') as writer:
+        del writer.book['Info']  # 删除旧的工作表
+        df_info.to_excel(writer, sheet_name='Info', index=False)
+
+    return res
+
+
+# 修改积分的接口
+@app.post("/{class_name}/change-points")
+async def change_points(student_request: StudentRequest, file_path: str = Depends(get_file_path)):
+
+    df_data = pd.read_excel(file_path, sheet_name='Data')
+    df_info = pd.read_excel(file_path, sheet_name='Info')
+
+    print(df_data)
+    index = -1
+    for i, row in df_data.iterrows():
+        print(row['学号'], student_request.id)
+        print(row['姓名'], student_request.name)
+        if (str(row['学号']) == str(student_request.id) and str(row['姓名']) == str(student_request.name)):
+            index = i
+            break
+
+    if (index < 0):
+        raise HTTPException(status_code=400, detail="学号姓名无效")
+    
+    df_data.loc[index, '积分'] = student_request.points
+    df_data = df_data.sort_values(by='积分', ascending=False)
+    with pd.ExcelWriter(file_path, mode='a', engine='openpyxl') as writer:
+        del writer.book['Data']  # 删除旧的工作表
+        df_data.to_excel(writer, sheet_name='Data', index=False)
+    
+    df_info.loc[0, 'maxPoint'] = max(df_info.loc[0, 'maxPoint'], student_request.points)
+    df_info.loc[0, 'minPoint'] = min(df_info.loc[0, 'minPoint'], student_request.points)
+    with pd.ExcelWriter(file_path, mode='a', engine='openpyxl') as writer:
+        del writer.book['Info']  # 删除旧的工作表
+        df_info.to_excel(writer, sheet_name='Info', index=False)
+
+    return {"message": "积分已修改"}
+
+
+if __name__ == "__main__":
+    import uvicorn
+    import sys
+    random.seed(int(time.time()))
+    # 使用 uvicorn 启动服务器
+    uvicorn.run(app, host="0.0.0.0", port=8000)
\ No newline at end of file