diff --git a/event_routing_backends/processors/xapi/constants.py b/event_routing_backends/processors/xapi/constants.py index aca42274..d6d54b23 100644 --- a/event_routing_backends/processors/xapi/constants.py +++ b/event_routing_backends/processors/xapi/constants.py @@ -50,7 +50,9 @@ 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_ACTIVITY_ASSESSMENT_FORMAT = 'https://w3id.org/xapi/openedx/activity/{}-assessment' +XAPI_ACTIVITY_TIMED_ASSESSMENT = 'https://w3id.org/xapi/openedx/activity/timed-assessment' +XAPI_ACTIVITY_PRACTICE_ASSESSMENT = 'https://w3id.org/xapi/openedx/activity/practice-assessment' +XAPI_ACTIVITY_PROCTORED_ASSESSMENT = 'https://w3id.org/xapi/openedx/activity/proctored-assessment' # 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' diff --git a/event_routing_backends/processors/xapi/event_transformers/__init__.py b/event_routing_backends/processors/xapi/event_transformers/__init__.py index 0b40297a..5a285b3b 100644 --- a/event_routing_backends/processors/xapi/event_transformers/__init__.py +++ b/event_routing_backends/processors/xapi/event_transformers/__init__.py @@ -7,8 +7,12 @@ EnrollmentDeactivatedTransformer, ) from event_routing_backends.processors.xapi.event_transformers.exam_events import ( - PracticeExamStartedTransformer, + PracticeExamCreatedTransformer, PracticeExamSubmittedTransformer, + ProctoredExamCreatedTransformer, + ProctoredExamSubmittedTransformer, + TimedExamCreatedTransformer, + TimedExamSubmittedTransformer, ) from event_routing_backends.processors.xapi.event_transformers.forum_events import ( ThreadCreatedTransformer, diff --git a/event_routing_backends/processors/xapi/event_transformers/exam_events.py b/event_routing_backends/processors/xapi/event_transformers/exam_events.py index 22546ae5..43309060 100644 --- a/event_routing_backends/processors/xapi/event_transformers/exam_events.py +++ b/event_routing_backends/processors/xapi/event_transformers/exam_events.py @@ -14,6 +14,8 @@ class BaseExamTransformer(XApiTransformer): Base transformer for exam events. """ + exam_type_activity = None + def get_object(self): """ Get object for xAPI transformed event. @@ -22,12 +24,18 @@ def get_object(self): `Activity` """ object_id = self.get_data("event.exam_content_id") - exam_type = self.get_data("name").split(".")[2] + + if self.exam_type_activity is None: + raise NotImplementedError( + "Make sure to define exam_type_activity for class {}".format( + self.__class__.__name__ + ) + ) return Activity( id=object_id, definition=ActivityDefinition( - type=constants.XAPI_ACTIVITY_ASSESSMENT_FORMAT.format(exam_type), + type=self.exam_type_activity, name=LanguageMap(**({constants.EN: self.get_data("event.exam_name")})), extensions=Extensions( { @@ -59,7 +67,9 @@ def get_context_activities(self): constants.XAPI_CONTEXT_DURATION: self.get_data( "event.attempt_event_elapsed_time_secs" ), - constants.XAPI_ACTIVITY_ATTEMPT: self.get_data("event.attempt_id"), + constants.XAPI_ACTIVITY_ATTEMPT: self.get_data( + "event.attempt_id" + ), } ), ), @@ -69,12 +79,33 @@ def get_context_activities(self): return context_activities -@XApiTransformersRegistry.register("edx.special_exam.timed.attempt.created") -@XApiTransformersRegistry.register("edx.special_exam.practice.attempt.created") -@XApiTransformersRegistry.register("edx.special_exam.proctored.attempt.created") -class PracticeExamStartedTransformer(BaseExamTransformer): +class BaseTimedExamTransformer(BaseExamTransformer): """ - Transformers for event generated when learner start an exam attempt. + Base transformer for timed exam events. + """ + + exam_type_activity = constants.XAPI_ACTIVITY_TIMED_ASSESSMENT + + +class BasePracticeExamTransformer(BaseExamTransformer): + """ + Base transformer for practice exam events. + """ + + exam_type_activity = constants.XAPI_ACTIVITY_PRACTICE_ASSESSMENT + + +class BaseProctoredExamTransformer(BaseExamTransformer): + """ + Base transformer for proctored exam events. + """ + + exam_type_activity = constants.XAPI_ACTIVITY_PROCTORED_ASSESSMENT + + +class InitializedMixin: + """ + Base transformer for initialized exam events """ verb = Verb( @@ -83,15 +114,54 @@ class PracticeExamStartedTransformer(BaseExamTransformer): ) -@XApiTransformersRegistry.register("edx.special_exam.timed.attempt.submitted") -@XApiTransformersRegistry.register("edx.special_exam.practice.attempt.submitted") -@XApiTransformersRegistry.register("edx.special_exam.proctored.attempt.submitted") -class PracticeExamSubmittedTransformer(BaseExamTransformer): +class TerminatedMixin: """ - Transformers for event generated when learner submit an exam attempt. + Base transformer for terminated exam events """ verb = Verb( id=constants.XAPI_VERB_TERMINATED, display=LanguageMap({constants.EN: constants.TERMINATED}), ) + + +@XApiTransformersRegistry.register("edx.special_exam.timed.attempt.created") +class TimedExamCreatedTransformer(BaseTimedExamTransformer, InitializedMixin): + """ + Transformers for event generated when learner start an exam attempt. + """ + + +@XApiTransformersRegistry.register("edx.special_exam.practice.attempt.created") +class PracticeExamCreatedTransformer(BasePracticeExamTransformer, InitializedMixin): + """ + Transformers for event generated when learner start an exam attempt. + """ + + +@XApiTransformersRegistry.register("edx.special_exam.proctored.attempt.created") +class ProctoredExamCreatedTransformer(BaseProctoredExamTransformer, InitializedMixin): + """ + Transformers for event generated when learner start an exam attempt. + """ + + +@XApiTransformersRegistry.register("edx.special_exam.timed.attempt.submitted") +class TimedExamSubmittedTransformer(BaseTimedExamTransformer, TerminatedMixin): + """ + Transformers for event generated when learner submit an exam attempt. + """ + + +@XApiTransformersRegistry.register("edx.special_exam.practice.attempt.submitted") +class PracticeExamSubmittedTransformer(BasePracticeExamTransformer, TerminatedMixin): + """ + Transformers for event generated when learner submit an exam attempt. + """ + + +@XApiTransformersRegistry.register("edx.special_exam.proctored.attempt.submitted") +class ProctoredExamSubmittedTransformer(BaseProctoredExamTransformer, TerminatedMixin): + """ + Transformers for event generated when learner submit an exam attempt. + """