def test_AsVersion(self): adef = ActivityDefinition({ 'description': {'en-US': 'test'}, 'name': {'en-US': 'test'}, 'type': 'test', 'more_info': 'test', 'interaction_type': 'choice', 'correct_responses_pattern': ['test'], 'choices': InteractionComponentList(), 'scale': InteractionComponentList(), 'source': InteractionComponentList(), 'target': InteractionComponentList(), 'steps': InteractionComponentList(), 'extensions': {'test': 'test'} }) adef2 = adef.as_version() self.assertEqual(adef2, { "name": {"en-US": "test"}, "correctResponsesPattern": ["test"], "scale": [], "description": {"en-US": "test"}, "choices": [], "source": [], "steps": [], "moreInfo": "test", "extensions": {"test": "test"}, "interactionType": "choice", "target": [], "type": "test", })
def test_AsVersion(self): adef = ActivityDefinition( { "description": {"en-US": "test"}, "name": {"en-US": "test"}, "type": "test", "more_info": "test", "interaction_type": "choice", "correct_responses_pattern": ["test"], "choices": InteractionComponentList(), "scale": InteractionComponentList(), "source": InteractionComponentList(), "target": InteractionComponentList(), "steps": InteractionComponentList(), "extensions": {"test": "test"}, } ) adef2 = adef.as_version() self.assertEqual( adef2, { "name": {"en-US": "test"}, "correctResponsesPattern": ["test"], "scale": [], "description": {"en-US": "test"}, "choices": [], "source": [], "steps": [], "moreInfo": "test", "extensions": {"test": "test"}, "interactionType": "choice", "target": [], "type": "test", }, )
def test_ToJSONIgnoreNone(self): adef = ActivityDefinition({ 'description': { 'en-US': 'test' }, 'more_info': None }) self.assertEqual(adef.to_json(), '{"description": {"en-US": "test"}}')
def test_AsVersionIgnoreNone(self): adef = ActivityDefinition({ 'description': {'en-US': 'test'}, 'more_info': None }) self.assertEqual(adef.description, {'en-US': 'test'}) self.assertIsNone(adef.more_info) adef2 = adef.as_version() self.assertEqual(adef2, {'description': {'en-US': 'test'}})
def test_build_statement(self): """ The build_statement function should return a valid tincan Statement. """ user = UserFactory() verb = Verb( id="https://activitystrea.ms/schema/1.0/create", display=LanguageMap({"en-US": "created"}), ) activity = Activity( id=f"id://ashley/topic/{uuid.uuid4()}", definition=ActivityDefinition( name=LanguageMap({"en-US": "test topic"}), type="http://id.tincanapi.com/activitytype/discussion", ), ) context = Context(context_activities=ContextActivities(parent=[ Activity( id=f"uuid://{uuid.uuid4()}", definition=ActivityDefinition( name=LanguageMap({"en-US": "test forum"}), type="http://id.tincanapi.com/activitytype/community-site", ), ) ])) statement1 = build_statement(user, verb, activity, context) statement2 = build_statement(user, verb, activity, context) # The function should generate a random, non empty uuid as a # statement ID self.assertIsInstance(statement1.id, uuid.UUID) self.assertIsInstance(statement2.id, uuid.UUID) self.assertNotEqual(statement1.id, statement2.id) # The statement id can also be specified statement3_id = uuid.uuid4() statement3 = build_statement(user, verb, activity, context, statement3_id) self.assertEqual(statement3_id, statement3.id) # The verb, object and context should correspond to the given arguments self.assertEqual(statement1.verb, verb) self.assertEqual(statement1.object, activity) self.assertEqual(statement1.context, context) # The Actor part of the statement should reflect the user passed as an # argument self.assertEqual(statement1.actor.account.name, user.lti_remote_user_id) self.assertEqual(statement1.actor.account.home_page, user.lti_consumer.url)
def setUp(self): self.endpoint = lrs_properties.endpoint self.version = lrs_properties.version self.username = lrs_properties.username self.password = lrs_properties.password self.lrs = RemoteLRS( version=self.version, endpoint=self.endpoint, username=self.username, password=self.password, ) self.agent = Agent(mbox="mailto:[email protected]") self.agent2 = Agent(mbox="mailto:[email protected]") self.verb = Verb(id="http://adlnet.gov/expapi/verbs/experienced", display=LanguageMap({"en-US": "experienced"})) self.group = Group(member=[self.agent, self.agent2]) self.activity = Activity( id="http://tincanapi.com/TinCanPython/Test/Unit/0", definition=ActivityDefinition()) self.activity.definition.type = "http://id.tincanapi.com/activitytype/unit-test" self.activity.definition.name = LanguageMap({"en-US": "Python Tests"}) self.activity.definition.description = LanguageMap( {"en-US": "Unit test in the test suite for the Python library"}) self.activity.object_type = 'Activity' self.parent = Activity(id="http://tincanapi.com/TinCanPython/Test", definition=ActivityDefinition()) self.parent.definition.type = "http://id.tincanapi.com/activitytype/unit-test-suite" self.parent.definition.name = LanguageMap({"en-US": "Python Tests"}) self.parent.definition.description = LanguageMap( {"en-US": "Unit test in the test suite for the Python library"}) self.parent.object_type = 'Activity' self.statement_ref = StatementRef(id=uuid.uuid4()) self.context = Context(registration=uuid.uuid4(), statement=self.statement_ref) # self.context.context_activities = ContextActivities(parent=[self.parent]) self.score = Score(raw=97, scaled=0.97, max=100, min=0) self.result = Result(score=self.score, success=True, completion=True, duration="PT120S") self.substatement = SubStatement( actor=self.agent, verb=self.verb, object=self.activity, )
def track_forum_view(sender, forum, user, request, response, **kwargs): """Log a XAPI statement when a user views a forum.""" parent_activities = None consumer = getattr(user, "lti_consumer", None) if consumer is None: logger.warning("Unable to get LTI consumer of user %s", user) return xapi_logger = logging.getLogger(f"xapi.{user.lti_consumer.slug}") verb = Verb( id="http://id.tincanapi.com/verb/viewed", display=LanguageMap({"en-US": "viewed"}), ) obj = Activity( id=f"id://ashley/forum/{forum.pk}", definition=ActivityDefinition( name=LanguageMap( {to_locale(settings.LANGUAGE_CODE).replace("_", "-"): forum.name} ), type="http://id.tincanapi.com/activitytype/community-site", ), ) if request.forum_permission_handler.current_lti_context_id is not None: try: lti_context = LTIContext.objects.get( pk=request.forum_permission_handler.current_lti_context_id ) parent_activities = [ Activity( id=lti_context.lti_id, definition=ActivityDefinition( type="http://adlnet.gov/expapi/activities/course" ), ) ] except LTIContext.DoesNotExist: pass if parent_activities is not None: context = Context( context_activities=ContextActivities(parent=parent_activities), ) else: context = None statement = build_statement(user, verb, obj, context) if statement: xapi_logger.info(statement.to_json())
def comparison_criterion(cls, comparison, comparison_criterion): return Activity( id=XAPIResourceIRI.comparison_criterion(comparison_criterion.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('solution'), name=LanguageMap({'en-US': "Assignment criterion comparison"})))
def sendstatement_tally_shared(self, conn, tally_obj): # self._SC._active_presentation_name and tally_obj['id'] give me the id. # self._presentation_activity_id = 'https://iltserver.com/presentations/' + presentation_slug tally_activity_id = 'https://iltserver.com/presentations/' + self._SC._active_presentation_name + '/interaction_stats/' + tally_obj[ 'id'] verb = Verb( id='http://adlnet.gov/expapi/verbs/shared', display=LanguageMap({'en-US': 'shared'}), ) obj = Activity( id=tally_activity_id, definition=ActivityDefinition( name=LanguageMap({'en-US': 'Interaction statistics'}), description=LanguageMap({ 'en-US': 'Statistics about the responses to an interaction in the Reveal JS presentation.' }), type= 'https://xapi.xapicohort.org/iltxapiteam/activity-types/interaction-stats' ), ) result_obj = Result(extensions=Extensions({ 'https://iltserver.com/extensions/interaction-response-info': tally_obj })) statement = Statement(actor=conn._actor, verb=verb, object=obj, result=result_obj) self._send_to_LRS(statement)
def compair_source(cls): return Activity( id='http://xapi.learninganalytics.ubc.ca/category/compair', definition=ActivityDefinition( type='http://id.tincanapi.com/activitytype/source' ) )
def self_evaluation_question(cls, answer_comment): return Activity(id=XAPIResourceIRI.self_evaluation_question( answer_comment.assignment_uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('question'), name=LanguageMap( {'en-US': "Assignment self-evaluation"})))
def get_object(self, event): """ Get object for the statement. """ try: display_name = event['context']['module']['display_name'] except KeyError: display_name = "Problem" try: event_data = self.get_event_data(event) submission = event_data['submission'][event_data['submission'].keys()[0]] question = submission['question'].replace('\"', '').replace('\\', '') question = re.sub(r'\(\$(\w+)\)', r'<\1>', question) except KeyError: question = event['context']['question'] return Activity( id=self._get_activity_id(event), definition=ActivityDefinition( type=constants.XAPI_ACTIVITY_INTERACTION, # could be _QUESTION if not CAPA name=LanguageMap({'ru-RU': question}), description=LanguageMap({'ru-RU': display_name}), # TODO: interactionType, correctResponsesPattern, choices, if possible ), )
def course(cls, course): activity = Activity(id=XAPIResourceIRI.course(course.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('course'), name=LanguageMap({'en-US': course.name}))) return activity
def get_context_activities(self): """ Get context activities for xAPI transformed event. Returns: `ContextActivities` """ if self.get_data('context.course_id') is not None: course = get_course_from_id(self.get_data('context.course_id')) course_name = LanguageMap({constants.EN_US: course["display_name"]}) parent_activities = [ Activity( id=self.get_object_iri('course', self.get_data('context.course_id')), object_type=constants.XAPI_ACTIVITY_COURSE, definition=ActivityDefinition( type=constants.XAPI_ACTIVITY_COURSE, name=course_name ) ), ] return ContextActivities( parent=ActivityList(parent_activities), ) else: return None
def user_profile(cls, user): return Activity( id=XAPIResourceIRI.user_profile(user.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('user profile'), name=LanguageMap({ 'en-US': "user profile" }) ) )
def report(cls, file_name): return Activity( id=XAPIResourceIRI.report(file_name), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('file'), name=LanguageMap({ 'en-US': "Report" }) ) )
def assignment_attachment(cls, file): return Activity( id=XAPIResourceIRI.attachment(file.name), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('file'), name=LanguageMap({ 'en-US': "Assignment attachment" }) ) )
def answer_comment(cls, answer_comment): return Activity( id=XAPIResourceIRI.answer_comment(answer_comment.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('comment'), name=LanguageMap({ 'en-US': "Assignment answer comment" }) ) )
def answer_evaluation_on_criterion(cls, answer, comparison_criterion): return Activity( id=XAPIResourceIRI.answer_criterion(answer.uuid, comparison_criterion.criterion_uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('solution'), name=LanguageMap({ 'en-US': "Assignment answer based on criterion" }) ) )
def answer(cls, answer): return Activity( id=XAPIResourceIRI.answer(answer.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('solution'), name=LanguageMap({ 'en-US': "Assignment answer" }) ) )
def setUp(self): self.activity = Activity( id="http://tincanapi.com/TinCanPython/Test/Unit/0", definition=ActivityDefinition()) self.activity.definition.type = "http://id.tincanapi.com/activitytype/unit-test" self.activity.definition.name = LanguageMap({"en-US": "Python Tests"}) self.activity.definition.description = LanguageMap( {"en-US": "Unit test in the test suite for the Python library"})
def compair(cls): return Activity( id=XAPIResourceIRI.compair(), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('service'), name=LanguageMap({ 'en-US': "ComPAIR" }) ) )
def test_InitUnpack(self): obj = { 'id': 'test', 'definition': ActivityDefinition(), 'object_type': 'Activity' } activity = Activity(**obj) self.activityVerificationHelper(activity)
def report(cls, file_name, mimetype): activity = Activity(id=ResourceIRI.report(file_name), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('file'), name=LanguageMap({'en-US': file_name}), extensions=Extensions())) activity.definition.extensions[ 'http://id.tincanapi.com/extension/mime-type'] = mimetype return activity
def test_AsVersion(self): activity = Activity(id='test', definition=ActivityDefinition(), object_type='Activity') activity2 = activity.as_version() self.assertEqual(activity2, { 'id': 'test', 'definition': {}, 'objectType': 'Activity' })
def test_FromJSON(self): json_str = '{"name":{"en-US":"test"},\ "description":{"en-US":"test"},\ "type":"test",\ "more_info":"test",\ "interaction_type":"choice",\ "correct_responses_pattern": ["test"],\ "choices": [], "scale": [], "source": [], "target": [], "steps": [],\ "extensions": {"test": "test"}}' adef = ActivityDefinition.from_json(json_str) self.definitionVerificationHelper(adef)
def course(cls, course): activity = Activity(id=ResourceIRI.course(course.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('course'), name=LanguageMap({ 'en-US': LearningRecord.trim_text_to_size_limit( course.name) }))) return activity
def comparison_question(cls, assignment, comparison_number): return Activity( id=ResourceIRI.comparison_question(assignment.course_uuid, assignment.uuid, comparison_number), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('question'), name=LanguageMap({ 'en-US': "Assignment comparison #" + str(comparison_number) })))
def assignment(cls, assignment): activity = Activity( id=XAPIResourceIRI.assignment(assignment.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('assessment'), name=LanguageMap({'en-US': assignment.name}))) if assignment.description: activity.definition.description = LanguageMap( {'en-US': assignment.description}) return activity
def criterion(cls, criterion): activity = Activity( id=XAPIResourceIRI.criterion(criterion.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('question'), name=LanguageMap({'en-US': criterion.name}))) if criterion.description: activity.definition.description = LanguageMap( {'en-US': criterion.description}) return activity
def get_object(self): """ Get object for xAPI transformed event. Returns: `Activity` """ return Activity( id=self.get_data('data.target_url'), definition=ActivityDefinition(type=constants.XAPI_ACTIVITY_LINK), )
def answer(cls, answer): activity = Activity( id=ResourceIRI.answer(answer.course_uuid, answer.assignment_uuid, answer.uuid), definition=ActivityDefinition( type=XAPIActivity.activity_types.get('solution'), extensions=Extensions())) activity.definition.extensions[ 'http://id.tincanapi.com/extension/isDraft'] = answer.draft return activity
def test_FromJSONExceptionBadJSON(self): with self.assertRaises(ValueError): ActivityDefinition.from_json('{"bad JSON"}')
def test_FromJSONExceptionPartiallyMalformedJSON(self): with self.assertRaises(AttributeError): ActivityDefinition.from_json( '{"test": "invalid property", "id": \ "valid property"}' )
def test_FromJSONExceptionEmpty(self): with self.assertRaises(ValueError): ActivityDefinition.from_json("")
def test_ToJSONEmpty(self): adef = ActivityDefinition() self.assertEqual(adef.to_json(), "{}")
def test_ToJSONIgnoreNone(self): adef = ActivityDefinition({"description": {"en-US": "test"}, "more_info": None}) self.assertEqual(adef.to_json(), '{"description": {"en-US": "test"}}')
def test_AsVersionIgnoreNone(self): adef = ActivityDefinition({"description": {"en-US": "test"}, "more_info": None}) self.assertEqual(adef.description, {"en-US": "test"}) self.assertIsNone(adef.more_info) adef2 = adef.as_version() self.assertEqual(adef2, {"description": {"en-US": "test"}})
def test_AsVersionEmpty(self): adef = ActivityDefinition() adef2 = adef.as_version() self.assertEqual(adef2, {})