From 5a2ed309ff2f5f70571240b551978e25e51cd51f Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 20 Feb 2018 11:43:50 +0530 Subject: Change in models.py, views.py and ursl.py - Change urls to take two types of course clone - Change view duplicate_course to copy or clone depending on type - Change view function prof_manage to avoid error while deleting trial answerpapers - Add new model methods for course, module, unit, lesson and quiz to create copies --- yaksh/models.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 1e45851..d5b2923 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -161,6 +161,23 @@ class Lesson(models.Model): def get_files(self): return LessonFile.objects.filter(lesson=self) + def _create_lesson_copy(self, user): + lesson_files = self.get_files() + new_lesson = self + new_lesson.id = None + new_lesson.name = "Copy of {0}".format(self.name) + new_lesson.creator = user + new_lesson.save() + for _file in lesson_files: + file_name = os.path.basename(_file.file.name) + if os.path.exists(_file.file.path): + lesson_file = open(_file.file.path, "rb") + django_file = File(lesson_file) + lesson_file_obj = LessonFile() + lesson_file_obj.lesson = new_lesson + lesson_file_obj.file.save(file_name, django_file, save=True) + return new_lesson + ############################################################################# class LessonFile(models.Model): @@ -352,6 +369,17 @@ class Quiz(models.Model): course=course, passed=False ).values_list("user", flat=True).distinct().count() + def _create_quiz_copy(self, user): + question_papers = self.questionpaper_set.all() + new_quiz = self + new_quiz.id = None + new_quiz.description = "Copy of {0}".format(self.description) + new_quiz.creator = user + new_quiz.save() + for qp in question_papers: + qp._create_duplicate_questionpaper(new_quiz) + return new_quiz + def __str__(self): desc = self.description or 'Quiz' return '%s: on %s for %d minutes' % (desc, self.start_date_time, @@ -402,6 +430,17 @@ class LearningUnit(models.Model): success = False return success + def _create_unit_copy(self, user): + if self.type == "quiz": + new_quiz = self.quiz._create_quiz_copy(user) + new_unit = LearningUnit.objects.create( + order=self.order, type="quiz", quiz=new_quiz) + else: + new_lesson = self.lesson._create_lesson_copy(user) + new_unit = LearningUnit.objects.create( + order=self.order, type="lesson", lesson=new_lesson) + return new_unit + ############################################################################### class LearningModule(models.Model): @@ -496,6 +535,18 @@ class LearningModule(models.Model): percent = round((count / len(units)) * 100) return percent + def _create_module_copy(self, user, module_name): + learning_units = self.learning_unit.order_by("order") + new_module = self + new_module.id = None + new_module.name = module_name + new_module.creator = user + new_module.save() + for unit in learning_units: + new_unit = unit._create_unit_copy(user) + new_module.learning_unit.add(new_unit) + return new_module + def __str__(self): return self.name @@ -556,6 +607,15 @@ class Course(models.Model): return new_course + def create_shallow_copy(self, user): + learning_modules = self.learning_module.order_by("order") + copy_course_name = "Copy Of {0}".format(self.name) + new_course = self._create_duplicate_instance(user, copy_course_name) + for module in learning_modules: + copy_module_name = "Copy of {0}".format(module.name) + new_module = module._create_module_copy(user, copy_module_name) + new_course.learning_module.add(new_module) + def request(self, *users): self.requests.add(*users) @@ -1129,8 +1189,8 @@ class QuestionPaper(models.Model): return questions def _create_duplicate_questionpaper(self, quiz): - new_questionpaper = QuestionPaper.objects.create(quiz=quiz, - shuffle_questions=self.shuffle_questions, + new_questionpaper = QuestionPaper.objects.create( + quiz=quiz, shuffle_questions=self.shuffle_questions, total_marks=self.total_marks, fixed_question_order=self.fixed_question_order ) -- cgit From 0ae21e437775b056d346311bd9f50220e5d9fb28 Mon Sep 17 00:00:00 2001 From: adityacp Date: Tue, 27 Feb 2018 15:41:08 +0530 Subject: Change in models.py, views.py, urls.py, test_views.py, courses.html - Allow only deep cloning of a course - Remove tests for shallow course clone --- yaksh/models.py | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 252bde6..7aa5f83 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -613,16 +613,6 @@ class Course(models.Model): return new_course def create_duplicate_course(self, user): - learning_modules = self.learning_module.all() - - new_course_name = "Copy Of {0}".format(self.name) - new_course = self._create_duplicate_instance(user, new_course_name) - - new_course.learning_module.add(*learning_modules) - - return new_course - - def create_shallow_copy(self, user): learning_modules = self.learning_module.order_by("order") copy_course_name = "Copy Of {0}".format(self.name) new_course = self._create_duplicate_instance(user, copy_course_name) -- cgit From 3bbaff2ebca026042cce3deb025effb9e83e0859 Mon Sep 17 00:00:00 2001 From: adityacp Date: Wed, 28 Feb 2018 16:54:22 +0530 Subject: Change forms.py, models.py, test_models.py and templates - Add help text for timezone field in user registration form - Add new method in course model to get days remaining to start a course - Show start time and end time of a course to the students - Disallow to enroll to a course which is not active - Add model test for the new course method --- yaksh/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index f065190..2e759ee 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -722,6 +722,14 @@ class Course(models.Model): percent = round((count / len(modules))) return percent + def days_remain_to_start(self): + """ Get the days remaining for the start of the course """ + if timezone.now() < self.start_enroll_time: + remaining_days = (self.start_enroll_time - timezone.now()).days + 1 + else: + remaining_days = 0 + return remaining_days + def __str__(self): return self.name -- cgit From b0df46ec36a043d3c51014cf5746d7def9cb17b9 Mon Sep 17 00:00:00 2001 From: adityacp Date: Thu, 8 Mar 2018 14:34:17 +0530 Subject: Change model method name in course model --- yaksh/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 2e759ee..c8a4d4d 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -722,7 +722,7 @@ class Course(models.Model): percent = round((count / len(modules))) return percent - def days_remain_to_start(self): + def days_before_start(self): """ Get the days remaining for the start of the course """ if timezone.now() < self.start_enroll_time: remaining_days = (self.start_enroll_time - timezone.now()).days + 1 -- cgit From 9c5464a6edaaf2aaafc0e42fe88c8734fd952e12 Mon Sep 17 00:00:00 2001 From: mahesh Date: Mon, 15 Jan 2018 17:40:06 +0530 Subject: Add shuffle testcases option to questions --- yaksh/models.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index f065190..6ba4589 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -815,8 +815,14 @@ class Question(models.Model): min_time = models.IntegerField("time in minutes", default=0) + #Solution for the question. solution = models.TextField(blank=True) + # Shuffle testcase order. + shuffle_testcases = models.BooleanField("Shuffle testcase for each user", + default=False + ) + def consolidate_answer_data(self, user_answer, user=None): question_data = {} metadata = {} @@ -928,6 +934,17 @@ class Question(models.Model): return test_case + def get_ordered_test_cases(self, answerpaper): + try: + order = TestcaseOrder.objects.get(answer_paper=answerpaper, + question = self + ).testcase_order.split(",") + return [self.get_test_cases(id=int(tc_id))[0]\ + for tc_id in order + ] + except TestcaseOrder.DoesNotExist: + return self.get_test_cases() + def get_maximum_test_case_weight(self, **kwargs): max_weight = 0.0 for test_case in self.get_test_cases(): @@ -1197,7 +1214,17 @@ class QuestionPaper(models.Model): ans_paper.save() questions = self._get_questions_for_answerpaper() ans_paper.questions.add(*questions) - question_ids = [str(que.id) for que in questions] + question_ids = [] + for question in questions: + question_ids.append(str(question.id)) + testcases = question.get_test_cases() + if question.shuffle_testcases: + random.shuffle(testcases) + testcases_ids = ",".join([str(tc.id) for tc in testcases]) + testcases_order = TestcaseOrder.objects.create( + answer_paper=ans_paper, + question=question, + testcase_order=testcases_ids) ans_paper.questions_order = ",".join(question_ids) ans_paper.save() ans_paper.questions_unanswered.add(*questions) @@ -1829,7 +1856,7 @@ class AnswerPaper(models.Model): .format(u.first_name, u.last_name, q.description) -################################################################################ +############################################################################## class AssignmentUploadManager(models.Manager): def get_assignments(self, qp, que_id=None, user_id=None): @@ -1851,7 +1878,7 @@ class AssignmentUploadManager(models.Manager): return assignment_files, file_name -################################################################################ +############################################################################## class AssignmentUpload(models.Model): user = models.ForeignKey(User) assignmentQuestion = models.ForeignKey(Question) @@ -1860,7 +1887,7 @@ class AssignmentUpload(models.Model): objects = AssignmentUploadManager() -############################################################################### +############################################################################## class TestCase(models.Model): question = models.ForeignKey(Question, blank=True, null=True) type = models.CharField(max_length=24, choices=test_case_types, null=True) @@ -1978,3 +2005,19 @@ class FloatTestCase(TestCase): return u'Testcase | Correct: {0} | Error Margin: +or- {1}'.format( self.correct, self.error_margin ) + + +############################################################################## +class TestcaseOrder(models.Model): + """Testcase order contains a set of ordered test cases for a given question + for each user. + """ + + # Answerpaper of the user. + answer_paper= models.ForeignKey(AnswerPaper,related_name="answer_paper") + + # Question in an answerpaper. + question = models.ForeignKey(Question) + + #Order of the test case for a question. + testcase_order = models.TextField() -- cgit From 009d6fb6e373ec9e24bb13924372ad77b4e3ccc5 Mon Sep 17 00:00:00 2001 From: mahesh Date: Thu, 1 Feb 2018 15:05:47 +0530 Subject: Change TestcaseOrder to TestCaseOrder --- yaksh/models.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 6ba4589..f823cda 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -936,13 +936,13 @@ class Question(models.Model): def get_ordered_test_cases(self, answerpaper): try: - order = TestcaseOrder.objects.get(answer_paper=answerpaper, + order = TestCaseOrder.objects.get(answer_paper=answerpaper, question = self - ).testcase_order.split(",") + ).order.split(",") return [self.get_test_cases(id=int(tc_id))[0]\ for tc_id in order ] - except TestcaseOrder.DoesNotExist: + except TestCaseOrder.DoesNotExist: return self.get_test_cases() def get_maximum_test_case_weight(self, **kwargs): @@ -1221,10 +1221,10 @@ class QuestionPaper(models.Model): if question.shuffle_testcases: random.shuffle(testcases) testcases_ids = ",".join([str(tc.id) for tc in testcases]) - testcases_order = TestcaseOrder.objects.create( + testcases_order = TestCaseOrder.objects.create( answer_paper=ans_paper, question=question, - testcase_order=testcases_ids) + order=testcases_ids) ans_paper.questions_order = ",".join(question_ids) ans_paper.save() ans_paper.questions_unanswered.add(*questions) @@ -2008,16 +2008,16 @@ class FloatTestCase(TestCase): ############################################################################## -class TestcaseOrder(models.Model): +class TestCaseOrder(models.Model): """Testcase order contains a set of ordered test cases for a given question for each user. """ # Answerpaper of the user. - answer_paper= models.ForeignKey(AnswerPaper,related_name="answer_paper") + answer_paper = models.ForeignKey(AnswerPaper, related_name="answer_paper") # Question in an answerpaper. question = models.ForeignKey(Question) #Order of the test case for a question. - testcase_order = models.TextField() + order = models.TextField() -- cgit From 366f9adce899b4cfd1e7a0e9a74dd5602fb0345a Mon Sep 17 00:00:00 2001 From: mahesh Date: Thu, 8 Feb 2018 15:19:27 +0530 Subject: Improve test cases for TestCaseOrder model --- yaksh/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index f823cda..0bb1e66 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -939,7 +939,7 @@ class Question(models.Model): order = TestCaseOrder.objects.get(answer_paper=answerpaper, question = self ).order.split(",") - return [self.get_test_cases(id=int(tc_id))[0]\ + return [self.get_test_case(id=int(tc_id)) for tc_id in order ] except TestCaseOrder.DoesNotExist: -- cgit From 140b6c6a06269cc39eae192605f623c7818e9260 Mon Sep 17 00:00:00 2001 From: mahesh Date: Fri, 16 Feb 2018 16:30:55 +0530 Subject: Add shuffle_testcases to QuestionPaper model instead of Question --- yaksh/models.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 0bb1e66..8e0bb4d 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -818,10 +818,6 @@ class Question(models.Model): #Solution for the question. solution = models.TextField(blank=True) - # Shuffle testcase order. - shuffle_testcases = models.BooleanField("Shuffle testcase for each user", - default=False - ) def consolidate_answer_data(self, user_answer, user=None): question_data = {} @@ -1151,6 +1147,11 @@ class QuestionPaper(models.Model): # Sequence or Order of fixed questions fixed_question_order = models.CharField(max_length=255, blank=True) + # Shuffle testcase order. + shuffle_testcases = models.BooleanField("Shuffle testcase for each user", + default=True + ) + objects = QuestionPaperManager() def get_question_bank(self): @@ -1218,7 +1219,8 @@ class QuestionPaper(models.Model): for question in questions: question_ids.append(str(question.id)) testcases = question.get_test_cases() - if question.shuffle_testcases: + if self.shuffle_testcases and \ + question.type in ["mcq", "mcc"]: random.shuffle(testcases) testcases_ids = ",".join([str(tc.id) for tc in testcases]) testcases_order = TestCaseOrder.objects.create( -- cgit From 4a5463d753c9af41d85a6be33257012c17d2ab15 Mon Sep 17 00:00:00 2001 From: mahesh Date: Tue, 20 Feb 2018 12:41:59 +0530 Subject: TestCaseOrder created only mcc/mcq questions --- yaksh/models.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 8e0bb4d..ecc0fc4 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1218,15 +1218,17 @@ class QuestionPaper(models.Model): question_ids = [] for question in questions: question_ids.append(str(question.id)) - testcases = question.get_test_cases() if self.shuffle_testcases and \ question.type in ["mcq", "mcc"]: + testcases = question.get_test_cases() random.shuffle(testcases) - testcases_ids = ",".join([str(tc.id) for tc in testcases]) - testcases_order = TestCaseOrder.objects.create( + testcases_ids = ",".join([str(tc.id) for tc in testcases] + ) + testcases_order = TestCaseOrder.objects.create( answer_paper=ans_paper, question=question, order=testcases_ids) + ans_paper.questions_order = ",".join(question_ids) ans_paper.save() ans_paper.questions_unanswered.add(*questions) -- cgit