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.
61 lines
2.0 KiB
61 lines
2.0 KiB
import random
|
|
import pandas as pd
|
|
from io import BytesIO
|
|
|
|
|
|
class ProbabilityCalculator:
|
|
@staticmethod
|
|
def weighted_random_selection(students):
|
|
if not students:
|
|
raise ValueError("学生列表不能为空")
|
|
|
|
base_weight = 100
|
|
decay_factor = 8 # 积分越高,权重越低
|
|
weights = []
|
|
for student in students:
|
|
score_deduction = min(student.total_score * decay_factor, 85)
|
|
weight = max(base_weight - score_deduction, 15)
|
|
weights.append({'student': student, 'weight': weight})
|
|
|
|
total_weight = sum(item['weight'] for item in weights)
|
|
random_value = random.uniform(0, total_weight)
|
|
current_sum = 0
|
|
for item in weights:
|
|
current_sum += item['weight']
|
|
if current_sum >= random_value:
|
|
return item['student']
|
|
return weights[0]['student']
|
|
|
|
|
|
class ScoreCalculator:
|
|
@staticmethod
|
|
def calculate_score(answer_type, performance):
|
|
score_map = {
|
|
'repeat_question': {'correct': 0.5, 'incorrect': -1},
|
|
'answer_question': {'excellent': 3, 'good': 2, 'normal': 1, 'poor': 0.5},
|
|
'present': {'present': 1}
|
|
}
|
|
return score_map.get(answer_type, {}).get(performance, 0)
|
|
|
|
|
|
class ExcelService:
|
|
|
|
# 导出详单(含专业、点名次数)
|
|
@staticmethod
|
|
def export_detailed_scores(students):
|
|
data = []
|
|
for student in students:
|
|
data.append({
|
|
'学号': student.student_id,
|
|
'姓名': student.name,
|
|
'专业': student.major,
|
|
'班级': student.class_name,
|
|
'随机点名次数': student.call_count,
|
|
'总积分': student.total_score
|
|
})
|
|
df = pd.DataFrame(data)
|
|
output = BytesIO()
|
|
with pd.ExcelWriter(output, engine='openpyxl') as writer:
|
|
df.to_excel(writer, sheet_name='积分详单', index=False)
|
|
output.seek(0)
|
|
return output |