scorm-again 3.1.2 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/scorm-again.js +185 -55
- package/dist/esm/scorm-again.js.map +1 -1
- package/dist/esm/scorm-again.min.js +1 -1
- package/dist/esm/scorm-again.min.js.map +1 -1
- package/dist/esm/scorm12.js +1 -0
- package/dist/esm/scorm12.js.map +1 -1
- package/dist/esm/scorm12.min.js +1 -1
- package/dist/esm/scorm12.min.js.map +1 -1
- package/dist/esm/scorm2004.js +184 -55
- package/dist/esm/scorm2004.js.map +1 -1
- package/dist/esm/scorm2004.min.js +1 -1
- package/dist/esm/scorm2004.min.js.map +1 -1
- package/dist/scorm-again.js +219 -43
- package/dist/scorm-again.js.map +1 -1
- package/dist/scorm-again.min.js +1 -1
- package/dist/scorm12.js +1 -0
- package/dist/scorm12.js.map +1 -1
- package/dist/scorm12.min.js +1 -1
- package/dist/scorm2004.js +218 -43
- package/dist/scorm2004.js.map +1 -1
- package/dist/scorm2004.min.js +1 -1
- package/dist/types/Scorm2004API.d.ts +1 -0
- package/dist/types/cmi/scorm2004/completion_status_evaluation.d.ts +7 -0
- package/dist/types/cmi/scorm2004/sequencing/handlers/termination_handler.d.ts +1 -0
- package/dist/types/types/sequencing_types.d.ts +6 -0
- package/package.json +1 -1
package/dist/esm/scorm-again.js
CHANGED
|
@@ -10646,6 +10646,26 @@ class RollupProcess {
|
|
|
10646
10646
|
}
|
|
10647
10647
|
}
|
|
10648
10648
|
|
|
10649
|
+
function evaluateCompletionStatusFromThreshold({
|
|
10650
|
+
completionThreshold,
|
|
10651
|
+
progressMeasure,
|
|
10652
|
+
storedCompletionStatus
|
|
10653
|
+
}) {
|
|
10654
|
+
if (completionThreshold !== "" && completionThreshold !== null && completionThreshold !== void 0) {
|
|
10655
|
+
const thresholdValue = parseFloat(String(completionThreshold));
|
|
10656
|
+
if (!isNaN(thresholdValue)) {
|
|
10657
|
+
if (progressMeasure !== "" && progressMeasure !== null && progressMeasure !== void 0) {
|
|
10658
|
+
const progressValue = parseFloat(String(progressMeasure));
|
|
10659
|
+
if (!isNaN(progressValue)) {
|
|
10660
|
+
return progressValue >= thresholdValue ? CompletionStatus.COMPLETED : CompletionStatus.INCOMPLETE;
|
|
10661
|
+
}
|
|
10662
|
+
}
|
|
10663
|
+
return CompletionStatus.UNKNOWN;
|
|
10664
|
+
}
|
|
10665
|
+
}
|
|
10666
|
+
return storedCompletionStatus || CompletionStatus.UNKNOWN;
|
|
10667
|
+
}
|
|
10668
|
+
|
|
10649
10669
|
const VALID_COMPLETION_STATUSES = [
|
|
10650
10670
|
CompletionStatus.COMPLETED,
|
|
10651
10671
|
CompletionStatus.INCOMPLETE,
|
|
@@ -10700,10 +10720,38 @@ class RteDataTransferService {
|
|
|
10700
10720
|
* @param {CMIDataForTransfer} cmiData - CMI data from runtime
|
|
10701
10721
|
*/
|
|
10702
10722
|
transferPrimaryObjective(activity, cmiData) {
|
|
10703
|
-
|
|
10704
|
-
if (
|
|
10705
|
-
|
|
10706
|
-
|
|
10723
|
+
let hasProgressMeasure = false;
|
|
10724
|
+
if (cmiData.progress_measure && cmiData.progress_measure !== "") {
|
|
10725
|
+
const progressMeasure = parseFloat(cmiData.progress_measure);
|
|
10726
|
+
if (!isNaN(progressMeasure)) {
|
|
10727
|
+
hasProgressMeasure = true;
|
|
10728
|
+
activity.progressMeasure = progressMeasure;
|
|
10729
|
+
activity.progressMeasureStatus = true;
|
|
10730
|
+
activity.attemptCompletionAmount = progressMeasure;
|
|
10731
|
+
activity.attemptCompletionAmountStatus = true;
|
|
10732
|
+
if (activity.primaryObjective) {
|
|
10733
|
+
activity.primaryObjective.progressMeasure = progressMeasure;
|
|
10734
|
+
activity.primaryObjective.progressMeasureStatus = true;
|
|
10735
|
+
}
|
|
10736
|
+
}
|
|
10737
|
+
}
|
|
10738
|
+
if (!hasProgressMeasure) {
|
|
10739
|
+
activity.attemptCompletionAmountStatus = false;
|
|
10740
|
+
}
|
|
10741
|
+
if (activity.completedByMeasure) {
|
|
10742
|
+
const completionStatus = evaluateCompletionStatusFromThreshold({
|
|
10743
|
+
completionThreshold: activity.minProgressMeasure,
|
|
10744
|
+
progressMeasure: cmiData.progress_measure,
|
|
10745
|
+
storedCompletionStatus: CompletionStatus.UNKNOWN
|
|
10746
|
+
});
|
|
10747
|
+
activity.completionStatus = completionStatus;
|
|
10748
|
+
activity.attemptProgressStatus = completionStatus !== CompletionStatus.UNKNOWN;
|
|
10749
|
+
} else {
|
|
10750
|
+
const validatedCompletionStatus = validateCompletionStatus(cmiData.completion_status);
|
|
10751
|
+
if (validatedCompletionStatus && validatedCompletionStatus !== CompletionStatus.UNKNOWN) {
|
|
10752
|
+
activity.completionStatus = validatedCompletionStatus;
|
|
10753
|
+
activity.attemptProgressStatus = true;
|
|
10754
|
+
}
|
|
10707
10755
|
}
|
|
10708
10756
|
let hasSuccessStatus = false;
|
|
10709
10757
|
let successStatus = false;
|
|
@@ -10737,17 +10785,6 @@ class RteDataTransferService {
|
|
|
10737
10785
|
activity.primaryObjective.progressStatus = true;
|
|
10738
10786
|
}
|
|
10739
10787
|
}
|
|
10740
|
-
if (cmiData.progress_measure && cmiData.progress_measure !== "") {
|
|
10741
|
-
const progressMeasure = parseFloat(cmiData.progress_measure);
|
|
10742
|
-
if (!isNaN(progressMeasure)) {
|
|
10743
|
-
activity.progressMeasure = progressMeasure;
|
|
10744
|
-
activity.progressMeasureStatus = true;
|
|
10745
|
-
if (activity.primaryObjective) {
|
|
10746
|
-
activity.primaryObjective.progressMeasure = progressMeasure;
|
|
10747
|
-
activity.primaryObjective.progressMeasureStatus = true;
|
|
10748
|
-
}
|
|
10749
|
-
}
|
|
10750
|
-
}
|
|
10751
10788
|
}
|
|
10752
10789
|
/**
|
|
10753
10790
|
* Transfer non-primary objective data from CMI to activity objectives
|
|
@@ -10952,6 +10989,18 @@ class TerminationHandler {
|
|
|
10952
10989
|
this.endAttempt(this.activityTree.currentActivity);
|
|
10953
10990
|
}
|
|
10954
10991
|
}
|
|
10992
|
+
const ancestorExitResult = this.applyAncestorExitActionRules(currentActivity);
|
|
10993
|
+
if (ancestorExitResult.action === "EXIT_ALL") {
|
|
10994
|
+
return this.handleExitAll(ancestorExitResult.activity || currentActivity);
|
|
10995
|
+
}
|
|
10996
|
+
if (ancestorExitResult.exception) {
|
|
10997
|
+
return {
|
|
10998
|
+
terminationRequest: SequencingRequestType.EXIT,
|
|
10999
|
+
sequencingRequest: null,
|
|
11000
|
+
exception: ancestorExitResult.exception,
|
|
11001
|
+
valid: false
|
|
11002
|
+
};
|
|
11003
|
+
}
|
|
10955
11004
|
let processedExit;
|
|
10956
11005
|
let postConditionResult;
|
|
10957
11006
|
do {
|
|
@@ -11179,16 +11228,14 @@ class TerminationHandler {
|
|
|
11179
11228
|
for (const rule of exitRules) {
|
|
11180
11229
|
let conditionsMet;
|
|
11181
11230
|
if (rule.conditionCombination === "all") {
|
|
11182
|
-
conditionsMet = rule.conditions.every(
|
|
11183
|
-
(condition) => condition.evaluate(activity)
|
|
11184
|
-
);
|
|
11231
|
+
conditionsMet = rule.conditions.every((condition) => condition.evaluate(activity));
|
|
11185
11232
|
} else {
|
|
11186
|
-
conditionsMet = rule.conditions.some(
|
|
11187
|
-
(condition) => condition.evaluate(activity)
|
|
11188
|
-
);
|
|
11233
|
+
conditionsMet = rule.conditions.some((condition) => condition.evaluate(activity));
|
|
11189
11234
|
}
|
|
11190
11235
|
if (conditionsMet) {
|
|
11191
|
-
if (rule.action === RuleActionType.
|
|
11236
|
+
if (rule.action === RuleActionType.EXIT) {
|
|
11237
|
+
return { action: "EXIT", recursionDepth };
|
|
11238
|
+
} else if (rule.action === RuleActionType.EXIT_PARENT) {
|
|
11192
11239
|
return { action: "EXIT_PARENT", recursionDepth };
|
|
11193
11240
|
} else if (rule.action === RuleActionType.EXIT_ALL) {
|
|
11194
11241
|
return { action: "EXIT_ALL", recursionDepth };
|
|
@@ -11222,6 +11269,55 @@ class TerminationHandler {
|
|
|
11222
11269
|
this.processExitAtLevel(rootActivity, 0);
|
|
11223
11270
|
this.terminateAll(rootActivity);
|
|
11224
11271
|
}
|
|
11272
|
+
/**
|
|
11273
|
+
* Sequencing Exit Action Rules Subprocess (TB.2.1) ancestor walk
|
|
11274
|
+
* @spec SN Book: TB.2.1 (Sequencing Exit Action Rules Subprocess)
|
|
11275
|
+
* @param {Activity} terminatingActivity - The activity whose attempt just ended
|
|
11276
|
+
* @return {{action: string | null, activity?: Activity, exception?: string}}
|
|
11277
|
+
*/
|
|
11278
|
+
applyAncestorExitActionRules(terminatingActivity) {
|
|
11279
|
+
const activityPath = [];
|
|
11280
|
+
let current = terminatingActivity.parent;
|
|
11281
|
+
while (current) {
|
|
11282
|
+
activityPath.unshift(current);
|
|
11283
|
+
current = current.parent;
|
|
11284
|
+
}
|
|
11285
|
+
for (const activity of activityPath) {
|
|
11286
|
+
const exitAction = this.exitActionRulesSubprocess(activity);
|
|
11287
|
+
if (exitAction === "EXIT_ALL") {
|
|
11288
|
+
this.fireEvent("onAncestorExitAction", {
|
|
11289
|
+
activity: activity.id,
|
|
11290
|
+
action: exitAction
|
|
11291
|
+
});
|
|
11292
|
+
return { action: "EXIT_ALL", activity };
|
|
11293
|
+
}
|
|
11294
|
+
if (exitAction === "EXIT_PARENT") {
|
|
11295
|
+
if (!activity.parent) {
|
|
11296
|
+
return { action: "EXIT_PARENT", activity, exception: "TB.2.3-4" };
|
|
11297
|
+
}
|
|
11298
|
+
this.terminateDescendants(activity.parent);
|
|
11299
|
+
this.activityTree.currentActivity = activity.parent;
|
|
11300
|
+
this.endAttempt(activity.parent);
|
|
11301
|
+
this.fireEvent("onAncestorExitAction", {
|
|
11302
|
+
activity: activity.id,
|
|
11303
|
+
action: exitAction,
|
|
11304
|
+
currentActivity: activity.parent.id
|
|
11305
|
+
});
|
|
11306
|
+
return { action: "EXIT_PARENT", activity: activity.parent };
|
|
11307
|
+
}
|
|
11308
|
+
if (exitAction === "EXIT") {
|
|
11309
|
+
this.terminateDescendants(activity);
|
|
11310
|
+
this.activityTree.currentActivity = activity;
|
|
11311
|
+
this.endAttempt(activity);
|
|
11312
|
+
this.fireEvent("onAncestorExitAction", {
|
|
11313
|
+
activity: activity.id,
|
|
11314
|
+
action: exitAction
|
|
11315
|
+
});
|
|
11316
|
+
return { action: "EXIT", activity };
|
|
11317
|
+
}
|
|
11318
|
+
}
|
|
11319
|
+
return { action: null };
|
|
11320
|
+
}
|
|
11225
11321
|
/**
|
|
11226
11322
|
* Process exit actions at specific level
|
|
11227
11323
|
* @param {Activity} activity - Activity to process
|
|
@@ -11304,16 +11400,14 @@ class TerminationHandler {
|
|
|
11304
11400
|
for (const rule of exitRules) {
|
|
11305
11401
|
let conditionsMet;
|
|
11306
11402
|
if (rule.conditionCombination === "all") {
|
|
11307
|
-
conditionsMet = rule.conditions.every(
|
|
11308
|
-
(condition) => condition.evaluate(activity)
|
|
11309
|
-
);
|
|
11403
|
+
conditionsMet = rule.conditions.every((condition) => condition.evaluate(activity));
|
|
11310
11404
|
} else {
|
|
11311
|
-
conditionsMet = rule.conditions.some(
|
|
11312
|
-
(condition) => condition.evaluate(activity)
|
|
11313
|
-
);
|
|
11405
|
+
conditionsMet = rule.conditions.some((condition) => condition.evaluate(activity));
|
|
11314
11406
|
}
|
|
11315
11407
|
if (conditionsMet) {
|
|
11316
|
-
if (rule.action === RuleActionType.
|
|
11408
|
+
if (rule.action === RuleActionType.EXIT) {
|
|
11409
|
+
return "EXIT";
|
|
11410
|
+
} else if (rule.action === RuleActionType.EXIT_PARENT) {
|
|
11317
11411
|
return "EXIT_PARENT";
|
|
11318
11412
|
} else if (rule.action === RuleActionType.EXIT_ALL) {
|
|
11319
11413
|
return "EXIT_ALL";
|
|
@@ -14867,7 +14961,29 @@ class SequencingService {
|
|
|
14867
14961
|
* Update activity properties from current CMI values
|
|
14868
14962
|
*/
|
|
14869
14963
|
updateActivityFromCMI(activity) {
|
|
14870
|
-
|
|
14964
|
+
let hasProgressMeasure = false;
|
|
14965
|
+
if (this.cmi.progress_measure !== "") {
|
|
14966
|
+
const progressMeasure = parseFloat(this.cmi.progress_measure);
|
|
14967
|
+
if (!isNaN(progressMeasure)) {
|
|
14968
|
+
hasProgressMeasure = true;
|
|
14969
|
+
activity.progressMeasure = progressMeasure;
|
|
14970
|
+
activity.progressMeasureStatus = true;
|
|
14971
|
+
activity.attemptCompletionAmount = progressMeasure;
|
|
14972
|
+
activity.attemptCompletionAmountStatus = true;
|
|
14973
|
+
}
|
|
14974
|
+
}
|
|
14975
|
+
if (!hasProgressMeasure) {
|
|
14976
|
+
activity.attemptCompletionAmountStatus = false;
|
|
14977
|
+
}
|
|
14978
|
+
if (activity.completedByMeasure) {
|
|
14979
|
+
const completionStatus = evaluateCompletionStatusFromThreshold({
|
|
14980
|
+
completionThreshold: activity.minProgressMeasure,
|
|
14981
|
+
progressMeasure: this.cmi.progress_measure,
|
|
14982
|
+
storedCompletionStatus: CompletionStatus.UNKNOWN
|
|
14983
|
+
});
|
|
14984
|
+
activity.completionStatus = completionStatus;
|
|
14985
|
+
activity.attemptProgressStatus = completionStatus !== CompletionStatus.UNKNOWN;
|
|
14986
|
+
} else if (this.cmi.completion_status !== "unknown") {
|
|
14871
14987
|
activity.completionStatus = this.cmi.completion_status;
|
|
14872
14988
|
activity.attemptProgressStatus = true;
|
|
14873
14989
|
}
|
|
@@ -14879,13 +14995,6 @@ class SequencingService {
|
|
|
14879
14995
|
activity.primaryObjective.progressStatus = true;
|
|
14880
14996
|
}
|
|
14881
14997
|
}
|
|
14882
|
-
if (this.cmi.progress_measure !== "") {
|
|
14883
|
-
const progressMeasure = parseFloat(this.cmi.progress_measure);
|
|
14884
|
-
if (!isNaN(progressMeasure)) {
|
|
14885
|
-
activity.progressMeasure = progressMeasure;
|
|
14886
|
-
activity.progressMeasureStatus = true;
|
|
14887
|
-
}
|
|
14888
|
-
}
|
|
14889
14998
|
if (this.cmi.score && this.cmi.score.scaled !== "") {
|
|
14890
14999
|
const scaledScore = parseFloat(this.cmi.score.scaled);
|
|
14891
15000
|
if (!isNaN(scaledScore)) {
|
|
@@ -18307,6 +18416,7 @@ let CMI$1 = class CMI extends BaseRootCMI {
|
|
|
18307
18416
|
*/
|
|
18308
18417
|
reset() {
|
|
18309
18418
|
this._initialized = false;
|
|
18419
|
+
this._start_time = void 0;
|
|
18310
18420
|
this._launch_data = "";
|
|
18311
18421
|
this._comments = "";
|
|
18312
18422
|
this.core?.reset();
|
|
@@ -21049,6 +21159,7 @@ class CMI extends BaseRootCMI {
|
|
|
21049
21159
|
*/
|
|
21050
21160
|
reset() {
|
|
21051
21161
|
this._initialized = false;
|
|
21162
|
+
this._start_time = void 0;
|
|
21052
21163
|
this.metadata?.reset();
|
|
21053
21164
|
this.learner?.reset();
|
|
21054
21165
|
this.status?.reset();
|
|
@@ -23012,22 +23123,11 @@ class Scorm2004CMIHandler {
|
|
|
23012
23123
|
* @returns {string} The evaluated completion status
|
|
23013
23124
|
*/
|
|
23014
23125
|
evaluateCompletionStatus() {
|
|
23015
|
-
|
|
23016
|
-
|
|
23017
|
-
|
|
23018
|
-
|
|
23019
|
-
|
|
23020
|
-
if (!isNaN(thresholdValue)) {
|
|
23021
|
-
if (progressMeasure !== "" && progressMeasure !== null && progressMeasure !== void 0) {
|
|
23022
|
-
const progressValue = parseFloat(String(progressMeasure));
|
|
23023
|
-
if (!isNaN(progressValue)) {
|
|
23024
|
-
return progressValue >= thresholdValue ? CompletionStatus.COMPLETED : CompletionStatus.INCOMPLETE;
|
|
23025
|
-
}
|
|
23026
|
-
}
|
|
23027
|
-
return CompletionStatus.UNKNOWN;
|
|
23028
|
-
}
|
|
23029
|
-
}
|
|
23030
|
-
return storedStatus || CompletionStatus.UNKNOWN;
|
|
23126
|
+
return evaluateCompletionStatusFromThreshold({
|
|
23127
|
+
completionThreshold: this.context.cmi.completion_threshold,
|
|
23128
|
+
progressMeasure: this.context.cmi.progress_measure,
|
|
23129
|
+
storedCompletionStatus: this.context.cmi.completion_status
|
|
23130
|
+
});
|
|
23031
23131
|
}
|
|
23032
23132
|
/**
|
|
23033
23133
|
* Evaluates success_status per SCORM 2004 RTE Table 4.2.21.1a
|
|
@@ -23687,6 +23787,21 @@ class ActivityTreeBuilder {
|
|
|
23687
23787
|
if (activitySettings.rollupConsiderations) {
|
|
23688
23788
|
activity.applyRollupConsiderations(activitySettings.rollupConsiderations);
|
|
23689
23789
|
}
|
|
23790
|
+
if (activitySettings.completionThreshold) {
|
|
23791
|
+
const threshold = activitySettings.completionThreshold;
|
|
23792
|
+
if (threshold.completedByMeasure !== void 0) {
|
|
23793
|
+
activity.completedByMeasure = threshold.completedByMeasure;
|
|
23794
|
+
}
|
|
23795
|
+
if (threshold.minProgressMeasure !== void 0) {
|
|
23796
|
+
activity.minProgressMeasure = threshold.minProgressMeasure;
|
|
23797
|
+
activity.completionThreshold = threshold.minProgressMeasure.toString();
|
|
23798
|
+
} else if (threshold.completedByMeasure) {
|
|
23799
|
+
activity.completionThreshold = activity.minProgressMeasure.toString();
|
|
23800
|
+
}
|
|
23801
|
+
if (threshold.progressWeight !== void 0) {
|
|
23802
|
+
activity.progressWeight = threshold.progressWeight;
|
|
23803
|
+
}
|
|
23804
|
+
}
|
|
23690
23805
|
if (activitySettings.hideLmsUi) {
|
|
23691
23806
|
const mergedHide = this.sequencingConfigBuilder.mergeHideLmsUi(
|
|
23692
23807
|
activity.hideLmsUi,
|
|
@@ -24730,8 +24845,23 @@ class Scorm2004API extends BaseAPI {
|
|
|
24730
24845
|
reset(settings) {
|
|
24731
24846
|
this.commonReset(settings);
|
|
24732
24847
|
this.cmi?.reset();
|
|
24848
|
+
this.applyCurrentActivityLaunchData();
|
|
24733
24849
|
this.adl?.reset();
|
|
24734
24850
|
}
|
|
24851
|
+
/**
|
|
24852
|
+
* Apply launch-static activity data to CMI while the new SCO is pre-initialize.
|
|
24853
|
+
*
|
|
24854
|
+
* @spec SCORM 2004 4th Ed. RTE 4.2.9 - cmi.completion_threshold
|
|
24855
|
+
*/
|
|
24856
|
+
applyCurrentActivityLaunchData() {
|
|
24857
|
+
const currentActivity = this._sequencing?.getCurrentActivity();
|
|
24858
|
+
if (!this.cmi || !currentActivity) {
|
|
24859
|
+
return;
|
|
24860
|
+
}
|
|
24861
|
+
const contentActivityData = this._sequencing.overallSequencingProcess?.getContentActivityData(currentActivity);
|
|
24862
|
+
const completionThreshold = contentActivityData?.completionThreshold ?? currentActivity.completionThreshold?.toString() ?? "";
|
|
24863
|
+
this.cmi.completion_threshold = completionThreshold;
|
|
24864
|
+
}
|
|
24735
24865
|
/**
|
|
24736
24866
|
* Getter for _version
|
|
24737
24867
|
* @return {string}
|
|
@@ -25242,14 +25372,14 @@ class Scorm2004API extends BaseAPI {
|
|
|
25242
25372
|
if (this.cmi.mode === "normal") {
|
|
25243
25373
|
if (this.cmi.credit === "credit") {
|
|
25244
25374
|
if (this.cmi.completion_threshold && this.cmi.progress_measure) {
|
|
25245
|
-
if (this.cmi.progress_measure >= this.cmi.completion_threshold) {
|
|
25375
|
+
if (parseFloat(this.cmi.progress_measure) >= parseFloat(this.cmi.completion_threshold)) {
|
|
25246
25376
|
this.cmi.completion_status = "completed";
|
|
25247
25377
|
} else {
|
|
25248
25378
|
this.cmi.completion_status = "incomplete";
|
|
25249
25379
|
}
|
|
25250
25380
|
}
|
|
25251
25381
|
if (this.cmi.scaled_passing_score && this.cmi.score.scaled) {
|
|
25252
|
-
if (this.cmi.score.scaled >= this.cmi.scaled_passing_score) {
|
|
25382
|
+
if (parseFloat(this.cmi.score.scaled) >= parseFloat(this.cmi.scaled_passing_score)) {
|
|
25253
25383
|
this.cmi.success_status = "passed";
|
|
25254
25384
|
} else {
|
|
25255
25385
|
this.cmi.success_status = "failed";
|