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