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..8389502b 100644 --- a/event_routing_backends/processors/xapi/event_transformers/__init__.py +++ b/event_routing_backends/processors/xapi/event_transformers/__init__.py @@ -2,6 +2,9 @@ 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..847f743c --- /dev/null +++ b/event_routing_backends/processors/xapi/event_transformers/completion_events.py @@ -0,0 +1,39 @@ +""" +Transformers for forum related events. +""" +from django.conf import settings +from tincan import Activity, ActivityDefinition, LanguageMap, Verb, Extensions + +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 +import json + + +@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}), + ) + + def get_object(self): + """ + Get object for xAPI transformed event related to a thread. + + Returns: + `Activity` + """ + print(json.dumps(self.event)) + return Activity( + id=self.get_object_iri('xblock', self.get_data('data.block_key')), + definition=ActivityDefinition( + type=constants.XAPI_ACTIVITY_RESOURCE, + extensions=Extensions({ + constants.XAPI_ACTIVITY_PROGRESS: self.get_data('data.completion')*100 + }) + ), + ) diff --git a/event_routing_backends/processors/xapi/event_transformers/event.json b/event_routing_backends/processors/xapi/event_transformers/event.json new file mode 100644 index 00000000..54c3d63d --- /dev/null +++ b/event_routing_backends/processors/xapi/event_transformers/event.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:asdasd+asdasd+asdas", + "context_key": "course-v1:asdasd+asdasd+asdas", + "block_key": "block-v1:asdasd+asdasd+asdas+type@problem+block@7c54b16c8ed34f9f8772015178c7a175", + "block_type": "problem", + "completion": 1.0, + "is_new": false + }, + "context": { + "course_id": "course-v1:asdasd+asdasd+asdas", + "course_user_tags": {}, + "session": "056aca2a1c6b76742b283e73d3424453", + "user_id": 4, + "username": "yourusername", + "ip": "172.19.0.1", + "host": "local.overhang.io:8000", + "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:asdasd+asdasd+asdas/xblock/block-v1:asdasd+asdasd+asdas+type@problem+block@7c54b16c8ed34f9f8772015178c7a175/handler/xmodule_handler/problem_check", + "referer": "http://local.overhang.io:8000/xblock/block-v1:asdasd+asdasd+asdas+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": "asdasd", + "enterprise_uuid": "", + "module": { + "display_name": "Checkboxes", + "usage_key": "block-v1:asdasd+asdasd+asdas+type@problem+block@7c54b16c8ed34f9f8772015178c7a175" + } + } +} 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',