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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)()