summaryrefslogtreecommitdiff
path: root/yaksh/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh/models.py')
-rw-r--r--yaksh/models.py144
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):
"""