def update(self, subsection, only_if_higher=None): """ Updates the SubsectionGrade object for the student and subsection. """ # Save ourselves the extra queries if the course does not persist # subsection grades. self._log_event(log.warning, u"update, subsection: {}".format(subsection.location), subsection) calculated_grade = SubsectionGrade(subsection).init_from_structure( self.student, self.course_structure, self._submissions_scores, self._csm_scores, ) if PersistentGradesEnabledFlag.feature_enabled(self.course.id): if only_if_higher: try: grade_model = PersistentSubsectionGrade.read_grade(self.student.id, subsection.location) except PersistentSubsectionGrade.DoesNotExist: pass else: orig_subsection_grade = SubsectionGrade(subsection).init_from_model( self.student, grade_model, self.course_structure, self._submissions_scores, self._csm_scores, ) if not is_score_higher_or_equal( orig_subsection_grade.graded_total.earned, orig_subsection_grade.graded_total.possible, calculated_grade.graded_total.earned, calculated_grade.graded_total.possible, ): return orig_subsection_grade grade_model = calculated_grade.update_or_create_model(self.student) self._update_saved_subsection_grade(subsection.location, grade_model) return calculated_grade
def update(self, subsection, only_if_higher=None, score_deleted=False, force_update_subsections=False, persist_grade=True): """ Updates the SubsectionGrade object for the student and subsection. """ self._log_event(log.debug, u"update, subsection: {}".format(subsection.location), subsection) calculated_grade = CreateSubsectionGrade( subsection, self.course_data.structure, self._submissions_scores, self._csm_scores, ) if persist_grade and should_persist_grades(self.course_data.course_key): if only_if_higher: try: grade_model = PersistentSubsectionGrade.read_grade(self.student.id, subsection.location) except PersistentSubsectionGrade.DoesNotExist: pass else: orig_subsection_grade = ReadSubsectionGrade(subsection, grade_model, self) if not is_score_higher_or_equal( orig_subsection_grade.graded_total.earned, orig_subsection_grade.graded_total.possible, calculated_grade.graded_total.earned, calculated_grade.graded_total.possible, treat_undefined_as_zero=True, ): return orig_subsection_grade grade_model = calculated_grade.update_or_create_model( self.student, score_deleted, force_update_subsections ) self._update_saved_subsection_grade(subsection.location, grade_model) return calculated_grade
def update(self, subsection, only_if_higher=None, score_deleted=False): """ Updates the SubsectionGrade object for the student and subsection. """ self._log_event(log.debug, u"update, subsection: {}".format(subsection.location), subsection) calculated_grade = CreateSubsectionGrade( subsection, self.course_data.structure, self._submissions_scores, self._csm_scores, ) if should_persist_grades(self.course_data.course_key): if only_if_higher: try: grade_model = PersistentSubsectionGrade.read_grade(self.student.id, subsection.location) except PersistentSubsectionGrade.DoesNotExist: pass else: orig_subsection_grade = ReadSubsectionGrade(subsection, grade_model, self) if not is_score_higher_or_equal( orig_subsection_grade.graded_total.earned, orig_subsection_grade.graded_total.possible, calculated_grade.graded_total.earned, calculated_grade.graded_total.possible, ): return orig_subsection_grade grade_model = calculated_grade.update_or_create_model(self.student, score_deleted) self._update_saved_subsection_grade(subsection.location, grade_model) return calculated_grade
def score_published_handler(sender, block, user, raw_earned, raw_possible, only_if_higher, **kwargs): # pylint: disable=unused-argument """ Handles whenever a block's score is published. Returns whether the score was actually updated. """ update_score = True if only_if_higher: previous_score = get_score(user.id, block.location) if previous_score is not None: prev_raw_earned, prev_raw_possible = (previous_score.grade, previous_score.max_grade) if not is_score_higher_or_equal(prev_raw_earned, prev_raw_possible, raw_earned, raw_possible): update_score = False log.warning( u"Grades: Rescore is not higher than previous: " u"user: {}, block: {}, previous: {}/{}, new: {}/{} ". format( user, block.location, prev_raw_earned, prev_raw_possible, raw_earned, raw_possible, )) if update_score: # Set the problem score in CSM. score_modified_time = set_score(user.id, block.location, raw_earned, raw_possible) # Set the problem score on the xblock. if isinstance(block, ScorableXBlockMixin): block.set_score( Score(raw_earned=raw_earned, raw_possible=raw_possible)) # Fire a signal (consumed by enqueue_subsection_update, below) PROBLEM_RAW_SCORE_CHANGED.send( sender=None, raw_earned=raw_earned, raw_possible=raw_possible, weight=getattr(block, 'weight', None), user_id=user.id, course_id=unicode(block.location.course_key), usage_id=unicode(block.location), only_if_higher=only_if_higher, modified=score_modified_time, score_db_table=ScoreDatabaseTableEnum.courseware_student_module, score_deleted=kwargs.get('score_deleted', False), ) return update_score
def update(self, subsection, only_if_higher=None, score_deleted=False, force_update_subsections=False, persist_grade=True): # lint-amnesty, pylint: disable=line-too-long """ Updates the SubsectionGrade object for the student and subsection. """ self._log_event(log.debug, u"update, subsection: {}".format(subsection.location), subsection) calculated_grade = CreateSubsectionGrade( subsection, self.course_data.structure, self._submissions_scores, self._csm_scores, ) if persist_grade and should_persist_grades( self.course_data.course_key): if only_if_higher: try: grade_model = PersistentSubsectionGrade.read_grade( self.student.id, subsection.location) except PersistentSubsectionGrade.DoesNotExist: pass else: orig_subsection_grade = ReadSubsectionGrade( subsection, grade_model, self) if not is_score_higher_or_equal( orig_subsection_grade.graded_total.earned, orig_subsection_grade.graded_total.possible, calculated_grade.graded_total.earned, calculated_grade.graded_total.possible, treat_undefined_as_zero=True, ): return orig_subsection_grade grade_model = calculated_grade.update_or_create_model( self.student, score_deleted, force_update_subsections) self._update_saved_subsection_grade(subsection.location, grade_model) if settings.FEATURES.get( 'ENABLE_COURSE_ASSESSMENT_GRADE_CHANGE_SIGNAL'): COURSE_ASSESSMENT_GRADE_CHANGED.send( sender=self, course_id=self.course_data.course_key, user=self.student, subsection_id=calculated_grade.location, subsection_grade=calculated_grade.graded_total.earned) return calculated_grade
def update(self, subsection, only_if_higher=None, score_deleted=False): """ Updates the SubsectionGrade object for the student and subsection. """ # Save ourselves the extra queries if the course does not persist # subsection grades. self._log_event(log.warning, u"update, subsection: {}".format(subsection.location), subsection) calculated_grade = SubsectionGrade(subsection).init_from_structure( self.student, self.course_data.structure, self._submissions_scores, self._csm_scores, ) if should_persist_grades(self.course_data.course_key): if only_if_higher: try: grade_model = PersistentSubsectionGrade.read_grade( self.student.id, subsection.location) except PersistentSubsectionGrade.DoesNotExist: pass else: orig_subsection_grade = SubsectionGrade( subsection).init_from_model( self.student, grade_model, self.course_data.structure, self._submissions_scores, self._csm_scores, ) if not is_score_higher_or_equal( orig_subsection_grade.graded_total.earned, orig_subsection_grade.graded_total.possible, calculated_grade.graded_total.earned, calculated_grade.graded_total.possible, ): return orig_subsection_grade grade_model = calculated_grade.update_or_create_model( self.student, score_deleted) self._update_saved_subsection_grade(subsection.location, grade_model) return calculated_grade
def score_published_handler(sender, block, user, raw_earned, raw_possible, only_if_higher, **kwargs): # pylint: disable=unused-argument """ Handles whenever a block's score is published. Returns whether the score was actually updated. """ update_score = True if only_if_higher: previous_score = get_score(user.id, block.location) if previous_score is not None: prev_raw_earned, prev_raw_possible = (previous_score.grade, previous_score.max_grade) if not is_score_higher_or_equal(prev_raw_earned, prev_raw_possible, raw_earned, raw_possible): update_score = False log.warning( u"Grades: Rescore is not higher than previous: " u"user: {}, block: {}, previous: {}/{}, new: {}/{} ".format( user, block.location, prev_raw_earned, prev_raw_possible, raw_earned, raw_possible, ) ) if update_score: # Set the problem score in CSM. score_modified_time = set_score(user.id, block.location, raw_earned, raw_possible) # Set the problem score on the xblock. if isinstance(block, ScorableXBlockMixin): block.set_score(Score(raw_earned=raw_earned, raw_possible=raw_possible)) # Fire a signal (consumed by enqueue_subsection_update, below) PROBLEM_RAW_SCORE_CHANGED.send( sender=None, raw_earned=raw_earned, raw_possible=raw_possible, weight=getattr(block, 'weight', None), user_id=user.id, course_id=six.text_type(block.location.course_key), usage_id=six.text_type(block.location), only_if_higher=only_if_higher, modified=score_modified_time, score_db_table=ScoreDatabaseTableEnum.courseware_student_module, score_deleted=kwargs.get('score_deleted', False), grader_response=kwargs.get('grader_response', False) ) return update_score