Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xapi trackable state saving + restoring on models #1523

Closed
oliverfoster opened this issue Apr 11, 2017 · 8 comments
Closed

xapi trackable state saving + restoring on models #1523

oliverfoster opened this issue Apr 11, 2017 · 8 comments

Comments

@oliverfoster
Copy link
Member

oliverfoster commented Apr 11, 2017

  • trackable model value / function returning an array of trackable properties - flat, no hierarchy
  • getTrackableState() model function returns current model state as json filtered by trackable
  • setTrackableState(state) model function restores model state as filtered by trackable, rejecting data which doesn't match
  • triggerTrackableState() model function performs an Adapt.trigger("state:change", this.getTrackableState());
  • "state:change" will trigger batched and debounced when the model changes so as not to interfere with existing code
@oliverfoster
Copy link
Member Author

oliverfoster commented Apr 11, 2017

  • we need to consider moving the tracking ids to the components and updating spoor + grunt accordingly. tracking ids are a useful way for maintaining version compatibility with minor course updates over time, i think it would be silly to remove them, having said that. it'd be great if we could. using a non-integer index (such as the _id) introduces more complexity than it's worth in my opinion. if we moved the tracking ids to the components we could mostly side-step restoration mismatch issues.
  • spoor needs to also track presentation component _userAnswers

@oliverfoster
Copy link
Member Author

oliverfoster commented Apr 11, 2017

I've made the libraries @moloko suggested to tidy up the default inheritance and copy calls.

They're located at:
https://github.com/cgkineo/backbone.controller.results
https://github.com/cgkineo/underscore.results

Further reading at:
https://lostechies.com/chrismissal/2012/10/05/extending-objects-in-underscore/
http://backbonejs.org/#Model-defaults
http://underscorejs.org/#result

To extend defaults and trackable would now look like this:

    var AdaptModel = Backbone.Model.extend({

        defaults: {
            _canShowFeedback: true,
            _classes: "",
            _canReset: false,
            _isComplete: false,
            _isInteractionComplete: false,
            _requireCompletionOf: -1,
            _isEnabled: true,
            _isResetOnRevisit: false,
            _isAvailable: true,
            _isOptional: false,
            _isReady: false,
            _isVisible: true,
            _isLocked: false
        },

        trackable: [
            '_id',
            '_isComplete',
            '_isInteractionComplete'
        ]

    });
    var ComponentModel = AdaptModel.extend({

        trackable: AdaptModel.resultExtend("trackable", [
            '_userAnswer'
        ])

    });
    var QuestionModel = ComponentModel.extend({

        // Used to set model defaults
        defaults: function() {
            // Extend from the ComponentModel defaults
            return ComponentModel.resultExtend("defaults", {
                _isQuestionType: true,
                _shouldDisplayAttempts: false,
                _canShowModelAnswer: true,
                _canShowFeedback: true,
                _canShowMarking: true,
                _questionWeight: Adapt.config.get("_questionWeight"),
            });
        },

        // Extend from the ComponentModel trackable
        trackable: ComponentModel.resultExtend("trackable", [
            '_isSubmitted',
            '_score',
            '_isCorrect',
            '_attemptsLeft'
        ])

    });

@brian-learningpool
Copy link
Member

Regarding the change to the tracking ID values and the associated grunt task, how about if we just add a suffix to the tracking numbers for components? For example, if a block has a _trackingId of 19, the first component in that block could have a _trackingId of 19.1, the second 19.2, etc.?

This could maintain backwards compatibility for SCORM tracking at the block level.

@oliverfoster
Copy link
Member Author

oliverfoster commented Jun 8, 2017

We would need to keep the running count for each block, a _lastComponentTrackingId per block, so that any later components would carry on indexing upwards. If you replace a component at index 1 tracking id 19, it'd have the same id as the one it was replacing, potentially screwing up any pre-existing saved data. It would need to be block._trackingId+"."+(block._lastComponentTrackingId++)

It might be more work to do 19.1, 19.2 etc than to move them up one?

@oliverfoster
Copy link
Member Author

I've updated the comments above to reflect the implementation ^

@oliverfoster oliverfoster changed the title xapi state saving on models xapi trackable state saving + restoring on models Jun 8, 2017
@brian-learningpool
Copy link
Member

That's a good point about the count per block, I was thinking (selfishly) of the authoring tool.

@oliverfoster
Copy link
Member Author

oliverfoster commented Sep 6, 2017

After a conversation, Brian and I agreed that _trackingIds can remain as is for spoor and xapi can use the _id attribute to track model states. This may mean that we move the _trackingId reset, remove and insert behaviour into the spoor plugin and out of the grunt task.

@oliverfoster
Copy link
Member Author

oliverfoster commented Sep 6, 2017

I think the PR is ready to roll @brian-learningpool #1524

I would say, instead of having xapi record all the states by iterating through the models, you should probably listen to Adapt.on("state:change", function(model, stateObject) {}); That way we're only saving and restoring the changes over time. The stateObject now includes the _id as discussed, so you can map up the states by id and send only changed states over xapi. In reverse it should be easy to get the stateObject and do:

var restoreModel = Adapt.findById(stateObject._id);
if (!restoreModel) continue;
restoreModel.setTrackableState(stateObject);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants