From 898fa80556ddd2ddcf5837b98c15c5b8cc933f37 Mon Sep 17 00:00:00 2001 From: Dan Ghost Date: Mon, 3 Apr 2023 14:10:23 +0100 Subject: [PATCH] Bug: score logic (#267) --- js/scorm/wrapper.js | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/js/scorm/wrapper.js b/js/scorm/wrapper.js index d948cb3e..dc275ff7 100644 --- a/js/scorm/wrapper.js +++ b/js/scorm/wrapper.js @@ -212,18 +212,34 @@ class ScormWrapper { return this.getValue(this.isSCORM2004() ? 'cmi.score.raw' : 'cmi.core.score.raw'); } - setScore(score, minScore = 0, maxScore = 100) { + setScore(score, minScore = 0, maxScore = 100, isPercentageBased = true) { if (this.isSCORM2004()) { + // `raw`, `min`, `max` sum absolute values assigned to questions this.setValue('cmi.score.raw', score); this.setValue('cmi.score.min', minScore); this.setValue('cmi.score.max', maxScore); - - const range = maxScore - minScore; - const scaledScore = ((score - minScore) / range).toFixed(7); - this.setValue('cmi.score.scaled', scaledScore); + // range split into negative/positive ranges (rather than minScore-maxScore) depending on score + const range = (score < 0) ? Math.abs(minScore) : maxScore; + // `scaled` converted to -1-1 range to indicate negative/positive weighting now that negative values can be assigned to questions + const scaledScore = score / range; + this.setValue('cmi.score.scaled', scaledScore.toFixed(7)); return; } - // SCORM 1.2 + if (isPercentageBased) { + // convert values to 0-100 range + // negative scores are capped to 0 due to SCORM 1.2 limitations + score = (score < 0) ? 0 : Math.round((score / maxScore) * 100); + minScore = 0; + maxScore = 100; + } else { + const validate = (attribute, value) => { + const isValid = value >= 0 && score <= 100; + if (!isValid) this.logger.warn(`${attribute} must be between 0-100.`); + } + validate('cmi.core.score.raw', score); + validate('cmi.core.score.min', minScore); + validate('cmi.core.score.max', maxScore); + } this.setValue('cmi.core.score.raw', score); if (this.isSupported('cmi.core.score.min')) this.setValue('cmi.core.score.min', minScore); if (this.isSupported('cmi.core.score.max')) this.setValue('cmi.core.score.max', maxScore);