import channels.layers from asgiref.sync import async_to_sync from django.db import models from django.conf import settings from django.utils.translation import gettext_lazy as _ from university.db.fields import JSONField class UserOnlineExam(models.Model): STATUS_REGISTE_WAIT_CONFIRM = -1 STATUS_REGISTERED = 0 STATUS_WAIT = 1 STATUS_UNDERWAY = 2 STATUS_FINISHED = 3 STATUS_NOT_JOIN = 4 STATUS_CHOICES = ( (STATUS_REGISTE_WAIT_CONFIRM, _('registration wait to cofirm')), (STATUS_REGISTERED, _('registered')), (STATUS_WAIT, _('wait to join')), (STATUS_UNDERWAY, _('underway')), (STATUS_FINISHED, _('finished')), (STATUS_NOT_JOIN, _('not join')) ) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING) online_exam = models.ForeignKey( 'university.OnlineExam', on_delete=models.CASCADE) examinee_name = models.CharField(max_length=64, blank=True, null=True) examinee_chinese_id = models.CharField(max_length=64, blank=True, null=True) start_at = models.DateTimeField(blank=True, null=True) end_at = models.DateTimeField(blank=True, null=True) score = models.IntegerField(blank=True, null=True) passed = models.BooleanField(blank=True, null=True) status = models.SmallIntegerField(choices=STATUS_CHOICES, default=STATUS_REGISTE_WAIT_CONFIRM) draft = JSONField(default={}) answers = JSONField(default={}) is_force_submitted = models.BooleanField(default=False) force_submit_reason = models.CharField(max_length=64, blank=True, null=True) identity_face = models.ForeignKey( 'university.UserOnlineExamFace', blank=True, null=True, on_delete=models.PROTECT) face_identity_num = models.IntegerField(default=0) face_identity_passed = models.BooleanField(default=False) face_identity_at = models.DateTimeField(blank=True, null=True) cheating_record = JSONField(default={}) cert = models.ForeignKey( 'university.Upload', on_delete=models.PROTECT, blank=True, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = 'user_online_exams' unique_together = ('user', 'online_exam') def send_warning_ws_message(self, comment): ws_message = { 'type': 'forward_event', 'event': 'warning_message', 'data': { 'message': comment } } self.send_ws_message_to_client(ws_message, comment) def send_admin_force_submit_ws_message(self, comment): ws_message = { 'type': 'forward_event', 'event': 'force_submit', 'data': { 'message': comment } } self.send_ws_message_to_client(ws_message, comment) def send_identity_failed_complete_information_ws_message(self, comment='实人认证未通过,需要补全信息'): ws_message = { 'type': 'forward_event', 'event': 'identity_failed_complete_information', 'data': { 'name': self.user.exam_real_name, 'chinese_id_number': self.user.exam_chinese_id_number } } self.send_ws_message_to_client(ws_message, comment) def send_ws_message_to_client(self, ws_message, comment): from university.models import UserOnlineExamMessage event_message = UserOnlineExamMessage.objects.create( user=self.user, online_exam=self.online_exam, user_online_exam=self, content=ws_message, comment=comment ) ws_message['sequence_id'] = event_message.id group_name = 'online_exam-{}-{}'.format(self.user_id, self.online_exam_id) channel_layer = channels.layers.get_channel_layer() async_to_sync(channel_layer.group_send)(group_name, ws_message) class UserOnlineExamFace(models.Model): FACE_TYPE_IDENTITY = 0 FACE_TYPE_CAPTURE = 1 STATUS_PENDING = 0 STATUS_PASSED = 1 STATUS_FAILED = 2 STATUS_CHOICES = ( (STATUS_PENDING, _('pending')), (STATUS_PASSED, _('passed')), (STATUS_FAILED, _('failed')) ) user_online_exam = models.ForeignKey( 'university.UserOnlineExam', on_delete=models.CASCADE) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING) online_exam = models.ForeignKey( 'university.OnlineExam', on_delete=models.CASCADE) face = models.ForeignKey( 'university.Upload', on_delete=models.PROTECT) face_type = models.SmallIntegerField( choices=( (FACE_TYPE_IDENTITY, _('identity')), (FACE_TYPE_CAPTURE, _('capture')) ), default=FACE_TYPE_CAPTURE) status = models.SmallIntegerField( choices=STATUS_CHOICES, default=STATUS_PENDING) comment = models.CharField(max_length=128, default='') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = 'user_online_exam_face' class UserOnlineExamMessage(models.Model): user_online_exam = models.ForeignKey( 'university.UserOnlineExam', on_delete=models.CASCADE) user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING) online_exam = models.ForeignKey( 'university.OnlineExam', on_delete=models.CASCADE) content = JSONField(default={}) ack = models.BooleanField(default=False) comment = models.CharField(max_length=128, default='') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = 'user_online_exam_messages'