""" 概率计算工具 根据积分计算随机点名概率 积分越高,被点到的概率越低 """ 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