'Gauge a user\'s progress towards program completion.
Keyword Arguments:
programs (list): Specific list of programs to check the user\'s progress
against. If left unspecified, self.engaged_programs will be used.
count_only (bool): Whether or not to return counts of completed, in
progress, and unstarted courses instead of serialized representations
of the courses.
Returns:
list of dict, each containing information about a user\'s progress
towards completing a program.'

def progress(self, programs=None, count_only=True):

    now = datetime.datetime.now(utc)
    progress = []
    programs = (programs or self.engaged_programs)
    for program in programs:
        program_copy = deepcopy(program)
        (completed, in_progress, not_started) = ([], [], [])
        for course in program_copy['courses']:
            if self._is_course_complete(course):
                completed.append(course)
            elif self._is_course_enrolled(course):
                course_in_progress = self._is_course_in_progress(now, course)
                if course_in_progress:
                    in_progress.append(course)
                else:
                    course['expired'] = (not course_in_progress)
                    not_started.append(course)
            else:
                not_started.append(course)
        progress.append({'uuid': program_copy['uuid'], 'completed': (len(completed) if count_only else completed), 'in_progress': (len(in_progress) if count_only else in_progress), 'not_started': (len(not_started) if count_only else not_started)})
    return progress
