def to_representation(self, instance): '''Takes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API. ''' # Don't use the instance argument here since it is a submission instance # if a new submission has been created by calling serializer.save() # This method needs to return the LTI Outcome parameters for the response renderer. ret = self.validated_data # using self.validated_data here implies that the serializer should always # be instantiated with the data argument, which is fine for LTI since # even read requests are posted with a request body if ret['req_type'] == LTIOutcomeXMLParser.TYPE_READ: exercise = ret['exercise'] submitter = ret['submitter'] summary = UserExerciseSummary(exercise, submitter.user) best_submission = summary.get_best_submission() if best_submission: # LTI score is a decimal value in the range 0.0 - 1.0. The decimal point must be a period. if exercise.max_points: ret['score'] = "{:f}".format(min(1, abs(best_submission.grade / exercise.max_points))) else: ret['score'] = '1.0' else: ret['score'] = '' # an empty result score should be returned if no grade has been set or it has been deleted elif ret['req_type'] == LTIOutcomeXMLParser.TYPE_DELETE: # we don't delete any submissions ret['code_major'] = LTIOutcomeResponseRenderer.CODE_MAJOR_UNSUPPORTED return ret
def to_representation(self, instance): '''Takes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API. ''' # Don't use the instance argument here since it is a submission instance # if a new submission has been created by calling serializer.save() # This method needs to return the LTI Outcome parameters for the response renderer. ret = self.validated_data # using self.validated_data here implies that the serializer should always # be instantiated with the data argument, which is fine for LTI since # even read requests are posted with a request body if ret['req_type'] == LTIOutcomeXMLParser.TYPE_READ: exercise = ret['exercise'] submitter = ret['submitter'] summary = UserExerciseSummary(exercise, submitter.user) best_submission = summary.get_best_submission() if best_submission: # LTI score is a decimal value in the range 0.0 - 1.0. The decimal point must be a period. if exercise.max_points: ret['score'] = "{:f}".format( min(1, abs(best_submission.grade / exercise.max_points))) else: ret['score'] = '1.0' else: ret['score'] = '' # an empty result score should be returned if no grade has been set or it has been deleted elif ret['req_type'] == LTIOutcomeXMLParser.TYPE_DELETE: # we don't delete any submissions ret['code_major'] = LTIOutcomeResponseRenderer.CODE_MAJOR_UNSUPPORTED return ret
def get_points(self, user, no_scaling=False): total_points = 0 tc_max_points = self.target_category_maxpoints max_points = self.max_points if tc_max_points == 0: return None timing, d1 = self.get_timing([user.userprofile],timezone.now()) if (timing == self.TIMING.CLOSED_AFTER or timing == self.TIMING.ARCHIVED or timing == self.TIMING.CLOSED_BEFORE or timing == self.TIMING.UNOFFICIAL): return None for exercise in self.exercises: summary = UserExerciseSummary(exercise, user) if summary.best_submission is not None: total_points += summary.best_submission.grade if timing == self.TIMING.LATE: total_points = round(total_points * (1 - self.course_module.late_submission_penalty)) if tc_max_points == max_points or no_scaling: return total_points total_points = total_points / (tc_max_points / max_points) return total_points
def _generate_grading_data(self, profile): feedback = "" grading_data = "" exercise_counter = 1 for exercise in self.exercises: submission = UserExerciseSummary(exercise, profile.user).best_submission if submission is None: grade = 0 else: grade = submission.grade feedback += "Exercise {}: {}/{}\n Course: {} - {}\n Exercise: {}\n".format( exercise_counter, grade, exercise.max_points, exercise.category.course_instance.course.name, exercise.category.course_instance.instance_name, exercise.name, ) exercise_counter += 1 feedback = "<pre>\n" + feedback + "\n</pre>\n" return {"grading_data": grading_data}, feedback
def test_unofficial_submission(self): self.course_module_with_late_submissions_allowed.late_submissions_allowed = False self.course_module_with_late_submissions_allowed.save() self.learning_object_category.accept_unofficial_submits = True self.learning_object_category.save() self.late_submission_when_late_allowed.set_points(10, 10) self.late_submission_when_late_allowed.set_ready() self.late_submission_when_late_allowed.save() self.assertEqual(self.late_submission_when_late_allowed.grade, 100) self.assertEqual(self.late_submission_when_late_allowed.status, Submission.STATUS.UNOFFICIAL) summary = UserExerciseSummary( self.base_exercise_with_late_submission_allowed, self.user) self.assertEqual(summary.get_submission_count(), 3) self.assertEqual(summary.get_points(), 0) # unofficial points are not shown here self.assertFalse(summary.is_graded()) self.assertTrue(summary.is_unofficial()) self.submission_when_late_allowed.set_points(5, 10) self.submission_when_late_allowed.set_ready() self.submission_when_late_allowed.save() self.assertEqual(self.submission_when_late_allowed.grade, 50) self.assertEqual(self.submission_when_late_allowed.status, Submission.STATUS.READY) summary = UserExerciseSummary( self.base_exercise_with_late_submission_allowed, self.user) self.assertEqual(summary.get_points(), 50) self.assertTrue(summary.is_graded()) self.assertFalse(summary.is_unofficial()) sub = Submission.objects.create( exercise=self.base_exercise_with_late_submission_allowed, grader=self.grader.userprofile) sub.submission_time = self.two_days_from_now + timedelta(days=1) sub.save() sub.submitters.add(self.user.userprofile) sub.set_points(10, 10) sub.save() summary = UserExerciseSummary( self.base_exercise_with_late_submission_allowed, self.user) self.assertEqual(summary.get_points(), 50) self.assertTrue(summary.is_graded()) self.assertFalse(summary.is_unofficial())
def test_unofficial_submission(self): self.course_module_with_late_submissions_allowed.late_submissions_allowed = False self.course_module_with_late_submissions_allowed.save() self.learning_object_category.accept_unofficial_submits = True self.learning_object_category.save() self.late_submission_when_late_allowed.set_points(10, 10) self.late_submission_when_late_allowed.set_ready() self.late_submission_when_late_allowed.save() self.assertEqual(self.late_submission_when_late_allowed.grade, 100) self.assertEqual(self.late_submission_when_late_allowed.status, Submission.STATUS.UNOFFICIAL) summary = UserExerciseSummary(self.base_exercise_with_late_submission_allowed, self.user) self.assertEqual(summary.get_submission_count(), 3) self.assertEqual(summary.get_points(), 100) self.assertFalse(summary.is_graded()) self.assertTrue(summary.is_unofficial()) self.submission_when_late_allowed.set_points(5, 10) self.submission_when_late_allowed.set_ready() self.submission_when_late_allowed.save() self.assertEqual(self.submission_when_late_allowed.grade, 50) self.assertEqual(self.submission_when_late_allowed.status, Submission.STATUS.READY) summary = UserExerciseSummary(self.base_exercise_with_late_submission_allowed, self.user) self.assertEqual(summary.get_points(), 50) self.assertTrue(summary.is_graded()) self.assertFalse(summary.is_unofficial()) sub = Submission.objects.create( exercise=self.base_exercise_with_late_submission_allowed, grader=self.grader.userprofile ) sub.submission_time = self.two_days_from_now + timedelta(days = 1) sub.save() sub.submitters.add(self.user.userprofile) sub.set_points(10, 10) sub.save() summary = UserExerciseSummary(self.base_exercise_with_late_submission_allowed, self.user) self.assertEqual(summary.get_points(), 50) self.assertTrue(summary.is_graded()) self.assertFalse(summary.is_unofficial())