예제 #1
0
    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
예제 #2
0
    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()
예제 #3
0
    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()
예제 #4
0
    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()
예제 #5
0
    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
예제 #6
0
 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,
     }
예제 #7
0
 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,
     }
예제 #8
0
    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
예제 #9
0
    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,
            ))
예제 #10
0
    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
예제 #11
0
    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
예제 #12
0
    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
예제 #13
0
    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
예제 #15
0
    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
예제 #16
0
    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,
            )
        )
예제 #17
0
    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()
예제 #18
0
 def url_name(self):
     """
     Returns this course's URL name.
     """
     return block_metadata_utils.url_name_for_block(self)
예제 #19
0
 def url_name(self):
     """
     Returns this course's URL name.
     """
     return block_metadata_utils.url_name_for_block(self)
예제 #20
0
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)
예제 #21
0
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)