diff --git a/docs/event-mapping/Supported_events.rst b/docs/event-mapping/Supported_events.rst index 1bf8bae6..92b980c6 100644 --- a/docs/event-mapping/Supported_events.rst +++ b/docs/event-mapping/Supported_events.rst @@ -15,6 +15,8 @@ Course grading events ----------------------- * edx.course.grade.passed.first_time | edX `sample <../../event_routing_backends/processors/tests/fixtures/current/edx.course.grade.passed.first_time.json>`__ | xAPI `map <./xAPI_mapping.rst#edx-course-grade-passed-first-time>`__ , `sample <../../event_routing_backends/processors/xapi/tests/fixtures/expected/edx.course.grade.passed.first_time.json>`__ | Caliper `map <./Caliper_mapping.rst#edx-course-grade-passed-first-time>`__ , `sample <../../event_routing_backends/processors/caliper/tests/fixtures/expected/edx.course.grade.passed.first_time.json>`__ +* `edx.grades.subsection.grade_calculated`_ | edX `sample <../../event_routing_backends/processors/tests/fixtures/current/edx.grades.subsection.grade_calculated.json>`__ | xAPI `map <./xAPI_mapping.rst#edx-grades-subsection-grade-calculated>`__ , `sample <../../event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.subsection.grade_calculated.json>`__ +* `edx.grades.course.grade_calculated`_ | edX `sample <../../event_routing_backends/processors/tests/fixtures/current/edx.grades.course.grade_calculated.json>`__ | xAPI `map <./xAPI_mapping.rst#edx-grades-course-grade-calculated>`__ , `sample <../../event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.course.grade_calculated.json>`__ Problem interaction events --------------------------- @@ -74,6 +76,8 @@ Forum events .. _edx.course.enrollment.activated: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/student_event_types.html#edx-course-enrollment-activated-and-edx-course-enrollment-deactivated .. _edx.course.enrollment.deactivated: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/student_event_types.html#edx-course-enrollment-activated-and-edx-course-enrollment-deactivated .. _edx.course.enrollment.mode_changed: https://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/student_event_types.html#edx-course-enrollment-mode-changed +.. _edx.grades.subsection.grade_calculated: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/course_team_event_types.html#edx-grades-subsection-grade-calculated +.. _edx.grades.course.grade_calculated: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/course_team_event_types.html#edx-grades-course-grade-calculated .. _edx.grades.problem.submitted: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/course_team_event_types.html#edx-grades-problem-submitted .. _problem_check: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/student_event_types.html#problem-check .. _showanswer: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/student_event_types.html#showanswer diff --git a/event_routing_backends/__init__.py b/event_routing_backends/__init__.py index cc729ac4..2fbe0f36 100644 --- a/event_routing_backends/__init__.py +++ b/event_routing_backends/__init__.py @@ -2,4 +2,4 @@ Various backends for receiving edX LMS events.. """ -__version__ = '5.5.6' +__version__ = '5.6.0' diff --git a/event_routing_backends/processors/tests/fixtures/current/edx.grades.course.grade_calculated_letter_grade.json b/event_routing_backends/processors/tests/fixtures/current/edx.grades.course.grade_calculated_letter_grade.json new file mode 100644 index 00000000..82b9fb1b --- /dev/null +++ b/event_routing_backends/processors/tests/fixtures/current/edx.grades.course.grade_calculated_letter_grade.json @@ -0,0 +1,37 @@ +{ + "name": "edx.grades.course.grade_calculated", + "context": { + "course_id": "course-v1:edX+DemoX+Demo_Course", + "course_user_tags": {}, + "user_id": 3, + "path": "/courses/course-v1:edX+DemoX+Demo_Course/xblock/block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2/handler/xmodule_handler/problem_check", + "org_id": "edX", + "enterprise_uuid": "", + "module": { + "display_name": "Checkboxes", + "usage_key": "block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2" + } + }, + "username": "edX", + "session": "056aca2a1c6b76742b283e73d3424453", + "ip": "172.19.0.1", + "agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36", + "host": "localhost:18000", + "referer": "http://localhost:18000/xblock/block-v1:edX+DemoX+Demo_Course+type@vertical+block@ea9e33c0ad15445195f96d3c42ebc9f0?show_title=0&show_bookmark_button=0&recheck_access=1&view=student_view&format=Homework", + "accept_language": "en-US,en;q=0.9,es;q=0.8", + "data": { + "user_id": "3", + "course_id": "course-v1:edX+DemoX+Demo_Course", + "course_version": "64e64c6835fe1d2093ba4d69", + "percent_grade": 1.0, + "letter_grade": "Pass", + "course_edited_timestamp": "2023-08-23 18:14:00.070241+00:00", + "event_transaction_id": "a47772a0-3c7f-4a0e-9c11-7e903a03e503", + "event_transaction_type": "edx.grades.problem.submitted", + "grading_policy_hash": "ChVp0lHGQGCevD0t4njna/C44zQ=" + }, + "time": "2023-08-23T20:37:45.526615+00:00", + "event_type": "edx.grades.course.grade_calculated", + "event_source": "server", + "page": null +} diff --git a/event_routing_backends/processors/tests/fixtures/current/edx.grades.course.grade_calculated_no_letter_grade.json b/event_routing_backends/processors/tests/fixtures/current/edx.grades.course.grade_calculated_no_letter_grade.json new file mode 100644 index 00000000..1829b8e5 --- /dev/null +++ b/event_routing_backends/processors/tests/fixtures/current/edx.grades.course.grade_calculated_no_letter_grade.json @@ -0,0 +1,37 @@ +{ + "name": "edx.grades.course.grade_calculated", + "context": { + "course_id": "course-v1:edX+DemoX+Demo_Course", + "course_user_tags": {}, + "user_id": 3, + "path": "/courses/course-v1:edX+DemoX+Demo_Course/xblock/block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2/handler/xmodule_handler/problem_check", + "org_id": "edX", + "enterprise_uuid": "", + "module": { + "display_name": "Checkboxes", + "usage_key": "block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2" + } + }, + "username": "edX", + "session": "056aca2a1c6b76742b283e73d3424453", + "ip": "172.19.0.1", + "agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36", + "host": "localhost:18000", + "referer": "http://localhost:18000/xblock/block-v1:edX+DemoX+Demo_Course+type@vertical+block@ea9e33c0ad15445195f96d3c42ebc9f0?show_title=0&show_bookmark_button=0&recheck_access=1&view=student_view&format=Homework", + "accept_language": "en-US,en;q=0.9,es;q=0.8", + "data": { + "user_id": "3", + "course_id": "course-v1:edX+DemoX+Demo_Course", + "course_version": "64e64c6835fe1d2093ba4d69", + "percent_grade": 0.02, + "letter_grade": "", + "course_edited_timestamp": "2023-08-23 18:14:00.070241+00:00", + "event_transaction_id": "a47772a0-3c7f-4a0e-9c11-7e903a03e503", + "event_transaction_type": "edx.grades.problem.submitted", + "grading_policy_hash": "ChVp0lHGQGCevD0t4njna/C44zQ=" + }, + "time": "2023-08-23T20:37:45.526615+00:00", + "event_type": "edx.grades.course.grade_calculated", + "event_source": "server", + "page": null +} diff --git a/event_routing_backends/processors/tests/fixtures/current/edx.grades.subsection.grade_calculated.json b/event_routing_backends/processors/tests/fixtures/current/edx.grades.subsection.grade_calculated.json new file mode 100644 index 00000000..18cab77c --- /dev/null +++ b/event_routing_backends/processors/tests/fixtures/current/edx.grades.subsection.grade_calculated.json @@ -0,0 +1,41 @@ +{ + "name": "edx.grades.subsection.grade_calculated", + "context": { + "course_id": "course-v1:edX+DemoX+Demo_Course", + "course_user_tags": {}, + "user_id": 3, + "path": "/courses/course-v1:edX+DemoX+Demo_Course/xblock/block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2/handler/xmodule_handler/problem_check", + "org_id": "edX", + "enterprise_uuid": "", + "module": { + "display_name": "Checkboxes", + "usage_key": "block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2" + } + }, + "username": "edX", + "session": "056aca2a1c6b76742b283e73d3424453", + "ip": "172.19.0.1", + "agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36", + "host": "localhost:18000", + "referer": "http://localhost:18000/xblock/block-v1:edX+DemoX+Demo_Course+type@vertical+block@ea9e33c0ad15445195f96d3c42ebc9f0?show_title=0&show_bookmark_button=0&recheck_access=1&view=student_view&format=Homework", + "accept_language": "en-US,en;q=0.9,es;q=0.8", + "data": { + "user_id": "4", + "course_id": "course-v1:edX+DemoX+Demo_Course", + "block_id": "block-v1:edX+DemoX+Demo_Course+type@sequential+block@a2184f8ebf9d478ba57edcc4f288854a", + "course_version": "64e64c6835fe1d2093ba4d69", + "weighted_total_earned": 3.0, + "weighted_total_possible": 3.0, + "weighted_graded_earned": 3.0, + "weighted_graded_possible": 3.0, + "first_attempted": "2023-08-22 17:58:21.710578+00:00", + "subtree_edited_timestamp": "2023-08-23 18:14:00.070241+00:00", + "event_transaction_id": "a47772a0-3c7f-4a0e-9c11-7e903a03e503", + "event_transaction_type": "edx.grades.problem.submitted", + "visible_blocks_hash": "7bcnLlOwpFfmByYbwqBmWHskIEY=" + }, + "time": "2023-08-23T20:37:44.920732+00:00", + "event_type": "edx.grades.subsection.grade_calculated", + "event_source": "server", + "page": null +} diff --git a/event_routing_backends/processors/tests/fixtures/current/edx.grades.subsection.grade_calculated.weighted_possible_0.json b/event_routing_backends/processors/tests/fixtures/current/edx.grades.subsection.grade_calculated.weighted_possible_0.json new file mode 100644 index 00000000..7f2eb659 --- /dev/null +++ b/event_routing_backends/processors/tests/fixtures/current/edx.grades.subsection.grade_calculated.weighted_possible_0.json @@ -0,0 +1,41 @@ +{ + "name": "edx.grades.subsection.grade_calculated", + "context": { + "course_id": "course-v1:edX+DemoX+Demo_Course", + "course_user_tags": {}, + "user_id": 3, + "path": "/courses/course-v1:edX+DemoX+Demo_Course/xblock/block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2/handler/xmodule_handler/problem_check", + "org_id": "edX", + "enterprise_uuid": "", + "module": { + "display_name": "Checkboxes", + "usage_key": "block-v1:edX+DemoX+Demo_Course+type@problem+block@185ffd73e23843168ca02e8d070ffcf2" + } + }, + "username": "edX", + "session": "056aca2a1c6b76742b283e73d3424453", + "ip": "172.19.0.1", + "agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36", + "host": "localhost:18000", + "referer": "http://localhost:18000/xblock/block-v1:edX+DemoX+Demo_Course+type@vertical+block@ea9e33c0ad15445195f96d3c42ebc9f0?show_title=0&show_bookmark_button=0&recheck_access=1&view=student_view&format=Homework", + "accept_language": "en-US,en;q=0.9,es;q=0.8", + "data": { + "user_id": "4", + "course_id": "course-v1:edX+DemoX+Demo_Course", + "block_id": "block-v1:edX+DemoX+Demo_Course+type@sequential+block@a2184f8ebf9d478ba57edcc4f288854a", + "course_version": "64e64c6835fe1d2093ba4d69", + "weighted_total_earned": 0.0, + "weighted_total_possible": 0.0, + "weighted_graded_earned": 0.0, + "weighted_graded_possible": 0.0, + "first_attempted": "2023-08-22 17:58:21.710578+00:00", + "subtree_edited_timestamp": "2023-08-23 18:14:00.070241+00:00", + "event_transaction_id": "a47772a0-3c7f-4a0e-9c11-7e903a03e503", + "event_transaction_type": "edx.grades.problem.submitted", + "visible_blocks_hash": "7bcnLlOwpFfmByYbwqBmWHskIEY=" + }, + "time": "2023-08-23T20:37:44.920732+00:00", + "event_type": "edx.grades.subsection.grade_calculated", + "event_source": "server", + "page": null +} diff --git a/event_routing_backends/processors/xapi/constants.py b/event_routing_backends/processors/xapi/constants.py index 36496cfe..2d8308c4 100644 --- a/event_routing_backends/processors/xapi/constants.py +++ b/event_routing_backends/processors/xapi/constants.py @@ -21,6 +21,7 @@ XAPI_VERB_VOTED = 'https://w3id.org/xapi/openedx/verb/voted' XAPI_VERB_REPORTED = 'https://w3id.org/xapi/acrossx/verbs/reported' XAPI_VERB_UNREPORTED = 'https://w3id.org/xapi/openedx/verb/unreported' +XAPI_VERB_EARNED = 'http://id.tincanapi.com/verb/earned' XAPI_VERB_TERMINATED = 'http://adlnet.gov/expapi/verbs/terminated' XAPI_VERB_ASKED = 'http://adlnet.gov/expapi/verbs/asked' @@ -47,7 +48,8 @@ XAPI_ACTIVITY_TOTAL_COUNT = 'https://w3id.org/xapi/acrossx/extensions/total-items' XAPI_ACTIVITY_MODE = 'https://w3id.org/xapi/acrossx/extensions/type' XAPI_ACTIVITY_ATTEMPT = 'http://id.tincanapi.com/extension/attempt-id' - +XAPI_ACTIVITY_GRADE_CLASSIFICATION = 'http://www.tincanapi.co.uk/activitytypes/grade_classification' +XAPI_ACTIVITY_GRADE = 'http://www.tincanapi.co.uk/extensions/result/classification' # xAPI context XAPI_CONTEXT_VIDEO_LENGTH = 'https://w3id.org/xapi/video/extensions/length' XAPI_CONTEXT_VIDEO_CC_LANGUAGE = 'https://w3id.org/xapi/video/extensions/cc-subtitle-lang' @@ -97,6 +99,7 @@ VOTED = 'voted' REPORTED = 'reported' UNREPORTED = 'unreported' +EARNED = 'earned' TERMINATED = 'terminated' NAVIGATED = 'navigated' diff --git a/event_routing_backends/processors/xapi/event_transformers/__init__.py b/event_routing_backends/processors/xapi/event_transformers/__init__.py index 4240e075..d5c60147 100644 --- a/event_routing_backends/processors/xapi/event_transformers/__init__.py +++ b/event_routing_backends/processors/xapi/event_transformers/__init__.py @@ -16,6 +16,10 @@ ThreadViewedTransformer, ThreadVotedTransformer, ) +from event_routing_backends.processors.xapi.event_transformers.grading_events import ( + CourseGradedTransformer, + SubsectionGradedTransformer, +) from event_routing_backends.processors.xapi.event_transformers.navigation_events import ( LinkClickedTransformer, OutlineSelectedTransformer, diff --git a/event_routing_backends/processors/xapi/event_transformers/grading_events.py b/event_routing_backends/processors/xapi/event_transformers/grading_events.py new file mode 100644 index 00000000..24fed82f --- /dev/null +++ b/event_routing_backends/processors/xapi/event_transformers/grading_events.py @@ -0,0 +1,126 @@ +""" +Transformers for grading related events. +""" +from tincan import Activity, ActivityDefinition, Extensions, LanguageMap, Result, Verb + +from event_routing_backends.helpers import get_course_from_id +from event_routing_backends.processors.xapi import constants +from event_routing_backends.processors.xapi.registry import XApiTransformersRegistry +from event_routing_backends.processors.xapi.transformer import XApiTransformer + + +@XApiTransformersRegistry.register("edx.grades.subsection.grade_calculated") +class SubsectionGradedTransformer(XApiTransformer): + """ + Transformer for event generated when an subsection is graded. + """ + + verb = Verb( + id=constants.XAPI_VERB_EARNED, + display=LanguageMap({constants.EN: constants.EARNED}), + ) + + additional_fields = ("result",) + + def get_object(self): + """ + Get object for xAPI transformed event related to subsection grading. + + Returns: + `Activity` + """ + + return Activity( + id=self.get_object_iri("xblock", self.get_data("data.block_id", True)), + definition=ActivityDefinition( + type=constants.XAPI_ACTIVITY_RESOURCE, + ), + ) + + def get_result(self): + """ + Get result for xAPI transformed event. + + Returns: + `Result` + """ + event_data = self.get_data("data") + weighted_possible = event_data["weighted_total_possible"] or 0 + weighted_earned = event_data["weighted_total_earned"] or 0 + + if weighted_possible > 0: + scaled = weighted_earned / weighted_possible + else: + scaled = 0 + return Result( + success=weighted_earned >= weighted_possible, + score={ + "min": 0, + "max": weighted_possible, + "raw": weighted_earned, + "scaled": scaled, + }, + ) + + +@XApiTransformersRegistry.register("edx.grades.course.grade_calculated") +class CourseGradedTransformer(XApiTransformer): + """ + Transformer for event generated when an course is graded. + """ + + verb = Verb( + id=constants.XAPI_VERB_EARNED, + display=LanguageMap({constants.EN: constants.EARNED}), + ) + + additional_fields = ("result",) + + def get_object(self): + """ + Get object for xAPI transformed event related to course grading. + + Returns: + `Activity` + """ + course_id = self.get_data("context.course_id", True) + object_id = self.get_object_iri("course", course_id) + course = get_course_from_id(course_id) + display_name = course["display_name"] + + return Activity( + id=object_id, + definition=ActivityDefinition( + type=constants.XAPI_ACTIVITY_COURSE, + name=LanguageMap( + **({constants.EN: display_name} if display_name is not None else {}) + ), + ), + ) + + def get_result(self): + """ + Get result for xAPI transformed event. + + Returns: + `Result` + """ + event_data = self.get_data("data") + weighted_possible = 1.0 + weighted_earned = event_data["percent_grade"] or 0 + + letter_grade = self.get_data("data.letter_grade") or "Fail" + + return Result( + score={ + "min": 0, + "max": weighted_possible, + "raw": weighted_earned, + "scaled": weighted_earned, + }, + extensions=Extensions( + { + constants.XAPI_ACTIVITY_GRADE_CLASSIFICATION: letter_grade + } + ), + ) diff --git a/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.course.grade_calculated_letter_grade.json b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.course.grade_calculated_letter_grade.json new file mode 100644 index 00000000..ea2b45ec --- /dev/null +++ b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.course.grade_calculated_letter_grade.json @@ -0,0 +1,59 @@ +{ + "id": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "result": { + "score": { + "scaled": 1.0, + "raw": 1.0, + "min": 0.0, + "max": 1.0 + }, + "extensions": { + "http://www.tincanapi.co.uk/activitytypes/grade_classification": "Pass" + } + }, + "version": "1.0.3", + "actor": { + "objectType": "Agent", + "account": { + "name": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "homePage": "http://localhost:18000" + } + }, + "verb": { + "id": "http://id.tincanapi.com/verb/earned", + "display": { + "en": "earned" + } + }, + "object": { + "id": "http://localhost:18000/course/course-v1:edX+DemoX+Demo_Course", + "objectType": "Activity", + "definition": { + "name": { + "en": "Demonstration Course" + }, + "type": "http://adlnet.gov/expapi/activities/course" + } + }, + "timestamp": "2023-08-23T20:37:45.526615+00:00", + "context": { + "contextActivities": { + "parent": [ + { + "id": "http://localhost:18000/course/course-v1:edX+DemoX+Demo_Course", + "objectType": "Activity", + "definition": { + "name": { + "en-US": "Demonstration Course" + }, + "type": "http://adlnet.gov/expapi/activities/course" + } + } + ] + }, + "extensions": { + "https://w3id.org/xapi/openedx/extension/transformer-version": "event-routing-backends@1.1.1", + "https://w3id.org/xapi/openedx/extensions/session-id": "056aca2a1c6b76742b283e73d3424453" + } + } +} diff --git a/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.course.grade_calculated_no_letter_grade.json b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.course.grade_calculated_no_letter_grade.json new file mode 100644 index 00000000..85135e05 --- /dev/null +++ b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.course.grade_calculated_no_letter_grade.json @@ -0,0 +1,59 @@ +{ + "id": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "result": { + "score": { + "scaled": 0.02, + "raw": 0.02, + "min": 0.0, + "max": 1.0 + }, + "extensions": { + "http://www.tincanapi.co.uk/activitytypes/grade_classification": "Fail" + } + }, + "version": "1.0.3", + "actor": { + "objectType": "Agent", + "account": { + "name": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "homePage": "http://localhost:18000" + } + }, + "verb": { + "id": "http://id.tincanapi.com/verb/earned", + "display": { + "en": "earned" + } + }, + "object": { + "id": "http://localhost:18000/course/course-v1:edX+DemoX+Demo_Course", + "objectType": "Activity", + "definition": { + "name": { + "en": "Demonstration Course" + }, + "type": "http://adlnet.gov/expapi/activities/course" + } + }, + "timestamp": "2023-08-23T20:37:45.526615+00:00", + "context": { + "contextActivities": { + "parent": [ + { + "id": "http://localhost:18000/course/course-v1:edX+DemoX+Demo_Course", + "objectType": "Activity", + "definition": { + "name": { + "en-US": "Demonstration Course" + }, + "type": "http://adlnet.gov/expapi/activities/course" + } + } + ] + }, + "extensions": { + "https://w3id.org/xapi/openedx/extension/transformer-version": "event-routing-backends@1.1.1", + "https://w3id.org/xapi/openedx/extensions/session-id": "056aca2a1c6b76742b283e73d3424453" + } + } +} diff --git a/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.subsection.grade_calculated.json b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.subsection.grade_calculated.json new file mode 100644 index 00000000..231ecb37 --- /dev/null +++ b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.subsection.grade_calculated.json @@ -0,0 +1,33 @@ +{ + "id": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "result": { "score": { "scaled": 1.0, "raw": 3.0, "min": 0.0, "max": 3.0 }, "success": true }, + "version": "1.0.3", + "actor": { + "objectType": "Agent", + "account": { "name": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", "homePage": "http://localhost:18000" } + }, + "verb": { "id": "http://id.tincanapi.com/verb/earned", "display": { "en": "earned" } }, + "object": { + "id": "http://localhost:18000/xblock/block-v1:edX+DemoX+Demo_Course+type@sequential+block@a2184f8ebf9d478ba57edcc4f288854a", + "objectType": "Activity", + "definition": { + "type": "http://id.tincanapi.com/activitytype/resource" + } + }, + "timestamp": "2023-08-23T20:37:44.920732+00:00", + "context": { + "contextActivities": { + "parent": [ + { + "id": "http://localhost:18000/course/course-v1:edX+DemoX+Demo_Course", + "objectType": "Activity", + "definition": { "name": { "en-US": "Demonstration Course" }, "type": "http://adlnet.gov/expapi/activities/course" } + } + ] + }, + "extensions": { + "https://w3id.org/xapi/openedx/extension/transformer-version": "event-routing-backends@1.1.1", + "https://w3id.org/xapi/openedx/extensions/session-id": "056aca2a1c6b76742b283e73d3424453" + } + } +} diff --git a/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.subsection.grade_calculated.weighted_possible_0.json b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.subsection.grade_calculated.weighted_possible_0.json new file mode 100644 index 00000000..3fb42447 --- /dev/null +++ b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.grades.subsection.grade_calculated.weighted_possible_0.json @@ -0,0 +1,33 @@ +{ + "id": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "result": { "score": { "scaled": 0.0, "raw": 0.0, "min": 0.0, "max": 0.0 }, "success": true }, + "version": "1.0.3", + "actor": { + "objectType": "Agent", + "account": { "name": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", "homePage": "http://localhost:18000" } + }, + "verb": { "id": "http://id.tincanapi.com/verb/earned", "display": { "en": "earned" } }, + "object": { + "id": "http://localhost:18000/xblock/block-v1:edX+DemoX+Demo_Course+type@sequential+block@a2184f8ebf9d478ba57edcc4f288854a", + "objectType": "Activity", + "definition": { + "type": "http://id.tincanapi.com/activitytype/resource" + } + }, + "timestamp": "2023-08-23T20:37:44.920732+00:00", + "context": { + "contextActivities": { + "parent": [ + { + "id": "http://localhost:18000/course/course-v1:edX+DemoX+Demo_Course", + "objectType": "Activity", + "definition": { "name": { "en-US": "Demonstration Course" }, "type": "http://adlnet.gov/expapi/activities/course" } + } + ] + }, + "extensions": { + "https://w3id.org/xapi/openedx/extension/transformer-version": "event-routing-backends@1.1.1", + "https://w3id.org/xapi/openedx/extensions/session-id": "056aca2a1c6b76742b283e73d3424453" + } + } +} diff --git a/event_routing_backends/processors/xapi/transformer.py b/event_routing_backends/processors/xapi/transformer.py index 74f2ff0e..15586b6d 100644 --- a/event_routing_backends/processors/xapi/transformer.py +++ b/event_routing_backends/processors/xapi/transformer.py @@ -92,7 +92,7 @@ def get_timestamp(self): Returns: str """ - return self.get_data('timestamp') + return self.get_data('timestamp') or self.get_data('time') def get_context_activities(self): """ diff --git a/event_routing_backends/settings/common.py b/event_routing_backends/settings/common.py index 5d78074e..02c1b671 100644 --- a/event_routing_backends/settings/common.py +++ b/event_routing_backends/settings/common.py @@ -72,6 +72,8 @@ def plugin_settings(settings): 'edx.course.enrollment.activated', 'edx.course.enrollment.deactivated', 'edx.course.enrollment.mode_changed', + 'edx.grades.subsection.grade_calculated', + 'edx.grades.course.grade_calculated', 'edx.forum.thread.created', 'edx.forum.thread.deleted', 'edx.forum.thread.edited',