diff options
Diffstat (limited to 'yaksh/models.py')
-rw-r--r-- | yaksh/models.py | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/yaksh/models.py b/yaksh/models.py index d9e07fd..787daa6 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals from datetime import datetime, timedelta import json +import random import ruamel.yaml from ruamel.yaml.scalarstring import PreservedScalarString from ruamel.yaml.comments import CommentedMap @@ -350,7 +351,7 @@ class Question(models.Model): tags = TaggableManager(blank=True) # Snippet of code provided to the user. - snippet = models.CharField(max_length=256, blank=True) + snippet = models.TextField(blank=True) # user for particular question user = models.ForeignKey(User, related_name="user") @@ -851,7 +852,11 @@ class QuestionPaper(models.Model): questions = self.get_ordered_questions() for question_set in self.random_questions.all(): questions += question_set.get_random_questions() - return questions + if self.shuffle_questions: + all_questions = self.get_shuffled_questions(questions) + else: + all_questions = questions + return all_questions def make_answerpaper(self, user, ip, attempt_num): """Creates an answer paper for the user to attempt the quiz""" @@ -872,10 +877,11 @@ class QuestionPaper(models.Model): ans_paper.question_paper = self ans_paper.save() questions = self._get_questions_for_answerpaper() - for question in questions: - ans_paper.questions.add(question) - for question in questions: - ans_paper.questions_unanswered.add(question) + ans_paper.questions.add(*questions) + question_ids = [str(que.id) for que in questions] + ans_paper.questions_order = ",".join(question_ids) + ans_paper.save() + ans_paper.questions_unanswered.add(*questions) except AnswerPaper.MultipleObjectsReturned: ans_paper = AnswerPaper.objects.get(user=user, attempt_number=attempt_num, @@ -918,7 +924,7 @@ class QuestionPaper(models.Model): def create_demo_quiz_ppr(self, demo_quiz, user): question_paper = QuestionPaper.objects.create(quiz=demo_quiz, total_marks=6.0, - shuffle_questions=True + shuffle_questions=False ) summaries = ['Roots of quadratic equation', 'Print Output', 'Adding decimals', 'For Loop over String', @@ -941,9 +947,19 @@ class QuestionPaper(models.Model): for que_id in que_order: ques.append(self.fixed_questions.get(id=que_id)) else: - ques = self.fixed_questions.all() + ques = list(self.fixed_questions.all()) return ques + def get_shuffled_questions(self, questions): + """Get shuffled questions if auto suffle is enabled""" + random.shuffle(questions) + return questions + + def has_questions(self): + questions = self.get_ordered_questions() + \ + list(self.random_questions.all()) + return len(questions) > 0 + def __str__(self): return "Question Paper for " + self.quiz.description @@ -1164,12 +1180,27 @@ class AnswerPaper(models.Model): default='inprogress' ) + # set question order + questions_order = models.TextField(blank=True, default='') + objects = AnswerPaperManager() def current_question(self): """Returns the current active question to display.""" - if self.questions_unanswered.all(): - return self.questions_unanswered.all()[0] + unanswered_questions = self.questions_unanswered.all() + if unanswered_questions.exists(): + cur_question = self.get_current_question(unanswered_questions) + else: + cur_question = self.get_current_question(self.questions.all()) + return cur_question + + def get_current_question(self, questions): + if self.questions_order: + question_id = int(self.questions_order.split(',')[0]) + question = questions.get(id=question_id) + else: + question = questions.first() + return question def questions_left(self): """Returns the number of questions left.""" @@ -1194,19 +1225,30 @@ class AnswerPaper(models.Model): Skips the current question and returns the next sequentially available question. """ - all_questions = self.questions.all() - unanswered_questions = self.questions_unanswered.all() - questions = list(all_questions.values_list('id', flat=True)) - if len(questions) == 0: - return None - if unanswered_questions.count() == 0: + if self.questions_order: + all_questions = [int(q_id) + for q_id in self.questions_order.split(',')] + else: + all_questions = list(self.questions.all().values_list( + 'id', flat=True)) + if len(all_questions) == 0: return None try: - index = questions.index(int(question_id)) - next_id = questions[index+1] + index = all_questions.index(int(question_id)) + next_id = all_questions[index+1] except (ValueError, IndexError): - next_id = questions[0] - return all_questions.get(id=next_id) + next_id = all_questions[0] + return self.questions.get(id=next_id) + + def get_all_ordered_questions(self): + """Get all questions in a specific order for answerpaper""" + if self.questions_order: + que_ids = [int(q_id) for q_id in self.questions_order.split(',')] + questions = [self.questions.get(id=que_id) + for que_id in que_ids] + else: + questions = list(self.questions.all()) + return questions def time_left(self): """Return the time remaining for the user in seconds.""" @@ -1284,6 +1326,9 @@ class AnswerPaper(models.Model): }] return q_a + def get_latest_answer(self, question_id): + return self.answers.filter(question=question_id).order_by("id").last() + def get_questions(self): return self.questions.filter(active=True) @@ -1303,8 +1348,7 @@ class AnswerPaper(models.Model): return self.time_left() > 0 def get_previous_answers(self, question): - if question.type == 'code': - return self.answers.filter(question=question).order_by('-id') + return self.answers.filter(question=question).order_by('-id') def validate_answer(self, user_answer, question, json_data=None, uid=None): """ @@ -1320,15 +1364,15 @@ class AnswerPaper(models.Model): 'weight': 0.0} if user_answer is not None: if question.type == 'mcq': - expected_answer = question.get_test_case(correct=True).options - if user_answer.strip() == expected_answer.strip(): + expected_answer = question.get_test_case(correct=True).id + if user_answer.strip() == str(expected_answer).strip(): result['success'] = True result['error'] = ['Correct answer'] elif question.type == 'mcc': expected_answers = [] for opt in question.get_test_cases(correct=True): - expected_answers.append(opt.options) + expected_answers.append(str(opt.id)) if set(user_answer) == set(expected_answers): result['success'] = True result['error'] = ['Correct answer'] |