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.
82 lines
2.6 KiB
82 lines
2.6 KiB
"""
|
|
概率计算工具
|
|
根据积分计算随机点名概率
|
|
积分越高,被点到的概率越低
|
|
"""
|
|
import random
|
|
from typing import List, Optional
|
|
from sqlalchemy.orm import Session
|
|
from backend.models import Student
|
|
|
|
def calculate_probability_weights(students: List[Student]) -> List[float]:
|
|
"""
|
|
计算每个学生的权重(积分越低,权重越高)
|
|
|
|
算法:使用反比例函数,权重 = 1 / (积分 + 1)
|
|
这样可以确保:
|
|
1. 积分为0的学生权重最高
|
|
2. 积分越高,权重越低
|
|
3. 所有学生都有被点到的可能
|
|
"""
|
|
weights = []
|
|
for student in students:
|
|
# 使用反比例函数,+1避免除零
|
|
weight = 1.0 / (student.total_score + 1.0)
|
|
weights.append(weight)
|
|
return weights
|
|
|
|
def weighted_random_select(students: List[Student], weights: List[float]) -> Student:
|
|
"""
|
|
根据权重随机选择一个学生
|
|
"""
|
|
if not students:
|
|
raise ValueError("学生列表为空")
|
|
|
|
if len(students) != len(weights):
|
|
raise ValueError("学生列表和权重列表长度不匹配")
|
|
|
|
# 使用random.choices进行加权随机选择
|
|
selected = random.choices(students, weights=weights, k=1)[0]
|
|
return selected
|
|
|
|
def get_random_student(db: Session) -> Student:
|
|
"""
|
|
从数据库中随机选择一个学生(考虑积分权重)
|
|
"""
|
|
students = db.query(Student).all()
|
|
if not students:
|
|
raise ValueError("数据库中没有学生")
|
|
|
|
weights = calculate_probability_weights(students)
|
|
selected = weighted_random_select(students, weights)
|
|
return selected
|
|
|
|
def get_next_order_student(db: Session, current_student_id: Optional[int] = None) -> Student:
|
|
"""
|
|
按学号顺序获取下一个学生
|
|
"""
|
|
if current_student_id is None:
|
|
# 获取第一个学生(按学号排序)
|
|
student = db.query(Student).order_by(Student.student_id).first()
|
|
else:
|
|
# 获取当前学生的下一个学生
|
|
current_student = db.query(Student).filter(Student.id == current_student_id).first()
|
|
if current_student:
|
|
student = (
|
|
db.query(Student)
|
|
.filter(Student.student_id > current_student.student_id)
|
|
.order_by(Student.student_id)
|
|
.first()
|
|
)
|
|
# 如果没有下一个,返回第一个(循环)
|
|
if not student:
|
|
student = db.query(Student).order_by(Student.student_id).first()
|
|
else:
|
|
student = db.query(Student).order_by(Student.student_id).first()
|
|
|
|
if not student:
|
|
raise ValueError("数据库中没有学生")
|
|
|
|
return student
|
|
|