From 053e27000540396b84c26d5a5f593d4389e0787a Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Wed, 2 Nov 2016 16:02:03 +0530 Subject: dd basic partial marking feature per test case --- yaksh/models.py | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 7f9eead..e7a96c9 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -245,6 +245,9 @@ class Question(models.Model): # user for particular question user = models.ForeignKey(User, related_name="user") + # Does this question allow partial grading + partial_grading = models.BooleanField(default=False) + def consolidate_answer_data(self, user_answer): question_data = {} test_case_data = [] @@ -257,6 +260,7 @@ class Question(models.Model): question_data['test_case_data'] = test_case_data question_data['user_answer'] = user_answer + question_data['partial_grading'] = self.partial_grading files = FileUpload.objects.filter(question=self) if files: question_data['file_paths'] = [(file.file.path, file.extract) @@ -937,11 +941,17 @@ class AnswerPaper(models.Model): def _update_marks_obtained(self): """Updates the total marks earned by student for this paper.""" - marks = sum([x.marks for x in self.answers.filter(marks__gt=0.0)]) - if not marks: - self.marks_obtained = 0 - else: - self.marks_obtained = marks + # marks = sum([x.marks for x in self.answers.filter(marks__gt=0.0)]) + # if not marks: + # self.marks_obtained = 0 + # else: + # self.marks_obtained = marks + marks = 0 + for question in self.questions.all(): + max_marks = max([a.marks for a in self.answers.filter(question=question)]) + marks += max_marks + self.marks_obtained = marks + def _update_percent(self): """Updates the percent gained by the student for this paper.""" @@ -1023,7 +1033,7 @@ class AnswerPaper(models.Model): For code questions success is True only if the answer is correct. """ - result = {'success': True, 'error': 'Incorrect answer'} + result = {'success': True, 'error': 'Incorrect answer', 'marks': 0.0} correct = False if user_answer is not None: if question.type == 'mcq': @@ -1071,11 +1081,16 @@ class AnswerPaper(models.Model): json_data = question.consolidate_answer_data(answer) \ if question.type == 'code' else None correct, result = self.validate_answer(answer, question, json_data) - user_answer.marks = question.points if correct else 0.0 user_answer.correct = correct user_answer.error = result.get('error') + if correct: + user_answer.marks = question.points * result['marks'] \ + if question.partial_grading and question.type == 'code' else question.points + else: + user_answer.marks = question.points * result['marks'] \ + if question.partial_grading and question.type == 'code' else 0 user_answer.save() - self.update_marks('complete') + self.update_marks('completed') return True, msg def __str__(self): @@ -1098,9 +1113,11 @@ class TestCase(models.Model): class StandardTestCase(TestCase): test_case = models.TextField(blank=True) + marks = models.FloatField(default=0.0) def get_field_value(self): - return {"test_case": self.test_case} + return {"test_case": self.test_case, + "marks": self.marks} def __str__(self): return u'Question: {0} | Test Case: {1}'.format(self.question, -- cgit From 4904a8305e7e83a00cef718a42bbbf8e7d5f8740 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Fri, 4 Nov 2016 19:20:20 +0530 Subject: Add partial grade mark for stdio test case and fix model test cases --- yaksh/models.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index e7a96c9..33c3b42 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -941,14 +941,10 @@ class AnswerPaper(models.Model): def _update_marks_obtained(self): """Updates the total marks earned by student for this paper.""" - # marks = sum([x.marks for x in self.answers.filter(marks__gt=0.0)]) - # if not marks: - # self.marks_obtained = 0 - # else: - # self.marks_obtained = marks marks = 0 for question in self.questions.all(): - max_marks = max([a.marks for a in self.answers.filter(question=question)]) + marks_list = [a.marks for a in self.answers.filter(question=question)] + max_marks = max(marks_list) if marks_list else 0.0 marks += max_marks self.marks_obtained = marks @@ -1128,10 +1124,12 @@ class StandardTestCase(TestCase): class StdioBasedTestCase(TestCase): expected_input = models.TextField(blank=True) expected_output = models.TextField() + marks = models.FloatField(default=0.0) def get_field_value(self): return {"expected_output": self.expected_output, - "expected_input": self.expected_input} + "expected_input": self.expected_input, + "marks": self.marks} def __str__(self): return u'Question: {0} | Exp. Output: {1} | Exp. Input: {2}'.format(self.question, -- cgit From a09df642d4f3623ee517aaed2eac1372ebacc0e0 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Thu, 10 Nov 2016 12:36:13 +0530 Subject: Add point based weightage for partial grading instead of percentage based partial grading --- yaksh/models.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 33c3b42..05528c7 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -325,6 +325,13 @@ class Question(models.Model): return test_case + def get_maximum_test_case_weightage(self, **kwargs): + max_weightage = 0.0 + for test_case in self.get_test_cases(): + max_weightage += test_case.weightage + + return max_weightage + def _add_and_get_files(self, zip_file): files = FileUpload.objects.filter(question=self) files_list = [] @@ -1029,7 +1036,7 @@ class AnswerPaper(models.Model): For code questions success is True only if the answer is correct. """ - result = {'success': True, 'error': 'Incorrect answer', 'marks': 0.0} + result = {'success': True, 'error': 'Incorrect answer', 'weightage': 0.0} correct = False if user_answer is not None: if question.type == 'mcq': @@ -1080,11 +1087,17 @@ class AnswerPaper(models.Model): user_answer.correct = correct user_answer.error = result.get('error') if correct: - user_answer.marks = question.points * result['marks'] \ + user_answer.marks = (question.points * result['weightage'] / + question.get_maximum_test_case_weightage()) \ if question.partial_grading and question.type == 'code' else question.points + # user_answer.marks = question.points * result['weightage'] \ + # if question.partial_grading and question.type == 'code' else question.points else: - user_answer.marks = question.points * result['marks'] \ + user_answer.marks = (question.points * result['weightage'] / + question.get_maximum_test_case_weightage()) \ if question.partial_grading and question.type == 'code' else 0 + # user_answer.marks = question.points * result['weightage'] \ + # if question.partial_grading and question.type == 'code' else 0 user_answer.save() self.update_marks('completed') return True, msg @@ -1109,11 +1122,11 @@ class TestCase(models.Model): class StandardTestCase(TestCase): test_case = models.TextField(blank=True) - marks = models.FloatField(default=0.0) + weightage = models.FloatField(default=0.0) def get_field_value(self): return {"test_case": self.test_case, - "marks": self.marks} + "weightage": self.weightage} def __str__(self): return u'Question: {0} | Test Case: {1}'.format(self.question, @@ -1124,12 +1137,12 @@ class StandardTestCase(TestCase): class StdioBasedTestCase(TestCase): expected_input = models.TextField(blank=True) expected_output = models.TextField() - marks = models.FloatField(default=0.0) + weightage = models.IntegerField(default=0.0) def get_field_value(self): return {"expected_output": self.expected_output, "expected_input": self.expected_input, - "marks": self.marks} + "weightage": self.weightage} def __str__(self): return u'Question: {0} | Exp. Output: {1} | Exp. Input: {2}'.format(self.question, -- cgit From 2100ef108b7119370051f8117c3bb58315fad270 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Thu, 10 Nov 2016 17:49:24 +0530 Subject: Fix minor errors, fix template rendering in grade user --- yaksh/models.py | 4 ---- 1 file changed, 4 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index 05528c7..bdcc43e 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -1090,14 +1090,10 @@ class AnswerPaper(models.Model): user_answer.marks = (question.points * result['weightage'] / question.get_maximum_test_case_weightage()) \ if question.partial_grading and question.type == 'code' else question.points - # user_answer.marks = question.points * result['weightage'] \ - # if question.partial_grading and question.type == 'code' else question.points else: user_answer.marks = (question.points * result['weightage'] / question.get_maximum_test_case_weightage()) \ if question.partial_grading and question.type == 'code' else 0 - # user_answer.marks = question.points * result['weightage'] \ - # if question.partial_grading and question.type == 'code' else 0 user_answer.save() self.update_marks('completed') return True, msg -- cgit From b32d7e91fe608c4cbd09b50520d4a3cab75d2e53 Mon Sep 17 00:00:00 2001 From: ankitjavalkar Date: Wed, 16 Nov 2016 11:25:30 +0530 Subject: Change test_case weightage field name to weight --- yaksh/models.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'yaksh/models.py') diff --git a/yaksh/models.py b/yaksh/models.py index bdcc43e..8907df0 100644 --- a/yaksh/models.py +++ b/yaksh/models.py @@ -325,12 +325,12 @@ class Question(models.Model): return test_case - def get_maximum_test_case_weightage(self, **kwargs): - max_weightage = 0.0 + def get_maximum_test_case_weight(self, **kwargs): + max_weight = 0.0 for test_case in self.get_test_cases(): - max_weightage += test_case.weightage + max_weight += test_case.weight - return max_weightage + return max_weight def _add_and_get_files(self, zip_file): files = FileUpload.objects.filter(question=self) @@ -1036,7 +1036,7 @@ class AnswerPaper(models.Model): For code questions success is True only if the answer is correct. """ - result = {'success': True, 'error': 'Incorrect answer', 'weightage': 0.0} + result = {'success': True, 'error': 'Incorrect answer', 'weight': 0.0} correct = False if user_answer is not None: if question.type == 'mcq': @@ -1087,12 +1087,12 @@ class AnswerPaper(models.Model): user_answer.correct = correct user_answer.error = result.get('error') if correct: - user_answer.marks = (question.points * result['weightage'] / - question.get_maximum_test_case_weightage()) \ + user_answer.marks = (question.points * result['weight'] / + question.get_maximum_test_case_weight()) \ if question.partial_grading and question.type == 'code' else question.points else: - user_answer.marks = (question.points * result['weightage'] / - question.get_maximum_test_case_weightage()) \ + user_answer.marks = (question.points * result['weight'] / + question.get_maximum_test_case_weight()) \ if question.partial_grading and question.type == 'code' else 0 user_answer.save() self.update_marks('completed') @@ -1118,11 +1118,11 @@ class TestCase(models.Model): class StandardTestCase(TestCase): test_case = models.TextField(blank=True) - weightage = models.FloatField(default=0.0) + weight = models.FloatField(default=0.0) def get_field_value(self): return {"test_case": self.test_case, - "weightage": self.weightage} + "weight": self.weight} def __str__(self): return u'Question: {0} | Test Case: {1}'.format(self.question, @@ -1133,12 +1133,12 @@ class StandardTestCase(TestCase): class StdioBasedTestCase(TestCase): expected_input = models.TextField(blank=True) expected_output = models.TextField() - weightage = models.IntegerField(default=0.0) + weight = models.IntegerField(default=0.0) def get_field_value(self): return {"expected_output": self.expected_output, "expected_input": self.expected_input, - "weightage": self.weightage} + "weight": self.weight} def __str__(self): return u'Question: {0} | Exp. Output: {1} | Exp. Input: {2}'.format(self.question, -- cgit