scorm-again 3.1.3 → 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 +183 -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/scorm2004.js +183 -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 +217 -43
- package/dist/scorm-again.js.map +1 -1
- package/dist/scorm-again.min.js +1 -1
- package/dist/scorm2004.js +217 -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/scorm2004.js
CHANGED
|
@@ -10426,6 +10426,26 @@ class RollupProcess {
|
|
|
10426
10426
|
}
|
|
10427
10427
|
}
|
|
10428
10428
|
|
|
10429
|
+
function evaluateCompletionStatusFromThreshold({
|
|
10430
|
+
completionThreshold,
|
|
10431
|
+
progressMeasure,
|
|
10432
|
+
storedCompletionStatus
|
|
10433
|
+
}) {
|
|
10434
|
+
if (completionThreshold !== "" && completionThreshold !== null && completionThreshold !== void 0) {
|
|
10435
|
+
const thresholdValue = parseFloat(String(completionThreshold));
|
|
10436
|
+
if (!isNaN(thresholdValue)) {
|
|
10437
|
+
if (progressMeasure !== "" && progressMeasure !== null && progressMeasure !== void 0) {
|
|
10438
|
+
const progressValue = parseFloat(String(progressMeasure));
|
|
10439
|
+
if (!isNaN(progressValue)) {
|
|
10440
|
+
return progressValue >= thresholdValue ? CompletionStatus.COMPLETED : CompletionStatus.INCOMPLETE;
|
|
10441
|
+
}
|
|
10442
|
+
}
|
|
10443
|
+
return CompletionStatus.UNKNOWN;
|
|
10444
|
+
}
|
|
10445
|
+
}
|
|
10446
|
+
return storedCompletionStatus || CompletionStatus.UNKNOWN;
|
|
10447
|
+
}
|
|
10448
|
+
|
|
10429
10449
|
const VALID_COMPLETION_STATUSES = [
|
|
10430
10450
|
CompletionStatus.COMPLETED,
|
|
10431
10451
|
CompletionStatus.INCOMPLETE,
|
|
@@ -10480,10 +10500,38 @@ class RteDataTransferService {
|
|
|
10480
10500
|
* @param {CMIDataForTransfer} cmiData - CMI data from runtime
|
|
10481
10501
|
*/
|
|
10482
10502
|
transferPrimaryObjective(activity, cmiData) {
|
|
10483
|
-
|
|
10484
|
-
if (
|
|
10485
|
-
|
|
10486
|
-
|
|
10503
|
+
let hasProgressMeasure = false;
|
|
10504
|
+
if (cmiData.progress_measure && cmiData.progress_measure !== "") {
|
|
10505
|
+
const progressMeasure = parseFloat(cmiData.progress_measure);
|
|
10506
|
+
if (!isNaN(progressMeasure)) {
|
|
10507
|
+
hasProgressMeasure = true;
|
|
10508
|
+
activity.progressMeasure = progressMeasure;
|
|
10509
|
+
activity.progressMeasureStatus = true;
|
|
10510
|
+
activity.attemptCompletionAmount = progressMeasure;
|
|
10511
|
+
activity.attemptCompletionAmountStatus = true;
|
|
10512
|
+
if (activity.primaryObjective) {
|
|
10513
|
+
activity.primaryObjective.progressMeasure = progressMeasure;
|
|
10514
|
+
activity.primaryObjective.progressMeasureStatus = true;
|
|
10515
|
+
}
|
|
10516
|
+
}
|
|
10517
|
+
}
|
|
10518
|
+
if (!hasProgressMeasure) {
|
|
10519
|
+
activity.attemptCompletionAmountStatus = false;
|
|
10520
|
+
}
|
|
10521
|
+
if (activity.completedByMeasure) {
|
|
10522
|
+
const completionStatus = evaluateCompletionStatusFromThreshold({
|
|
10523
|
+
completionThreshold: activity.minProgressMeasure,
|
|
10524
|
+
progressMeasure: cmiData.progress_measure,
|
|
10525
|
+
storedCompletionStatus: CompletionStatus.UNKNOWN
|
|
10526
|
+
});
|
|
10527
|
+
activity.completionStatus = completionStatus;
|
|
10528
|
+
activity.attemptProgressStatus = completionStatus !== CompletionStatus.UNKNOWN;
|
|
10529
|
+
} else {
|
|
10530
|
+
const validatedCompletionStatus = validateCompletionStatus(cmiData.completion_status);
|
|
10531
|
+
if (validatedCompletionStatus && validatedCompletionStatus !== CompletionStatus.UNKNOWN) {
|
|
10532
|
+
activity.completionStatus = validatedCompletionStatus;
|
|
10533
|
+
activity.attemptProgressStatus = true;
|
|
10534
|
+
}
|
|
10487
10535
|
}
|
|
10488
10536
|
let hasSuccessStatus = false;
|
|
10489
10537
|
let successStatus = false;
|
|
@@ -10517,17 +10565,6 @@ class RteDataTransferService {
|
|
|
10517
10565
|
activity.primaryObjective.progressStatus = true;
|
|
10518
10566
|
}
|
|
10519
10567
|
}
|
|
10520
|
-
if (cmiData.progress_measure && cmiData.progress_measure !== "") {
|
|
10521
|
-
const progressMeasure = parseFloat(cmiData.progress_measure);
|
|
10522
|
-
if (!isNaN(progressMeasure)) {
|
|
10523
|
-
activity.progressMeasure = progressMeasure;
|
|
10524
|
-
activity.progressMeasureStatus = true;
|
|
10525
|
-
if (activity.primaryObjective) {
|
|
10526
|
-
activity.primaryObjective.progressMeasure = progressMeasure;
|
|
10527
|
-
activity.primaryObjective.progressMeasureStatus = true;
|
|
10528
|
-
}
|
|
10529
|
-
}
|
|
10530
|
-
}
|
|
10531
10568
|
}
|
|
10532
10569
|
/**
|
|
10533
10570
|
* Transfer non-primary objective data from CMI to activity objectives
|
|
@@ -10732,6 +10769,18 @@ class TerminationHandler {
|
|
|
10732
10769
|
this.endAttempt(this.activityTree.currentActivity);
|
|
10733
10770
|
}
|
|
10734
10771
|
}
|
|
10772
|
+
const ancestorExitResult = this.applyAncestorExitActionRules(currentActivity);
|
|
10773
|
+
if (ancestorExitResult.action === "EXIT_ALL") {
|
|
10774
|
+
return this.handleExitAll(ancestorExitResult.activity || currentActivity);
|
|
10775
|
+
}
|
|
10776
|
+
if (ancestorExitResult.exception) {
|
|
10777
|
+
return {
|
|
10778
|
+
terminationRequest: SequencingRequestType.EXIT,
|
|
10779
|
+
sequencingRequest: null,
|
|
10780
|
+
exception: ancestorExitResult.exception,
|
|
10781
|
+
valid: false
|
|
10782
|
+
};
|
|
10783
|
+
}
|
|
10735
10784
|
let processedExit;
|
|
10736
10785
|
let postConditionResult;
|
|
10737
10786
|
do {
|
|
@@ -10959,16 +11008,14 @@ class TerminationHandler {
|
|
|
10959
11008
|
for (const rule of exitRules) {
|
|
10960
11009
|
let conditionsMet;
|
|
10961
11010
|
if (rule.conditionCombination === "all") {
|
|
10962
|
-
conditionsMet = rule.conditions.every(
|
|
10963
|
-
(condition) => condition.evaluate(activity)
|
|
10964
|
-
);
|
|
11011
|
+
conditionsMet = rule.conditions.every((condition) => condition.evaluate(activity));
|
|
10965
11012
|
} else {
|
|
10966
|
-
conditionsMet = rule.conditions.some(
|
|
10967
|
-
(condition) => condition.evaluate(activity)
|
|
10968
|
-
);
|
|
11013
|
+
conditionsMet = rule.conditions.some((condition) => condition.evaluate(activity));
|
|
10969
11014
|
}
|
|
10970
11015
|
if (conditionsMet) {
|
|
10971
|
-
if (rule.action === RuleActionType.
|
|
11016
|
+
if (rule.action === RuleActionType.EXIT) {
|
|
11017
|
+
return { action: "EXIT", recursionDepth };
|
|
11018
|
+
} else if (rule.action === RuleActionType.EXIT_PARENT) {
|
|
10972
11019
|
return { action: "EXIT_PARENT", recursionDepth };
|
|
10973
11020
|
} else if (rule.action === RuleActionType.EXIT_ALL) {
|
|
10974
11021
|
return { action: "EXIT_ALL", recursionDepth };
|
|
@@ -11002,6 +11049,55 @@ class TerminationHandler {
|
|
|
11002
11049
|
this.processExitAtLevel(rootActivity, 0);
|
|
11003
11050
|
this.terminateAll(rootActivity);
|
|
11004
11051
|
}
|
|
11052
|
+
/**
|
|
11053
|
+
* Sequencing Exit Action Rules Subprocess (TB.2.1) ancestor walk
|
|
11054
|
+
* @spec SN Book: TB.2.1 (Sequencing Exit Action Rules Subprocess)
|
|
11055
|
+
* @param {Activity} terminatingActivity - The activity whose attempt just ended
|
|
11056
|
+
* @return {{action: string | null, activity?: Activity, exception?: string}}
|
|
11057
|
+
*/
|
|
11058
|
+
applyAncestorExitActionRules(terminatingActivity) {
|
|
11059
|
+
const activityPath = [];
|
|
11060
|
+
let current = terminatingActivity.parent;
|
|
11061
|
+
while (current) {
|
|
11062
|
+
activityPath.unshift(current);
|
|
11063
|
+
current = current.parent;
|
|
11064
|
+
}
|
|
11065
|
+
for (const activity of activityPath) {
|
|
11066
|
+
const exitAction = this.exitActionRulesSubprocess(activity);
|
|
11067
|
+
if (exitAction === "EXIT_ALL") {
|
|
11068
|
+
this.fireEvent("onAncestorExitAction", {
|
|
11069
|
+
activity: activity.id,
|
|
11070
|
+
action: exitAction
|
|
11071
|
+
});
|
|
11072
|
+
return { action: "EXIT_ALL", activity };
|
|
11073
|
+
}
|
|
11074
|
+
if (exitAction === "EXIT_PARENT") {
|
|
11075
|
+
if (!activity.parent) {
|
|
11076
|
+
return { action: "EXIT_PARENT", activity, exception: "TB.2.3-4" };
|
|
11077
|
+
}
|
|
11078
|
+
this.terminateDescendants(activity.parent);
|
|
11079
|
+
this.activityTree.currentActivity = activity.parent;
|
|
11080
|
+
this.endAttempt(activity.parent);
|
|
11081
|
+
this.fireEvent("onAncestorExitAction", {
|
|
11082
|
+
activity: activity.id,
|
|
11083
|
+
action: exitAction,
|
|
11084
|
+
currentActivity: activity.parent.id
|
|
11085
|
+
});
|
|
11086
|
+
return { action: "EXIT_PARENT", activity: activity.parent };
|
|
11087
|
+
}
|
|
11088
|
+
if (exitAction === "EXIT") {
|
|
11089
|
+
this.terminateDescendants(activity);
|
|
11090
|
+
this.activityTree.currentActivity = activity;
|
|
11091
|
+
this.endAttempt(activity);
|
|
11092
|
+
this.fireEvent("onAncestorExitAction", {
|
|
11093
|
+
activity: activity.id,
|
|
11094
|
+
action: exitAction
|
|
11095
|
+
});
|
|
11096
|
+
return { action: "EXIT", activity };
|
|
11097
|
+
}
|
|
11098
|
+
}
|
|
11099
|
+
return { action: null };
|
|
11100
|
+
}
|
|
11005
11101
|
/**
|
|
11006
11102
|
* Process exit actions at specific level
|
|
11007
11103
|
* @param {Activity} activity - Activity to process
|
|
@@ -11084,16 +11180,14 @@ class TerminationHandler {
|
|
|
11084
11180
|
for (const rule of exitRules) {
|
|
11085
11181
|
let conditionsMet;
|
|
11086
11182
|
if (rule.conditionCombination === "all") {
|
|
11087
|
-
conditionsMet = rule.conditions.every(
|
|
11088
|
-
(condition) => condition.evaluate(activity)
|
|
11089
|
-
);
|
|
11183
|
+
conditionsMet = rule.conditions.every((condition) => condition.evaluate(activity));
|
|
11090
11184
|
} else {
|
|
11091
|
-
conditionsMet = rule.conditions.some(
|
|
11092
|
-
(condition) => condition.evaluate(activity)
|
|
11093
|
-
);
|
|
11185
|
+
conditionsMet = rule.conditions.some((condition) => condition.evaluate(activity));
|
|
11094
11186
|
}
|
|
11095
11187
|
if (conditionsMet) {
|
|
11096
|
-
if (rule.action === RuleActionType.
|
|
11188
|
+
if (rule.action === RuleActionType.EXIT) {
|
|
11189
|
+
return "EXIT";
|
|
11190
|
+
} else if (rule.action === RuleActionType.EXIT_PARENT) {
|
|
11097
11191
|
return "EXIT_PARENT";
|
|
11098
11192
|
} else if (rule.action === RuleActionType.EXIT_ALL) {
|
|
11099
11193
|
return "EXIT_ALL";
|
|
@@ -14647,7 +14741,29 @@ class SequencingService {
|
|
|
14647
14741
|
* Update activity properties from current CMI values
|
|
14648
14742
|
*/
|
|
14649
14743
|
updateActivityFromCMI(activity) {
|
|
14650
|
-
|
|
14744
|
+
let hasProgressMeasure = false;
|
|
14745
|
+
if (this.cmi.progress_measure !== "") {
|
|
14746
|
+
const progressMeasure = parseFloat(this.cmi.progress_measure);
|
|
14747
|
+
if (!isNaN(progressMeasure)) {
|
|
14748
|
+
hasProgressMeasure = true;
|
|
14749
|
+
activity.progressMeasure = progressMeasure;
|
|
14750
|
+
activity.progressMeasureStatus = true;
|
|
14751
|
+
activity.attemptCompletionAmount = progressMeasure;
|
|
14752
|
+
activity.attemptCompletionAmountStatus = true;
|
|
14753
|
+
}
|
|
14754
|
+
}
|
|
14755
|
+
if (!hasProgressMeasure) {
|
|
14756
|
+
activity.attemptCompletionAmountStatus = false;
|
|
14757
|
+
}
|
|
14758
|
+
if (activity.completedByMeasure) {
|
|
14759
|
+
const completionStatus = evaluateCompletionStatusFromThreshold({
|
|
14760
|
+
completionThreshold: activity.minProgressMeasure,
|
|
14761
|
+
progressMeasure: this.cmi.progress_measure,
|
|
14762
|
+
storedCompletionStatus: CompletionStatus.UNKNOWN
|
|
14763
|
+
});
|
|
14764
|
+
activity.completionStatus = completionStatus;
|
|
14765
|
+
activity.attemptProgressStatus = completionStatus !== CompletionStatus.UNKNOWN;
|
|
14766
|
+
} else if (this.cmi.completion_status !== "unknown") {
|
|
14651
14767
|
activity.completionStatus = this.cmi.completion_status;
|
|
14652
14768
|
activity.attemptProgressStatus = true;
|
|
14653
14769
|
}
|
|
@@ -14659,13 +14775,6 @@ class SequencingService {
|
|
|
14659
14775
|
activity.primaryObjective.progressStatus = true;
|
|
14660
14776
|
}
|
|
14661
14777
|
}
|
|
14662
|
-
if (this.cmi.progress_measure !== "") {
|
|
14663
|
-
const progressMeasure = parseFloat(this.cmi.progress_measure);
|
|
14664
|
-
if (!isNaN(progressMeasure)) {
|
|
14665
|
-
activity.progressMeasure = progressMeasure;
|
|
14666
|
-
activity.progressMeasureStatus = true;
|
|
14667
|
-
}
|
|
14668
|
-
}
|
|
14669
14778
|
if (this.cmi.score && this.cmi.score.scaled !== "") {
|
|
14670
14779
|
const scaledScore = parseFloat(this.cmi.score.scaled);
|
|
14671
14780
|
if (!isNaN(scaledScore)) {
|
|
@@ -20823,22 +20932,11 @@ class Scorm2004CMIHandler {
|
|
|
20823
20932
|
* @returns {string} The evaluated completion status
|
|
20824
20933
|
*/
|
|
20825
20934
|
evaluateCompletionStatus() {
|
|
20826
|
-
|
|
20827
|
-
|
|
20828
|
-
|
|
20829
|
-
|
|
20830
|
-
|
|
20831
|
-
if (!isNaN(thresholdValue)) {
|
|
20832
|
-
if (progressMeasure !== "" && progressMeasure !== null && progressMeasure !== void 0) {
|
|
20833
|
-
const progressValue = parseFloat(String(progressMeasure));
|
|
20834
|
-
if (!isNaN(progressValue)) {
|
|
20835
|
-
return progressValue >= thresholdValue ? CompletionStatus.COMPLETED : CompletionStatus.INCOMPLETE;
|
|
20836
|
-
}
|
|
20837
|
-
}
|
|
20838
|
-
return CompletionStatus.UNKNOWN;
|
|
20839
|
-
}
|
|
20840
|
-
}
|
|
20841
|
-
return storedStatus || CompletionStatus.UNKNOWN;
|
|
20935
|
+
return evaluateCompletionStatusFromThreshold({
|
|
20936
|
+
completionThreshold: this.context.cmi.completion_threshold,
|
|
20937
|
+
progressMeasure: this.context.cmi.progress_measure,
|
|
20938
|
+
storedCompletionStatus: this.context.cmi.completion_status
|
|
20939
|
+
});
|
|
20842
20940
|
}
|
|
20843
20941
|
/**
|
|
20844
20942
|
* Evaluates success_status per SCORM 2004 RTE Table 4.2.21.1a
|
|
@@ -21498,6 +21596,21 @@ class ActivityTreeBuilder {
|
|
|
21498
21596
|
if (activitySettings.rollupConsiderations) {
|
|
21499
21597
|
activity.applyRollupConsiderations(activitySettings.rollupConsiderations);
|
|
21500
21598
|
}
|
|
21599
|
+
if (activitySettings.completionThreshold) {
|
|
21600
|
+
const threshold = activitySettings.completionThreshold;
|
|
21601
|
+
if (threshold.completedByMeasure !== void 0) {
|
|
21602
|
+
activity.completedByMeasure = threshold.completedByMeasure;
|
|
21603
|
+
}
|
|
21604
|
+
if (threshold.minProgressMeasure !== void 0) {
|
|
21605
|
+
activity.minProgressMeasure = threshold.minProgressMeasure;
|
|
21606
|
+
activity.completionThreshold = threshold.minProgressMeasure.toString();
|
|
21607
|
+
} else if (threshold.completedByMeasure) {
|
|
21608
|
+
activity.completionThreshold = activity.minProgressMeasure.toString();
|
|
21609
|
+
}
|
|
21610
|
+
if (threshold.progressWeight !== void 0) {
|
|
21611
|
+
activity.progressWeight = threshold.progressWeight;
|
|
21612
|
+
}
|
|
21613
|
+
}
|
|
21501
21614
|
if (activitySettings.hideLmsUi) {
|
|
21502
21615
|
const mergedHide = this.sequencingConfigBuilder.mergeHideLmsUi(
|
|
21503
21616
|
activity.hideLmsUi,
|
|
@@ -22541,8 +22654,23 @@ class Scorm2004API extends BaseAPI {
|
|
|
22541
22654
|
reset(settings) {
|
|
22542
22655
|
this.commonReset(settings);
|
|
22543
22656
|
this.cmi?.reset();
|
|
22657
|
+
this.applyCurrentActivityLaunchData();
|
|
22544
22658
|
this.adl?.reset();
|
|
22545
22659
|
}
|
|
22660
|
+
/**
|
|
22661
|
+
* Apply launch-static activity data to CMI while the new SCO is pre-initialize.
|
|
22662
|
+
*
|
|
22663
|
+
* @spec SCORM 2004 4th Ed. RTE 4.2.9 - cmi.completion_threshold
|
|
22664
|
+
*/
|
|
22665
|
+
applyCurrentActivityLaunchData() {
|
|
22666
|
+
const currentActivity = this._sequencing?.getCurrentActivity();
|
|
22667
|
+
if (!this.cmi || !currentActivity) {
|
|
22668
|
+
return;
|
|
22669
|
+
}
|
|
22670
|
+
const contentActivityData = this._sequencing.overallSequencingProcess?.getContentActivityData(currentActivity);
|
|
22671
|
+
const completionThreshold = contentActivityData?.completionThreshold ?? currentActivity.completionThreshold?.toString() ?? "";
|
|
22672
|
+
this.cmi.completion_threshold = completionThreshold;
|
|
22673
|
+
}
|
|
22546
22674
|
/**
|
|
22547
22675
|
* Getter for _version
|
|
22548
22676
|
* @return {string}
|
|
@@ -23053,14 +23181,14 @@ class Scorm2004API extends BaseAPI {
|
|
|
23053
23181
|
if (this.cmi.mode === "normal") {
|
|
23054
23182
|
if (this.cmi.credit === "credit") {
|
|
23055
23183
|
if (this.cmi.completion_threshold && this.cmi.progress_measure) {
|
|
23056
|
-
if (this.cmi.progress_measure >= this.cmi.completion_threshold) {
|
|
23184
|
+
if (parseFloat(this.cmi.progress_measure) >= parseFloat(this.cmi.completion_threshold)) {
|
|
23057
23185
|
this.cmi.completion_status = "completed";
|
|
23058
23186
|
} else {
|
|
23059
23187
|
this.cmi.completion_status = "incomplete";
|
|
23060
23188
|
}
|
|
23061
23189
|
}
|
|
23062
23190
|
if (this.cmi.scaled_passing_score && this.cmi.score.scaled) {
|
|
23063
|
-
if (this.cmi.score.scaled >= this.cmi.scaled_passing_score) {
|
|
23191
|
+
if (parseFloat(this.cmi.score.scaled) >= parseFloat(this.cmi.scaled_passing_score)) {
|
|
23064
23192
|
this.cmi.success_status = "passed";
|
|
23065
23193
|
} else {
|
|
23066
23194
|
this.cmi.success_status = "failed";
|