def send_statement_without_timeout(statement, success, result): # construct an LRS lrs = RemoteLRS( version=settings.LRS_VERSION, endpoint=settings.LRS_ENDPOINT, auth=settings.LRS_AUTH, ) try: # save our statement to the remote_lrs and store the response in 'response' lrs_response = lrs.save_statement(statement) if lrs_response: if lrs_response.success: try: # retrieve our statement from the remote_lrs using the id returned in the response lrs_response = lrs.retrieve_statement( lrs_response.content.id) if lrs_response.success: result = lrs_response.content success = True else: result = lrs_response.data except Exception as e: result = e else: result = lrs_response.data except Exception as e: result = e
def _emit_to_lrs(cls, statement_json): if not cls.enabled: return # should only be called by delayed task send_lrs_statement lrs_settings = { 'version': cls._version, 'endpoint': current_app.config.get('LRS_XAPI_STATEMENT_ENDPOINT') } if current_app.config.get('LRS_XAPI_AUTH'): lrs_settings['auth'] = current_app.config.get('LRS_XAPI_AUTH') else: lrs_settings['username'] = current_app.config.get( 'LRS_XAPI_USERNAME') lrs_settings['password'] = current_app.config.get( 'LRS_XAPI_PASSWORD') statement = Statement(statement_json) lrs = RemoteLRS(**lrs_settings) lrs_response = lrs.save_statement(statement) if not lrs_response.success: current_app.logger.error("xAPI Failed with: " + str(lrs_response.data)) current_app.logger.error("xAPI Request Body: " + lrs_response.request.content)
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 _setup_LRSs(self): with open('lrs_config.json', 'r') as fi: llist = json.load(fi) for lrsconf in llist: obj = {'name': lrsconf['name'], 'online': True} if 'active' in lrsconf: obj['active'] = lrsconf['active'] del (lrsconf['active']) else: obj['active'] = True del (lrsconf['name']) lrs = RemoteLRS(**lrsconf) obj['lrs'] = lrs #self._LRSs.append(lrs) self._LRSs.append(obj)
def _send_lrs_statement(cls, statement_json): if not cls.enabled: return # should only be called by delayed task send_lrs_statement lrs_settings = { 'version': cls._version, 'endpoint': current_app.config.get('LRS_STATEMENT_ENDPOINT') } if current_app.config.get('LRS_AUTH'): lrs_settings['auth'] = current_app.config.get('LRS_AUTH') else: lrs_settings['username'] = current_app.config.get('LRS_USERNAME') lrs_settings['password'] = current_app.config.get('LRS_PASSWORD') statement = Statement(statement_json) # check statement.result.response, object.definition.name, object.definition.description if statement.result and statement.result.response: statement.result.response = cls._trim_text_to_size( statement.result.response) if statement.object and statement.object.definition and statement.object.definition.name: statement.object.definition.name['en-US'] = cls._trim_text_to_size( statement.object.definition.name['en-US']) if statement.object and statement.object.definition and statement.object.definition.description: statement.object.definition.description[ 'en-US'] = cls._trim_text_to_size( statement.object.definition.description['en-US']) lrs = RemoteLRS(**lrs_settings) lrs_response = lrs.save_statement(statement) if not lrs_response.success: current_app.logger.error("xAPI Failed with: " + str(lrs_response.data)) current_app.logger.error("xAPI Request Body: " + lrs_response.request.content)
def test_about_failure(self): lrs = RemoteLRS(endpoint="http://cloud.scorm.com/tc/3TQLAI9/sandbox/") response = lrs.about() self.assertFalse(response.success)
def test_instantiation(self): lrs = RemoteLRS() self.assertIsInstance(lrs, RemoteLRS) self.assertIsNone(lrs.endpoint) self.assertIsNone(lrs.auth) self.assertEqual(Version.latest, lrs.version)
RemoteLRS, Statement, Agent, Verb, Activity, Context, LanguageMap, ActivityDefinition, StateDocument, ) # construct an LRS print "constructing the LRS..." lrs = RemoteLRS( version=lrs_properties.version, endpoint=lrs_properties.endpoint, username=lrs_properties.username, password=lrs_properties.password, ) print "...done" # construct the actor of the statement print "constructing the Actor..." actor = Agent( name='UserMan', mbox='mailto:[email protected]', ) print "...done" # construct the verb of the statement print "constructing the Verb..." verb = Verb(
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)
verb=verb, object=object, context=context, ) if __name__ == '__main__': import fileinput import sys csv_entries = (l.strip() for l in fileinput.input()) remote_lrs = RemoteLRS( endpoint=lrs['endpoint'], # RemoteLRS uses HTTP Basic Auth # so username, password will be sent out # with the authorization header. username=lrs['username'], password=lrs['password'], ) for csv_entry in csv_entries: try: statement = create_statement(csv_entry) except ValueError, e: # ignore invalid entries print("Failed to create statement for %s with the error: %s" % (csv_entry, e), file=sys.stderr) continue # XXX: Look out for response == None # and possibly add the statement to a retry queue
# # global variables used during tracing # statement_number = 1 # keep number order for statements # Identifiers machine_id, student_hash, partner_hash, input_type = _init_id() session_id = None # Session ID, Initialized in initialize_tracing() # Tracing behaviour tracing_enabled = None # Enable user to enable/disable tracing, Initialized in initialize_tracing() send_to_LRS = config.send_to_LRS # Send the created statements to the LRS debug_log_print = config.debug_log_print # Keep Log of statements and Print messages related to tracing # Error and function data error_groups = config.error_groups function_names_context = config.function_names_context # Timestamps opened_timestamp = None # Opened app last_typing_timestamp = None # Last typed in editor last_interacting_timestamp = None # Last interacted with software start_execution_timestamp = None # Last execution start # # xAPI and LRS setup # lrs = RemoteLRS(version=config.lrs_version, endpoint=config.lrs_endpoint, username=config.lrs_username, password=config.lrs_password) actor = _create_actor() verbs = config.verbs activities = config.activities
class LRSClient: # config LRS endpoint and auth info here LRS = RemoteLRS( version="1.0.1", endpoint="http://localhost/learninglocker/public/data/xAPI/", username="******", password="******" ) verbs = { "selected": "http://id.tincanapi.com/verb/selected", "access": "http://activitystrea.ms/schema/1.0/access", "experienced": "http://adlnet.gov/expapi/verbs/experienced", "listen": "http://activitystrea.ms/schema/1.0/listen", "answered": "http://adlnet.gov/expapi/verbs/answered", "requested": "https://w3id.org/xapi/adb/verbs/requested", "logged-in": "https://w3id.org/xapi/adl/verbs/logged-in", "logged-out": "https://w3id.org/xapi/adl/verbs/logged-out", "create": "http://activitystrea.ms/schema/1.0/create", "delete": "http://activitystrea.ms/schema/1.0/delete", "update": "http://activitystrea.ms/schema/1.0/update", "completed": "http://adlnet.gov/expapi/verbs/completed", "consume": "http://activitystrea.ms/schema/1.0/consume", "earned": "http://id.tincanapi.com/verb/earned", "passed": "http://adlnet.gov/expapi/verbs/passed", "failed": "http://adlnet.gov/expapi/verbs/failed", "launched": "http://adlnet.gov/expapi/verbs/launched", "start": "http://activitystrea.ms/schema/1.0/start", "leave": "http://activitystrea.ms/schema/1.0/leave", "paused": "http://id.tincanapi.com/verb/paused", "resumed": "http://adlnet.gov/expapi/verbs/resumed", "terminated": "http://adlnet.gov/expapi/verbs/terminated" } objects = { "resource": "http://id.tincanapi.com/activitytype/resource" } extensions = { "topic": "http://id.tincanapi.com/extension/topic", "interaction": "http://id.tincanapi.com/extension/interaction", "difficulty": "http://id.tincanapi.com/extension/difficulty", "feedback": "http://id.tincanapi.com/extension/feedback" } def sendStatement(self, reqData): #load requested data for statement generation data = json.loads(reqData) # create RemoteLRS endpoint lrs = self.LRS # generate statement # 1. actor actor = Agent( name=data["name"], mbox='mailto:' + data["name"] + '@id.lrs', ) # 2. verb verb = Verb( id=self.verbs.get(data["verb"]), display=LanguageMap({'en-US': data["verb"]}), ) # 3. object obj = Activity( id=self.objects.get(data["activity"]), definition=ActivityDefinition( name=LanguageMap({'en-US': data["activityid"]}) ) ) # 4. context context = Context( extensions=Extensions({ self.extensions.get("difficulty"): data["difficulty"], self.extensions.get("interaction"): data["interaction"], self.extensions.get("topic"): data["topic"] }) ) # 5. result result = Result( score=Score( raw=data["score"] ), success=data["success"] ) # build statement statement = Statement( actor=actor, verb=verb, object=obj, context=context, result=result ) # save statement response = lrs.save_statement(statement) # check response if not response: raise ValueError("statement failed to save") return str(True) # returns statements of an user def getStatements(self, name): # connect LRS lrs = self.LRS # specify user as agent actor = Agent( name=name, mbox='mailto:' + name + '@id.lrs', ) # optional specify verb verb = Verb( id=self.verbs.get("experienced"), display=LanguageMap({'en-US': 'experienced'}), ) query = { "agent": actor, #"verb": verb, "limit": 1000 #change limit if needed } # query LRS for statements response = lrs.query_statements(query) # check response if not response: raise ValueError("statements could not be queried") # return queried statements return response
# Nice formatting + Headings # ##################################### print "=" * 43 print " " * 3 + " MOAT project's moodle xAPI importer " + " " * 9 print "=" * 43 print "" # Print settings ##################################### # Construct actual connections # ##################################### print "Creating Connections" sys.stdout.write("\tLRS Connection...") sys.stdout.flush() lrs = RemoteLRS(version=config.LRS_VERSION, endpoint=config.LRS_ENDPOINT, username=config.LRS_USERNAME, password=config.LRS_PASSWORD) print "done" ## sys.stdout.write("\tMoodle Connection...") sys.stdout.flush() try: conn = psycopg2.connect(database=config.DB_NAME, user=config.DB_USER, password=config.DB_PASS, host=config.DB_HOST) cur = conn.cursor('cursor_one', cursor_factory=psycopg2.extras.RealDictCursor) cur.itersize = config.ITER_SIZE cur2 = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) except:
statement_number = 1 # keep number order for statements # Identifiers machine_id, student_hash, partner_hash, input_type = _init_id() session_id = None # Session ID, Initialized in initialize_tracing() # Tracing behaviour tracing_enabled = None # Enable user to enable/disable tracing, Initialized in initialize_tracing() send_to_LRS = config.send_to_LRS # Send the created statements to the LRS debug_log_print = config.debug_log_print # Keep Log of statements and Print messages related to tracing # Error and function data error_groups = config.error_groups function_names_context = config.function_names_context # Timestamps opened_timestamp = None # Opened app last_typing_timestamp = None # Last typed in editor last_interacting_timestamp = None # Last interacted with software start_execution_timestamp = None # Last execution start # # xAPI and LRS setup # lrs = RemoteLRS( version=config.lrs_version, endpoint=config.lrs_endpoint, username=config.lrs_username, password=config.lrs_password, proxy_name=config.proxy_name, proxy_port=config.proxy_port) actor = _create_actor() verbs = config.verbs activities = config.activities