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 )
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