xAPI event multi-choice questions - distinguish between Submit and Finish

Hi everyone,

I have a question regarding the xAPI event data we get back from the externalDispatcher call. We have an embedded multi-choice quiz on a page, and we find that (possibly after the last update to the API) each time a user clicks the Submit button to submit an answer they have selected, we get a Verb Display value of "completed" back. However, this is interferring with how we are detecting whether the user has completed the entire quiz, as we also get a Verb Display value of "complete" when the user clicks the Finish button to signify they have answered every question of the quiz.

My quesiton is, is there a standard way to distinguish between the user clicking the Submit button and the Finish button?

Many thanks.

falcon's picture

Hi!

Could you please provide a link? We still get attempted here http://h5p.org/multichoice

Hi Falcon,

It's not really possible to provide a URL as the system we're working from is currently not strictly live.

But in terms of what functionality we have implemented, we have the multi-page multiple-choice activity embedded in an iFrame with an ID of "targetFrame". Also on the page is the following JS that sets up the monitoring of the activity:

document.getElementById('targetFrame').onload = function () {
    var H5P = document.getElementById('targetFrame').contentWindow.H5P;
    H5P.externalDispatcher.on('xAPI', function (event) {
        var statement = event.data.statement;
    }
}

Each time the user clicks either the Submit button in the activity to submit the answer to the current multi-choice question, the H5P.externalDispatcher xAPI event is fired and the statement variable is populated with the event data. One of the values in the event data is the statement.verb.display['en-US'] which is set to the value of "complete".

The above process also happens when the user clicks the "Finish" button. So is there a way we can determine which button the user clicks from this event?

Thanks,

falcon's picture

Hi Falcon.

We are using Question Set.

Cheers.

falcon's picture

I see. The verbs will be the same then with the current implementation but you may distinguish them by looking at the parent in the context part of the statement. The multichoices will have a parent while the questionset is the parent. In future versions we'll change the verbs so that only the question set uses completed. The multichoices will probably use answered.

I'm thinking of something along the lines of - if the question set lived at the URL http://www.example.com/questionset1 then for a statement involving the answering of question 1, the activity ID would be http://www.example.com/questionset1#question1  and the parent would be http://www.example.com/questionset1. It's important that two separate statements don't share the same Activity ID.

In fact, I think what's really required at this stage is the adoption of TinCan/xAPI recipes for each type of H5P: http://tincanapi.com/recipes/

That way you can start to bring in certain contexts and extensions depending on what H5P you're using. For example, the Result field of the xAPI spec (https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md#415-result) could be utilised just for the questionset, and any other appropriate H5P type. 

Hi Falcon.

There doesn't appear to be a parent context as part of the event data.

Here is the contents of the event that gets fired for when an individual question is submitted:

{"type":"xAPI","data":{"statement":{"actor":{"name":"","mbox":"","objectType":"Agent"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://domain/content/customer-service-course-delivery-drivers-unit-1-m...","objectType":"Activity","definition":{"extensions":{"http://h5p.org/x-api/h5p-local-content-id":28,"http://h5p.org/x-api/h5p-subContentId":"25c38c19-43b2-4168-ae0e-295680621022"}}},"result":{"score":{"min":0,"max":1,"raw":1}}}}}

And here is the contents of the event that gets fired for when the question set is "Finished" after the user has submitted an answer for each individual question.

{"type":"xAPI","data":{"statement":{"actor":{"name":"","mbox":"","objectType":"Agent"},"verb":{"id":"http://adlnet.gov/expapi/verbs/completed","display":{"en-US":"completed"}},"object":{"id":"https://domain/content/customer-service-course-delivery-drivers-unit-1-mcqs","objectType":"Activity","definition":{"extensions":{"http://h5p.org/x-api/h5p-local-content-id":28},"name":{"en-US":"Customer Service Course for Delivery Drivers - Unit 1 MCQs"}}},"result":{"score":{"min":0,"max":5,"raw":4}}}}}

Apart from the inclusion of a subContentID value for when the user submits an individual question, the two data sets are practically identical.

Can you advise on how we can determine if the current context has a "parent". As we could add in a rule that states if a parent exists, then ignore the event entirely as we must be dealing with a question that is only part of an overall activity.

Thanks.

I should have added:

Can we use the "http://h5p.org/x-api/h5p-subContentId" property of the event data is safely assume that, if this exists, it must be a child activity that has a parent?

Basically it would involve writing the following JavaScript:

if (event.data.statement.object.definition.extensions['http://h5p.org/x-api/h5p-subContentId']) {
    // is child activity so ignore
} else {   // process xAPI call
}

falcon's picture

In all foreseeable future it will be like that, but are you sure you have the newest libraries?

If you go to http://h5p.org/question-set

And you paste

H5P.externalDispatcher.on('xAPI', function(event) {console.log(event.data.statement);});

in your console you'll see that the parent is in the context part of the statements there?

Libraries were last updated the 9th of July: http://h5p.org/update-all-content-types

Thanks Falcon. Updating the libraries has revealed the parent context object as part of the event data. I have been able to use this to determine whether the event is from a question or the entire activity. Thanks for your help.

falcon's picture

:)

Hi Falcon. Just a general implementation question then as we use the activity URL ID as a way of reporting. Is there no way distinguishing between the individual question and the question set (in terms of the activity ID URL)? Even if the verb changes, the question set and question will still live on the same URL. So the test http://../Test1 will be the parent of the question http://../Test1. 

Is there any way of passing a different activity ID down to the question?

Thanks

falcon's picture

Hi,

They should have different IDs already. For instance the first question of http://h5p.org/question-set has the activity id "http://h5p.org/question-set?subContentId=bd03477a-90a1-486d-890b-0657d6e...

We chose to use UUID for subContentId so that the question keeps its id if it gets reordered inside the question set.

The activity ID for that question set is http://h5p.org/question-set and it is set as the parent of its questions in the statements generated by the questions.

When "check" is pressed there is also a result object in the statement, but it doesn't contain all result properties yet. Just the score.

There aren't many recipes available yet afaik, we will be contributing recipes when we feel we have a more complete coverage.