Exemple #1
0
    def basic(cls, **kwargs):
        context = Context()

        if kwargs and kwargs.get('registration') != None:
            context.registration = kwargs.get('registration')

        return context
Exemple #2
0
 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)
Exemple #3
0
 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)
Exemple #4
0
    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
Exemple #5
0
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()
Exemple #6
0
 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,
         }, ))
Exemple #7
0
    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)
Exemple #8
0
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())
Exemple #9
0
 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})
Exemple #10
0
 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 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,
    )
Exemple #12
0
    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
Exemple #13
0
 def get_context(self, event):
     """Get Context for the statement."""
     return Context(platform=settings.OPENEDX_PLATFORM_URI, )
Exemple #14
0
def track_topic_view(sender, topic, user, request, response, **kwargs):
    """Log a XAPI statement when a user views a topic."""

    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/topic/{topic.pk}",
        definition=ActivityDefinition(
            name=LanguageMap(
                {to_locale(settings.LANGUAGE_CODE).replace("_", "-"): topic.subject}
            ),
            type="http://id.tincanapi.com/activitytype/discussion",
            extensions={
                "https://w3id.org/xapi/acrossx/extensions/total-items": topic.posts_count,
                "https://w3id.org/xapi/acrossx/extensions/total-pages": (
                    (topic.posts_count - 1)
                    // machina_settings.TOPIC_POSTS_NUMBER_PER_PAGE
                )
                + 1,
            },
        ),
    )

    parent_activities = [
        Activity(
            id=f"uuid://{topic.forum.lti_id}",
            definition=ActivityDefinition(
                name=LanguageMap(
                    {
                        to_locale(settings.LANGUAGE_CODE).replace(
                            "_", "-"
                        ): topic.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.append(
                Activity(
                    id=lti_context.lti_id,
                    definition=ActivityDefinition(
                        type="http://adlnet.gov/expapi/activities/course"
                    ),
                )
            )

        except LTIContext.DoesNotExist:
            pass

    context = Context(
        context_activities=ContextActivities(parent=parent_activities),
        extensions={
            "http://www.risc-inc.com/annotator/extensions/page": int(
                request.GET.get("page", default=1)
            )
        },
    )

    statement = build_statement(user, verb, obj, context)
    if statement:
        xapi_logger.info(statement.to_json())
    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)
Exemple #16
0
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
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...")