def _get_subsections(self, course, graded_only=False): """ Helper function that returns a list of subsections contained in the given course. Args: course - A course object. graded_only - If true, returns only graded subsections (defaults to False). """ subsections = [] short_labeler = get_default_short_labeler(course) for subsection in self._get_visible_subsections(course): if graded_only and not subsection.graded: continue short_label = None if subsection.graded: short_label = short_labeler(subsection.format) subsections.append({ 'assignment_type': subsection.format, 'graded': subsection.graded, 'short_label': short_label, 'module_id': text_type(subsection.location), 'display_name': subsection.display_name, }) return subsections
def _get_subsections(self, course, graded_only=False): """ Helper function that returns a list of subsections contained in the given course. Args: course - A course object. graded_only - If true, returns only graded subsections (defaults to False). """ subsections = [] short_labeler = get_default_short_labeler(course) for subsection in self._get_visible_subsections(course): if graded_only and not subsection.graded: continue short_label = None if subsection.graded: short_label = short_labeler(subsection.format) subsections.append({ 'assignment_type': subsection.format, 'graded': subsection.graded, 'short_label': short_label, 'module_id': text_type(subsection.location), 'display_name': subsection.display_name, }) return subsections
def _section_breakdown(self, course, graded_subsections, course_grade): """ Given a course_grade and a list of graded subsections for a given course, returns a list of grade data broken down by subsection. Args: course: A Course Descriptor object graded_subsections: A list of graded subsection objects in the given course. course_grade: A CourseGrade object. """ breakdown = [] default_labeler = get_default_short_labeler(course) for subsection in graded_subsections: subsection_grade = course_grade.subsection_grade(subsection.location) short_label = default_labeler(subsection_grade.format) graded_description = 'Not Attempted' score_earned = 0 score_possible = 0 # For ZeroSubsectionGrades, we don't want to crawl the subsection's # subtree to find the problem scores specific to this user # (ZeroSubsectionGrade.attempted_graded is always False). # We've already fetched the whole course structure in a non-user-specific way # when creating `graded_subsections`. Looking at the problem scores # specific to this user (the user in `course_grade.user`) would require # us to re-fetch the user-specific course structure from the modulestore, # which is a costly operation. So we only drill into the `graded_total` # attribute if the user has attempted this graded subsection, or if there # has been a grade override applied. if subsection_grade.attempted_graded or subsection_grade.override: graded_description = '({earned:.2f}/{possible:.2f})'.format( earned=subsection_grade.graded_total.earned, possible=subsection_grade.graded_total.possible, ) score_earned = subsection_grade.graded_total.earned score_possible = subsection_grade.graded_total.possible # TODO: https://openedx.atlassian.net/browse/EDUCATOR-3559 -- Some fields should be renamed, others removed: # 'displayed_value' should maybe be 'description_percent' # 'grade_description' should be 'description_ratio' breakdown.append({ 'category': subsection_grade.format, 'displayed_value': '{:.2f}'.format(subsection_grade.percent_graded), 'is_graded': subsection_grade.graded, 'grade_description': graded_description, 'label': short_label, 'letter_grade': course_grade.letter_grade, 'module_id': text_type(subsection_grade.location), 'percent': subsection_grade.percent_graded, 'score_earned': score_earned, 'score_possible': score_possible, 'subsection_name': subsection_grade.display_name, }) return breakdown
def _section_breakdown(self, course, graded_subsections, course_grade): """ Given a course_grade and a list of graded subsections for a given course, returns a list of grade data broken down by subsection. Args: course: A Course Descriptor object graded_subsections: A list of graded subsection objects in the given course. course_grade: A CourseGrade object. """ breakdown = [] default_labeler = get_default_short_labeler(course) for subsection in graded_subsections: subsection_grade = course_grade.subsection_grade(subsection.location) short_label = default_labeler(subsection_grade.format) graded_description = 'Not Attempted' score_earned = 0 score_possible = 0 # For ZeroSubsectionGrades, we don't want to crawl the subsection's # subtree to find the problem scores specific to this user # (ZeroSubsectionGrade.attempted_graded is always False). # We've already fetched the whole course structure in a non-specific way # when creating `graded_subsections`. Looking at the problem scores # specific to this user (the user in `course_grade.user`) would require # us to re-fetch the user-specific course structure from the modulestore, # which is a costly operation. if subsection_grade.attempted_graded: graded_description = '({earned:.2f}/{possible:.2f})'.format( earned=subsection_grade.graded_total.earned, possible=subsection_grade.graded_total.possible, ) score_earned = subsection_grade.graded_total.earned score_possible = subsection_grade.graded_total.possible # TODO: https://openedx.atlassian.net/browse/EDUCATOR-3559 -- Some fields should be renamed, others removed: # 'displayed_value' should maybe be 'description_percent' # 'grade_description' should be 'description_ratio' breakdown.append({ 'category': subsection_grade.format, 'displayed_value': '{:.2f}'.format(subsection_grade.percent_graded), 'is_graded': subsection_grade.graded, 'grade_description': graded_description, 'label': short_label, 'letter_grade': course_grade.letter_grade, 'module_id': text_type(subsection_grade.location), 'percent': subsection_grade.percent_graded, 'score_earned': score_earned, 'score_possible': score_possible, 'subsection_name': subsection_grade.display_name, }) return breakdown
def _section_breakdown(self, course, course_grade): """ Given a course_grade, returns a list of grade data broken down by subsection and a dictionary containing aggregate grade data by subsection format for the course. Args: course_grade: A CourseGrade object. """ breakdown = [] aggregates = defaultdict(lambda: defaultdict(float)) # TODO: https://openedx.atlassian.net/browse/EDUCATOR-3559 # Fields we may not need: # ['are_grades_published', 'auto_grade', 'comment', 'detail', 'is_ag', 'is_average', 'is_manually_graded'] # Some fields should be renamed: # 'displayed_value' should maybe be 'description_percent' # 'grade_description' should be 'description_ratio' label_finder = SubsectionLabelFinder(course_grade) default_labeler = get_default_short_labeler(course) for chapter_location, section_data in course_grade.chapter_grades.items(): for subsection_grade in section_data['sections']: default_short_label = default_labeler(subsection_grade.format) breakdown.append({ 'are_grades_published': True, 'auto_grade': False, 'category': subsection_grade.format, 'chapter_name': section_data['display_name'], 'comment': '', 'detail': '', 'displayed_value': '{:.2f}'.format(subsection_grade.percent_graded), 'is_graded': subsection_grade.graded, 'grade_description': '({earned:.2f}/{possible:.2f})'.format( earned=subsection_grade.graded_total.earned, possible=subsection_grade.graded_total.possible, ), 'is_ag': False, 'is_average': False, 'is_manually_graded': False, 'label': label_finder.get_label(subsection_grade.display_name) or default_short_label, 'letter_grade': course_grade.letter_grade, 'module_id': text_type(subsection_grade.location), 'percent': subsection_grade.percent_graded, 'score_earned': subsection_grade.graded_total.earned, 'score_possible': subsection_grade.graded_total.possible, 'section_block_id': text_type(chapter_location), 'subsection_name': subsection_grade.display_name, }) if subsection_grade.graded and subsection_grade.graded_total.possible > 0: aggregates[subsection_grade.format]['score_earned'] += subsection_grade.graded_total.earned aggregates[subsection_grade.format]['score_possible'] += subsection_grade.graded_total.possible return breakdown, aggregates