def test_reset_different_student_item(self, changed):
        # Create a submissions for two students
        submission = sub_api.create_submission(self.STUDENT_ITEM, "test answer")
        sub_api.set_score(submission["uuid"], 1, 2)

        other_student = copy.copy(self.STUDENT_ITEM)
        other_student.update(changed)
        submission = sub_api.create_submission(other_student, "other test answer")
        sub_api.set_score(submission["uuid"], 3, 4)

        # Reset the score for the first student
        sub_api.reset_score(
            self.STUDENT_ITEM["student_id"], self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["item_id"]
        )

        # The first student's scores should be reset
        self.assertIs(sub_api.get_score(self.STUDENT_ITEM), None)
        scores = sub_api.get_scores(self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["student_id"])
        self.assertNotIn(self.STUDENT_ITEM["item_id"], scores)

        # But the second student should still have a score
        score = sub_api.get_score(other_student)
        self.assertEqual(score["points_earned"], 3)
        self.assertEqual(score["points_possible"], 4)
        scores = sub_api.get_scores(other_student["course_id"], other_student["student_id"])
        self.assertIn(other_student["item_id"], scores)
Exemple #2
0
    def test_reset_different_student_item(self, changed):
        # Create a submissions for two students
        submission = sub_api.create_submission(self.STUDENT_ITEM,
                                               'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        other_student = copy.copy(self.STUDENT_ITEM)
        other_student.update(changed)
        submission = sub_api.create_submission(other_student,
                                               'other test answer')
        sub_api.set_score(submission['uuid'], 3, 4)

        # Reset the score for the first student
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )

        # The first student's scores should be reset
        self.assertIs(sub_api.get_score(self.STUDENT_ITEM), None)
        scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'],
                                    self.STUDENT_ITEM['student_id'])
        self.assertNotIn(self.STUDENT_ITEM['item_id'], scores)

        # But the second student should still have a score
        score = sub_api.get_score(other_student)
        self.assertEqual(score['points_earned'], 3)
        self.assertEqual(score['points_possible'], 4)
        scores = sub_api.get_scores(other_student['course_id'],
                                    other_student['student_id'])
        self.assertIn(other_student['item_id'], scores)
    def test_override_with_no_score(self):

        sub_api.score_override(
            self.STUDENT_ITEM,
            8,
            10,
        )

        self.assertEqual(sub_api.get_score(self.STUDENT_ITEM)['points_earned'], 8)
        self.assertEqual(sub_api.get_score(self.STUDENT_ITEM)['points_possible'], 10)
Exemple #4
0
    def test_peer_evaluation_workflow(self):
        tim = self._create_student_and_submission("Tim", "Tim's answer")
        bob = self._create_student_and_submission("Bob", "Bob's answer")
        sally = self._create_student_and_submission("Sally", "Sally's answer")
        jim = self._create_student_and_submission("Jim", "Jim's answer")
        buffy = self._create_student_and_submission("Buffy", "Buffy's answer")
        xander = self._create_student_and_submission("Xander", "Xander's answer")

        # Tim should not have a score, because he has not evaluated enough
        # peer submissions.
        scores = sub_api.get_score(STUDENT_ITEM)
        self.assertFalse(scores)

        self.assertFalse(api.has_finished_required_evaluating("Tim", REQUIRED_GRADED))
        api.create_evaluation(
            bob["uuid"], "Tim", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )
        api.create_evaluation(
            sally["uuid"], "Tim", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )
        self.assertFalse(api.has_finished_required_evaluating("Tim", REQUIRED_GRADED))
        api.create_evaluation(
            jim["uuid"], "Tim", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )
        self.assertFalse(api.has_finished_required_evaluating("Tim", REQUIRED_GRADED))
        api.create_evaluation(
            buffy["uuid"], "Tim", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )
        self.assertFalse(api.has_finished_required_evaluating("Tim", REQUIRED_GRADED))
        api.create_evaluation(
            xander["uuid"], "Tim", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )
        self.assertTrue(api.has_finished_required_evaluating("Tim", REQUIRED_GRADED))

        # Tim should not have a score, because his submission does not have
        # enough evaluations.
        scores = sub_api.get_score(STUDENT_ITEM)
        self.assertFalse(scores)

        api.create_evaluation(
            tim["uuid"], "Bob", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )
        api.create_evaluation(
            tim["uuid"], "Sally", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )
        api.create_evaluation(
            tim["uuid"], "Jim", REQUIRED_GRADED, REQUIRED_GRADED_BY, ASSESSMENT_DICT
        )

        # Tim has met the critera, and should now have a score.
        scores = sub_api.get_score(STUDENT_ITEM)
        self.assertTrue(scores)
        self.assertEqual(6, scores[0]["points_earned"])
        self.assertEqual(12, scores[0]["points_possible"])
    def test_override_with_no_score(self):

        sub_api.score_override(
            self.STUDENT_ITEM,
            8,
            10,
        )

        self.assertEqual(
            sub_api.get_score(self.STUDENT_ITEM)['points_earned'], 8)
        self.assertEqual(
            sub_api.get_score(self.STUDENT_ITEM)['points_possible'], 10)
    def test_override_with_one_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 10)

        sub_api.score_override(
            self.STUDENT_ITEM,
            5,
            10,
        )

        self.assertEqual(sub_api.get_score(self.STUDENT_ITEM)['points_earned'], 5)
        self.assertEqual(sub_api.get_score(self.STUDENT_ITEM)['points_possible'], 10)
Exemple #7
0
    def test_delete_submission_scores(self):
        user = UserFactory()
        course_id = 'ora2/1/1'
        item_id = 'i4x://ora2/1/openassessment/b3dce2586c9c4876b73e7f390e42ef8f'

        # Create a student module for the user
        StudentModule.objects.create(
            student=user, course_id=course_id, module_state_key=item_id, state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, course_id),
            'course_id': course_id,
            'item_id': item_id,
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(course_id, user, item_id, delete_module=True)

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Exemple #8
0
 def get_score(self, id=None):
     """
     Get student's current score.
     """
     score = submissions_api.get_score(self.student_submission_id(id))
     if score:
         return score['points_earned']
    def test_delete_student_state_resets_scores(self):
        item_id = 'i4x://MITx/999/openassessment/b3dce2586c9c4876b73e7f390e42ef8f'

        # Create a student module for the user
        StudentModule.objects.create(
            student=self.student, course_id=self.course.id, module_state_key=item_id, state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(self.student, self.course.id),
            'course_id': self.course.id,
            'item_id': item_id,
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        url = reverse('instructor_dashboard_legacy', kwargs={'course_id': self.course.id})
        response = self.client.post(url, {
            'action': 'Delete student state for module',
            'unique_student_identifier': self.student.email,
            'problem_for_student': 'openassessment/b3dce2586c9c4876b73e7f390e42ef8f',
        })

        self.assertEqual(response.status_code, 200)

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
    def test_delete_submission_scores(self, _lti_mock):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key("dummy", "module")

        # Create a student module for the user
        StudentModule.objects.create(
            student=user, course_id=self.course_key, module_state_key=problem_location, state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            "student_id": anonymous_id_for_user(user, self.course_key),
            "course_id": self.course_key.to_deprecated_string(),
            "item_id": problem_location.to_deprecated_string(),
            "item_type": "openassessment",
        }
        submission = sub_api.create_submission(student_item, "test answer")
        sub_api.set_score(submission["uuid"], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(self.course_key, user, problem_location, requesting_user=user, delete_module=True)

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Exemple #11
0
    def code_submit(self, data, suffix=''):
        """
        AJAX handler for Submit button
        """

        if (self.grader_id == ''):
            return {
                'error':
                'You can not submit the assignment as no grader_id is configured'
            }

        submission = sub_api.create_submission(self.student_item_key, data)

        submitted_code = data["submitted_code"]
        grading_result = java_code_grader.grade(self.grader_id, submitted_code)
        if grading_result.has_key("error"):
            sub_api.set_score(submission['uuid'], 0, self.max_points)
        else:
            sub_api.set_score(submission['uuid'], self.max_points,
                              self.max_points)

        new_score = sub_api.get_score(self.student_item_key)

        submit_result = {
            'points_earned': new_score['points_earned'],
            'points_possible': new_score['points_possible']
        }

        if grading_result.has_key("error"):
            submit_result["error"] = grading_result["error"]

        return submit_result
Exemple #12
0
def _has_database_updated_with_new_score(
    user_id,
    scored_block_usage_key,
    expected_modified_time,
    score_deleted,
):
    """
    Returns whether the database has been updated with the
    expected new score values for the given problem and user.
    """
    score = get_score(user_id, scored_block_usage_key)

    if score is None:
        # score should be None only if it was deleted.
        # Otherwise, it hasn't yet been saved.
        return score_deleted
    elif score.module_type == 'openassessment':
        anon_id = anonymous_id_for_user(User.objects.get(id=user_id),
                                        scored_block_usage_key.course_key)
        course_id = unicode(scored_block_usage_key.course_key)
        item_id = unicode(scored_block_usage_key)

        api_score = sub_api.get_score({
            "student_id": anon_id,
            "course_id": course_id,
            "item_id": item_id,
            "item_type": "openassessment"
        })
        reported_modified_time = api_score.created_at
    else:
        reported_modified_time = score.modified

    return reported_modified_time >= expected_modified_time
    def test_delete_student_state_resets_scores(self):
        problem_location = self.course.id.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(student=self.student,
                                     course_id=self.course.id,
                                     module_state_key=problem_location,
                                     state=json.dumps({}))

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(self.student, self.course.id),
            'course_id': self.course.id.to_deprecated_string(),
            'item_id': problem_location.to_deprecated_string(),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        url = reverse(
            'instructor_dashboard_legacy',
            kwargs={'course_id': self.course.id.to_deprecated_string()})
        response = self.client.post(
            url, {
                'action': 'Delete student state for module',
                'unique_student_identifier': self.student.email,
                'problem_for_student': problem_location.to_deprecated_string(),
            })

        self.assertEqual(response.status_code, 200)

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Exemple #14
0
    def test_reset_then_add_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM,
                                               'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Reset scores
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )

        # Score the student again
        sub_api.set_score(submission['uuid'], 3, 4)

        # Expect that the new score is available
        score = sub_api.get_score(self.STUDENT_ITEM)
        self.assertEqual(score['points_earned'], 3)
        self.assertEqual(score['points_possible'], 4)

        scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'],
                                    self.STUDENT_ITEM['student_id'])
        self.assertIn(self.STUDENT_ITEM['item_id'], scores)
        self.assertEqual(scores[self.STUDENT_ITEM['item_id']], (3, 4))
Exemple #15
0
def _has_database_updated_with_new_score(
        user_id, scored_block_usage_key, expected_modified_time, score_deleted,
):
    """
    Returns whether the database has been updated with the
    expected new score values for the given problem and user.
    """
    score = get_score(user_id, scored_block_usage_key)

    if score is None:
        # score should be None only if it was deleted.
        # Otherwise, it hasn't yet been saved.
        return score_deleted
    elif score.module_type == 'openassessment':
        anon_id = anonymous_id_for_user(User.objects.get(id=user_id), scored_block_usage_key.course_key)
        course_id = unicode(scored_block_usage_key.course_key)
        item_id = unicode(scored_block_usage_key)

        api_score = sub_api.get_score(
            {
                "student_id": anon_id,
                "course_id": course_id,
                "item_id": item_id,
                "item_type": "openassessment"
            }
        )
        reported_modified_time = api_score.created_at
    else:
        reported_modified_time = score.modified

    return reported_modified_time >= expected_modified_time
    def test_override_with_one_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM,
                                               'test answer')
        sub_api.set_score(submission['uuid'], 1, 10)

        sub_api.score_override(
            self.STUDENT_ITEM,
            5,
            10,
        )

        self.assertEqual(
            sub_api.get_score(self.STUDENT_ITEM)['points_earned'], 5)
        self.assertEqual(
            sub_api.get_score(self.STUDENT_ITEM)['points_possible'], 10)
Exemple #17
0
    def test_delete_submission_scores(self):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(
            student=user,
            course_id=self.course_key,
            module_state_key=problem_location,
            state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, self.course_key),
            'course_id': self.course_key.to_deprecated_string(),
            'item_id': problem_location.to_deprecated_string(),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(
            self.course_key, user, problem_location,
            delete_module=True
        )

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
 def get_score(self, user):
     """
     Return student's current score.
     """
     score = submissions_api.get_score(self.get_submission_id(user))
     if score:
         return score['points_earned']
    def test_delete_student_state_resets_scores(self):
        item_id = 'i4x://MITx/999/openassessment/b3dce2586c9c4876b73e7f390e42ef8f'

        # Create a student module for the user
        StudentModule.objects.create(
            student=self.student, course_id=self.course.id, module_state_key=item_id, state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(self.student, self.course.id),
            'course_id': self.course.id,
            'item_id': item_id,
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id})
        response = self.client.post(url, {
            'action': 'Delete student state for module',
            'unique_student_identifier': self.student.email,
            'problem_for_student': 'openassessment/b3dce2586c9c4876b73e7f390e42ef8f',
        })

        self.assertEqual(response.status_code, 200)

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
    def test_delete_student_state_resets_scores(self):
        problem_location = self.course.id.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(
            student=self.student,
            course_id=self.course.id,
            module_state_key=problem_location,
            state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(self.student, self.course.id),
            'course_id': self.course.id.to_deprecated_string(),
            'item_id': problem_location.to_deprecated_string(),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        url = reverse('instructor_dashboard_legacy', kwargs={'course_id': self.course.id.to_deprecated_string()})
        response = self.client.post(url, {
            'action': 'Delete student state for module',
            'unique_student_identifier': self.student.email,
            'problem_for_student': problem_location.to_deprecated_string(),
        })

        self.assertEqual(response.status_code, 200)

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Exemple #21
0
    def test_delete_submission_scores(self):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(student=user,
                                     course_id=self.course_key,
                                     module_state_key=problem_location,
                                     state=json.dumps({}))

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, self.course_key),
            'course_id': self.course_key.to_deprecated_string(),
            'item_id': problem_location.to_deprecated_string(),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(self.course_key,
                               user,
                               problem_location,
                               delete_module=True)

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
Exemple #22
0
 def get_score(self, id=None):
     """
     Get student's current score.
     """
     score = submissions_api.get_score(self.student_submission_id(id))
     if score:
         return score['points_earned']
Exemple #23
0
 def get_score(self, student_id=None):
     """
     Return student's current score.
     """
     score = submissions_api.get_score(
         self.get_student_item_dict(student_id))
     if score:
         return score['points_earned']
    def point_string(self):
        if self.show_points_earned:
            score = sub_api.get_score(self.student_item_key)
            if score != None:
                return str(score['points_earned']) + ' / ' + str(
                    score['points_possible']) + ' point(s)'

        return str(self.max_points) + ' point(s) possible'
    def test_reset_with_no_scores(self):
        sub_api.reset_score(
            self.STUDENT_ITEM["student_id"], self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["item_id"]
        )
        self.assertIs(sub_api.get_score(self.STUDENT_ITEM), None)

        scores = sub_api.get_scores(self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["student_id"])
        self.assertEqual(len(scores), 0)
Exemple #26
0
 def get_score(self, student_id=None):
     """
     Return student's current score.
     """
     score = submissions_api.get_score(
         self.get_student_item_dict(student_id)
     )
     if score:
         return score['points_earned']
    def test_override_after_reset_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 10)

        # Reset score
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )

        sub_api.score_override(
            self.STUDENT_ITEM,
            5,
            10,
        )

        self.assertEqual(sub_api.get_score(self.STUDENT_ITEM)['points_earned'], 5)
        self.assertEqual(sub_api.get_score(self.STUDENT_ITEM)['points_possible'], 10)
Exemple #28
0
    def test_clear_state(self):
        # Create a submission, give it a score, and verify that score exists
        submission = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
        api.set_score(submission["uuid"], 11, 12)
        score = api.get_score(STUDENT_ITEM)
        self._assert_score(score, 11, 12)
        self.assertEqual(score['submission_uuid'], submission['uuid'])

        # Reset the score with clear_state=True
        # This should set the submission's score to None, and make it unavailable to get_submissions
        api.reset_score(
            STUDENT_ITEM["student_id"],
            STUDENT_ITEM["course_id"],
            STUDENT_ITEM["item_id"],
            clear_state=True,
        )
        score = api.get_score(STUDENT_ITEM)
        self.assertIsNone(score)
        subs = api.get_submissions(STUDENT_ITEM)
        self.assertEqual(subs, [])
Exemple #29
0
    def test_clear_state(self):
        # Create a submission, give it a score, and verify that score exists
        submission = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
        api.set_score(submission["uuid"], 11, 12)
        score = api.get_score(STUDENT_ITEM)
        self._assert_score(score, 11, 12)
        self.assertEqual(score['submission_uuid'], submission['uuid'])

        # Reset the score with clear_state=True
        # This should set the submission's score to None, and make it unavailable to get_submissions
        api.reset_score(
            STUDENT_ITEM["student_id"],
            STUDENT_ITEM["course_id"],
            STUDENT_ITEM["item_id"],
            clear_state=True,
        )
        score = api.get_score(STUDENT_ITEM)
        self.assertIsNone(score)
        subs = api.get_submissions(STUDENT_ITEM)
        self.assertEqual(subs, [])
Exemple #30
0
    def test_reset_with_no_scores(self):
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )
        self.assertIs(sub_api.get_score(self.STUDENT_ITEM), None)

        scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'],
                                    self.STUDENT_ITEM['student_id'])
        self.assertEqual(len(scores), 0)
Exemple #31
0
    def setUp(self):
        super(TestOraAggregateDataIntegration, self).setUp()
        # Create submissions and assessments
        self.submission = self._create_submission(STUDENT_ITEM)
        self.scorer_submission = self._create_submission(SCORER_ITEM)
        self.earned_points = 1
        self.possible_points = 2
        peer_api.get_submission_to_assess(self.scorer_submission['uuid'], 1)
        self.assessment = self._create_assessment(self.scorer_submission['uuid'])

        sub_api.set_score(self.submission['uuid'], self.earned_points, self.possible_points)
        self.score = sub_api.get_score(STUDENT_ITEM)
        peer_api.get_score(self.submission['uuid'], {'must_be_graded_by': 1, 'must_grade': 0})
        self._create_assessment_feedback(self.submission['uuid'])
    def test_override_after_reset_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM,
                                               'test answer')
        sub_api.set_score(submission['uuid'], 1, 10)

        # Reset score
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )

        sub_api.score_override(
            self.STUDENT_ITEM,
            5,
            10,
        )

        self.assertEqual(
            sub_api.get_score(self.STUDENT_ITEM)['points_earned'], 5)
        self.assertEqual(
            sub_api.get_score(self.STUDENT_ITEM)['points_possible'], 10)
    def test_reset_with_one_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM, "test answer")
        sub_api.set_score(submission["uuid"], 1, 2)

        # Reset scores
        sub_api.reset_score(
            self.STUDENT_ITEM["student_id"], self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["item_id"]
        )

        # Expect that no scores are available for the student
        self.assertIs(sub_api.get_score(self.STUDENT_ITEM), None)
        scores = sub_api.get_scores(self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["student_id"])
        self.assertEqual(len(scores), 0)
Exemple #34
0
def _has_db_updated_with_new_score(self, scored_block_usage_key, **kwargs):
    """
    Returns whether the database has been updated with the
    expected new score values for the given problem and user.
    """
    if kwargs[
            'score_db_table'] == ScoreDatabaseTableEnum.courseware_student_module:
        score = get_score(kwargs['user_id'], scored_block_usage_key)
        found_modified_time = score.modified if score is not None else None

    elif kwargs['score_db_table'] == ScoreDatabaseTableEnum.submissions:
        score = sub_api.get_score({
            "student_id":
            kwargs['anonymous_user_id'],
            "course_id":
            six.text_type(scored_block_usage_key.course_key),
            "item_id":
            six.text_type(scored_block_usage_key),
            "item_type":
            scored_block_usage_key.block_type,
        })
        found_modified_time = score['created_at'] if score is not None else None
    else:
        assert kwargs['score_db_table'] == ScoreDatabaseTableEnum.overrides
        from . import api
        score = api.get_subsection_grade_override(
            user_id=kwargs['user_id'],
            course_key_or_id=kwargs['course_id'],
            usage_key_or_id=kwargs['usage_id'])
        found_modified_time = score.modified if score is not None else None

    if score is None:
        # score should be None only if it was deleted.
        # Otherwise, it hasn't yet been saved.
        db_is_updated = kwargs['score_deleted']
    else:
        db_is_updated = found_modified_time >= from_timestamp(
            kwargs['expected_modified_time'])

    if not db_is_updated:
        log.info(
            u"Grades: tasks._has_database_updated_with_new_score is False. Task ID: {}. Kwargs: {}. Found "
            u"modified time: {}".format(
                self.request.id,
                kwargs,
                found_modified_time,
            ))

    return db_is_updated
Exemple #35
0
    def test_asynch_generate_score(self, xblock, mock_is_admin):
        # Test that AI grading, which creates assessments asynchronously,
        # updates the workflow so students can receive a score.
        mock_is_admin.return_value = True

        # Train classifiers for the problem
        self.request(xblock, 'schedule_training', json.dumps({}), response_format='json')

        # Submit a response
        self.request(xblock, 'submit', self.SUBMISSION, response_format='json')

        # BEFORE viewing the grade page, check that we get a score
        score = sub_api.get_score(xblock.get_student_item_dict())
        self.assertIsNot(score, None)
        self.assertEqual(score['submission_uuid'], xblock.submission_uuid)
Exemple #36
0
    def setUp(self):
        super(TestOraAggregateDataIntegration, self).setUp()
        self.maxDiff = None  # pylint: disable=invalid-name
        # Create submissions and assessments
        self.submission = self._create_submission(STUDENT_ITEM)
        self.scorer_submission = self._create_submission(SCORER_ITEM)
        self.earned_points = 1
        self.possible_points = 2
        peer_api.get_submission_to_assess(self.scorer_submission['uuid'], 1)
        self.assessment = self._create_assessment(self.scorer_submission['uuid'])
        self.assertEqual(self.assessment['parts'][0]['criterion']['label'], "criterion_1")

        sub_api.set_score(self.submission['uuid'], self.earned_points, self.possible_points)
        self.score = sub_api.get_score(STUDENT_ITEM)
        peer_api.get_score(self.submission['uuid'], {'must_be_graded_by': 1, 'must_grade': 0})
        self._create_assessment_feedback(self.submission['uuid'])
    def test_reset_with_multiple_scores(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)
        sub_api.set_score(submission['uuid'], 2, 2)

        # Reset scores
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )

        # Expect that no scores are available for the student
        self.assertIs(sub_api.get_score(self.STUDENT_ITEM), None)
        scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'], self.STUDENT_ITEM['student_id'])
        self.assertEqual(len(scores), 0)
Exemple #38
0
def _has_db_updated_with_new_score(self, scored_block_usage_key, **kwargs):
    """
    Returns whether the database has been updated with the
    expected new score values for the given problem and user.
    """
    if kwargs['score_db_table'] == ScoreDatabaseTableEnum.courseware_student_module:
        score = get_score(kwargs['user_id'], scored_block_usage_key)
        found_modified_time = score.modified if score is not None else None

    elif kwargs['score_db_table'] == ScoreDatabaseTableEnum.submissions:
        score = sub_api.get_score(
            {
                "student_id": kwargs['anonymous_user_id'],
                "course_id": unicode(scored_block_usage_key.course_key),
                "item_id": unicode(scored_block_usage_key),
                "item_type": scored_block_usage_key.block_type,
            }
        )
        found_modified_time = score['created_at'] if score is not None else None
    else:
        assert kwargs['score_db_table'] == ScoreDatabaseTableEnum.overrides
        score = GradesService().get_subsection_grade_override(
            user_id=kwargs['user_id'],
            course_key_or_id=kwargs['course_id'],
            usage_key_or_id=kwargs['usage_id']
        )
        found_modified_time = score.modified if score is not None else None

    if score is None:
        # score should be None only if it was deleted.
        # Otherwise, it hasn't yet been saved.
        db_is_updated = kwargs['score_deleted']
    else:
        db_is_updated = found_modified_time >= from_timestamp(kwargs['expected_modified_time'])

    if not db_is_updated:
        log.info(
            u"Grades: tasks._has_database_updated_with_new_score is False. Task ID: {}. Kwargs: {}. Found "
            u"modified time: {}".format(
                self.request.id,
                kwargs,
                found_modified_time,
            )
        )

    return db_is_updated
Exemple #39
0
    def test_reset_with_one_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM,
                                               'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Reset scores
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )

        # Expect that no scores are available for the student
        self.assertIs(sub_api.get_score(self.STUDENT_ITEM), None)
        scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'],
                                    self.STUDENT_ITEM['student_id'])
        self.assertEqual(len(scores), 0)
Exemple #40
0
    def test_asynch_generate_score(self, xblock, mock_is_admin):
        # Test that AI grading, which creates assessments asynchronously,
        # updates the workflow so students can receive a score.
        mock_is_admin.return_value = True

        # Train classifiers for the problem
        self.request(xblock,
                     'schedule_training',
                     json.dumps({}),
                     response_format='json')

        # Submit a response
        self.request(xblock, 'submit', self.SUBMISSION, response_format='json')

        # BEFORE viewing the grade page, check that we get a score
        score = sub_api.get_score(xblock.get_student_item_dict())
        self.assertIsNot(score, None)
        self.assertEqual(score['submission_uuid'], xblock.submission_uuid)
    def test_reset_then_add_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM, "test answer")
        sub_api.set_score(submission["uuid"], 1, 2)

        # Reset scores
        sub_api.reset_score(
            self.STUDENT_ITEM["student_id"], self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["item_id"]
        )

        # Score the student again
        sub_api.set_score(submission["uuid"], 3, 4)

        # Expect that the new score is available
        score = sub_api.get_score(self.STUDENT_ITEM)
        self.assertEqual(score["points_earned"], 3)
        self.assertEqual(score["points_possible"], 4)

        scores = sub_api.get_scores(self.STUDENT_ITEM["course_id"], self.STUDENT_ITEM["student_id"])
        self.assertIn(self.STUDENT_ITEM["item_id"], scores)
        self.assertEqual(scores[self.STUDENT_ITEM["item_id"]], (3, 4))
Exemple #42
0
    def test_delete_submission_scores(self, _mock_send_signal,
                                      mock_set_receiver, mock_reset_receiver):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(student=user,
                                     course_id=self.course_key,
                                     module_state_key=problem_location,
                                     state=json.dumps({}))

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, self.course_key),
            'course_id': text_type(self.course_key),
            'item_id': text_type(problem_location),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(
            self.course_key,
            user,
            problem_location,
            requesting_user=user,
            delete_module=True,
        )

        # Make sure our grades signal receivers handled the reset properly
        mock_set_receiver.assert_not_called()
        mock_reset_receiver.assert_called_once()

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
    def test_delete_submission_scores(self, _mock_send_signal, mock_set_receiver, mock_reset_receiver):
        user = UserFactory()
        problem_location = self.course_key.make_usage_key('dummy', 'module')

        # Create a student module for the user
        StudentModule.objects.create(
            student=user,
            course_id=self.course_key,
            module_state_key=problem_location,
            state=json.dumps({})
        )

        # Create a submission and score for the student using the submissions API
        student_item = {
            'student_id': anonymous_id_for_user(user, self.course_key),
            'course_id': text_type(self.course_key),
            'item_id': text_type(problem_location),
            'item_type': 'openassessment'
        }
        submission = sub_api.create_submission(student_item, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Delete student state using the instructor dash
        reset_student_attempts(
            self.course_key, user, problem_location,
            requesting_user=user,
            delete_module=True,
        )

        # Make sure our grades signal receivers handled the reset properly
        mock_set_receiver.assert_not_called()
        mock_reset_receiver.assert_called_once()

        # Verify that the student's scores have been reset in the submissions API
        score = sub_api.get_score(student_item)
        self.assertIs(score, None)
    def test_reset_then_add_score(self):
        # Create a submission for the student and score it
        submission = sub_api.create_submission(self.STUDENT_ITEM, 'test answer')
        sub_api.set_score(submission['uuid'], 1, 2)

        # Reset scores
        sub_api.reset_score(
            self.STUDENT_ITEM['student_id'],
            self.STUDENT_ITEM['course_id'],
            self.STUDENT_ITEM['item_id'],
        )

        # Score the student again
        sub_api.set_score(submission['uuid'], 3, 4)

        # Expect that the new score is available
        score = sub_api.get_score(self.STUDENT_ITEM)
        self.assertEqual(score['points_earned'], 3)
        self.assertEqual(score['points_possible'], 4)

        scores = sub_api.get_scores(self.STUDENT_ITEM['course_id'], self.STUDENT_ITEM['student_id'])
        self.assertIn(self.STUDENT_ITEM['item_id'], scores)
        item_score = scores[self.STUDENT_ITEM['item_id']]
        self.assertEqual((item_score['points_earned'], item_score['points_possible']), (3, 4))
Exemple #45
0
    def student_view(self, *args, **kwargs):
        """
        Отображение MultiEngineXBlock студенту (LMS).
        """
        
        scenarios = self.load_scenarios
        context = {
            "display_name": self.display_name,
            "weight": self.weight,
            "question": self.question,
            "correct_answer": self.correct_answer,
            "answer": self.answer,
            "attempts": self.attempts,
            "student_state_json": self.student_state_json,
            "student_view_template": self.student_view_template,
            "scenario": self.scenario,
            "scenarios": scenarios,
        }

        # Rescore student
        score = submissions_api.get_score(self.get_student_item_dict())

        # It's temporary! It's crutch, not magick.
        self.runtime.publish(self, 'grade', {
                'value': self.points,
                'max_value': self.weight,
        })

        if self.max_attempts != 0:
            context["max_attempts"] = self.max_attempts

        if self.past_due():
            context["past_due"] = True

        if self.answer != '{}':
            context["points"] = self.points

        if answer_opportunity(self):
            context["answer_opportunity"] = True

        if self.is_course_staff() is True or self.is_instructor() is True:
            context['is_course_staff'] = True

        fragment = Fragment()
        fragment.add_content(
            render_template(
                'static/html/multiengine.html',
                context
            )
        )

        js_urls = (
            'static/js/multiengine.js',
        )

        css_urls = (
            'static/css/multiengine.css',
        )

        self.load_resources(js_urls, css_urls, fragment)

        fragment.initialize_js('MultiEngineXBlock')
        return fragment
Exemple #46
0
 def score(self):
     """Score: The student score."""
     api_score = submissions_api.get_score(self.submission_id)
     if api_score:
         return Score(api_score['points_earned'], api_score['points_possible'])
    def student_view(self, *args, **kwargs):
        """
        Отображение MultiEngineXBlock студенту (LMS).
        """
        
        scenarios = self.load_scenarios
        context = {
            "display_name": self.display_name,
            "weight": self.weight,
            "question": self.question,
            "correct_answer": self.correct_answer,
            #"answer": self.answer,
            "attempts": self.attempts,
            "student_state_json": self.student_state_json,
            "student_view_template": self.student_view_template,
            "scenario": self.scenario,
            "scenarios": scenarios,
        }

        # Rescore student
        score = submissions_api.get_score(self.get_student_item_dict())

        # It's temporary! It's crutch, not magick.
        self.runtime.publish(self, 'grade', {
                'value': self.points,
                'max_value': self.weight,
        })

        if self.max_attempts != 0:
            context["max_attempts"] = self.max_attempts

        if self.past_due():
            context["past_due"] = True

        if self.answer != '{}':
            context["points"] = self.points

        if answer_opportunity(self):
            context["answer_opportunity"] = True

        if self.is_course_staff() is True or self.is_instructor() is True:
            context['is_course_staff'] = True

        fragment = Fragment()
        fragment.add_content(
            render_template(
                'static/html/multiengine.html',
                context
            )
        )

        js_urls = (
            'static/js/multiengine.js',
        )

        css_urls = (
            'static/css/multiengine.css',
        )

        self.load_resources(js_urls, css_urls, fragment)

        fragment.initialize_js('MultiEngineXBlock')
        return fragment
Exemple #48
0
    def handle_grades_file(self, file):
        """Read the file and set score and finalize flag and fresh flag and grade date and comment.
        Note:
            We expect a csv file following this structure:
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
                | Username | Name | Filename | Uploaded at          | Fresh answer | Finalized | Grade Date           | Grade | Max grade | Comment  |
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
                | student1 | S.St | 5.PNG    | 10-03-2020 16:01 MSK | False        | False     | 10-03-2020 16:05 MSK | 23    | 100       | bad work |
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
                | student2 | Mary | 7.JPG    | 15-03-2020 11:01 MSK | True         | False     |                      |       | 100       |          |
                +----------+------+----------+----------------------+--------------+-----------+----------------------+-------+-----------+----------+
        Args:
            file: The grades csv file.
        """
        grades_file = csv.DictReader(file, [
            'username', 'fullname', 'filename', 'timestamp', 'fresh',
            'finalized', 'date_fin', 'score', 'max_score', 'comment'
        ],
                                     delimiter=',')
        for line, row in enumerate(grades_file):
            if line:
                user = get_user_by_username_or_email(row['username'])
                module = self.get_or_create_student_module(user)
                state = json.loads(module.state)
                student_id = anonymous_id_for_user(
                    user, CourseKey.from_string(self.block_course_id))
                score = submissions_api.get_score(
                    self.get_student_item_dict(student_id))
                new = False
                if score and score['points_earned'] == row['score']:
                    pass
                elif score or row['score']:
                    new = True

                submission = self.get_submission(student_id)
                if not submission:
                    continue
                uuid = submission['uuid']
                if new:
                    submissions_api.set_score(uuid, row['score'],
                                              self.max_score())
                submission_obj = Submission.objects.get(uuid=uuid)
                if submission_obj.answer['finalized'] != json.loads(
                        row['finalized'].lower()):
                    submission_obj.answer['finalized'] = json.loads(
                        row['finalized'].lower())
                    submission_obj.save()
                    new = True
                if row['comment']:
                    try:
                        if state['comment'].encode('utf-8') != row['comment']:
                            new = True
                            state['comment'] = row['comment']
                    except:
                        state.update({'comment': row['comment']})
                        new = True
                if new:
                    state['date_fin'] = force_text(django_now())
                    state['fresh'] = False
                module.state = json.dumps(state)
                module.save()
Exemple #49
0
 def test_get_score(self):
     self.test_create_score()
     scores = api.get_score(STUDENT_ITEM)
     self._assert_score(scores[0], 11, 12)
Exemple #50
0
 def test_get_score(self):
     submission = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
     api.set_score(submission["uuid"], 11, 12)
     score = api.get_score(STUDENT_ITEM)
     self._assert_score(score, 11, 12)
     self.assertEqual(score['submission_uuid'], submission['uuid'])
Exemple #51
0
 def test_get_score_no_student_id(self):
     student_item = copy.deepcopy(STUDENT_ITEM)
     student_item['student_id'] = None
     self.assertIs(api.get_score(student_item), None)
Exemple #52
0
 def test_get_score(self):
     submission = api.create_submission(STUDENT_ITEM, ANSWER_ONE)
     api.set_score(submission["uuid"], 11, 12)
     score = api.get_score(STUDENT_ITEM)
     self._assert_score(score, 11, 12)
     self.assertEqual(score['submission_uuid'], submission['uuid'])
Exemple #53
0
 def test_get_score_no_student_id(self):
     student_item = copy.deepcopy(STUDENT_ITEM)
     student_item['student_id'] = None
     self.assertIs(api.get_score(student_item), None)
Exemple #54
0
 def score(self):
     """Score: The student score."""
     api_score = submissions_api.get_score(self.submission_id)
     if api_score:
         return Score(api_score['points_earned'],
                      api_score['points_possible'])
Exemple #55
0
    def test_peer_assessment_workflow(self):
        tim_sub, tim = self._create_student_and_submission("Tim", "Tim's answer")
        bob_sub, bob = self._create_student_and_submission("Bob", "Bob's answer")
        sally_sub, sally = self._create_student_and_submission("Sally", "Sally's answer")
        jim_sub, jim = self._create_student_and_submission("Jim", "Jim's answer")
        self._create_student_and_submission("Buffy", "Buffy's answer")
        self._create_student_and_submission("Xander", "Xander's answer")

        # Tim should not have a score, because he has not evaluated enough
        # peer submissions.
        requirements = {
            "peer": {
                "must_grade": REQUIRED_GRADED,
                "must_be_graded_by": REQUIRED_GRADED_BY,
            }
        }
        score = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements
        )["score"]
        self.assertIsNone(score)

        for i in range(5):
            self.assertEquals((False, i), peer_api.has_finished_required_evaluating(tim_sub['uuid'], REQUIRED_GRADED))
            sub = peer_api.get_submission_to_assess(tim_sub['uuid'], REQUIRED_GRADED)
            peer_api.create_assessment(
                tim_sub["uuid"], tim["student_id"],
                ASSESSMENT_DICT['options_selected'],
                ASSESSMENT_DICT['criterion_feedback'],
                ASSESSMENT_DICT['overall_feedback'],
                RUBRIC_DICT,
                REQUIRED_GRADED_BY,
            )

        self.assertEquals((True, 5), peer_api.has_finished_required_evaluating(tim_sub['uuid'], REQUIRED_GRADED))

        # Tim should not have a score, because his submission does not have
        # enough assessments.
        self.assertIsNone(sub_api.get_score(STUDENT_ITEM))

        sub = peer_api.get_submission_to_assess(bob_sub['uuid'], REQUIRED_GRADED)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])
        peer_api.create_assessment(
            bob_sub["uuid"], bob["student_id"],
            ASSESSMENT_DICT['options_selected'],
            ASSESSMENT_DICT['criterion_feedback'],
            ASSESSMENT_DICT['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        sub = peer_api.get_submission_to_assess(sally_sub['uuid'], REQUIRED_GRADED)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])
        peer_api.create_assessment(
            sally_sub["uuid"], sally["student_id"],
            ASSESSMENT_DICT_FAIL['options_selected'],
            ASSESSMENT_DICT_FAIL['criterion_feedback'],
            ASSESSMENT_DICT_FAIL['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        sub = peer_api.get_submission_to_assess(jim_sub['uuid'], REQUIRED_GRADED)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])
        peer_api.create_assessment(
            jim_sub["uuid"], jim["student_id"],
            ASSESSMENT_DICT_PASS['options_selected'],
            ASSESSMENT_DICT_PASS['criterion_feedback'],
            ASSESSMENT_DICT_PASS['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # Tim has met the critera, and should now be complete.
        requirements = {
            'must_grade': REQUIRED_GRADED,
            'must_be_graded_by': REQUIRED_GRADED_BY
        }
        self.assertTrue(peer_api.is_complete(tim_sub["uuid"], requirements))