def test_AsVersion(self): obj = { "registration": "016699c6-d600-48a7-96ab-86187498f16f", "instructor": {"member": [{"name": "instructorGroupMember"}]}, "team": {"member": [{"name": "teamGroupMember"}]}, "context_activities": {"category": {"id": "contextActivityCategory"}}, "revision": "revision", "platform": "platform", "language": "en-US", "extensions": {"extensions": "extend!"} } """ Keys are corrected, and ContextActivities is properly listified """ check_obj = { "registration": "016699c6-d600-48a7-96ab-86187498f16f", "instructor": {"member": [{"name": "instructorGroupMember", "objectType": "Agent"}], "objectType": "Group"}, "team": {"member": [{"name": "teamGroupMember", "objectType": "Agent"}], "objectType": "Group"}, "contextActivities": {"category": [{"id": "contextActivityCategory", "objectType": "Activity"}]}, "revision": "revision", "platform": "platform", "language": "en-US", "extensions": {"extensions": "extend!"} } ctx = Context(**obj) ctx2 = ctx.as_version() self.assertEqual(ctx2, check_obj)
def basic(cls, **kwargs): context = Context() if kwargs and kwargs.get('registration') != None: context.registration = kwargs.get('registration') return context
def basic(cls, **kwargs): context = Context() if kwargs: if kwargs.get("registration") != None: context.registration = kwargs.get("registration") return context
def test_InitLanguages(self): language_ids = ['en', 'ast', 'zh-yue', 'ar-afb', 'zh-Hans', 'az-Latn', 'en-GB', 'es-005', 'zh-Hant-HK', 'sl-nedis', 'sl-IT-nedis', 'de-CH-1901', 'de-DE-u-co-phonebk', 'en-US-x-twain'] for tag in language_ids: ctx = Context(language=tag) self.assertEqual(ctx.language, tag) self.assertIsInstance(ctx, Context)
def _add_default(cls, user, statement): if not statement.timestamp: statement.timestamp = LearningRecord.generate_timestamp() if impersonation.is_impersonating() and user.id == current_user.id: statement.actor = XAPIActor.generate_actor( impersonation.get_impersonation_original_user()) else: statement.actor = XAPIActor.generate_actor(user) # add default context info if not statement.context: statement.context = Context() if not statement.context.context_activities: statement.context.context_activities = ContextActivities() if not statement.context.context_activities.category: statement.context.context_activities.category = ActivityList() statement.context.context_activities.category.append( XAPIActivity.compair_source()) statement.context.platform = ResourceIRI.compair() if not statement.context.extensions: statement.context.extensions = Extensions() statement.context.extensions[ 'http://id.tincanapi.com/extension/session-info'] = { 'id': ResourceIRI.user_session(sess.get('session_id', '')), 'start_at': sess.get('start_at'), 'login_method': sess.get('login_method'), } if sess.get('end_at'): statement.context.extensions[ 'http://id.tincanapi.com/extension/session-info'][ 'end_at'] = sess.get('end_at') if impersonation.is_impersonating() and user.id == current_user.id: statement.context.extensions[ 'http://id.tincanapi.com/extension/session-info'][ 'impersonating-as'] = XAPIActor.generate_actor( user).as_version() statement.context.extensions[ 'http://id.tincanapi.com/extension/browser-info'] = {} if request and request.environ.get('HTTP_USER_AGENT'): statement.context.extensions[ 'http://id.tincanapi.com/extension/browser-info'][ 'user-agent'] = request.environ.get('HTTP_USER_AGENT') if request and request.environ.get('HTTP_REFERER'): statement.context.extensions[ 'http://id.tincanapi.com/extension/browser-info'][ 'referer'] = request.environ.get('HTTP_REFERER') return statement
def send_statement(verb_key, activity_key, activity_extensions=None): """Send a statement with the verb and activity keys and the context extensions""" if not tracing_enabled: return def thread_function(statement): # Send statement and receive HTTP response if not _send_statement_lrs(statement): io.add_statement( statement) # Backup the statement if it couldn't been sent global statement_number # Create the statement from the actor, the verb, the context and the activity keys if verb_key not in verbs: if debug_log_print: print("Tracing: Missing verb key {}".format(verb_key)) return if activity_key not in activities: if debug_log_print: print("Tracing: Missing activity key {}".format(activity_key)) return if send_to_LRS and debug_log_print: print("Tracing: Creating and Sending statement {}, {} {}".format( statement_number, verb_key, activity_key)) elif debug_log_print: print("Tracing: Creating (without sending) statement {}, {} {}".format( statement_number, verb_key, activity_key)) statement_number += 1 verb = verbs[verb_key] activity = activities[activity_key] extensions = { "https://www.lip6.fr/mocah/invalidURI/extensions/session-id": session_id, "https://www.lip6.fr/mocah/invalidURI/extensions/machine-id": machine_id, "https://www.lip6.fr/mocah/invalidURI/extensions/input-context": input_type } context = Context(extensions=extensions) if activity_extensions: activity = copy.deepcopy(activity) activity.definition.extensions = activity_extensions statement_time = datetime.datetime.utcnow() statement_time = statement_time.replace(tzinfo=datetime.timezone.utc) statement = Statement(actor=actor, verb=verb, object=activity, context=context, timestamp=statement_time) if debug_log_print: io.add_statement_debug(statement, statement_number) # Send the statement from another thread if send_to_LRS: x = threading.Thread(target=thread_function, args=(statement, )) x.start()
def test_InitContext(self): statement = Statement(context=Context(registration='016699c6-d600-48a7-96ab-86187498f16f')) self.assertIsNone(statement.id) self.assertIsNone(statement.actor) self.assertIsNone(statement.verb) self.assertIsNone(statement.object) self.assertIsNone(statement.timestamp) self.assertIsNone(statement.stored) self.assertIsNone(statement.authority) self.contextVerificationHelper(statement.context)
def get_context(self, user_details, course_details): """ Get Context for the statement. """ return Context(extensions=Extensions( { 'http://id.tincanapi.com/extension/user-details': user_details, 'http://id.tincanapi.com/extension/course-details': course_details, }, ))
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 get_context(self): """ Get context for xAPI transformed event. Returns: `Context` """ context = Context( extensions=self.get_context_extensions(), contextActivities=self.get_context_activities() ) return context
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 _enhance_statement(self, statement): context = Context(registration=self._SC._session_id, instructor=self._SC._instructor_actor) statement.context = context statement.timestamp = time.time() statement.id = str(uuid.uuid4()) # embed more info into the statement: # in the context extensions encode the settings: if follow/mode and locked_navigationis on, # add result: time spent on slide, average slide time (if available in slide DOM node) # slide indices # progress? return statement
def test_FromJSON(self): json_str = '{\ "registration": "016699c6-d600-48a7-96ab-86187498f16f",\ "instructor": {"member": [{"name": "instructorGroupMember"}]},\ "team": {"member": [{"name": "teamGroupMember"}]},\ "context_activities": {"category": {"id": "contextActivityCategory"}},\ "revision": "revision",\ "platform": "platform",\ "language": "en-US",\ "extensions": {"extensions": "extend!"}}' ctx = Context.from_json(json_str) self.ctxVerificationHelper(ctx)
def test_InitEmpty(self): ctx = Context() self.assertIsInstance(ctx, Context) self.assertEqual(vars(ctx), {'_context_activities': None, '_extensions': None, '_instructor': None, '_language': None, '_platform': None, '_registration': None, '_revision': None, '_statement': None, '_team': None})
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 test_InitAll(self): ctx = Context( registration=uuid.uuid4(), instructor=Group(member=[Agent(name='instructorGroupMember')]), team=Group(member=[Agent(name='teamGroupMember')]), context_activities=ContextActivities(category=Activity( id='contextActivityCategory')), revision='revision', platform='platform', language='en-US', statement=StatementRef(id='016699c6-d600-48a7-96ab-86187498f16f'), extensions=Extensions({'extensions': 'extend!'})) self.ctxVerificationHelper(ctx)
def _add_default(cls, user, statement): if not statement.timestamp: statement.timestamp = datetime.datetime.now().replace( tzinfo=pytz.utc).isoformat() if impersonation.is_impersonating() and user.id == current_user.id: statement.actor = XAPIActor.generate_actor( impersonation.get_impersonation_original_user()) else: statement.actor = XAPIActor.generate_actor(user) # add default context info if not statement.context: statement.context = Context() if not statement.context.context_activities: statement.context.context_activities = ContextActivities() if not statement.context.context_activities.category: statement.context.context_activities.category = ActivityList() statement.context.context_activities.category.append( XAPIActivity.compair_source()) statement.context.platform = XAPIResourceIRI.compair() if request and request.environ.get('HTTP_USER_AGENT'): if not statement.context.extensions: statement.context.extensions = Extensions() browser_info_key = XAPIExtension.context_extensions.get( 'browser information') statement.context.extensions[ browser_info_key] = request.environ.get('HTTP_USER_AGENT') if request and request.environ.get('HTTP_REFERER'): if not statement.context.extensions: statement.context.extensions = Extensions() referer_key = XAPIExtension.context_extensions.get('referer') statement.context.extensions[referer_key] = request.environ.get( 'HTTP_REFERER') if impersonation.is_impersonating() and user.id == current_user.id: if not statement.context.extensions: statement.context.extensions = Extensions() impersonating_as_key = XAPIExtension.context_extensions.get( 'impersonating as') statement.context.extensions[ impersonating_as_key] = XAPIActor.generate_actor(user) return statement
def create_statement(arbtt_csv_entry): """Creates a Tincan statement from arbtt csv input""" arbtt_record = ArbttRecord(arbtt_csv_entry) app = arbtt_record.application duration = arbtt_record.duration # XXX: Look for a cleaner way to get user details user = os.environ['LOGNAME'] email_address = "*****@*****.**" % (user, ) actor = Agent( name=user, mbox='mailto:' + email_address, ) verb = Verb( id='http://adlnet.gov/expapi/verbs/interacted', display=LanguageMap({'en-US': 'interacted'}), ) # Get activity from config or set the activity as 'unknown' activity_from_map = activity_map.get(app, "unknown") object = Activity( id=os.path.join(lrs['activities_uri'], activity_from_map), definition=ActivityDefinition( name=LanguageMap({'en-US': activity_from_map}), extensions=Extensions( {'http://id.tincanapi.com/extension/duration': duration}, ), ), ) context = Context(platform=app) # Construct the statement return Statement( actor=actor, verb=verb, object=object, context=context, )
def handle(self, *args, **options): # make sure file option is present if options['extract_event_number'] is None: extract_event_number = 100 else: extract_event_number = int(options['extract_event_number']) evt_list = TrackingLog.objects \ .filter(tincan_error='WRONG_VERB_OBJECT') \ .order_by('dtcreated')[:extract_event_number] for evt in evt_list: statement_json = json.loads(evt.statement) statement = { 'actor': Agent.from_json(json.dumps(statement_json['actor'])), 'verb': Verb.from_json(json.dumps(statement_json['verb'])), 'object': Activity.from_json(json.dumps(statement_json['object'])), 'timestamp': statement_json['timestamp'], 'context': Context.from_json(json.dumps(statement_json['context'])), } evt.statement = json.dumps(statement) evt.tincan_error = "CONVERTED" evt.save()
def _add_default(cls, user, statement): if not statement.timestamp: statement.timestamp = datetime.datetime.now().replace( tzinfo=pytz.utc).isoformat() statement.actor = XAPIActor.generate_actor(user) # add default context info if not statement.context: statement.context = Context() if not statement.context.context_activities: statement.context.context_activities = ContextActivities() if not statement.context.context_activities.category: statement.context.context_activities.category = ActivityList() statement.context.context_activities.category.append( XAPIActivity.compair_source()) if request and request.environ.get('HTTP_USER_AGENT'): if not statement.context.extensions: statement.context.extensions = Extensions() browser_info_key = XAPIExtension.context_extensions.get( 'browser information') statement.context.extensions[ browser_info_key] = request.environ.get('HTTP_USER_AGENT') if request and request.environ.get('HTTP_REFERER'): if not statement.context.extensions: statement.context.extensions = Extensions() referer_key = XAPIExtension.context_extensions.get('referer') statement.context.extensions[referer_key] = request.environ.get( 'HTTP_REFERER') return statement
def post(self, request, *args, **kwargs): form = self.form_class(request.POST, request.FILES) if form.is_valid(): data = form.cleaned_data project = get_object_or_404(Project, id=data['project']) user = data['user'] timezone = pytz.timezone("Europe/Rome") actor = Agent( name=user.get_display_name(), mbox='mailto:%s' % user.email, ) project_id = get_object_id(request, project) activity_type = xapi_activities['assessment']['type'] object_language = 'it' verb = Verb( id=xapi_verbs['completed']['id'], display=LanguageMap(**xapi_verbs['completed']['display']), ) file = request.FILES['file'] filename = file.name extension = filename.split(".")[-1] content = file.read() records = pyexcel.get_records(file_type=extension, file_content=content) name_dict = records[0] keys = name_dict.keys() rows = [] for record in records: date_time = record['Ora'] lesson = record['Lezione'] course = record['Corso'] activity = record['Attività'] duration_seconds = record['Durata (Secondi)'] response_seconds = record['Tempo medio di risposta (Secondi)'] score_percent = record['Punteggio (%)'] questions = record['Domande con risposta'] correct_answers = record['Risposte corrette'] timestamp = datetime.strptime(date_time, "%d/%m/%Y %H.%M") timestamp = timezone.localize(timestamp) object_name = 'EarMaster: {}'.format(activity) object_description = 'Esercizio di {} in lezione EarMaster "{}"'.format( activity, lesson) activity_definition = ActivityDefinition( name=LanguageMap(**{object_language: object_name}), description=object_description and LanguageMap(**{object_language: object_description}) or None, type=activity_type, ) course_id = '{}{}'.format(project_id, slugify(course)) lesson_id = '{}/{}'.format(course_id, slugify(lesson)) object = Activity( objectType='Activity', id=lesson_id, definition=activity_definition, ) parent = { 'objectType': 'Activity', 'id': course_id, 'definition': { 'type': xapi_activities['course']['type'], 'name': { 'it': course } } } grouping = { 'objectType': 'Activity', 'id': project_id, 'definition': { 'type': xapi_activities['project']['type'], 'name': LanguageMap(**{get_language(project): project.name}) } } context = { 'platform': 'EarMaster', 'context_activities': { 'parent': parent, 'grouping': grouping } } context = Context(**context) score_scaled = float(score_percent.replace('%', '')) / 100 score_max = questions score_raw = correct_answers score = { 'min': 0, 'max': score_max, 'raw': score_raw, 'scaled': score_scaled } score = Score(**score) result = {'duration': duration_seconds, 'score': score} result = Result(**result) statement = Statement(actor=actor, verb=verb, object=object, context=context, result=result, timestamp=timestamp) result = send_statement(statement) return HttpResponseRedirect('/project/%s/' % project.slug) return render(request, self.template_name, {'earmaster_import_results_form': form})
def get_context(self, event): """Get Context for the statement.""" return Context(platform=settings.OPENEDX_PLATFORM_URI, )
def test_FromJSONExceptionMalformedJSON(self): with self.assertRaises(AttributeError): Context.from_json('{"test": "invalid property"}')
def test_FromJSONExceptionBadJSON(self): with self.assertRaises(ValueError): Context.from_json('{"bad JSON"}')
def test_InitExceptionInvalidLanguage(self): regional_id = 'In-valiD-Code' with self.assertRaises(ValueError): Context(language=regional_id)
def test_InitExceptionInvalidUUID(self): reg = 'not a valid uuid' with self.assertRaises(ValueError): Context(registration=reg)
def test_InitUUIDFromString(self): reg = uuid.uuid4() """ Uses same regex as PHP """ ctx = Context(registration=str(reg)) self.assertEqual(ctx.registration, reg)
def test_FromJSONExceptionBadJSON(self): with self.assertRaises(ValueError): ctx = Context.from_json('{"bad JSON"}')
def get_context(self, event): """Get Context for the statement.""" return Context( platform=settings.OPENEDX_PLATFORM_URI, # registration=self._get_enrollment_id(event) TODO: not sure why this format doesn't work )
id='http://tincanapi.com/TinCanPython/Example/0', definition=ActivityDefinition( name=LanguageMap({'en-US': 'TinCanPython Library'}), description=LanguageMap( {'en-US': 'Use of, or interaction with, the TinCanPython Library'}), ), ) print "...done" # construct a context for the statement print "constructing the Context..." context = Context( registration=uuid.uuid4(), instructor=Agent( name='Lord TinCan', mbox='mailto:[email protected]', ), # language='en-US', ) print "...done" # construct the actual statement print "constructing the Statement..." statement = Statement( actor=actor, verb=verb, object=object, context=context, ) print "...done"
object = Activity( id='http://tincanapi.com/TinCanPython/Example/0', definition=ActivityDefinition( name=LanguageMap({'en-US': 'TinCanPython Library'}), description=LanguageMap( {'en-US': 'Use of, or interaction with, the TinCanPython Library'}), ), ) print("...done") # construct a context for the statement print("constructing the Context...") context = Context( registration=uuid.uuid4(), instructor=Agent( name='Lord TinCan', mbox='mailto:[email protected]', ), # language='en-US', ) print("...done") # construct the actual statement print("constructing the Statement...") statement = Statement( actor=actor, verb=verb, object=object, context=context, ) print("...done") # save our statement to the remote_lrs and store the response in 'response' print("saving the Statement...")
def put_statement(request, user, verb, object, target, language=XAPI_LANGUAGE): # construct an LRS lrs = RemoteLRS( version=settings.LRS_VERSION, endpoint=settings.LRS_ENDPOINT, auth=settings.LRS_AUTH, ) # construct the actor of the statement # IMPORTANT - account is OK but cannot coexist with mbox or other way of uniquely identifying the actor try: actor = Agent( name=user.get_display_name(), mbox='mailto:%s' % user.email, # account=AgentAccount(name=str(user.pk), home_page='https://www.commonspaces.eu') ) except: return False # construct the verb of the statement verb = XAPI_VERB_ALIASES.get(verb, verb) # for compatibility with CommonSpaces verb = Verb( id=xapi_verbs[verb]['id'], display=LanguageMap(**xapi_verbs[verb]['display']), ) action = object.__class__.__name__ action = XAPI_ACTIVITY_ALIASES.get( action, action) # for compatibility with CommonSpaces activity_type = xapi_activities[action]['type'] object_id = get_object_id(request, object) # 190307 GT: defined get_object_id object_name = get_name(object) # 190307 GT: defined get_name object_description = get_description(object) object_language = get_language(object) activity_definition = ActivityDefinition( name=LanguageMap(**{object_language: object_name}), description=object_description and LanguageMap(**{object_language: object_description}) or None, type=activity_type, ) # construct the object of the statement object = Activity( id=object_id, definition=activity_definition, ) context = {'platform': XAPI_PLATFORM, 'language': get_current_language()} """ 190308 GT: would produce the exception "Object of type 'UUID' is not JSON serializable" in getting the response if request: context['registration'] = str(get_registration(request)) """ if target: target_type = target.__class__.__name__ context_activities = {} if target_type in ['Folder', 'Forum', 'LearningPath']: context_activities['parent'] = { 'objectType': 'Activity', 'id': get_object_id(request, target), 'definition': { 'type': xapi_activities[XAPI_ACTIVITY_ALIASES.get( target_type, target_type)]['type'], 'name': { 'en': get_name(target) } } } if target_type == 'Folder': project = target.get_project() if project: context_activities['grouping'] = get_context_grouping( request, project) elif target_type == 'Forum': # project = target.forum_get_project() project = target.get_project() if project: context_activities['grouping'] = get_context_grouping( request, project) elif target_type == 'LearningPath': if target.project: context_activities['grouping'] = get_context_grouping( request, target.project) elif target_type == 'Project': context_activities['grouping'] = get_context_grouping( request, target) if context_activities: context['context_activities'] = context_activities context = Context(**context) # construct the actual statement statement = Statement( actor=actor, verb=verb, object=object, context=context, ) return send_statement(statement)
def socialmedia_builder(statement_id, verb, platform, account_name, account_homepage, object_type, object_id, message, tags=[], parent_object_type=None, parent_id=None, rating=None, instructor_name=None, instructor_email=None, team_name=None, unit=None, account_email=None, user_name=None, timestamp=None, other_contexts=[]): agentaccount = AgentAccount(name=account_name, home_page=account_homepage) actor = Agent(account=agentaccount) # XAPI statements can only have one of: AgentAccount, mbox, mboxsha1 or Openid #if (account_email is not None): # actor.mbox = account_email #if (user_name is not None): # actor.name = user_name verb_obj = Verb(id=xapi_settings.get_verb_iri(verb), display=LanguageMap({'en-US': verb})) #message = message.decode('utf-8').encode('ascii', 'ignore') #message.decode('utf-8').replace(u"\u2018", "'").replace(u"\u2019", "'").replace(u"\u2013", "-").replace(u"\ud83d", " ").replace(u"\ude09", " ").replace(u"\u00a0l", " ").replace(u"\ud83d", " ").replace(u"\u2026", " ").replace(u"\ude09", " ").replace(u"\u00a0"," ") object = Activity( id=object_id, object_type=object_type, definition=ActivityDefinition( name=LanguageMap({'en-US': message}), type=xapi_settings.get_object_iri(object_type)), ) taglist = [] for tag in tags: tagobject = Activity( id='http://id.tincanapi.com/activity/tags/tincan', object_type='Activity', definition=ActivityDefinition( name=LanguageMap({'en-US': tag}), type=xapi_settings.get_object_iri('Tag')), ) taglist.append(tagobject) # Add "other" in contextActivities other_contexts_list = [] for other in other_contexts: other_context_obj = Activity( id=other['obj_id'], object_type=other['obj_type'], definition=ActivityDefinition(name=LanguageMap( {'en-US': other['definition']['name']}), type=other['definition']['type']), ) other_contexts_list.append(other_context_obj) taglist.extend(other_contexts_list) parentlist = [] if (verb in ['liked', 'shared', 'commented', 'rated']): #recipe specific config parentobject = Activity( id=parent_id, object_type=parent_object_type, ) parentlist.append(parentobject) elif (platform == 'GitHub' or platform.lower() == 'trello'): parentobject = Activity( id=parent_id, object_type=parent_object_type, ) parentlist.append(parentobject) courselist = [] if unit is not None: courseobject = Activity( id="http://adlnet.gov/expapi/activities/course", object_type='Course', definition=ActivityDefinition( name=LanguageMap({'en-US': unit.code}), description=LanguageMap({ 'en-US': "A course/unit of learning hosted on the CLAToolkit" }))) courselist.append(courseobject) instructor = None if (instructor_name is not None): instructor = Agent(name=instructor_name, mbox=instructor_email) team = None if (team_name is not None): team = Group(Agent(name=team_name), object_type='Group') result = None if (rating is not None): rating_as_float = float(rating) result = Result(score=Score(raw=rating_as_float)) context = Context(registration=uuid.uuid4(), platform=platform, instructor=instructor, team=team, context_activities=ContextActivities( other=ActivityList(taglist), parent=ActivityList(parentlist), grouping=ActivityList(courselist))) # Xapi spec requires that the learning provider SHOULD provide the authority # Authority is a group with Agent as oauth consumer app where name is token url and homepage is consumer_key account = AgentAccount(name=unit.get_lrs_key(), home_page=unit.get_lrs_access_token_url()) authority = Group(Agent(account=account)) statement = statement_builder(statement_id, actor, verb_obj, object, context, result, authority, timestamp) return statement
def test_FromJSONExceptionPartiallyMalformedJSON(self): with self.assertRaises(AttributeError): ctx = Context.from_json('{"test": "invalid property", "id": \ "valid property"}')