Exemplo n.º 1
0
 def __init__(self, _xmodule_instance_args, _entry_id, course_id,
              _task_input, action_name):
     task_id = _xmodule_instance_args.get(
         'task_id') if _xmodule_instance_args is not None else None
     self.task_info_string = ('Task: {task_id}, '
                              'InstructorTask ID: {entry_id}, '
                              'Course: {course_id}, '
                              'Input: {task_input}').format(
                                  task_id=task_id,
                                  entry_id=_entry_id,
                                  course_id=course_id,
                                  task_input=_task_input,
                              )
     self.task_id = task_id
     self.entry_id = _entry_id
     self.task_input = _task_input
     self.action_name = action_name
     self.course_id = course_id
     self.report_for_verified_only = problem_grade_report_verified_only(
         self.course_id)
     self.task_progress = TaskProgress(self.action_name,
                                       total=None,
                                       start_time=time())
     self.upload_filename = _task_input.get('filename',
                                            'problem_grade_report')
     self.upload_dir = _task_input.get('upload_parent_dir', '')
Exemplo n.º 2
0
    def generate(cls, _xmodule_instance_args, _entry_id, course_id,
                 _task_input, action_name):
        """
        Generate a CSV containing all students' problem grades within a given
        `course_id`.
        """
        def log_task_info(message):
            """
            Updates the status on the celery task to the given message.
            Also logs the update.
            """
            fmt = u'Task: {task_id}, InstructorTask ID: {entry_id}, Course: {course_id}, Input: {task_input}'
            task_info_string = fmt.format(task_id=task_id,
                                          entry_id=_entry_id,
                                          course_id=course_id,
                                          task_input=_task_input)
            TASK_LOG.info(u'%s, Task type: %s, %s, %s', task_info_string,
                          action_name, message, task_progress.state)

        start_time = time()
        start_date = datetime.now(UTC)
        status_interval = 100
        task_id = _xmodule_instance_args.get(
            'task_id') if _xmodule_instance_args is not None else None

        enrolled_students = CourseEnrollment.objects.users_enrolled_in(
            course_id,
            include_inactive=True,
            verified_only=problem_grade_report_verified_only(course_id),
        )
        task_progress = TaskProgress(action_name, enrolled_students.count(),
                                     start_time)

        # This struct encapsulates both the display names of each static item in the
        # header row as values as well as the django User field names of those items
        # as the keys.  It is structured in this way to keep the values related.
        header_row = OrderedDict([('id', 'Student ID'), ('email', 'Email'),
                                  ('username', 'Username')])

        course = get_course_by_id(course_id)
        log_task_info(u'Retrieving graded scorable blocks')
        graded_scorable_blocks = cls._graded_scorable_blocks_to_header(course)

        # Just generate the static fields for now.
        rows = [
            list(header_row.values()) + ['Enrollment Status', 'Grade'] +
            _flatten(list(graded_scorable_blocks.values()))
        ]
        error_rows = [list(header_row.values()) + ['error_msg']]

        # Bulk fetch and cache enrollment states so we can efficiently determine
        # whether each user is currently enrolled in the course.
        log_task_info(u'Fetching enrollment status')
        CourseEnrollment.bulk_fetch_enrollment_states(enrolled_students,
                                                      course_id)

        for student, course_grade, error in CourseGradeFactory().iter(
                enrolled_students, course):
            student_fields = [
                getattr(student, field_name) for field_name in header_row
            ]
            task_progress.attempted += 1

            if not course_grade:
                err_msg = text_type(error)
                # There was an error grading this student.
                if not err_msg:
                    err_msg = u'Unknown error'
                error_rows.append(student_fields + [err_msg])
                task_progress.failed += 1
                continue

            enrollment_status = _user_enrollment_status(student, course_id)

            earned_possible_values = []
            for block_location in graded_scorable_blocks:
                try:
                    problem_score = course_grade.problem_scores[block_location]
                except KeyError:
                    earned_possible_values.append(
                        [u'Not Available', u'Not Available'])
                else:
                    if problem_score.first_attempted:
                        earned_possible_values.append(
                            [problem_score.earned, problem_score.possible])
                    else:
                        earned_possible_values.append(
                            [u'Not Attempted', problem_score.possible])

            rows.append(student_fields +
                        [enrollment_status, course_grade.percent] +
                        _flatten(earned_possible_values))

            task_progress.succeeded += 1
            if task_progress.attempted % status_interval == 0:
                step = u'Calculating Grades'
                task_progress.update_task_state(extra_meta={'step': step})
                log_message = u'{0} {1}/{2}'.format(step,
                                                    task_progress.attempted,
                                                    task_progress.total)
                log_task_info(log_message)

        log_task_info('Uploading CSV to store')
        # Perform the upload if any students have been successfully graded
        if len(rows) > 1:
            upload_csv_to_report_store(rows, 'problem_grade_report', course_id,
                                       start_date)
        # If there are any error rows, write them out as well
        if len(error_rows) > 1:
            upload_csv_to_report_store(error_rows, 'problem_grade_report_err',
                                       course_id, start_date)

        return task_progress.update_task_state(
            extra_meta={'step': 'Uploading CSV'})