def sendstatement_interaction_completed(self, conn, interaction_info): # HERE TO-DO: I want to change 'completion' ... if the submission was forced, say completion = NO # although it's probably not nessary... verb = Verb( id='http://adlnet.gov/expapi/verbs/completed', display=LanguageMap({'en-US': 'completed'}), ) if (interaction_info['interaction_type'] == 'choice'): result_obj = Result( completion=interaction_info['interaction_type'], response=','.join(interaction_info['options_checked']), success=interaction_info['correct']) else: result_obj = Result( completion=interaction_info['interaction_type'], response=interaction_info['response'], success=interaction_info['correct']) statement = Statement( actor=conn._actor, verb=verb, object=self._make_interaction_object(interaction_info), result=result_obj) #app_log.info('SENDING INTERACTION Statement: '+ statement.actor.mbox + ' ' + statement.verb.id + ' ' + statement.object.id) self._send_to_LRS(statement)
def basic(cls, **kwargs): result = Result() if kwargs: if kwargs.get('success') != None: result.success = kwargs.get('success') if kwargs.get('completion') != None: result.completion = kwargs.get('completion') if kwargs.get('changes') != None: result.extensions = Extensions() if not result.extensions else result.extensions result.extensions['http://xapi.learninganalytics.ubc.ca/extension/changes'] = kwargs.get('changes') return result
def get_result(self, event): event_data = self.get_event_data(event) cur_time = event_data.get('currentTime', event_data.get('current_time', 0)) return Result(extensions={ constants.XAPI_RESULT_VIDEO_TIME: cur_time, })
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 get_result(self, event): event_data = self.get_event_data(event) cur_time = event_data.get('currentTime', event_data.get('current_time', 0)) cur_time = float('{:.2f}'.format(cur_time)) cur_time = jsonify_timedelta((datetime.timedelta(seconds=cur_time))) return Result(success=True, completion=False, duration=cur_time)
def test_serialize_deserialize(self): res = Result() res.completion = True res.duration = timedelta(seconds=1.75) # res.duration = 'PT1.75S' # ISO 8601 res.extensions = self.extensions res.response = "Here's a response" res.score = self.score res.success = False self.assertSerializeDeserialize(res)
def test_InitResult(self): statement = Statement(result=Result(duration=timedelta(days=7))) 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.resultVerificationHelper(statement.result)
def get_result(self): """ Get result for xAPI transformed event. Returns: `Result` """ return Result(extensions=Extensions({ constants.XAPI_RESULT_VIDEO_TIME: convert_seconds_to_float(self.get_data('data.currentTime')) }))
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_result(self, event): event_data = self.get_event_data(event) earned = event_data['weighted_earned'] possible = event_data['weighted_possible'] return Result( score={ 'raw': earned, 'min': 0, 'max': possible, 'scaled': float(earned / possible) if possible > 0 else 0 }, success=True if earned >= possible else False, )
def test_serialize_deserialize_init(self): data = { 'completion': True, 'duration': timedelta(seconds=1.75), # 'duration': 'PT1.75S', # ISO 8601 'extensions': self.extensions, 'response': "Here's a response", 'score': self.score, 'success': False, } res = Result(**data) self.assertSerializeDeserialize(res)
def get_result(self): """ Get result for xAPI transformed event. Returns: `Result` """ return Result(extensions=Extensions({ constants.XAPI_RESULT_VIDEO_TIME_FROM: convert_seconds_to_float(self.get_data('data.old_time')), constants.XAPI_RESULT_VIDEO_TIME_TO: convert_seconds_to_float(self.get_data('data.new_time')), }), )
def sendstatement_unlocked_followme(self, conn): # the object of this statement is the presentation, in the context of session verb = Verb( id='http://adlnet.gov/expapi/verbs/interacted', display=LanguageMap({'en-US': 'interacted'}), ) result_obj = Result(extensions=Extensions( {'https://iltserver.com/extensions/follow-me': 'off'})) statement = Statement(actor=conn._actor, verb=verb, object=self._presentation_object, result=result_obj) self._send_to_LRS(statement)
def get_result(self): """ Get result for xAPI transformed event. Returns: `Result` """ return Result(extensions=Extensions({ constants.XAPI_RESULT_VIDEO_TIME: convert_seconds_to_float(self.get_data('data.duration')) }), completion=True, duration=convert_seconds_to_float( self.get_data('data.duration')))
def sendstatement_sync_all_to_instructor(self, conn): # the object of this statement is the presentation, in the context of session verb = Verb( id='http://adlnet.gov/expapi/verbs/interacted', display=LanguageMap({'en-US': 'interacted'}), ) result_obj = Result(extensions=Extensions({ 'https://iltserver.com/extensions/sync-all-to-instructor': 'request' })) statement = Statement(actor=conn._actor, verb=verb, object=self._presentation_object, result=result_obj) self._send_to_LRS(statement)
def get_result(self, course_grade): """ Get result for the statement. Arguments: course_grade (CourseGrade): Course grade. """ return Result(score=Score( scaled=course_grade.percent, raw=course_grade.percent * 100, min=MIN_SCORE, max=MAX_SCORE, ), success=course_grade.passed, completion=course_grade.passed)
def get_result(self, event): return Result(score={ 'raw': event['context']['module']['progress'][0], 'min': 0, 'max': event['context']['module']['progress'][1], 'scaled': float(event['context']['module']['progress'][0] / event['context']['module']['progress'][1]) }, success=event['context']['module']['done'], completion=True)
def get_result(self, event): event_data = self.get_event_data(event) # for now we are going to assume one submission # TODO: when is that not true? is it ever not true? What problem types? submission = event_data['submission'][event_data['submission'].keys() [0]] return Result( score={ 'raw': event_data['grade'], 'min': 0, 'max': event_data['max_grade'], 'scaled': float(event_data['grade'] / event_data['max_grade']) }, success=event_data['success'] == 'correct', # TODO: to determine completion would need to know max allowed attempts? # probably should return True here but uswe a result extension for num attempts/attempts left response=json.dumps(submission['answer']))
def basic(cls, **kwargs): result = Result() if kwargs: if kwargs.get('duration') != None: result.duration = kwargs.get('duration') if kwargs.get('success') != None: result.success = kwargs.get('success') if kwargs.get('completion') != None: result.completion = kwargs.get('completion') if kwargs.get('changes') != None: result.extensions = Extensions( ) if not result.extensions else result.extensions fields_changed_key = XAPIExtension.result_extensions.get( 'fields changed') result.extensions[fields_changed_key] = kwargs.get('changes') return result
def get_result(self, event): event_data = self.get_event_data(event) # for now we are going to assume one submission # TODO: when is that not true? is it ever not true? What problem types? try: data = event_data['submission'] answer = [] for key in data: log.error('key {} - {}'.format(key, data[key])) trash = data[key]['answer'] log.error(trash) if type(trash) is not unicode: for i in trash: p = re.sub(r"(\n.*)", r'', i) answer.append(p) else: answer.append(trash) if len(answer) > 1: answer = ', '.join("<%s>" % item for item in answer) else: answer = ''.join(answer[0]) answer = answer.replace('\"', '').strip() #.replace('\\\\', '') except: answer = event['context']['answer'].strip() #.replace('\\\\', '') try: success = event_data['success'] == 'correct' except: success = event['event']['grade'] == event['event']['max_grade'] return Result( score={ 'raw': event_data['grade'], 'min': 0, 'max': event_data['max_grade'], 'scaled': float(event_data['grade']) / float(event_data['max_grade']) }, success=success, # TODO: to determine completion would need to know max allowed attempts? # probably should return True here but uswe a result extension for num attempts/attempts left response=answer.encode('utf-8') )
def get_result(self): """ Get result for xAPI transformed event. Returns: `Result` """ event_data = self.get_data('data') return Result(success=event_data['weighted_earned'] >= event_data['weighted_possible'], score={ 'min': 0, 'max': event_data['weighted_possible'], 'raw': event_data['weighted_earned'], 'scaled': event_data['weighted_earned'] / event_data['weighted_possible'] })
def basic(cls, **kwargs): result = Result() if kwargs: if kwargs.get('duration') != None: result.duration = kwargs.get('duration') if kwargs.get('success') != None: result.success = kwargs.get('success') if kwargs.get('completion') != None: result.completion = kwargs.get('completion') if kwargs.get('changes') != None: result.extensions = Extensions() if not result.extensions else result.extensions fields_changed_key = XAPIExtension.result_extensions.get('fields changed') result.extensions[fields_changed_key] = kwargs.get('changes') return result
def get_result(self, persistent_course_grade): """ Get result for the statement. Arguments: persistent_course_grade (PersistentCourseGrade): PersistentCourseGrade record """ completed = 0 success = 0 if persistent_course_grade.passed_timestamp is not None: completed = 1 success = 1 return Result(score=Score( scaled=persistent_course_grade.percent_grade, raw=persistent_course_grade.percent_grade * 100, min=MIN_SCORE, max=MAX_SCORE, ), success=success, completion=completed)
def get_result(self): """ Get result for xAPI transformed event. Returns: Result """ # Do not transform result if the event is generated from browser if self.get_data('context.event_source') == 'browser': return None event_data = self.get_data('data') if event_data is None: event_data = {} submission = self._get_submission() if submission: response = submission["answer"] else: response = event_data.get('answers', None) return Result( success=event_data.get('success', None) == 'correct', score={ 'min': 0, 'max': event_data.get('max_grade', None), 'raw': event_data.get('grade', None), 'scaled': event_data.get('grade', None) / event_data.get('max_grade', None) if event_data.get('max_grade', None) is not None and event_data.get('grade', None) is not None else None }, response=response)
def test_bad_property_init(self): with self.assertRaises(AttributeError): Result(bad_name=2) with self.assertRaises(AttributeError): Result({'bad_name': 2})
def socialmedia_builder(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, course_code=None, account_email=None, user_name=None, timestamp=None): verbmapper = {'created': 'http://activitystrea.ms/schema/1.0/create', 'shared': 'http://activitystrea.ms/schema/1.0/share', 'liked': 'http://activitystrea.ms/schema/1.0/like', 'rated': 'http://id.tincanapi.com/verb/rated', 'commented': 'http://adlnet.gov/expapi/verbs/commented'} objectmapper = {'Note': 'http://activitystrea.ms/schema/1.0/note', 'Tag': 'http://id.tincanapi.com/activitytype/tag', 'Article': 'http://activitystrea.ms/schema/1.0/article', 'Video': 'http://activitystrea.ms/schema/1.0/video'} agentaccount = AgentAccount(name=account_name, home_page=account_homepage) actor = Agent(account=agentaccount) if (account_email is not None): actor.mbox = account_email if (user_name is not None): actor.name = user_name verb_obj = Verb(id=verbmapper[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=objectmapper[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=objectmapper['Tag'] ), ) taglist.append(tagobject) parentlist = [] if (verb in ['liked','shared','commented','rated']): parentobject = Activity( id=parent_id, object_type=parent_object_type, ) parentlist.append(parentobject) courselist = [] if (course_code is not None): courseobject = Activity( id=course_code, object_type='Course', definition=ActivityDefinition(type="http://adlnet.gov/expapi/activities/course") ) 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)) ) statement = statement_builder(actor, verb_obj, object, context, result, timestamp) return statement
def get_result(self, event): return Result(completion=True, success=True)
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 get_result(self, event): event_data = self.get_event_data(event) return Result(completion=False, response=json.dumps("[]"))
def get_result(self, event): event_data = self.get_event_data(event) return Result( success=event_data.get('success', True), completion=True, )
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})