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.

120 lines
4.1 KiB

1 month ago
from channels.generic.websocket import AsyncWebsocketConsumer
import json
import random
from asgiref.sync import sync_to_async
from .models import Students
class ClassroomConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.teacher_group = 'teacher_group'
self.student_group = 'student_group'
await self.channel_layer.group_add(self.teacher_group, self.channel_name)
await self.channel_layer.group_add(self.student_group, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard(self.teacher_group, self.channel_name)
await self.channel_layer.group_discard(self.student_group, self.channel_name)
async def receive(self, text_data):
data = json.loads(text_data)
if data['action'] == 'pick_student':
selected_student = await self.pick_student()
await self.send_student_message(selected_student)
elif data['action'] == 'use_exemption_card':
# 处理学生使用豁免卡的信息
student_id = data['studentId']
new_score = data['newScore']
# 更新学生积分等逻辑,假设在数据库中保存
await self.update_student_score(student_id, new_score)
# 将豁免卡信息发送给教师组
await self.channel_layer.group_send(
self.teacher_group,
{
'type': 'exemption_card_used',
'student_id': student_id,
'student_name': data['studentName'],
'new_score': new_score,
}
)
# 处理教师端收到豁免卡使用信息
async def exemption_card_used(self, event):
student_id = event['student_id']
student_name = event['student_name']
new_score = event['new_score']
# 在教师端显示学生使用豁免卡的信息
await self.send(text_data=json.dumps({
'action': 'exemption_card_used',
'student_id': student_id,
'student_name': student_name,
'new_score': new_score,
}))
async def send_student_message(self, student):
if student is None:
return # 如果没有选中学生,直接返回
message = {
'name': student.name,
'student_id': student.sid,
}
# 将点名结果发送到学生组
await self.channel_layer.group_send(
self.student_group,
{
'type': 'student_message',
'message': message,
}
)
# 接收到点名结果后发送给学生端
async def student_message(self, event):
message = event['message']
await self.send(text_data=json.dumps({
'action': 'student_picked',
'name': message['name'],
'student_id': message['student_id'],
}))
async def pick_student(self):
# 使用 sync_to_async 获取学生列表
students = await sync_to_async(list)(Students.objects.all())
if not students:
return None
# 计算权重
weights = []
for student in students:
score = float(student.score)
if score < 0:
weights.append(-score) # 负分数,绝对值越大权重越大
elif score == 0:
weights.append(0.2) # 分数为0设置为一个中等权重
else:
weights.append(1 / (score + 10)) # 正分数,分数越大权重越小
# 防止所有权重为0的情况
if sum(weights) == 0:
return random.choice(students) # 如果所有权重为0随机选一个学生
# 根据权重选择学生
chosen_student = random.choices(students, weights=weights, k=1)[0]
return chosen_student
async def update_student_score(self, student_id, new_score):
# 使用 Django ORM 更新学生积分
student = await sync_to_async(Students.objects.get)(sid=student_id)
student.score = new_score
await sync_to_async(student.save)()