from rest_framework import serializers from apps.course.access import user_has_course_access from apps.quiz.models import QuizParticipant, ParticipantAnswer class ParticipantAnswerSerializer(serializers.ModelSerializer): class Meta: model = ParticipantAnswer fields = ['question', 'option_num', 'at_time', 'answer_timing'] class QuizParticipantSerializer(serializers.ModelSerializer): user = serializers.HiddenField(default=serializers.CurrentUserDefault()) answers = ParticipantAnswerSerializer(many=True) def validate_quiz(self, obj): if QuizParticipant.objects.filter(quiz=obj, user=self.context['request'].user).exists(): raise serializers.ValidationError('you have already participated in the quiz') course = getattr(obj, 'course', None) if course and not user_has_course_access(self.context['request'].user, course): raise serializers.ValidationError('you do not have access to this quiz') return obj class Meta: model = QuizParticipant fields = [ 'quiz', 'user', 'started_at', 'ended_at', 'total_timing', 'question_score', 'timing_score', 'total_score', 'answers', ] def create(self, validated_data): answers = validated_data.pop('answers', []) quiz = validated_data.get('quiz') total_questions = quiz.questions.count() correct_count = 0 questions_map = {q.id: q.correct_answer for q in quiz.questions.all()} for ans in answers: # Depending on if ans['question'] is an instance or ID q_id = ans.get('question').id if hasattr(ans.get('question'), 'id') else ans.get('question') option_num = ans.get('option_num') if q_id in questions_map and questions_map[q_id] == option_num: correct_count += 1 question_score = round((correct_count / total_questions) * 100) if total_questions > 0 else 0 validated_data['question_score'] = question_score validated_data['timing_score'] = 0 validated_data['total_score'] = question_score obj = super().create(validated_data) answers_objs = [] for ans in answers: answers_objs.append( ParticipantAnswer( participant=obj, **ans, ) ) ParticipantAnswer.objects.bulk_create(answers_objs) return obj