context.py 2.81 KB
Newer Older
1 2 3
"""
Grading Context
"""
4
from collections import OrderedDict
5

6 7 8 9 10
from openedx.core.djangoapps.content.block_structure.api import get_course_in_cache

from .scores import possibly_scored


11
def grading_context_for_course(course_key):
12
    """
13
    Same as grading_context, but takes in a course key.
14
    """
15
    course_structure = get_course_in_cache(course_key)
16 17 18 19 20 21
    return grading_context(course_structure)


def grading_context(course_structure):
    """
    This returns a dictionary with keys necessary for quickly grading
22
    a student.
23 24

    The grading context has two keys:
25 26
    all_graded_subsections_by_type - This contains all subsections that are
        graded, keyed by subsection format (assignment type).
27

28 29 30
        The values are arrays of dictionaries containing
            "subsection_block" : The subsection block
            "scored_descendants" : An array of usage keys for blocks
31
                that could possibly be in the subsection, for any student
32 33 34 35 36 37 38 39

    all_graded_blocks - This contains a list of all blocks that can
        affect grading a student. This is used to efficiently fetch
        all the xmodule state for a FieldDataCache without walking
        the descriptor tree again.

    """
    all_graded_blocks = []
40
    all_graded_subsections_by_type = OrderedDict()
41 42

    for chapter_key in course_structure.get_children(course_structure.root_block_usage_key):
43 44 45 46
        for subsection_key in course_structure.get_children(chapter_key):
            subsection = course_structure[subsection_key]
            scored_descendants_of_subsection = []
            if subsection.graded:
47 48
                for descendant_key in course_structure.post_order_traversal(
                        filter_func=possibly_scored,
49
                        start_node=subsection_key,
50
                ):
51
                    scored_descendants_of_subsection.append(
52 53 54 55
                        course_structure[descendant_key],
                    )

                # include only those blocks that have scores, not if they are just a parent
56 57
                subsection_info = {
                    'subsection_block': subsection,
58
                    'scored_descendants': [
59
                        child for child in scored_descendants_of_subsection
60 61 62
                        if getattr(child, 'has_score', None)
                    ]
                }
63 64 65 66 67
                subsection_format = getattr(subsection, 'format', '')
                if subsection_format not in all_graded_subsections_by_type:
                    all_graded_subsections_by_type[subsection_format] = []
                all_graded_subsections_by_type[subsection_format].append(subsection_info)
                all_graded_blocks.extend(scored_descendants_of_subsection)
68 69

    return {
70
        'all_graded_subsections_by_type': all_graded_subsections_by_type,
71 72
        'all_graded_blocks': all_graded_blocks,
    }