diff --git a/docs/event-mapping/Supported_events.rst b/docs/event-mapping/Supported_events.rst index 1bf8bae6..45d63e3b 100644 --- a/docs/event-mapping/Supported_events.rst +++ b/docs/event-mapping/Supported_events.rst @@ -14,7 +14,11 @@ Enrollment events 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.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>`__ + +Completion events + +* `edx.completion.block_completion.changed`_ | edX `sample <../../event_routing_backends/processors/tests/fixtures/current/edx.completion.block_completion.changed.json>`___ | xAPI `map <./xAPI_mapping.rst#edx-completion-block-completion-changed>`__ , `sample <../../event_routing_backends/processors/xapi/tests/fixtures/expected/edx.completion.block_completion.changed.json>`__ Problem interaction events --------------------------- @@ -74,6 +78,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.course.grade.passed.first_time: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/course_team_event_types.html#edx-course-grade-passed-first-time +.. _edx.completion.block_completion.changed: http://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/student_event_types.html#edx-completion-block-completion-changed .. _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.completion.block_completion.changed.json b/event_routing_backends/processors/tests/fixtures/current/edx.completion.block_completion.changed.json new file mode 100644 index 00000000..ea994689 --- /dev/null +++ b/event_routing_backends/processors/tests/fixtures/current/edx.completion.block_completion.changed.json @@ -0,0 +1,33 @@ +{ + "name": "edx.completion.block_completion.changed", + "timestamp": "2023-08-22T20:16:25.500832Z", + "data": { + "user_id": 4, + "course_id": "course-v1:edX+DemoX+Demo_Course", + "context_key": "course-v1:edX+DemoX+Demo_Course", + "block_id": "block-v1:edX+DemoX+Demo_Course+type@problem+block@7c54b16c8ed34f9f8772015178c7a175", + "block_type": "problem", + "completion": 1.0, + "is_new": false + }, + "context": { + "course_id": "course-v1:edX+DemoX+Demo_Course", + "course_user_tags": {}, + "session": "056aca2a1c6b76742b283e73d3424453", + "user_id": 3, + "username": "edx", + "ip": "172.18.0.1", + "host": "localhost:18000", + "agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36", + "path": "/courses/course-v1:edX+DemoX+Demo_Course/xblock/block-v1:edX+DemoX+Demo_Course+type@problem+block@7c54b16c8ed34f9f8772015178c7a175/handler/xmodule_handler/problem_check", + "referer": "http://localhost:18000/courses/course-v1:edX+DemoX+Demo_Course+type@vertical+block@dd8110c941b94d929b56841195213797?show_title=0&show_bookmark_button=0&recheck_access=1&view=student_view", + "accept_language": "en-US,en;q=0.9,es;q=0.8", + "client_id": null, + "org_id": "edX", + "enterprise_uuid": "", + "module": { + "display_name": "Checkboxes", + "usage_key": "block-v1:edX+DemoX+Demo_Course+type@problem+block@7c54b16c8ed34f9f8772015178c7a175" + } + } +} diff --git a/event_routing_backends/processors/xapi/constants.py b/event_routing_backends/processors/xapi/constants.py index 36496cfe..d28d5132 100644 --- a/event_routing_backends/processors/xapi/constants.py +++ b/event_routing_backends/processors/xapi/constants.py @@ -21,7 +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_PROGRESSED = 'http://adlnet.gov/expapi/verbs/progressed' XAPI_VERB_TERMINATED = 'http://adlnet.gov/expapi/verbs/terminated' XAPI_VERB_ASKED = 'http://adlnet.gov/expapi/verbs/asked' @@ -47,6 +47,7 @@ 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_PROGRESS = 'https://w3id.org/xapi/cmi5/result/extensions/progress' # xAPI context XAPI_CONTEXT_VIDEO_LENGTH = 'https://w3id.org/xapi/video/extensions/length' @@ -97,6 +98,7 @@ VOTED = 'voted' REPORTED = 'reported' UNREPORTED = 'unreported' +PROGRESSED = 'progressed' 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..6ea4e69f 100644 --- a/event_routing_backends/processors/xapi/event_transformers/__init__.py +++ b/event_routing_backends/processors/xapi/event_transformers/__init__.py @@ -2,6 +2,7 @@ All xAPI transformers. """ +from event_routing_backends.processors.xapi.event_transformers.completion_events import CompletionCreatedTransformer from event_routing_backends.processors.xapi.event_transformers.enrollment_events import ( EnrollmentActivatedTransformer, EnrollmentDeactivatedTransformer, diff --git a/event_routing_backends/processors/xapi/event_transformers/completion_events.py b/event_routing_backends/processors/xapi/event_transformers/completion_events.py new file mode 100644 index 00000000..6e2945fe --- /dev/null +++ b/event_routing_backends/processors/xapi/event_transformers/completion_events.py @@ -0,0 +1,51 @@ +""" +Transformers for forum related events. +""" +from tincan import Activity, ActivityDefinition, Extensions, LanguageMap, Result, Verb + +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.completion.block_completion.changed") +class CompletionCreatedTransformer(XApiTransformer): + """ + Transformers for event generated when an student completion is created or updated. + """ + + verb = Verb( + id=constants.XAPI_VERB_PROGRESSED, + display=LanguageMap({constants.EN: constants.PROGRESSED}), + ) + + additional_fields = ('result', ) + + def get_object(self): + """ + Get object for xAPI transformed event related to a thread. + + Returns: + `Activity` + """ + print(f'\n\n\n BLOCK ID: {self.get_object_iri("xblock", self.get_data("data.block_id"))}\n\n\n') + return Activity( + id=self.get_object_iri("xblock", self.get_data("data.block_id")), + definition=ActivityDefinition( + type=constants.XAPI_ACTIVITY_RESOURCE, + ), + ) + + def get_result(self): + """ + Get result for xAPI transformed event related to a thread. + + Returns: + `Result` + """ + return Result( + completion=self.get_data("data.completion") == 1.0, + extensions=Extensions( + {constants.XAPI_ACTIVITY_PROGRESS: self.get_data("data.completion")*100} + ), + ) diff --git a/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.completion.block_completion.changed.json b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.completion.block_completion.changed.json new file mode 100644 index 00000000..4ea719af --- /dev/null +++ b/event_routing_backends/processors/xapi/tests/fixtures/expected/edx.completion.block_completion.changed.json @@ -0,0 +1,45 @@ +{ + "id": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "result": { + "completion": true, + "extensions": { "https://w3id.org/xapi/cmi5/result/extensions/progress": 100.0 } + }, + "version": "1.0.3", + "actor": { + "objectType": "Agent", + "account": { + "name": "32e08e30-f8ae-4ce2-94a8-c2bfe38a70cb", + "homePage": "http://localhost:18000" + } + }, + "verb": { + "id": "http://adlnet.gov/expapi/verbs/progressed", + "display": { "en": "progressed" } +}, + "object": { + "id": "http://localhost:18000/xblock/block-v1:edX+DemoX+Demo_Course+type@problem+block@7c54b16c8ed34f9f8772015178c7a175", + "objectType": "Activity", + "definition": { + "type": "http://id.tincanapi.com/activitytype/resource" + } + }, + "timestamp": "2023-08-22T20:16:25.500832+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/settings/common.py b/event_routing_backends/settings/common.py index 5d78074e..5abf4360 100644 --- a/event_routing_backends/settings/common.py +++ b/event_routing_backends/settings/common.py @@ -72,6 +72,7 @@ def plugin_settings(settings): 'edx.course.enrollment.activated', 'edx.course.enrollment.deactivated', 'edx.course.enrollment.mode_changed', + 'edx.completion.block_completion.changed', 'edx.forum.thread.created', 'edx.forum.thread.deleted', 'edx.forum.thread.edited',