From f30b65e85cba5d3f25b11787530afbee957ce599 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 5 Oct 2017 16:24:38 +0530 Subject: Change Answerpaper model method to get shuffled questions --- yaksh/models.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/yaksh/models.py b/yaksh/models.py index 4859d3e..1cc0634 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 @@ -851,6 +852,8 @@ class QuestionPaper(models.Model): questions = self.get_ordered_questions() for question_set in self.random_questions.all(): questions += question_set.get_random_questions() + if self.shuffle_questions: + return self.get_shuffled_questions(questions) return questions def make_answerpaper(self, user, ip, attempt_num): @@ -941,9 +944,14 @@ 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 __str__(self): return "Question Paper for " + self.quiz.description -- cgit From 3038ab21bc93b3dfebda82a10fc179dadb488bf3 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 5 Oct 2017 16:25:15 +0530 Subject: Add test to check shuffle questions --- yaksh/test_models.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/yaksh/test_models.py b/yaksh/test_models.py index 2c83024..6828b89 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -502,6 +502,7 @@ class AnswerPaperTestCases(unittest.TestCase): def setUpClass(self): self.ip = '101.0.0.1' self.user = User.objects.get(username='demo_user') + self.user2 = User.objects.get(username='demo_user2') self.profile = self.user.profile self.quiz = Quiz.objects.get(description='demo quiz 1') self.question_paper = QuestionPaper(quiz=self.quiz, total_marks=3) @@ -590,6 +591,23 @@ class AnswerPaperTestCases(unittest.TestCase): ) self.mcc_based_testcase.save() + # Setup quiz where questions are shuffled + # Create Quiz and Question Paper + self.quiz2 = Quiz.objects.get(description="demo quiz 2") + self.question_paper2 = QuestionPaper( + quiz=self.quiz2, total_marks=3, shuffle_questions=True) + self.question_paper2.save() + que_list = [self.question1, self.question2, self.question3] + self.question_paper2.fixed_questions.add(*que_list) + + # Create AnswerPaper for user1 and user2 + self.user1_answerpaper = self.question_paper2.make_answerpaper( + self.user, self.ip, 1 + ) + self.user2_answerpaper = self.question_paper2.make_answerpaper( + self.user2, self.ip, 1 + ) + def test_validate_and_regrade_mcc_correct_answer(self): # Given mcc_answer = [str(self.mcc_based_testcase.id)] @@ -663,7 +681,6 @@ class AnswerPaperTestCases(unittest.TestCase): self.assertEqual(self.answer.marks, 0) self.assertFalse(self.answer.correct) - def test_mcq_incorrect_answer(self): # Given mcq_answer = 'b' @@ -858,6 +875,21 @@ class AnswerPaperTestCases(unittest.TestCase): self.assertEqual(latest_answer.id, self.answer1.id) self.assertEqual(latest_answer.answer, "answer1") + def test_shuffle_questions(self): + success = False + user1_question_set = [] + user2_question_set = [] + while not success: + ques_set_1 = list(self.user1_answerpaper.questions.all()) + ques_set_2 = list(self.user2_answerpaper.questions.all()) + if ques_set_1 == ques_set_2: + continue + else: + user1_question_set = ques_set_1 + user2_question_set = ques_set_2 + success = True + self.assertFalse(user1_question_set == user2_question_set) + ############################################################################### class CourseTestCases(unittest.TestCase): -- cgit From 474fc2c54eda0e8c890ea17b791b2fe74d07c611 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 5 Oct 2017 17:07:41 +0530 Subject: Change models.py and test_models.py - Add else condition in make_answerpaper instead of direct return - Remove while loop in shuffle questions testcase --- yaksh/models.py | 8 ++++++-- yaksh/test_models.py | 20 ++++++-------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index 1cc0634..78669e7 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -853,8 +853,11 @@ class QuestionPaper(models.Model): for question_set in self.random_questions.all(): questions += question_set.get_random_questions() if self.shuffle_questions: - return self.get_shuffled_questions(questions) - return questions + all_questions = self.get_shuffled_questions(questions) + print("in _get_questions_for_answerpaper", all_questions, "\n") + 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""" @@ -950,6 +953,7 @@ class QuestionPaper(models.Model): def get_shuffled_questions(self, questions): """Get shuffled questions if auto suffle is enabled""" random.shuffle(questions) + print("in get_shuffled_questions", questions, "\n") return questions def __str__(self): diff --git a/yaksh/test_models.py b/yaksh/test_models.py index 6828b89..e3ef86e 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -597,7 +597,8 @@ class AnswerPaperTestCases(unittest.TestCase): self.question_paper2 = QuestionPaper( quiz=self.quiz2, total_marks=3, shuffle_questions=True) self.question_paper2.save() - que_list = [self.question1, self.question2, self.question3] + + que_list = Question.objects.filter(id__in=range(1, 21)) self.question_paper2.fixed_questions.add(*que_list) # Create AnswerPaper for user1 and user2 @@ -876,19 +877,10 @@ class AnswerPaperTestCases(unittest.TestCase): self.assertEqual(latest_answer.answer, "answer1") def test_shuffle_questions(self): - success = False - user1_question_set = [] - user2_question_set = [] - while not success: - ques_set_1 = list(self.user1_answerpaper.questions.all()) - ques_set_2 = list(self.user2_answerpaper.questions.all()) - if ques_set_1 == ques_set_2: - continue - else: - user1_question_set = ques_set_1 - user2_question_set = ques_set_2 - success = True - self.assertFalse(user1_question_set == user2_question_set) + ques_set_1 = list(self.user1_answerpaper.questions.all()) + ques_set_2 = list(self.user2_answerpaper.questions.all()) + print("set1:-", ques_set_1, "\n", "set2:-", ques_set_2) + self.assertFalse(ques_set_1 == ques_set_2) ############################################################################### -- cgit From 30f4b893d4a36e0e1408ef2a07c92521fc4074bc Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 6 Oct 2017 17:54:09 +0530 Subject: Add new field in AnswerPaper model and fetch questions as per order --- yaksh/models.py | 63 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/yaksh/models.py b/yaksh/models.py index 78669e7..9ac629c 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -854,7 +854,6 @@ class QuestionPaper(models.Model): questions += question_set.get_random_questions() if self.shuffle_questions: all_questions = self.get_shuffled_questions(questions) - print("in _get_questions_for_answerpaper", all_questions, "\n") else: all_questions = questions return all_questions @@ -878,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, @@ -953,9 +953,13 @@ class QuestionPaper(models.Model): def get_shuffled_questions(self, questions): """Get shuffled questions if auto suffle is enabled""" random.shuffle(questions) - print("in get_shuffled_questions", questions, "\n") return questions + def has_questions(self): + questions = self.get_ordered_questions() + \ + list(self.random_questions.all()) + return False if len(questions) == 0 else True + def __str__(self): return "Question Paper for " + self.quiz.description @@ -1176,13 +1180,27 @@ class AnswerPaper(models.Model): default='inprogress' ) + # set question order + questions_order = models.CharField(max_length=255, 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] - return self.questions.all()[0] + cur_question = self.get_current_question( + self.questions_unanswered.all()) + 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 = self.questions_unanswered.get(id=question_id) + else: + question = questions.first() + return question def questions_left(self): """Returns the number of questions left.""" @@ -1207,17 +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: + 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""" + 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.""" -- cgit From 9c6472c4a677248bc0f2de2a513368dc68d11f05 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 6 Oct 2017 17:58:39 +0530 Subject: Pep8 change in views.py --- yaksh/views.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/yaksh/views.py b/yaksh/views.py index 6abfa2b..b4cb844 100644 --- a/yaksh/views.py +++ b/yaksh/views.py @@ -392,8 +392,7 @@ def start(request, questionpaper_id=None, attempt_num=None): msg = 'Quiz not found, please contact your '\ 'instructor/administrator.' return complete(request, msg, attempt_num, questionpaper_id=None) - if not quest_paper.get_ordered_questions() and not \ - quest_paper.random_questions.all(): + if not quest_paper.has_questions(): msg = 'Quiz does not have Questions, please contact your '\ 'instructor/administrator.' return complete(request, msg, attempt_num, questionpaper_id=None) -- cgit From bf17148a234b77a4a4521d34e17afddb3cd34914 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 6 Oct 2017 18:01:25 +0530 Subject: Add test for shuffle questions and fix broken tests in test_views --- yaksh/test_models.py | 9 ++++----- yaksh/test_views.py | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/yaksh/test_models.py b/yaksh/test_models.py index e3ef86e..03af521 100644 --- a/yaksh/test_models.py +++ b/yaksh/test_models.py @@ -597,8 +597,8 @@ class AnswerPaperTestCases(unittest.TestCase): self.question_paper2 = QuestionPaper( quiz=self.quiz2, total_marks=3, shuffle_questions=True) self.question_paper2.save() - - que_list = Question.objects.filter(id__in=range(1, 21)) + summary_list = ['Q%d' % (i) for i in range(1, 21)] + que_list = Question.objects.filter(summary__in=summary_list) self.question_paper2.fixed_questions.add(*que_list) # Create AnswerPaper for user1 and user2 @@ -877,9 +877,8 @@ class AnswerPaperTestCases(unittest.TestCase): self.assertEqual(latest_answer.answer, "answer1") def test_shuffle_questions(self): - ques_set_1 = list(self.user1_answerpaper.questions.all()) - ques_set_2 = list(self.user2_answerpaper.questions.all()) - print("set1:-", ques_set_1, "\n", "set2:-", ques_set_2) + ques_set_1 = self.user1_answerpaper.get_all_ordered_questions() + ques_set_2 = self.user2_answerpaper.get_all_ordered_questions() self.assertFalse(ques_set_1 == ques_set_2) diff --git a/yaksh/test_views.py b/yaksh/test_views.py index 2d86b77..dc06126 100644 --- a/yaksh/test_views.py +++ b/yaksh/test_views.py @@ -2092,13 +2092,13 @@ class TestViewAnswerPaper(TestCase): self.quiz = Quiz.objects.create(time_between_attempts=0, course=self.course, description='demo quiz', language='Python') - + self.user3 = User.objects.get(username="demo_user3") self.question_paper = QuestionPaper.objects.create(quiz=self.quiz, total_marks=1.0) self.question_paper.fixed_questions.add(self.question) self.question_paper.save() - self.ans_paper = AnswerPaper.objects.create(user_id=3, + self.ans_paper = AnswerPaper.objects.create(user=self.user3, attempt_number=1, question_paper=self.question_paper, start_time=timezone.now(), user_ip='101.0.0.1', end_time=timezone.now()+timezone.timedelta(minutes=20)) @@ -2382,7 +2382,7 @@ class TestGrader(TestCase): self.question_paper.fixed_questions.add(self.question) self.question_paper.save() - self.answerpaper = AnswerPaper.objects.create(user_id=3, + self.answerpaper = AnswerPaper.objects.create(user=self.user2, attempt_number=1, question_paper=self.question_paper, start_time=timezone.now(), user_ip='101.0.0.1', end_time=timezone.now()+timezone.timedelta(minutes=20)) -- cgit From ab71b790f209e44b22142f360a9de1e95091ead3 Mon Sep 17 00:00:00 2001 From: adityacp Date: Fri, 6 Oct 2017 18:01:56 +0530 Subject: Get questions in particular order in template --- yaksh/templates/exam.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yaksh/templates/exam.html b/yaksh/templates/exam.html index 4d211d2..9596c1c 100644 --- a/yaksh/templates/exam.html +++ b/yaksh/templates/exam.html @@ -46,7 +46,7 @@