def chapter_grades(self): """ Returns a list of chapters, each containing its subsection grades, display name, and url name. """ chapter_grades = [] for chapter_key in self.course_structure.get_children( self.course.location): chapter = self.course_structure[chapter_key] chapter_subsection_grades = [] children = self.course_structure.get_children(chapter_key) for subsection_key in children: chapter_subsection_grades.append( self._subsection_grade_factory.create( self.course_structure[subsection_key], read_only=True)) chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped( chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades }) return chapter_grades
def compute(self): """ Computes the grade for the given student and course. """ subsection_grade_factory = SubsectionGradeFactory(self.student) for chapter_key in self.course_structure.get_children( self.course.location): chapter = self.course_structure[chapter_key] subsection_grades = [] for subsection_key in self.course_structure.get_children( chapter_key): subsection_grades.append( subsection_grade_factory.create( self.course_structure[subsection_key], self.course_structure, self.course)) self.chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped( chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': subsection_grades }) self._signal_listeners_when_grade_computed()
def compute_and_update(self, read_only=False): """ Computes the grade for the given student and course. If read_only is True, doesn't save any updates to the grades. """ self._log_event(log.warning, u"compute_and_update, read_only: {}".format(read_only)) subsection_grade_factory = SubsectionGradeFactory( self.student, self.course, self.course_structure) for chapter_key in self.course_structure.get_children( self.course.location): chapter = self.course_structure[chapter_key] chapter_subsection_grades = [] for subsection_key in self.course_structure.get_children( chapter_key): chapter_subsection_grades.append( subsection_grade_factory.create( self.course_structure[subsection_key], read_only=True)) self.chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped( chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades }) if not read_only: subsection_grade_factory.bulk_create_unsaved() self._signal_listeners_when_grade_computed()
def compute_and_update(self, read_only=False): """ Computes the grade for the given student and course. If read_only is True, doesn't save any updates to the grades. """ self._log_event(log.warning, u"compute_and_update, read_only: {}".format(read_only)) subsection_grade_factory = SubsectionGradeFactory(self.student, self.course, self.course_structure) for chapter_key in self.course_structure.get_children(self.course.location): chapter = self.course_structure[chapter_key] chapter_subsection_grades = [] for subsection_key in self.course_structure.get_children(chapter_key): chapter_subsection_grades.append( subsection_grade_factory.create(self.course_structure[subsection_key], read_only=True) ) self.chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped(chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades }) if not read_only: subsection_grade_factory.bulk_create_unsaved() self._signal_listeners_when_grade_computed()
def chapter_grades(self): """ Returns a dictionary of dictionaries. The primary dictionary is keyed by the chapter's usage_key. The secondary dictionary contains the chapter's subsection grades, display name, and url name. """ chapter_grades = OrderedDict() for chapter_key in self.course_structure.get_children( self.course.location): chapter = self.course_structure[chapter_key] chapter_subsection_grades = [] children = self.course_structure.get_children(chapter_key) for subsection_key in children: chapter_subsection_grades.append( self._subsection_grade_factory.create( self.course_structure[subsection_key], read_only=True)) chapter_grades[chapter_key] = { 'display_name': block_metadata_utils.display_name_with_default_escaped( chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades } return chapter_grades
def _get_chapter_grade_info(self, chapter, course_structure): """ Helper that returns a dictionary of chapter grade information. """ chapter_subsection_grades = self._get_subsection_grades(course_structure, chapter.location) return { 'display_name': block_metadata_utils.display_name_with_default_escaped(chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades, }
def __init__(self, subsection): self.location = subsection.location self.display_name = block_metadata_utils.display_name_with_default_escaped(subsection) self.url_name = block_metadata_utils.url_name_for_block(subsection) self.format = getattr(subsection, 'format', '') self.due = getattr(subsection, 'due', None) self.graded = getattr(subsection, 'graded', False) self.graded_total = None # aggregated grade for all graded problems self.all_total = None # aggregated grade for all problems, regardless of whether they are graded self.locations_to_weighted_scores = OrderedDict() # dict of problem locations to (Score, weight) tuples
def compute_and_update(self, read_only=False): """ Computes the grade for the given student and course. If read_only is True, doesn't save any updates to the grades. """ subsection_grade_factory = SubsectionGradeFactory( self.student, self.course, self.course_structure) subsections_total = 0 for chapter_key in self.course_structure.get_children( self.course.location): chapter = self.course_structure[chapter_key] chapter_subsection_grades = [] children = self.course_structure.get_children(chapter_key) subsections_total += len(children) for subsection_key in children: chapter_subsection_grades.append( subsection_grade_factory.create( self.course_structure[subsection_key], read_only=True)) self.chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped( chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades }) total_graded_subsections = sum( len(x) for x in self.subsection_grade_totals_by_format.itervalues()) subsections_created = len( subsection_grade_factory._unsaved_subsection_grades) # pylint: disable=protected-access subsections_read = subsections_total - subsections_created blocks_total = len(self.locations_to_scores) if not read_only: subsection_grade_factory.bulk_create_unsaved() self._signal_listeners_when_grade_computed() self._log_event( log.warning, u"compute_and_update, read_only: {0}, subsections read/created: {1}/{2}, blocks accessed: {3}, total " u"graded subsections: {4}".format( read_only, subsections_read, subsections_created, blocks_total, total_graded_subsections, ))
def __init__(self, subsection): self.location = subsection.location self.display_name = block_metadata_utils.display_name_with_default_escaped(subsection) self.url_name = block_metadata_utils.url_name_for_block(subsection) self.format = getattr(subsection, 'format', '') self.due = getattr(subsection, 'due', None) self.graded = getattr(subsection, 'graded', False) self.show_correctness = getattr(subsection, 'show_correctness', '') self.course_version = getattr(subsection, 'course_version', None) self.subtree_edited_timestamp = getattr(subsection, 'subtree_edited_on', None) self.override = None
def __init__(self, subsection): self.location = subsection.location self.display_name = block_metadata_utils.display_name_with_default_escaped(subsection) self.url_name = block_metadata_utils.url_name_for_block(subsection) self.format = getattr(subsection, 'format', '') self.due = getattr(subsection, 'due', None) self.graded = getattr(subsection, 'graded', False) self.course_version = getattr(subsection, 'course_version', None) self.subtree_edited_timestamp = getattr(subsection, 'subtree_edited_on', None) self.graded_total = None # aggregated grade for all graded problems self.all_total = None # aggregated grade for all problems, regardless of whether they are graded
def __init__(self, subsection): self.location = subsection.location self.display_name = escape(block_metadata_utils.display_name_with_default(subsection)) self.url_name = block_metadata_utils.url_name_for_block(subsection) self.format = getattr(subsection, 'format', '') self.due = getattr(subsection, 'due', None) self.graded = getattr(subsection, 'graded', False) self.show_correctness = getattr(subsection, 'show_correctness', '') self.course_version = getattr(subsection, 'course_version', None) self.subtree_edited_timestamp = getattr(subsection, 'subtree_edited_on', None) self.override = None
def __init__(self, subsection): self.location = subsection.location self.display_name = block_metadata_utils.display_name_with_default_escaped(subsection) self.url_name = block_metadata_utils.url_name_for_block(subsection) self.format = getattr(subsection, 'format', '') self.due = getattr(subsection, 'due', None) self.graded = getattr(subsection, 'graded', False) self.course_version = getattr(subsection, 'course_version', None) self.subtree_edited_timestamp = getattr(subsection, 'subtree_edited_on', None) self.graded_total = None # aggregated grade for all graded problems self.all_total = None # aggregated grade for all problems, regardless of whether they are graded self.locations_to_scores = OrderedDict() # dict of problem locations to ProblemScore
def __init__(self, subsection): self.location = subsection.location self.display_name = block_metadata_utils.display_name_with_default(subsection) self.url_name = block_metadata_utils.url_name_for_block(subsection) self.due = getattr(subsection, 'due', None) self.end = getattr(subsection, 'end', None) self.format = getattr(subsection, 'format', '') self.graded = getattr(subsection, 'graded', False) transformer_data = getattr(subsection, 'transformer_data', None) hidden_content_data = transformer_data and subsection.transformer_data.get('hidden_content') self.hide_after_due = hidden_content_data and hidden_content_data.fields.get('merged_hide_after_due') self.self_paced = subsection.self_paced self.show_correctness = getattr(subsection, 'show_correctness', '') self.course_version = getattr(subsection, 'course_version', None) self.subtree_edited_timestamp = getattr(subsection, 'subtree_edited_on', None) self.override = None
def chapter_grades(self): """ Returns a list of chapters, each containing its subsection grades, display name, and url name. """ chapter_grades = [] for chapter_key in self.course_structure.get_children(self.course.location): chapter = self.course_structure[chapter_key] chapter_subsection_grades = [] children = self.course_structure.get_children(chapter_key) for subsection_key in children: chapter_subsection_grades.append( self._subsection_grade_factory.create(self.course_structure[subsection_key], read_only=True) ) chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped(chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades }) return chapter_grades
def compute_and_update(self, read_only=False): """ Computes the grade for the given student and course. If read_only is True, doesn't save any updates to the grades. """ subsection_grade_factory = SubsectionGradeFactory(self.student, self.course, self.course_structure) for chapter_key in self.course_structure.get_children(self.course.location): chapter = self.course_structure[chapter_key] chapter_subsection_grades = [] for subsection_key in self.course_structure.get_children(chapter_key): chapter_subsection_grades.append( subsection_grade_factory.create(self.course_structure[subsection_key], read_only=True) ) self.chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped(chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': chapter_subsection_grades }) subsections_total = sum(len(x) for x in self.subsection_grade_totals_by_format.itervalues()) subsections_read = len(subsection_grade_factory._unsaved_subsection_grades) # pylint: disable=protected-access subsections_created = subsections_total - subsections_read blocks_total = len(self.locations_to_scores) if not read_only: subsection_grade_factory.bulk_create_unsaved() self._signal_listeners_when_grade_computed() self._log_event( log.warning, u"compute_and_update, read_only: {0}, subsections read/created: {1}/{2}, blocks accessed: {3}".format( read_only, subsections_read, subsections_created, blocks_total, ) )
def compute(self): """ Computes the grade for the given student and course. """ subsection_grade_factory = SubsectionGradeFactory(self.student) for chapter_key in self.course_structure.get_children(self.course.location): chapter = self.course_structure[chapter_key] subsection_grades = [] for subsection_key in self.course_structure.get_children(chapter_key): subsection_grades.append( subsection_grade_factory.create( self.course_structure[subsection_key], self.course_structure, self.course ) ) self.chapter_grades.append({ 'display_name': block_metadata_utils.display_name_with_default_escaped(chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': subsection_grades }) self._signal_listeners_when_grade_computed()
def url_name(self): """ Returns this course's URL name. """ return block_metadata_utils.url_name_for_block(self)
def summary(student, course, course_structure=None): """ This pulls a summary of all problems in the course. Returns - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters, each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded problems, and is good for displaying a course summary with due dates, etc. - None if the student does not have access to load the course module. Arguments: student: A User object for the student to grade course: A Descriptor containing the course to grade """ if course_structure is None: course_structure = get_course_blocks(student, course.location) if not len(course_structure): return ProgressSummary() scorable_locations = [ block_key for block_key in course_structure if possibly_scored(block_key) ] with outer_atomic(): scores_client = ScoresClient.create_for_locations( course.id, student.id, scorable_locations) # We need to import this here to avoid a circular dependency of the form: # XBlock --> submissions --> Django Rest Framework error strings --> # Django translation --> ... --> courseware --> submissions from submissions import api as sub_api # installed from the edx-submissions repository with outer_atomic(): submissions_scores = sub_api.get_scores( unicode(course.id), anonymous_id_for_user(student, course.id)) # Check for gated content gated_content = gating_api.get_gated_content(course, student) chapters = [] locations_to_weighted_scores = {} for chapter_key in course_structure.get_children( course_structure.root_block_usage_key): chapter = course_structure[chapter_key] sections = [] for section_key in course_structure.get_children(chapter_key): if unicode(section_key) in gated_content: continue section = course_structure[section_key] graded = getattr(section, 'graded', False) scores = [] for descendant_key in course_structure.post_order_traversal( filter_func=possibly_scored, start_node=section_key, ): descendant = course_structure[descendant_key] (correct, total) = get_score( student, descendant, scores_client, submissions_scores, ) if correct is None and total is None: continue weighted_location_score = Score( correct, total, graded, block_metadata_utils.display_name_with_default_escaped( descendant), descendant.location) scores.append(weighted_location_score) locations_to_weighted_scores[ descendant.location] = weighted_location_score escaped_section_name = block_metadata_utils.display_name_with_default_escaped( section) section_total, _ = graders.aggregate_scores( scores, escaped_section_name) sections.append({ 'display_name': escaped_section_name, 'url_name': block_metadata_utils.url_name_for_block(section), 'scores': scores, 'section_total': section_total, 'format': getattr(section, 'format', ''), 'due': getattr(section, 'due', None), 'graded': graded, }) chapters.append({ 'course': course.display_name_with_default_escaped, 'display_name': block_metadata_utils.display_name_with_default_escaped(chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': sections }) return ProgressSummary(chapters, locations_to_weighted_scores, course_structure.get_children)
def _progress_summary(student, course, course_structure=None): """ Unwrapped version of "progress_summary". This pulls a summary of all problems in the course. Returns - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters, each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded problems, and is good for displaying a course summary with due dates, etc. - None if the student does not have access to load the course module. Arguments: student: A User object for the student to grade course: A Descriptor containing the course to grade """ if course_structure is None: course_structure = get_course_blocks(student, course.location) if not len(course_structure): return None scorable_locations = [block_key for block_key in course_structure if possibly_scored(block_key)] with outer_atomic(): scores_client = ScoresClient.create_for_locations(course.id, student.id, scorable_locations) # We need to import this here to avoid a circular dependency of the form: # XBlock --> submissions --> Django Rest Framework error strings --> # Django translation --> ... --> courseware --> submissions from submissions import api as sub_api # installed from the edx-submissions repository with outer_atomic(): submissions_scores = sub_api.get_scores( unicode(course.id), anonymous_id_for_user(student, course.id) ) # Check for gated content gated_content = gating_api.get_gated_content(course, student) chapters = [] locations_to_weighted_scores = {} for chapter_key in course_structure.get_children(course_structure.root_block_usage_key): chapter = course_structure[chapter_key] sections = [] for section_key in course_structure.get_children(chapter_key): if unicode(section_key) in gated_content: continue section = course_structure[section_key] graded = getattr(section, 'graded', False) scores = [] for descendant_key in course_structure.post_order_traversal( filter_func=possibly_scored, start_node=section_key, ): descendant = course_structure[descendant_key] (correct, total) = get_score( student, descendant, scores_client, submissions_scores, ) if correct is None and total is None: continue weighted_location_score = Score( correct, total, graded, block_metadata_utils.display_name_with_default_escaped(descendant), descendant.location ) scores.append(weighted_location_score) locations_to_weighted_scores[descendant.location] = weighted_location_score escaped_section_name = block_metadata_utils.display_name_with_default_escaped(section) section_total, _ = graders.aggregate_scores(scores, escaped_section_name) sections.append({ 'display_name': escaped_section_name, 'url_name': block_metadata_utils.url_name_for_block(section), 'scores': scores, 'section_total': section_total, 'format': getattr(section, 'format', ''), 'due': getattr(section, 'due', None), 'graded': graded, }) chapters.append({ 'course': course.display_name_with_default_escaped, 'display_name': block_metadata_utils.display_name_with_default_escaped(chapter), 'url_name': block_metadata_utils.url_name_for_block(chapter), 'sections': sections }) return ProgressSummary(chapters, locations_to_weighted_scores, course_structure.get_children)