summaryrefslogtreecommitdiff
path: root/yaksh/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'yaksh/models.py')
-rw-r--r--yaksh/models.py127
1 files changed, 125 insertions, 2 deletions
diff --git a/yaksh/models.py b/yaksh/models.py
index 1094bb0..84cad1e 100644
--- a/yaksh/models.py
+++ b/yaksh/models.py
@@ -1045,6 +1045,14 @@ class Course(models.Model):
def get_learning_modules(self):
return self.learning_module.order_by("order")
+ def get_learning_module(self, quiz):
+ modules = self.get_learning_modules()
+ for module in modules:
+ for unit in module.get_learning_units():
+ if unit.quiz == quiz:
+ break
+ return module
+
def get_unit_completion_status(self, module, user, unit):
course_module = self.learning_module.get(id=module.id)
learning_unit = course_module.learning_unit.get(id=unit.id)
@@ -1776,7 +1784,7 @@ class QuestionPaper(models.Model):
all_questions = questions
return all_questions
- def make_answerpaper(self, user, ip, attempt_num, course_id):
+ def make_answerpaper(self, user, ip, attempt_num, course_id, special=False):
"""Creates an answer paper for the user to attempt the quiz"""
try:
ans_paper = AnswerPaper.objects.get(user=user,
@@ -1795,6 +1803,7 @@ class QuestionPaper(models.Model):
ans_paper.end_time = ans_paper.start_time + \
timedelta(minutes=self.quiz.duration)
ans_paper.question_paper = self
+ ans_paper.is_special = special
ans_paper.save()
questions = self._get_questions_for_answerpaper()
ans_paper.questions.add(*questions)
@@ -2139,6 +2148,10 @@ class AnswerPaper(models.Model):
# set question order
questions_order = models.TextField(blank=True, default='')
+ extra_time = models.FloatField('Additional time in mins', default=0.0)
+
+ is_special = models.BooleanField(default=False)
+
objects = AnswerPaperManager()
class Meta:
@@ -2221,11 +2234,16 @@ class AnswerPaper(models.Model):
questions = list(self.questions.all())
return questions
+ def set_extra_time(self, time=0):
+ self.extra_time = time
+ self.save()
+
def time_left(self):
"""Return the time remaining for the user in seconds."""
secs = self._get_total_seconds()
+ extra_time = self.extra_time * 60
total = self.question_paper.quiz.duration*60.0
- remain = max(total - secs, 0)
+ remain = max(total - (secs - extra_time), 0)
return int(remain)
def time_left_on_question(self, question):
@@ -2710,3 +2728,108 @@ class Comment(ForumBase):
def __str__(self):
return 'Comment by {0}: {1}'.format(self.creator.username,
self.post_field.title)
+
+
+class MicroManager(models.Model):
+ manager = models.ForeignKey(User, on_delete=models.CASCADE,
+ related_name='micromanaging', null=True)
+ student = models.ForeignKey(User, on_delete=models.CASCADE,
+ related_name='micromanaged')
+ course = models.ForeignKey(Course, on_delete=models.CASCADE)
+ quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, null=True)
+ special_attempt = models.BooleanField(default=False)
+ attempts_permitted = models.IntegerField(default=0)
+ permitted_time = models.DateTimeField(default=timezone.now)
+ attempts_utilised = models.IntegerField(default=0)
+ wait_time = models.IntegerField('Days to wait before special attempt',
+ default=0)
+ attempt_valid_for = models.IntegerField('Validity days', default=90)
+
+ class Meta:
+ unique_together = ('student', 'course', 'quiz')
+
+ def set_wait_time(self, days=0):
+ self.wait_time = days
+ self.save()
+
+ def increment_attempts_permitted(self):
+ self.attempts_permitted += 1
+ self.save()
+
+ def update_permitted_time(self, permit_time=None):
+ time_now = timezone.now()
+ self.permitted_time = time_now if not permit_time else permit_time
+ self.save()
+
+ def has_student_attempts_exhausted(self):
+ if self.quiz.attempts_allowed == -1:
+ return False
+ question_paper = self.quiz.questionpaper_set.first()
+ attempts = AnswerPaper.objects.get_total_attempt(
+ question_paper, self.student, course_id=self.course.id
+ )
+ last_attempt = AnswerPaper.objects.get_user_last_attempt(
+ question_paper, self.student, self.course.id
+ )
+ if last_attempt:
+ if last_attempt.is_attempt_inprogress():
+ return False
+ return attempts >= self.quiz.attempts_allowed
+
+ def is_last_attempt_inprogress(self):
+ question_paper = self.quiz.questionpaper_set.first()
+ last_attempt = AnswerPaper.objects.get_user_last_attempt(
+ question_paper, self.student, self.course.id
+ )
+ if last_attempt:
+ return last_attempt.is_attempt_inprogress()
+ return False
+
+ def has_quiz_time_exhausted(self):
+ return not self.quiz.active or self.quiz.is_expired()
+
+ def is_course_exhausted(self):
+ return not self.course.active or not self.course.is_active_enrollment()
+
+ def is_special_attempt_required(self):
+ return (self.has_student_attempts_exhausted() or
+ self.has_quiz_time_exhausted() or self.is_course_exhausted())
+
+ def allow_special_attempt(self, wait_time=0):
+ if (self.is_special_attempt_required() and
+ not self.is_last_attempt_inprogress()):
+ self.special_attempt = True
+ if self.attempts_utilised >= self.attempts_permitted:
+ self.increment_attempts_permitted()
+ self.update_permitted_time()
+ self.set_wait_time(days=wait_time)
+ self.save()
+
+ def has_special_attempt(self):
+ return (self.special_attempt and
+ (self.attempts_utilised < self.attempts_permitted))
+
+ def is_attempt_time_valid(self):
+ permit_time = self.permitted_time
+ wait_time = permit_time + timezone.timedelta(days=self.wait_time)
+ valid_time = permit_time + timezone.timedelta(
+ days=self.attempt_valid_for)
+ return wait_time <= timezone.now() <= valid_time
+
+ def can_student_attempt(self):
+ return self.has_special_attempt() and self.is_attempt_time_valid()
+
+ def get_attempt_number(self):
+ return self.quiz.attempts_allowed + self.attempts_utilised + 1
+
+ def increment_attempts_utilised(self):
+ self.attempts_utilised += 1
+ self.save()
+
+ def revoke_special_attempt(self):
+ self.special_attempt = False
+ self.save()
+
+ def __str__(self):
+ return 'MicroManager for {0} - {1}'.format(self.student.username,
+ self.course.name)