from django.db import models from django.db.models import F from django.utils.translation import gettext_lazy as _ from university.db.fields import JSONField from university.lectures.managers import lecture_manager from university.models.user_lesson_learn_history import UserLessonLearnHistory from university.models.user_quiz import UserQuiz from university.models.quiz import Quiz class Lesson(models.Model): slug = models.SlugField(blank=False, null=False, allow_unicode=True) title = models.CharField(max_length=128) description = models.TextField() # At first release, wo don't need teacher(Model) speaker = models.CharField(max_length=64) sequence = models.SmallIntegerField( default=0, help_text=_('lessons will be orderd by sequence number in list') ) periods = models.FloatField(default=1) chapter = models.ForeignKey('university.Chapter', on_delete=models.PROTECT) cover_image = models.ForeignKey( 'university.Upload', on_delete=models.PROTECT, blank=True, null=True) objectives = models.TextField() key_points = models.CharField(max_length=255, blank=True, null=True) markdown_raw = models.TextField() pdf = models.ForeignKey( 'university.Upload', related_name='pdf', on_delete=models.PROTECT, blank=True, null=True) is_free = models.BooleanField(default=False) types = JSONField(default=[]) class Meta: db_table = 'lessons' def __str__(self): return self.title @property def short_title(self): return '{} - {}.{}'.format( self.chapter.course.slug, self.chapter.sequence, self.sequence) def get_syllabus(self, user): data = {} for tp in self.types: install_lectures = lecture_manager.install_lectures lecture = install_lectures.get(tp) if lecture: data[tp] = lecture.description(self, user) return data def has_quiz(self): try: return bool(self.quiz) except Quiz.DoesNotExist: return False def get_quiz(self, user): # Raise lesson.RelatedObjectDoesNotExist if quiz not exsits is_passed = False questions = self.quiz.questions.values( 'id', 'question_type', 'problem', 'problem', 'options', 'answer') try: user_quiz = user.userquiz_set.get(quiz=self.quiz) is_passed = user_quiz.is_passed for question in questions: if not is_passed: question['answer'] = user_quiz.answer.get(str(question['id']), '') # AnonymousUser -> AttributeError # user_quiz not exists -> UserQuiz.DoesNotExist except (UserQuiz.DoesNotExist, AttributeError): for question in questions: question['answer'] = '' return list(questions), is_passed @classmethod def update_lesson_progress(cls, lesson_id, user_id): try: lesson = cls.objects.get(pk=lesson_id) except cls.DoesNotExist: return lecture_progress = [] for tp in lesson.types: lecture = lecture_manager.install_lectures.get(tp) if lecture: lecture_progress.append(lecture.get_progress(lesson_id, user_id)) lesson_progress = sum(map(lambda p: p / len(lecture_progress), lecture_progress)) lesson_progress = 1 if lesson_progress > 0.98 else lesson_progress history, _ = UserLessonLearnHistory.objects.get_or_create( course=lesson.chapter.course, chapter=lesson.chapter, lesson=lesson, user_id=user_id) UserLessonLearnHistory.objects.filter(pk=history.id).update( progress=lesson_progress if lesson_progress > history.progress else history.progress, total_visited_count=F('total_visited_count') + 1)