diff options
Diffstat (limited to 'yaksh/models.py')
-rw-r--r-- | yaksh/models.py | 144 |
1 files changed, 131 insertions, 13 deletions
diff --git a/yaksh/models.py b/yaksh/models.py index 480a111..6881b4f 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -6,7 +6,8 @@ import ruamel.yaml from ruamel.yaml.scalarstring import PreservedScalarString from ruamel.yaml.comments import CommentedMap from random import sample -from collections import Counter +from collections import Counter, defaultdict + from django.db import models from django.contrib.auth.models import User, Group, Permission from django.contrib.contenttypes.models import ContentType @@ -80,6 +81,17 @@ string_check_type = ( ("exact", "Case Sensitive"), ) +legend_display_types = { + "mcq": {"label": "Objective Type"}, + "mcc": {"label": "Objective Type"}, + "code": {"label": "Programming"}, + "upload": {"label": "Upload"}, + "integer": {"label": "Objective Type"}, + "string": {"label": "Objective Type"}, + "float": {"label": "Objective Type"}, + "arrange": {"label": "Objective Type"}, + } + attempts = [(i, i) for i in range(1, 6)] attempts.append((-1, 'Infinite')) @@ -286,7 +298,7 @@ class Lesson(models.Model): if os.path.exists(file_path): os.remove(file_path) - def _add_lesson_to_zip(self, module, course, zip_file, path): + def _add_lesson_to_zip(self, next_unit, module, course, zip_file, path): lesson_name = self.name.replace(" ", "_") course_name = course.name.replace(" ", "_") module_name = module.name.replace(" ", "_") @@ -304,10 +316,11 @@ class Lesson(models.Model): lesson_file.file.name))) zip_file.writestr(filename, lesson_file.file.read()) unit_file_path = os.sep.join(( - path, "templates", "yaksh", "unit.html" + path, "templates", "yaksh", "download_course_templates", "unit.html" )) lesson_data = {"course": course, "module": module, - "lesson": self, "lesson_files": lesson_files} + "lesson": self, "next_unit": next_unit, + "lesson_files": lesson_files} write_templates_to_zip(zip_file, unit_file_path, lesson_data, lesson_name, sub_folder_name) @@ -527,6 +540,18 @@ class Quiz(models.Model): status = "not attempted" return status + def get_answerpaper_passing_status(self, user, course): + try: + qp = self.questionpaper_set.get().id + except QuestionPaper.DoesNotExist: + qp = None + ans_ppr = AnswerPaper.objects.filter( + user=user, course=course, question_paper=qp + ).order_by("-attempt_number") + if ans_ppr.exists(): + return any([paper.passed for paper in ans_ppr]) + return False + def _create_quiz_copy(self, user): question_papers = self.questionpaper_set.all() new_quiz = self @@ -543,6 +568,22 @@ class Quiz(models.Model): return '%s: on %s for %d minutes' % (desc, self.start_date_time, self.duration) + def _add_quiz_to_zip(self, next_unit, module, course, zip_file, path): + quiz_name = self.description.replace(" ", "_") + course_name = course.name.replace(" ", "_") + module_name = module.name.replace(" ", "_") + sub_folder_name = os.sep.join(( + course_name, module_name, quiz_name + )) + unit_file_path = os.sep.join(( + path, "templates", "yaksh", "download_course_templates", "quiz.html" + )) + quiz_data = {"course": course, "module": module, + "quiz": self, "next_unit": next_unit} + + write_templates_to_zip(zip_file, unit_file_path, quiz_data, + quiz_name, sub_folder_name) + ########################################################################## class LearningUnit(models.Model): @@ -553,6 +594,9 @@ class LearningUnit(models.Model): quiz = models.ForeignKey(Quiz, null=True, blank=True) check_prerequisite = models.BooleanField(default=True) + def get_lesson_or_quiz(self): + return self.lesson if self.lesson else self.quiz + def toggle_check_prerequisite(self): if self.check_prerequisite: self.check_prerequisite = False @@ -574,7 +618,7 @@ class LearningUnit(models.Model): def has_prerequisite(self): return self.check_prerequisite - def is_prerequisite_passed(self, user, learning_module, course): + def is_prerequisite_complete(self, user, learning_module, course): ordered_units = learning_module.learning_unit.order_by("order") ordered_units_ids = list(ordered_units.values_list("id", flat=True)) current_unit_index = ordered_units_ids.index(self.id) @@ -612,6 +656,7 @@ class LearningModule(models.Model): order = models.IntegerField(default=0) creator = models.ForeignKey(User, related_name="module_creator") check_prerequisite = models.BooleanField(default=True) + check_prerequisite_passes = models.BooleanField(default=False) html_data = models.TextField(null=True, blank=True) active = models.BooleanField(default=True) is_trial = models.BooleanField(default=False) @@ -641,6 +686,9 @@ class LearningModule(models.Model): def toggle_check_prerequisite(self): self.check_prerequisite = not self.check_prerequisite + def toggle_check_prerequisite_passes(self): + self.check_prerequisite_passes = not self.check_prerequisite_passes + def get_next_unit(self, current_unit_id): ordered_units = self.learning_unit.order_by("order") ordered_units_ids = list(ordered_units.values_list("id", flat=True)) @@ -668,7 +716,7 @@ class LearningModule(models.Model): default_status = "inprogress" return default_status - def is_prerequisite_passed(self, user, course): + def is_prerequisite_complete(self, user, course): """ Check if prerequisite module is completed """ ordered_modules = course.learning_module.order_by("order") ordered_modules_ids = list(ordered_modules.values_list( @@ -686,6 +734,35 @@ class LearningModule(models.Model): success = False return success + def get_passing_status(self, user, course): + course_status = CourseStatus.objects.filter(user=user, course=course) + if course_status.exists(): + learning_units_with_quiz = self.learning_unit.filter(type='quiz') + ordered_units = learning_units_with_quiz.order_by("order") + + statuses = [ + unit.quiz.get_answerpaper_passing_status(user, course) + for unit in ordered_units + ] + + if not statuses: + status = False + else: + status = all(statuses) + return status + + def is_prerequisite_passed(self, user, course): + """ Check if prerequisite module is passed """ + ordered_modules = course.learning_module.order_by("order") + if ordered_modules.first() == self: + return True + else: + if self.order == 0: + return True + prev_module = ordered_modules.get(order=self.order-1) + status = prev_module.get_passing_status(user, course) + return status + def has_prerequisite(self): return self.check_prerequisite @@ -717,12 +794,27 @@ class LearningModule(models.Model): course_name = course.name.replace(" ", "_") folder_name = os.sep.join((course_name, module_name)) lessons = self.get_lesson_units() - for lesson in lessons: - lesson._add_lesson_to_zip(self, course, zip_file, path) + + units = self.get_learning_units() + for idx, unit in enumerate(units): + next_unit = units[(idx + 1) % len(units)] + if unit.type == 'lesson': + unit.lesson._add_lesson_to_zip(next_unit, + self, + course, + zip_file, + path) + else: + unit.quiz._add_quiz_to_zip(next_unit, + self, + course, + zip_file, + path) + module_file_path = os.sep.join(( - path, "templates", "yaksh", "module.html" + path, "templates", "yaksh", "download_course_templates", "module.html" )) - module_data = {"course": course, "module": self, "lessons": lessons} + module_data = {"course": course, "module": self, "units": units} write_templates_to_zip(zip_file, module_file_path, module_data, module_name, folder_name) @@ -746,6 +838,7 @@ class Course(models.Model): teachers = models.ManyToManyField(User, related_name='teachers') is_trial = models.BooleanField(default=False) instructions = models.TextField(default=None, null=True, blank=True) + view_grade = models.BooleanField(default=False) learning_module = models.ManyToManyField(LearningModule, related_name='learning_module') @@ -986,7 +1079,12 @@ class Course(models.Model): with zipfile.ZipFile(zip_file_name, "a") as zip_file: course_name = self.name.replace(" ", "_") modules = self.get_learning_modules() - file_path = os.sep.join((path, "templates", "yaksh", "index.html")) + file_path = os.sep.join( + ( + path, "templates", "yaksh", + "download_course_templates", "index.html" + ) + ) write_static_files_to_zip(zip_file, course_name, path, static_files) course_data = {"course": self, "modules": modules} @@ -1090,18 +1188,23 @@ class Profile(models.Model): def get_user_dir(self): """Return the output directory for the user.""" - user_dir = join(settings.OUTPUT_DIR, str(self.user.username)) + user_dir = join(settings.OUTPUT_DIR, str(self.user.id)) if not exists(user_dir): os.makedirs(user_dir) os.chmod(user_dir, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) return user_dir + def get_moderated_courses(self): + return Course.objects.filter(teachers=self.user) + def _toggle_moderator_group(self, group_name): group = Group.objects.get(name=group_name) if self.is_moderator: self.user.groups.add(group) else: self.user.groups.remove(group) + for course in self.get_moderated_courses(): + course.remove_teachers(self.user) def save(self, *args, **kwargs): if self.pk is not None: @@ -1391,6 +1494,9 @@ class FileUpload(models.Model): self.hide = True self.save() + def get_filename(self): + return os.path.basename(self.file.name) + ############################################################################### class Answer(models.Model): @@ -1583,7 +1689,9 @@ class QuestionPaper(models.Model): attempts = AnswerPaper.objects.get_total_attempt(questionpaper=self, user=user, course_id=course_id) - return attempts != self.quiz.attempts_allowed + attempts_allowed = attempts < self.quiz.attempts_allowed + infinite_attempts = self.quiz.attempts_allowed == -1 + return attempts_allowed or infinite_attempts def can_attempt_now(self, user, course_id): if self._is_attempt_allowed(user, course_id): @@ -2086,6 +2194,16 @@ class AnswerPaper(models.Model): def get_previous_answers(self, question): return self.answers.filter(question=question).order_by('-id') + def get_categorized_question_indices(self): + category_question_map = defaultdict(list) + for index, question in enumerate(self.get_all_ordered_questions(), 1): + question_category = legend_display_types.get(question.type) + if question_category: + category_question_map[ + question_category["label"] + ].append(index) + return dict(category_question_map) + def validate_answer(self, user_answer, question, json_data=None, uid=None, server_port=SERVER_POOL_PORT): """ |