Ejemplo n.º 1
0
    def collect_ora2_data(cls, course_id):
        """
        Query database for aggregated ora2 response data.

        Args:
            course_id (string) - the course id of the course whose data we would like to return

        Returns:
            A tuple containing two lists: headers and data.

            headers is a list containing strings corresponding to the column headers of the data.
            data is a list of lists, where each sub-list corresponds to a row in the table of all the data
                for this course.

        """

        all_submission_information = sub_api.get_all_course_submission_information(
            course_id, 'openassessment')

        rows = []
        for student_item, submission, score in all_submission_information:
            row = []
            assessments = cls._use_read_replica(
                Assessment.objects.prefetch_related('parts').prefetch_related(
                    'rubric').filter(submission_uuid=submission['uuid']))
            assessments_cell = cls._build_assessments_cell(assessments)
            assessments_parts_cell = cls._build_assessments_parts_cell(
                assessments)
            feedback_options_cell = cls._build_feedback_options_cell(
                assessments)
            feedback_cell = cls._build_feedback_cell(submission['uuid'])

            row = [
                submission['uuid'], submission['student_item'],
                student_item['student_id'], submission['submitted_at'],
                submission['answer'], assessments_cell, assessments_parts_cell,
                score.get('created_at', ''),
                score.get('points_earned', ''),
                score.get('points_possible',
                          ''), feedback_options_cell, feedback_cell
            ]
            rows.append(row)

        header = [
            'Submission ID', 'Item ID', 'Anonymized Student ID',
            'Date/Time Response Submitted', 'Response', 'Assessment Details',
            'Assessment Scores', 'Date/Time Final Score Given',
            'Final Score Points Earned', 'Final Score Points Possible',
            'Feedback Statements Selected', 'Feedback on Peer Assessments'
        ]
        return header, rows
Ejemplo n.º 2
0
    def test_get_course_submissions(self, set_scores):
        submission1 = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
        submission2 = api.create_submission(STUDENT_ITEM, ANSWER_TWO)
        submission3 = api.create_submission(SECOND_STUDENT_ITEM, ANSWER_ONE)
        submission4 = api.create_submission(SECOND_STUDENT_ITEM, ANSWER_TWO)

        if set_scores:
            api.set_score(submission1['uuid'], 1, 4)
            api.set_score(submission2['uuid'], 2, 4)
            api.set_score(submission3['uuid'], 3, 4)
            api.set_score(submission4['uuid'], 4, 4)

        submissions_and_scores = list(
            api.get_all_course_submission_information(
                STUDENT_ITEM['course_id'],
                STUDENT_ITEM['item_type'],
                read_replica=False,
            ))

        student_item1 = self._get_student_item(STUDENT_ITEM)
        student_item2 = self._get_student_item(SECOND_STUDENT_ITEM)

        self.assertDictEqual(SECOND_STUDENT_ITEM, submissions_and_scores[0][0])
        self._assert_submission(submissions_and_scores[0][1],
                                submission4['answer'], student_item2.pk, 2)

        self.assertDictEqual(SECOND_STUDENT_ITEM, submissions_and_scores[1][0])
        self._assert_submission(submissions_and_scores[1][1],
                                submission3['answer'], student_item2.pk, 1)

        self.assertDictEqual(STUDENT_ITEM, submissions_and_scores[2][0])
        self._assert_submission(submissions_and_scores[2][1],
                                submission2['answer'], student_item1.pk, 2)

        self.assertDictEqual(STUDENT_ITEM, submissions_and_scores[3][0])
        self._assert_submission(submissions_and_scores[3][1],
                                submission1['answer'], student_item1.pk, 1)

        # These scores will always be empty
        self.assertEqual(submissions_and_scores[1][2], {})
        self.assertEqual(submissions_and_scores[3][2], {})

        if set_scores:
            self._assert_score(submissions_and_scores[0][2], 4, 4)
            self._assert_score(submissions_and_scores[2][2], 2, 4)
        else:
            self.assertEqual(submissions_and_scores[0][2], {})
            self.assertEqual(submissions_and_scores[2][2], {})
Ejemplo n.º 3
0
    def test_get_course_submissions(self, set_scores):
        submission1 = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
        submission2 = api.create_submission(STUDENT_ITEM, ANSWER_TWO)
        submission3 = api.create_submission(SECOND_STUDENT_ITEM, ANSWER_ONE)
        submission4 = api.create_submission(SECOND_STUDENT_ITEM, ANSWER_TWO)

        if set_scores:
            api.set_score(submission1['uuid'], 1, 4)
            api.set_score(submission2['uuid'], 2, 4)
            api.set_score(submission3['uuid'], 3, 4)
            api.set_score(submission4['uuid'], 4, 4)

        submissions_and_scores = list(api.get_all_course_submission_information(
            STUDENT_ITEM['course_id'],
            STUDENT_ITEM['item_type'],
            read_replica=False,
        ))

        student_item1 = self._get_student_item(STUDENT_ITEM)
        student_item2 = self._get_student_item(SECOND_STUDENT_ITEM)

        self.assertDictEqual(SECOND_STUDENT_ITEM, submissions_and_scores[0][0])
        self._assert_submission(submissions_and_scores[0][1], submission4['answer'], student_item2.pk, 2)

        self.assertDictEqual(SECOND_STUDENT_ITEM, submissions_and_scores[1][0])
        self._assert_submission(submissions_and_scores[1][1], submission3['answer'], student_item2.pk, 1)

        self.assertDictEqual(STUDENT_ITEM, submissions_and_scores[2][0])
        self._assert_submission(submissions_and_scores[2][1], submission2['answer'], student_item1.pk, 2)

        self.assertDictEqual(STUDENT_ITEM, submissions_and_scores[3][0])
        self._assert_submission(submissions_and_scores[3][1], submission1['answer'], student_item1.pk, 1)

        # These scores will always be empty
        self.assertEqual(submissions_and_scores[1][2], {})
        self.assertEqual(submissions_and_scores[3][2], {})

        if set_scores:
            self._assert_score(submissions_and_scores[0][2], 4, 4)
            self._assert_score(submissions_and_scores[2][2], 2, 4)
        else:
            self.assertEqual(submissions_and_scores[0][2], {})
            self.assertEqual(submissions_and_scores[2][2], {})
Ejemplo n.º 4
0
    def collect_ora2_data(cls, course_id):
        """
        Query database for aggregated ora2 response data.

        Args:
            course_id (string) - the course id of the course whose data we would like to return

        Returns:
            A tuple containing two lists: headers and data.

            headers is a list containing strings corresponding to the column headers of the data.
            data is a list of lists, where each sub-list corresponds to a row in the table of all the data
                for this course.

        """

        all_submission_information = sub_api.get_all_course_submission_information(course_id, 'openassessment')

        rows = []
        for student_item, submission, score in all_submission_information:
            row = []
            assessments = cls._use_read_replica(
                Assessment.objects.prefetch_related('parts').
                prefetch_related('rubric').
                filter(
                    submission_uuid=submission['uuid']
                )
            )
            assessments_cell = cls._build_assessments_cell(assessments)
            assessments_parts_cell = cls._build_assessments_parts_cell(assessments)
            feedback_options_cell = cls._build_feedback_options_cell(assessments)
            feedback_cell = cls._build_feedback_cell(submission['uuid'])

            row = [
                submission['uuid'],
                submission['student_item'],
                student_item['student_id'],
                submission['submitted_at'],
                submission['answer'],
                assessments_cell,
                assessments_parts_cell,
                score.get('created_at', ''),
                score.get('points_earned', ''),
                score.get('points_possible', ''),
                feedback_options_cell,
                feedback_cell
            ]
            rows.append(row)

        header = [
            'Submission ID',
            'Item ID',
            'Anonymized Student ID',
            'Date/Time Response Submitted',
            'Response',
            'Assessment Details',
            'Assessment Scores',
            'Date/Time Final Score Given',
            'Final Score Points Earned',
            'Final Score Points Possible',
            'Feedback Statements Selected',
            'Feedback on Peer Assessments'
        ]
        return header, rows
Ejemplo n.º 5
0
    def collect_ora2_data(cls, course_id):
        """
        Query database for aggregated ora2 response data.

        Args:
            course_id (string) - the course id of the course whose data we would like to return

        Returns:
            A tuple containing two lists: headers and data.

            headers is a list containing strings corresponding to the column headers of the data.
            data is a list of lists, where each sub-list corresponds to a row in the table of all the data
                for this course.

        """
        all_submission_information = list(sub_api.get_all_course_submission_information(course_id, 'openassessment'))
        usernames_enabled = cls._usernames_enabled()

        usernames_map = (
            cls._map_sudents_and_scorers_ids_to_usernames(all_submission_information)
            if usernames_enabled
            else {}
        )
        block_display_names_map = cls._map_block_usage_keys_to_display_names(course_id)

        rows = []
        for student_item, submission, score in all_submission_information:
            assessments = cls._use_read_replica(
                Assessment.objects.prefetch_related('parts').
                prefetch_related('rubric').
                filter(
                    submission_uuid=submission['uuid']
                )
            )
            assessments_cell = cls._build_assessments_cell(assessments, usernames_map)
            assessments_parts_cell = cls._build_assessments_parts_cell(assessments)
            feedback_options_cell = cls._build_feedback_options_cell(assessments)
            feedback_cell = cls._build_feedback_cell(submission['uuid'])

            row_username_cell = (
                [usernames_map.get(student_item["student_id"], "")]
                if usernames_enabled
                else []
            )

            problem_name = block_display_names_map.get(student_item['item_id'])

            row = [
                submission['uuid'],
                student_item['item_id'],
                problem_name,
                submission['student_item'],
            ] + row_username_cell + [
                student_item['student_id'],
                submission['submitted_at'],
                #  Dumping required to render special characters in CSV
                json.dumps(submission['answer'], ensure_ascii=False),
                assessments_cell,
                assessments_parts_cell,
                score.get('created_at', ''),
                score.get('points_earned', ''),
                score.get('points_possible', ''),
                feedback_options_cell,
                feedback_cell
            ]
            rows.append(row)

        header_username_cell = (
            ['Username']
            if usernames_enabled
            else []
        )

        header = [
            'Submission ID',
            'Location',
            'Problem Name',
            'Item ID'
        ] + header_username_cell + [
            'Anonymized Student ID',
            'Date/Time Response Submitted',
            'Response',
            'Assessment Details',
            'Assessment Scores',
            'Date/Time Final Score Given',
            'Final Score Points Earned',
            'Final Score Points Possible',
            'Feedback Statements Selected',
            'Feedback on Peer Assessments'
        ]
        return header, rows
Ejemplo n.º 6
0
    def collect_ora2_submission_files(cls, course_id):
        """
        Generator, that yields dictionaries with information about submission
        attachment or answer text.
        """

        all_submission_information = sub_api.get_all_course_submission_information(
            course_id, 'openassessment')

        for student, submission, _ in all_submission_information:
            raw_answer = submission.get('answer', dict())
            answer = OraSubmissionAnswerFactory.parse_submission_raw_answer(
                raw_answer)
            for uploaded_file in answer.get_file_uploads():
                yield {
                    'type':
                    cls.ATTACHMENT,
                    'course_id':
                    course_id,
                    'block_id':
                    student['item_id'],
                    'student_id':
                    student['student_id'],
                    'key':
                    uploaded_file.key,
                    'name':
                    uploaded_file.name,
                    'description':
                    uploaded_file.description,
                    'size':
                    uploaded_file.size,
                    'file_path':
                    os.path.join(
                        str(course_id),
                        student['item_id'],
                        student['student_id'],
                        'attachments',
                        uploaded_file.name,
                    )
                }

            # collecting submission answer texts
            for index, text_response in enumerate(answer.get_text_responses()):
                file_name = 'part_{}.txt'.format(index)

                yield {
                    'type':
                    cls.TEXT,
                    'course_id':
                    course_id,
                    'block_id':
                    student['item_id'],
                    'student_id':
                    student['student_id'],
                    'key':
                    '',
                    'name':
                    file_name,
                    'description':
                    'Submission text.',
                    'content':
                    text_response,
                    'size':
                    len(text_response),
                    'file_path':
                    os.path.join(
                        str(course_id),
                        student['item_id'],
                        student['student_id'],
                        file_name,
                    )
                }
Ejemplo n.º 7
0
    def collect_ora2_submission_files(cls, course_id):
        """
        Generator, that yields dictionaries with information about submission
        attachment or answer text.
        """

        all_submission_information = sub_api.get_all_course_submission_information(
            course_id, 'openassessment')

        for student, submission, _ in all_submission_information:
            answer = submission.get('answer', dict())

            # collecting submission attachments with metadata
            for index, file_key in enumerate(answer.get('file_keys', [])):
                # Old submissions (approx. pre-2020) have file names under the key "files_name",
                # and even older ones don't have file names at all
                file_names = answer.get('files_names',
                                        answer.get('files_name', []))
                try:
                    file_name = file_names[index]
                except IndexError:
                    file_name = "File_" + str(index + 1)

                # 'files_sizes' was added sometime around the beginning of 2020, so older submissions
                # will not have it
                file_size = 0
                file_sizes = answer.get('files_sizes')
                if file_sizes:
                    file_size = file_sizes[index]

                yield {
                    'type':
                    cls.ATTACHMENT,
                    'course_id':
                    course_id,
                    'block_id':
                    student['item_id'],
                    'student_id':
                    student['student_id'],
                    'key':
                    file_key,
                    'name':
                    file_name,
                    'description':
                    answer['files_descriptions'][index],
                    'size':
                    file_size,
                    'file_path':
                    os.path.join(
                        str(course_id),
                        student['item_id'],
                        student['student_id'],
                        'attachments',
                        file_name,
                    )
                }

            # collecting submission answer texts
            for index, part in enumerate(answer.get('parts', [])):
                content = part['text']

                file_name = 'part_{}.txt'.format(index)

                yield {
                    'type':
                    cls.TEXT,
                    'course_id':
                    course_id,
                    'block_id':
                    student['item_id'],
                    'student_id':
                    student['student_id'],
                    'key':
                    '',
                    'name':
                    file_name,
                    'description':
                    'Submission text.',
                    'content':
                    content,
                    'size':
                    len(content),
                    'file_path':
                    os.path.join(
                        str(course_id),
                        student['item_id'],
                        student['student_id'],
                        file_name,
                    )
                }