Skip to content
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
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "adapt-contrib-scoring",
"version": "1.2.2",
"framework": ">=5.31.31",
"framework": ">=5.48.2",
"homepage": "https://github.com/adaptlearning/adapt-contrib-scoring",
"issues": "https://github.com/adaptlearning/adapt-contrib-scoring/issues/new",
"extension": "scoring",
Expand Down
128 changes: 104 additions & 24 deletions js/ScoringSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ export default class ScoringSet extends Backbone.Controller {
* @protected
*/
_setupListeners() {
if (this.subsetParent) return;
if (this.subsetParent || this.type === 'adapt') return;
this.listenTo(Adapt, 'questionView:submitted', this.onQuestionSubmitted);
if (OfflineStorage.ready) return this.restore();
this.listenTo(Adapt, 'offlineStorage:ready', this.restore);
}
Expand All @@ -81,6 +82,9 @@ export default class ScoringSet extends Backbone.Controller {
}

init() {
this._setObjectiveStatus = _.debounce(this._setObjectiveStatus, 100);
this._wasAvailable = this.isAvailable;
this._wasIncomplete = this.isIncomplete;
this._wasComplete = this.isComplete;
this._wasPassed = this.isPassed;
this._initializeObjective();
Expand All @@ -91,9 +95,12 @@ export default class ScoringSet extends Backbone.Controller {
*/
update() {
const isComplete = this.isComplete;
if (isComplete && !this._wasComplete) this.onCompleted();
const isPassed = this.isPassed;
if (isPassed && !this._wasPassed) this.onPassed();
if (isComplete && !this._wasComplete && this._wasAvailable) this.onCompleted();
if (isPassed && !this._wasPassed && this._wasAvailable) this.onPassed();
if (this.hasStatusChanged) this._setObjectiveStatus();
this._wasAvailable = this.isAvailable;
this._wasIncomplete = this.isIncomplete;
this._wasComplete = isComplete;
this._wasPassed = isPassed;
}
Expand Down Expand Up @@ -377,6 +384,31 @@ export default class ScoringSet extends Backbone.Controller {
return true;
}

/**
* Returns whether the set is started
* @returns {boolean}
*/
get isStarted() {
return this.models.some(model => model.get('_isVisited'));
}

/**
* Returns whether the set is started and incomplete
* @returns {boolean}
*/
get isIncomplete() {
return this.isStarted && !this.isComplete;
}

/**
* Returns whether the objective for the set is completed.
* Depending on the set logic, this can differ to `_isComplete`.
* @returns {boolean}
*/
get isObjectiveComplete() {
return this.isComplete;
}

/**
* Returns whether the set is completed
* @returns {boolean}
Expand All @@ -385,8 +417,13 @@ export default class ScoringSet extends Backbone.Controller {
Logging.error(`isComplete must be overriden for ${this.constructor.name}`);
}

get isIncomplete() {
return (this.isComplete === false);
/**
* Returns whether the objective for the set is passed.
* Depending on the set logic, this can differ to `isPassed`.
* @returns {boolean}
*/
get isObjectivePassed() {
return this.isPassed;
}

/**
Expand All @@ -401,6 +438,17 @@ export default class ScoringSet extends Backbone.Controller {
return (this.isPassed === false);
}

/**
* Check whether the status has changed since the last `update`
* @returns {boolean}
*/
get hasStatusChanged() {
return this.isAvailable !== this._wasAvailable ||
this.isIncomplete !== this._wasIncomplete ||
this.isComplete !== this._wasComplete ||
this.isPassed !== this._wasPassed;
}

/**
* Check to see if there are any child models
* @returns {boolean}
Expand All @@ -418,39 +466,61 @@ export default class ScoringSet extends Backbone.Controller {
* @protected
*/
_initializeObjective() {
if (this.subsetParent) return;
const id = this.id;
const description = this.title;
const completionStatus = COMPLETION_STATE.NOTATTEMPTED.asLowerCase;
OfflineStorage.set('objectiveDescription', id, description);
if (this.isComplete) return;
OfflineStorage.set('objectiveStatus', id, completionStatus);
if (this.subsetParent || this.isStarted) return;
OfflineStorage.set('objectiveDescription', this.id, this.title);
this._setObjectiveStatus();
}

/**
* Reset the objective data
* @protected
*/
_resetObjective() {
if (this.subsetParent || this.isComplete) return;
const id = this.id;
const completionStatus = COMPLETION_STATE.INCOMPLETE.asLowerCase;
OfflineStorage.set('objectiveScore', id, this.score, this.minScore, this.maxScore);
OfflineStorage.set('objectiveStatus', id, completionStatus);
if (this.subsetParent || this.isObjectiveComplete || !this.hasStatusChanged) return;
this._setObjectiveScore();
this._setObjectiveStatus();
}

/**
* Complete the objective
* @todo Always updates to latest data - is this desired?
* Complete the objective.
* Will update to the latest data/attempt unless overriden in a subset.
* @protected
*/
_completeObjective() {
if (this.subsetParent) return;
const id = this.id;
const completionStatus = COMPLETION_STATE.COMPLETED.asLowerCase;
const successStatus = (this.isPassed ? COMPLETION_STATE.PASSED : COMPLETION_STATE.FAILED).asLowerCase;
OfflineStorage.set('objectiveScore', id, this.score, this.minScore, this.maxScore);
OfflineStorage.set('objectiveStatus', id, completionStatus, successStatus);
this._setObjectiveScore();
this._setObjectiveStatus();
}

/**
* Set the objective score
* @protected
*/
_setObjectiveScore() {
if (this.subsetParent) return;
OfflineStorage.set('objectiveScore', this.id, this.score, this.minScore, this.maxScore);
}

/**
* Set the appropriate objective completion and success status.
* Will update to the latest data/attempt, unless controlled accordingly in a subset.
* @protected
*/
_setObjectiveStatus() {
if (this.subsetParent) return;
const isAvailable = this.isAvailable;
const isIncomplete = this.isIncomplete;
const isComplete = this.isObjectiveComplete;
const isPassed = this.isObjectivePassed;
let completionStatus = COMPLETION_STATE.UNKNOWN.asLowerCase;
let successStatus = COMPLETION_STATE.UNKNOWN.asLowerCase;
if (isAvailable && !isIncomplete) completionStatus = COMPLETION_STATE.NOTATTEMPTED.asLowerCase;
if (isAvailable && isIncomplete) completionStatus = COMPLETION_STATE.INCOMPLETE.asLowerCase;
if (isAvailable && isComplete) {
completionStatus = COMPLETION_STATE.COMPLETED.asLowerCase;
if (this.passmark.isEnabled) successStatus = (isPassed ? COMPLETION_STATE.PASSED : COMPLETION_STATE.FAILED).asLowerCase;
}
OfflineStorage.set('objectiveStatus', this.id, completionStatus, successStatus);
}

/**
Expand All @@ -474,4 +544,14 @@ export default class ScoringSet extends Backbone.Controller {
Logging.debug(`${this.id} passed`);
}

/**
* @param {QuestionView} view
* @listens Adapt#questionView:submitted
*/
onQuestionSubmitted(view) {
const model = view.model;
if (!this.questions.includes(model)) return;
model.addContextActivity(this.id, this.type, this.title);
}

}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "adapt-contrib-scoring",
"version": "1.2.2",
"framework": ">=5.31.31",
"framework": ">=5.48.2",
"homepage": "https://github.com/adaptlearning/adapt-contrib-scoring",
"issues": "https://github.com/adaptlearning/adapt-contrib-scoring/issues/new",
"extension": "scoring",
Expand Down