Exemple #1
0
    def get(self, request, username, course_key, subsection_id):
        """
        Returns completion for a (user, subsection, course).
        """

        def get_completion(course_completions, all_blocks, block_id):
            """
            Recursively get the aggregate completion for a subsection,
            given the subsection block and a list of all blocks.

            Parameters:
                course_completions: a dictionary of completion values by block IDs
                all_blocks: a dictionary of the block structure for a subsection
                block_id: an ID of a block for which to get completion
            """
            block = all_blocks.get(block_id)
            child_ids = block.get('children', [])
            if not child_ids:
                return course_completions.get(block.serializer.instance, 0)

            completion = 0
            total_children = 0
            for child_id in child_ids:
                completion += get_completion(course_completions, all_blocks, child_id)
                total_children += 1

            return int(completion == total_children)

        user_id = User.objects.get(username=username).id
        block_types_filter = [
            'course',
            'chapter',
            'sequential',
            'vertical',
            'html',
            'problem',
            'video',
            'discussion',
            'drag-and-drop-v2'
        ]

        blocks = get_blocks(
            request,
            UsageKey.from_string(subsection_id),
            nav_depth=2,
            requested_fields=[
                'children'
            ],
            block_types_filter=block_types_filter
        )

        course_key = LearningContextKey.from_string(course_key)
        context_completions = BlockCompletion.get_learning_context_completions(user_id, course_key)
        aggregated_completion = get_completion(context_completions, blocks['blocks'], blocks['root'])

        return Response({"completion": aggregated_completion}, status=status.HTTP_200_OK)
    def mark_blocks_completed(block, user, course_key):
        """
        Walk course tree, marking block completion.
        Mark 'most recent completed block as 'resume_block'

        """
        last_completed_child_position = BlockCompletion.get_latest_block_completed(user, course_key)

        if last_completed_child_position:
            # Mutex w/ NOT 'course_block_completions'
            recurse_mark_complete(
                course_block_completions=BlockCompletion.get_learning_context_completions(user, course_key),
                latest_completion=last_completed_child_position,
                block=block
            )
Exemple #3
0
def get_subsection_completion_percentage(subsection_usage_key, user):
    """
    Computes completion percentage for a subsection in a given course for a user
    Arguments:
        subsection_usage_key: key of subsection
        user: The user whose completion percentage needs to be computed
    Returns:
        User's completion percentage for given subsection
    """
    subsection_completion_percentage = 0.0
    try:
        subsection_structure = get_course_blocks(user, subsection_usage_key)
        if any(subsection_structure):
            completable_blocks = []
            for block in subsection_structure:
                completion_mode = subsection_structure.get_xblock_field(
                    block, 'completion_mode')

                #  always exclude html blocks (in addition to EXCLUDED blocks) for gating calculations
                #  See https://openedx.atlassian.net/browse/WL-1798
                if completion_mode not in (CompletionMode.AGGREGATOR, CompletionMode.EXCLUDED) \
                        and not block.block_type == 'html':
                    completable_blocks.append(block)

            if not completable_blocks:
                return 100
            subsection_completion_total = 0
            course_key = subsection_usage_key.course_key
            course_block_completions = BlockCompletion.get_learning_context_completions(
                user, course_key)
            for block in completable_blocks:
                if course_block_completions.get(block):
                    subsection_completion_total += course_block_completions.get(
                        block)
            subsection_completion_percentage = min(
                100 *
                (subsection_completion_total / float(len(completable_blocks))),
                100)

    except ItemNotFoundError as err:
        log.warning(u"Could not find course_block for subsection=%s error=%s",
                    subsection_usage_key, err)

    return subsection_completion_percentage