From f6a8c59230fb8bc85318d3a58bbeac8f49034222 Mon Sep 17 00:00:00 2001 From: Jansen Kantor Date: Wed, 6 Oct 2021 16:15:30 -0400 Subject: [PATCH] add get_student_ids_by_submission_uuid and get_team_ids_by_team_submission_uuid (#141) * add ORA enhanced staff grader api methods add get_student_ids_by_submission_uuid and get_team_ids_by_team_submission_uuid --- submissions/__init__.py | 2 +- submissions/api.py | 19 ++++++++ submissions/team_api.py | 16 +++++++ submissions/tests/test_api.py | 88 +++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/submissions/__init__.py b/submissions/__init__.py index c7174db..4885af0 100644 --- a/submissions/__init__.py +++ b/submissions/__init__.py @@ -1,2 +1,2 @@ """ API for creating submissions and scores. """ -__version__ = '3.3.2' +__version__ = '3.4.0' diff --git a/submissions/api.py b/submissions/api.py index b4fd1ac..c2e011d 100644 --- a/submissions/api.py +++ b/submissions/api.py @@ -585,6 +585,25 @@ def get_top_submissions(course_id, item_id, item_type, number_of_top_scores, use return top_submissions +def get_student_ids_by_submission_uuid(course_id, submission_uuids, read_replica=True): + """ + Given a list of submission uuids, and a course id for security, + return a dictionary mapping submission uuid to student_id. + """ + submissions = Submission.objects.filter( + student_item__course_id=course_id, + uuid__in=submission_uuids + ) + + if read_replica: + submissions = _use_read_replica(submissions) + + submissions = submissions.values( + "uuid", "student_item__student_id" + ) + return {str(submission['uuid']): submission['student_item__student_id'] for submission in submissions} + + def get_score(student_item): """Get the score for a particular student item diff --git a/submissions/team_api.py b/submissions/team_api.py index 34e9fcf..4465f16 100644 --- a/submissions/team_api.py +++ b/submissions/team_api.py @@ -321,6 +321,22 @@ def get_team_submission_student_ids(team_submission_uuid): return list(student_ids) +def get_team_ids_by_team_submission_uuid(team_submission_uuids): + """ + Given a list of team submission uuids, return a dict mapping + team submission uuids to team id + """ + values = TeamSubmission.objects.filter( + team_submission_uuid__in=team_submission_uuids + ).values( + "uuid", "team_id" + ) + return { + item['uuid']: item['team_id'] + for item in values + } + + def set_score(team_submission_uuid, points_earned, points_possible, annotation_creator=None, annotation_type=None, annotation_reason=None): """Set a score for a particular team submission. This score is calculated diff --git a/submissions/tests/test_api.py b/submissions/tests/test_api.py index 62a4475..d0e24d3 100644 --- a/submissions/tests/test_api.py +++ b/submissions/tests/test_api.py @@ -741,3 +741,91 @@ def _assert_score(self, score, expected_points_earned, expected_points_possible) self.assertIsNotNone(score) self.assertEqual(score["points_earned"], expected_points_earned) self.assertEqual(score["points_possible"], expected_points_possible) + + def test_get_student_ids_by_submission_uuid(self): + # Define two course ids, with some associated item ids, and some "student ids" + course_id = 'test_course_0000001' + course_item_ids = [f"{course_id}_item_{i}" for i in range(4)] + course_member_student_ids = [f'test_user_999{i}' for i in range(4)] + # other_course is just for database noise. It has an overlap of two learners with "course" + other_course_id = 'test_course_846292' + other_course_items_id = [f"{other_course_id}_item_{i}" for i in range(2)] + other_course_members_ids = [ + 'some_other_user', + 'another_guy', + course_member_student_ids[0], + course_member_student_ids[2] + ] + + def submit(course_id, item_id, student_ids): + result_dict = {} + for student_id in student_ids: + student_item = dict( + course_id=course_id, + item_id=item_id, + student_id=student_id, + item_type='test_get_student_ids_by_submission_uuid' + ) + submission_uuid = api.create_submission(student_item, ANSWER_ONE)['uuid'] + result_dict[submission_uuid] = student_id + return result_dict + + # Make some submissions for the target course + # Item 0, users 0 and 1 submit + item_0_expected_result = submit( + course_id, + course_item_ids[0], + course_member_student_ids[:2] + ) + # Item 1, all users submit + item_1_expected_result = submit( + course_id, + course_item_ids[1], + course_member_student_ids + ) + # Item 2, users 2 and 3 + item_2_expected_result = submit( + course_id, + course_item_ids[0], + course_member_student_ids[2:] + ) + # Item 3, users 1, 2, 3 + item_3_expected_result = submit( + course_id, + course_item_ids[0], + course_member_student_ids[1:] + ) + for item_id in other_course_items_id: + submit(other_course_id, item_id, other_course_members_ids) + self.assertDictEqual( + api.get_student_ids_by_submission_uuid( + course_id, + item_0_expected_result.keys(), + read_replica=False, + ), + item_0_expected_result + ) + self.assertDictEqual( + api.get_student_ids_by_submission_uuid( + course_id, + item_1_expected_result.keys(), + read_replica=False, + ), + item_1_expected_result + ) + self.assertDictEqual( + api.get_student_ids_by_submission_uuid( + course_id, + item_2_expected_result.keys(), + read_replica=False, + ), + item_2_expected_result + ) + self.assertDictEqual( + api.get_student_ids_by_submission_uuid( + course_id, + item_3_expected_result.keys(), + read_replica=False, + ), + item_3_expected_result + )