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

issue/2799 Remove redundant behaviour #230

Merged
merged 2 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions js/adapt-contrib-spoor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Adapt from 'core/js/adapt';
import ScormWrapper from './scorm/wrapper';
import StatefulSession from './adapt-stateful-session';
import OfflineStorage from './adapt-offlineStorage-scorm';
import offlineStorage from 'core/js/offlineStorage';

class Spoor extends Backbone.Controller {

Expand All @@ -14,16 +15,16 @@ class Spoor extends Backbone.Controller {
_prepare() {
this.config = Adapt.config.get('_spoor');
if (!this.isEnabled) {
Adapt.offlineStorage.setReadyStatus();
offlineStorage.setReadyStatus();
return;
}
this.statefulSession = new StatefulSession();
this.offlineStorage = new OfflineStorage(this.statefulSession);
// force offlineStorage-scorm to initialise suspendDataStore - this allows
// us to do things like store the user's chosen language before the rest
// of the course data loads
Adapt.offlineStorage.get();
Adapt.offlineStorage.setReadyStatus();
offlineStorage.get();
offlineStorage.setReadyStatus();
// setup debug window keyboard shortcut
require(['libraries/jquery.keycombo'], () => {
// listen for user holding 'd', 'e', 'v' keys together
Expand Down
8 changes: 4 additions & 4 deletions js/adapt-offlineStorage-scorm.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import Adapt from 'core/js/adapt';
import ScormWrapper from './scorm/wrapper';
import SCORMSuspendData from './serializers/SCORMSuspendData';
import OfflineStorage from 'core/js/offlineStorage';
import offlineStorage from 'core/js/offlineStorage';

/**
* SCORM handler for Adapt.offlineStorage interface.
* SCORM handler for offlineStorage interface.
*/
export default class OfflineStorageScorm extends Backbone.Controller {

initialize(statefulSession) {
this.offlineStorage = OfflineStorage;
this.offlineStorage = offlineStorage;
this.scorm = ScormWrapper.getInstance();
this.statefulSession = statefulSession;
this.temporaryStore = {};
this.suspendDataStore = {};
this.suspendDataRestored = false;
Adapt.offlineStorage.initialize(this);
offlineStorage.initialize(this);
}

save() {
Expand Down
47 changes: 26 additions & 21 deletions js/adapt-stateful-session.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import Adapt from 'core/js/adapt';
import data from 'core/js/data';
import logging from 'core/js/logging';
import ScormWrapper from './scorm/wrapper';
import COMPLETION_STATE from 'core/js/enums/completionStateEnum';
import ComponentSerializer from './serializers/ComponentSerializer';
import SCORMSuspendData from './serializers/SCORMSuspendData';
import offlineStorage from 'core/js/offlineStorage';

export default class StatefulSession extends Backbone.Controller {

Expand Down Expand Up @@ -94,11 +97,11 @@ export default class StatefulSession extends Backbone.Controller {
if (!globals._learnerInfo) {
globals._learnerInfo = {};
}
Object.assign(globals._learnerInfo, Adapt.offlineStorage.get('learnerinfo'));
Object.assign(globals._learnerInfo, offlineStorage.get('learnerinfo'));
}

restoreSessionState() {
const sessionPairs = Adapt.offlineStorage.get();
const sessionPairs = offlineStorage.get();
const hasNoPairs = !Object.keys(sessionPairs).length;
if (hasNoPairs) return;
if (sessionPairs.c) {
Expand All @@ -117,7 +120,7 @@ export default class StatefulSession extends Backbone.Controller {
this.listenTo(Adapt.components, 'change:_isComplete', this.debouncedSaveSession);
this.listenTo(Adapt.course, 'change:_isComplete', this.debouncedSaveSession);
if (this._shouldStoreResponses) {
this.listenTo(Adapt.data, 'change:_isSubmitted change:_userAnswer', this.debouncedSaveSession);
this.listenTo(data, 'change:_isSubmitted change:_userAnswer', this.debouncedSaveSession);
}
this.listenTo(Adapt, {
'app:languageChanged': this.onLanguageChanged,
Expand Down Expand Up @@ -147,7 +150,7 @@ export default class StatefulSession extends Backbone.Controller {
c: courseState,
q: componentStates
};
Adapt.offlineStorage.set(sessionPairs);
offlineStorage.set(sessionPairs);
this.printCompletionInformation(sessionPairs);
}

Expand All @@ -159,16 +162,16 @@ export default class StatefulSession extends Backbone.Controller {
const courseState = SCORMSuspendData.deserialize(suspendData.c);
const courseComplete = courseState[0];
const assessmentPassed = courseState[1];
const trackingIdModels = Adapt.data.filter(model => model.get('_type') === this._trackingIdType && model.has('_trackingId'));
const trackingIdModels = data.filter(model => model.get('_type') === this._trackingIdType && model.has('_trackingId'));
const trackingIds = trackingIdModels.map(model => model.get('_trackingId'));
if (!trackingIds.length) {
Adapt.log.info(`course._isComplete: ${courseComplete}, course._isAssessmentPassed: ${assessmentPassed}, ${this._trackingIdType} completion: no tracking ids found`);
logging.info(`course._isComplete: ${courseComplete}, course._isAssessmentPassed: ${assessmentPassed}, ${this._trackingIdType} completion: no tracking ids found`);
return;
}
const data = SCORMSuspendData.deserialize(suspendData.q);
const max = Math.max(...data.map(item => item[0][0]));
const shouldStoreResponses = (data[0].length === 3);
const completionString = data.reduce((markers, item) => {
const completionData = SCORMSuspendData.deserialize(suspendData.q);
const max = Math.max(...completionData.map(item => item[0][0]));
const shouldStoreResponses = (completionData[0].length === 3);
const completionString = completionData.reduce((markers, item) => {
const trackingId = item[0][0];
const isComplete = shouldStoreResponses ?
item[2][1][0] :
Expand All @@ -179,7 +182,7 @@ export default class StatefulSession extends Backbone.Controller {
'0';
return markers;
}, (new Array(max + 1).join('-').split(''))).join('');
Adapt.log.info(`course._isComplete: ${courseComplete}, course._isAssessmentPassed: ${assessmentPassed}, ${this._trackingIdType} completion: ${completionString}`);
logging.info(`course._isComplete: ${courseComplete}, course._isAssessmentPassed: ${assessmentPassed}, ${this._trackingIdType} completion: ${completionString}`);
}

onLanguageChanged() {
Expand All @@ -196,7 +199,7 @@ export default class StatefulSession extends Backbone.Controller {
this.setupEventListeners();
this.saveSessionState();
if (config?._reporting?._resetStatusOnLanguageChange !== true) return;
Adapt.offlineStorage.set('status', 'incomplete');
offlineStorage.set('status', 'incomplete');
}

onVisibilityChange() {
Expand All @@ -205,15 +208,17 @@ export default class StatefulSession extends Backbone.Controller {

onQuestionRecordInteraction(questionView) {
if (!this._shouldRecordInteractions) return;
const responseType = questionView.getResponseType();
// View functions are deprecated: getResponseType, getResponse, isCorrect, getLatency
const questionModel = questionView.model;
const responseType = (questionModel.getResponseType ? questionModel.getResponseType() : questionView.getResponseType());
// If responseType doesn't contain any data, assume that the question
// component hasn't been set up for cmi.interaction tracking
if (_.isEmpty(responseType)) return;
const id = questionView.model.get('_id');
const response = questionView.getResponse();
const result = questionView.isCorrect();
const latency = questionView.getLatency();
Adapt.offlineStorage.set('interaction', id, response, result, latency, responseType);
const id = questionModel.get('_id');
const response = (questionModel.getResponse ? questionModel.getResponse() : questionView.getResponse());
const result = (questionModel.isCorrect ? questionModel.isCorrect() : questionView.isCorrect());
const latency = (questionModel.getLatency ? questionModel.getLatency() : questionView.getLatency());
offlineStorage.set('interaction', id, response, result, latency, responseType);
}

onTrackingComplete(completionData) {
Expand All @@ -225,7 +230,7 @@ export default class StatefulSession extends Backbone.Controller {
case COMPLETION_STATE.COMPLETED:
case COMPLETION_STATE.PASSED: {
if (!config?._reporting?._onTrackingCriteriaMet) {
Adapt.log.warn(`No value defined for '_onTrackingCriteriaMet', so defaulting to '${completionStatus}'`);
logging.warn(`No value defined for '_onTrackingCriteriaMet', so defaulting to '${completionStatus}'`);
} else {
completionStatus = config._reporting._onTrackingCriteriaMet;
}
Expand All @@ -234,13 +239,13 @@ export default class StatefulSession extends Backbone.Controller {
}
case COMPLETION_STATE.FAILED: {
if (!config?._reporting?._onAssessmentFailure) {
Adapt.log.warn(`No value defined for '_onAssessmentFailure', so defaulting to '${completionStatus}'`);
logging.warn(`No value defined for '_onAssessmentFailure', so defaulting to '${completionStatus}'`);
} else {
completionStatus = config._reporting._onAssessmentFailure;
}
}
}
Adapt.offlineStorage.set('status', completionStatus);
offlineStorage.set('status', completionStatus);
}

endSession() {
Expand Down
3 changes: 2 additions & 1 deletion js/scorm/wrapper.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Adapt from 'core/js/adapt';
import notify from 'core/js/notify';
import pipwerks from 'libraries/SCORM_API_wrapper';
import Logger from './logger';
import ScormError from './error';
Expand Down Expand Up @@ -510,7 +511,7 @@ class ScormWrapper {

switch (error.name) {
case CLIENT_COULD_NOT_CONNECT:
Adapt.notify.popup({
notify.popup({
_isCancellable: false,
title: messages.title,
body: message
Expand Down
14 changes: 7 additions & 7 deletions js/serializers/ComponentSerializer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Adapt from 'core/js/adapt';
import log from 'core/js/logging';
import logging from 'core/js/logging';
import data from 'core/js/data';
import SCORMSuspendData from './SCORMSuspendData';

export default class ComponentSerializer extends Backbone.Controller {
Expand All @@ -11,10 +11,10 @@ export default class ComponentSerializer extends Backbone.Controller {

async serialize(shouldStoreResponses, shouldStoreAttempts) {
if (shouldStoreAttempts && !shouldStoreResponses) {
log.warnOnce('SPOOR configuration error, cannot use \'_shouldStoreAttempts\' without \'_shouldStoreResponses\'');
logging.warnOnce('SPOOR configuration error, cannot use \'_shouldStoreAttempts\' without \'_shouldStoreResponses\'');
}
const states = [];
Adapt.data.each(model => {
data.each(model => {
if (model.get('_type') !== this.trackingIdType) {
return;
}
Expand Down Expand Up @@ -97,12 +97,12 @@ export default class ComponentSerializer extends Backbone.Controller {
});
});
if (this.shouldCompress) return await SCORMSuspendData.serializeAsync(states);
return SCORMSuspendData.serialize(states)
return SCORMSuspendData.serialize(states);
}

deserialize(binary) {
// Build a table of models and their tracking ids
const trackingIdMap = Adapt.data.toArray().reduce((trackingIdMap, model) => {
const trackingIdMap = data.toArray().reduce((trackingIdMap, model) => {
const trackingId = model.get('_trackingId');
if (typeof trackingId === 'undefined') return trackingIdMap;
trackingIdMap[trackingId] = model;
Expand All @@ -126,7 +126,7 @@ export default class ComponentSerializer extends Backbone.Controller {
[model];
const component = components[index];
if (!component) {
log.warn(`SPOOR could not restore tracking id: ${trackingId}, index: ${index}`);
logging.warn(`SPOOR could not restore tracking id: ${trackingId}, index: ${index}`);
return;
}
if (!shouldStoreResponses) {
Expand Down