scorm-again 2.0.0 → 2.2.0
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/.github/workflows/stale.yml +14 -0
- package/.run/{Mocha Unit Tests.run.xml → Mocha Unit Tests (watch).run.xml } +1 -1
- package/.run/Template Mocha.run.xml +17 -0
- package/README.md +180 -72
- package/dist/aicc.js +1520 -1149
- package/dist/aicc.js.map +1 -1
- package/dist/aicc.min.js +1 -1
- package/dist/aicc.min.js.map +1 -1
- package/dist/scorm-again.js +2812 -2205
- package/dist/scorm-again.js.map +1 -1
- package/dist/scorm-again.min.js +1 -1
- package/dist/scorm-again.min.js.map +1 -1
- package/dist/scorm12.js +1129 -842
- package/dist/scorm12.js.map +1 -1
- package/dist/scorm12.min.js +1 -1
- package/dist/scorm12.min.js.map +1 -1
- package/dist/scorm2004.js +1921 -1564
- package/dist/scorm2004.js.map +1 -1
- package/dist/scorm2004.min.js +1 -1
- package/dist/scorm2004.min.js.map +1 -1
- package/package.json +20 -17
- package/src/AICC.ts +15 -17
- package/src/BaseAPI.ts +283 -420
- package/src/Scorm12API.ts +133 -41
- package/src/Scorm2004API.ts +224 -120
- package/src/cmi/aicc/attempts.ts +94 -0
- package/src/cmi/aicc/cmi.ts +100 -0
- package/src/cmi/aicc/core.ts +360 -0
- package/src/cmi/aicc/evaluation.ts +157 -0
- package/src/cmi/aicc/paths.ts +180 -0
- package/src/cmi/aicc/student_data.ts +86 -0
- package/src/cmi/aicc/student_demographics.ts +367 -0
- package/src/cmi/aicc/student_preferences.ts +176 -0
- package/src/cmi/aicc/tries.ts +116 -0
- package/src/cmi/aicc/validation.ts +25 -0
- package/src/cmi/common/array.ts +77 -0
- package/src/cmi/common/base_cmi.ts +46 -0
- package/src/cmi/common/score.ts +203 -0
- package/src/cmi/common/validation.ts +60 -0
- package/src/cmi/scorm12/cmi.ts +224 -0
- package/src/cmi/scorm12/interactions.ts +368 -0
- package/src/cmi/scorm12/nav.ts +54 -0
- package/src/cmi/scorm12/objectives.ts +112 -0
- package/src/cmi/scorm12/student_data.ts +130 -0
- package/src/cmi/scorm12/student_preference.ts +158 -0
- package/src/cmi/scorm12/validation.ts +48 -0
- package/src/cmi/scorm2004/adl.ts +272 -0
- package/src/cmi/scorm2004/cmi.ts +599 -0
- package/src/cmi/scorm2004/comments.ts +163 -0
- package/src/cmi/scorm2004/interactions.ts +466 -0
- package/src/cmi/scorm2004/learner_preference.ts +152 -0
- package/src/cmi/scorm2004/objectives.ts +212 -0
- package/src/cmi/scorm2004/score.ts +78 -0
- package/src/cmi/scorm2004/validation.ts +42 -0
- package/src/constants/default_settings.ts +82 -0
- package/src/constants/enums.ts +17 -0
- package/src/constants/regex.ts +2 -2
- package/src/constants/response_constants.ts +2 -0
- package/src/exceptions.ts +22 -1
- package/src/helpers/scheduled_commit.ts +42 -0
- package/src/interfaces/IBaseAPI.ts +35 -0
- package/src/types/api_types.ts +50 -0
- package/src/utilities/debounce.ts +31 -0
- package/src/utilities.ts +56 -0
- package/test/AICC.spec.ts +11 -1
- package/test/Scorm12API.spec.ts +372 -9
- package/test/Scorm2004API.spec.ts +558 -2
- package/test/cmi/aicc_cmi.spec.ts +188 -11
- package/test/cmi/scorm12_cmi.spec.ts +5 -5
- package/test/cmi/scorm2004_cmi.spec.ts +8 -8
- package/test/cmi_helpers.ts +1 -1
- package/test/types/api_types.spec.ts +126 -0
- package/test/utilities/debounce.spec.ts +56 -0
- package/src/cmi/aicc_cmi.ts +0 -1248
- package/src/cmi/common.ts +0 -411
- package/src/cmi/scorm12_cmi.ts +0 -1426
- package/src/cmi/scorm2004_cmi.ts +0 -1874
package/src/Scorm12API.ts
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
import BaseAPI
|
|
1
|
+
import BaseAPI from "./BaseAPI";
|
|
2
|
+
import { CMI } from "./cmi/scorm12/cmi";
|
|
3
|
+
import * as Utilities from "./utilities";
|
|
4
|
+
import { stringMatches } from "./utilities";
|
|
5
|
+
import APIConstants from "./constants/api_constants";
|
|
6
|
+
import ErrorCodes from "./constants/error_codes";
|
|
7
|
+
|
|
8
|
+
import { BaseCMI } from "./cmi/common/base_cmi";
|
|
9
|
+
import { CMIObjectivesObject } from "./cmi/scorm12/objectives";
|
|
2
10
|
import {
|
|
3
|
-
CMI,
|
|
4
11
|
CMIInteractionsCorrectResponsesObject,
|
|
5
12
|
CMIInteractionsObject,
|
|
6
13
|
CMIInteractionsObjectivesObject,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
} from "./cmi/scorm12/interactions";
|
|
15
|
+
import { NAV } from "./cmi/scorm12/nav";
|
|
16
|
+
import {
|
|
17
|
+
CommitObject,
|
|
18
|
+
RefObject,
|
|
19
|
+
ResultObject,
|
|
20
|
+
ScoreObject,
|
|
21
|
+
Settings,
|
|
22
|
+
} from "./types/api_types";
|
|
23
|
+
import Regex from "./constants/regex";
|
|
24
|
+
import { CompletionStatus, SuccessStatus } from "./constants/enums";
|
|
18
25
|
|
|
19
26
|
/**
|
|
20
27
|
* API class for SCORM 1.2
|
|
@@ -31,7 +38,7 @@ export default class Scorm12API extends BaseAPI {
|
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
super(
|
|
41
|
+
super(ErrorCodes.scorm12, settings);
|
|
35
42
|
|
|
36
43
|
this.cmi = new CMI();
|
|
37
44
|
this.nav = new NAV();
|
|
@@ -47,6 +54,8 @@ export default class Scorm12API extends BaseAPI {
|
|
|
47
54
|
this.LMSGetDiagnostic = this.lmsGetDiagnostic;
|
|
48
55
|
}
|
|
49
56
|
|
|
57
|
+
public statusSetByModule = false;
|
|
58
|
+
|
|
50
59
|
public cmi: CMI;
|
|
51
60
|
public nav: NAV;
|
|
52
61
|
|
|
@@ -59,6 +68,16 @@ export default class Scorm12API extends BaseAPI {
|
|
|
59
68
|
public LMSGetErrorString: (CMIErrorCode: string) => string;
|
|
60
69
|
public LMSGetDiagnostic: (CMIErrorCode: string) => string;
|
|
61
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Called when the API needs to be reset
|
|
73
|
+
*/
|
|
74
|
+
reset(settings?: Settings) {
|
|
75
|
+
this.commonReset(settings);
|
|
76
|
+
|
|
77
|
+
this.cmi = new CMI();
|
|
78
|
+
this.nav = new NAV();
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
/**
|
|
63
82
|
* lmsInitialize function from SCORM 1.2 Spec
|
|
64
83
|
*
|
|
@@ -66,6 +85,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
66
85
|
*/
|
|
67
86
|
lmsInitialize(): string {
|
|
68
87
|
this.cmi.initialize();
|
|
88
|
+
if (this.cmi.core.lesson_status) {
|
|
89
|
+
this.statusSetByModule = true;
|
|
90
|
+
} else {
|
|
91
|
+
this.cmi.core.lesson_status = "not attempted";
|
|
92
|
+
}
|
|
69
93
|
return this.initialize(
|
|
70
94
|
"LMSInitialize",
|
|
71
95
|
"LMS was already initialized!",
|
|
@@ -79,9 +103,16 @@ export default class Scorm12API extends BaseAPI {
|
|
|
79
103
|
* @return {string} bool
|
|
80
104
|
*/
|
|
81
105
|
lmsFinish(): string {
|
|
82
|
-
|
|
106
|
+
(async () => {
|
|
107
|
+
await this.internalFinish();
|
|
108
|
+
})();
|
|
109
|
+
return APIConstants.global.SCORM_TRUE;
|
|
110
|
+
}
|
|
83
111
|
|
|
84
|
-
|
|
112
|
+
async internalFinish(): Promise<string> {
|
|
113
|
+
const result = await this.terminate("LMSFinish", true);
|
|
114
|
+
|
|
115
|
+
if (result === APIConstants.global.SCORM_TRUE) {
|
|
85
116
|
if (this.nav.event !== "") {
|
|
86
117
|
if (this.nav.event === "continue") {
|
|
87
118
|
this.processListeners("SequenceNext");
|
|
@@ -114,6 +145,9 @@ export default class Scorm12API extends BaseAPI {
|
|
|
114
145
|
* @return {string}
|
|
115
146
|
*/
|
|
116
147
|
lmsSetValue(CMIElement: string, value: any): string {
|
|
148
|
+
if (CMIElement === "cmi.core.lesson_status") {
|
|
149
|
+
this.statusSetByModule = true;
|
|
150
|
+
}
|
|
117
151
|
return this.setValue("LMSSetValue", "LMSCommit", false, CMIElement, value);
|
|
118
152
|
}
|
|
119
153
|
|
|
@@ -123,7 +157,10 @@ export default class Scorm12API extends BaseAPI {
|
|
|
123
157
|
* @return {string} bool
|
|
124
158
|
*/
|
|
125
159
|
lmsCommit(): string {
|
|
126
|
-
|
|
160
|
+
(async () => {
|
|
161
|
+
await this.commit("LMSCommit", false);
|
|
162
|
+
})();
|
|
163
|
+
return APIConstants.global.SCORM_TRUE;
|
|
127
164
|
}
|
|
128
165
|
|
|
129
166
|
/**
|
|
@@ -189,11 +226,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
189
226
|
_value: any,
|
|
190
227
|
foundFirstIndex: boolean,
|
|
191
228
|
): BaseCMI | null {
|
|
192
|
-
if (
|
|
229
|
+
if (stringMatches(CMIElement, "cmi\\.objectives\\.\\d+")) {
|
|
193
230
|
return new CMIObjectivesObject();
|
|
194
231
|
} else if (
|
|
195
232
|
foundFirstIndex &&
|
|
196
|
-
|
|
233
|
+
stringMatches(
|
|
197
234
|
CMIElement,
|
|
198
235
|
"cmi\\.interactions\\.\\d+\\.correct_responses\\.\\d+",
|
|
199
236
|
)
|
|
@@ -201,15 +238,12 @@ export default class Scorm12API extends BaseAPI {
|
|
|
201
238
|
return new CMIInteractionsCorrectResponsesObject();
|
|
202
239
|
} else if (
|
|
203
240
|
foundFirstIndex &&
|
|
204
|
-
|
|
205
|
-
CMIElement,
|
|
206
|
-
"cmi\\.interactions\\.\\d+\\.objectives\\.\\d+",
|
|
207
|
-
)
|
|
241
|
+
stringMatches(CMIElement, "cmi\\.interactions\\.\\d+\\.objectives\\.\\d+")
|
|
208
242
|
) {
|
|
209
243
|
return new CMIInteractionsObjectivesObject();
|
|
210
244
|
} else if (
|
|
211
245
|
!foundFirstIndex &&
|
|
212
|
-
|
|
246
|
+
stringMatches(CMIElement, "cmi\\.interactions\\.\\d+")
|
|
213
247
|
) {
|
|
214
248
|
return new CMIInteractionsObject();
|
|
215
249
|
}
|
|
@@ -243,11 +277,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
243
277
|
|
|
244
278
|
// Set error number to string since inconsistent from modules if string or number
|
|
245
279
|
errorNumber = String(errorNumber);
|
|
246
|
-
if (
|
|
280
|
+
if (APIConstants.scorm12.error_descriptions[errorNumber]) {
|
|
247
281
|
basicMessage =
|
|
248
|
-
|
|
282
|
+
APIConstants.scorm12.error_descriptions[errorNumber].basicMessage;
|
|
249
283
|
detailMessage =
|
|
250
|
-
|
|
284
|
+
APIConstants.scorm12.error_descriptions[errorNumber].detailMessage;
|
|
251
285
|
}
|
|
252
286
|
|
|
253
287
|
return detail ? detailMessage : basicMessage;
|
|
@@ -294,16 +328,75 @@ export default class Scorm12API extends BaseAPI {
|
|
|
294
328
|
}
|
|
295
329
|
}
|
|
296
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Render the cmi object to the proper format for LMS commit
|
|
333
|
+
* @param {boolean} terminateCommit
|
|
334
|
+
* @return {CommitObject}
|
|
335
|
+
*/
|
|
336
|
+
renderCommitObject(terminateCommit: boolean): CommitObject {
|
|
337
|
+
const cmiExport = this.renderCommitCMI(terminateCommit);
|
|
338
|
+
const totalTimeHHMMSS = this.cmi.getCurrentTotalTime();
|
|
339
|
+
const totalTimeSeconds = Utilities.getTimeAsSeconds(
|
|
340
|
+
totalTimeHHMMSS,
|
|
341
|
+
Regex.scorm12.CMITimespan,
|
|
342
|
+
);
|
|
343
|
+
const lessonStatus = this.cmi.core.lesson_status;
|
|
344
|
+
let completionStatus = CompletionStatus.unknown;
|
|
345
|
+
let successStatus = SuccessStatus.unknown;
|
|
346
|
+
if (lessonStatus) {
|
|
347
|
+
completionStatus =
|
|
348
|
+
lessonStatus === "completed" || lessonStatus === "passed"
|
|
349
|
+
? CompletionStatus.completed
|
|
350
|
+
: CompletionStatus.incomplete;
|
|
351
|
+
if (lessonStatus === "passed") {
|
|
352
|
+
successStatus = SuccessStatus.passed;
|
|
353
|
+
} else if (lessonStatus === "failed") {
|
|
354
|
+
successStatus = SuccessStatus.failed;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const score = this.cmi.core.score;
|
|
359
|
+
let scoreObject: ScoreObject = null;
|
|
360
|
+
if (score) {
|
|
361
|
+
scoreObject = {};
|
|
362
|
+
|
|
363
|
+
if (!Number.isNaN(Number.parseFloat(score.raw))) {
|
|
364
|
+
scoreObject.raw = Number.parseFloat(score.raw);
|
|
365
|
+
}
|
|
366
|
+
if (!Number.isNaN(Number.parseFloat(score.min))) {
|
|
367
|
+
scoreObject.min = Number.parseFloat(score.min);
|
|
368
|
+
}
|
|
369
|
+
if (!Number.isNaN(Number.parseFloat(score.max))) {
|
|
370
|
+
scoreObject.max = Number.parseFloat(score.max);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const commitObject: CommitObject = {
|
|
375
|
+
successStatus: successStatus,
|
|
376
|
+
completionStatus: completionStatus,
|
|
377
|
+
runtimeData: cmiExport,
|
|
378
|
+
totalTimeSeconds: totalTimeSeconds,
|
|
379
|
+
};
|
|
380
|
+
if (scoreObject) {
|
|
381
|
+
commitObject.score = scoreObject;
|
|
382
|
+
}
|
|
383
|
+
return commitObject;
|
|
384
|
+
}
|
|
385
|
+
|
|
297
386
|
/**
|
|
298
387
|
* Attempts to store the data to the LMS
|
|
299
388
|
*
|
|
300
389
|
* @param {boolean} terminateCommit
|
|
301
390
|
* @return {ResultObject}
|
|
302
391
|
*/
|
|
303
|
-
storeData(terminateCommit: boolean): ResultObject {
|
|
392
|
+
async storeData(terminateCommit: boolean): Promise<ResultObject> {
|
|
304
393
|
if (terminateCommit) {
|
|
305
394
|
const originalStatus = this.cmi.core.lesson_status;
|
|
306
|
-
if (
|
|
395
|
+
if (
|
|
396
|
+
!this.cmi.core.lesson_status ||
|
|
397
|
+
(!this.statusSetByModule &&
|
|
398
|
+
this.cmi.core.lesson_status === "not attempted")
|
|
399
|
+
) {
|
|
307
400
|
this.cmi.core.lesson_status = "completed";
|
|
308
401
|
}
|
|
309
402
|
|
|
@@ -314,14 +407,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
314
407
|
this.cmi.student_data.mastery_score !== "" &&
|
|
315
408
|
this.cmi.core.score.raw !== ""
|
|
316
409
|
) {
|
|
317
|
-
|
|
410
|
+
this.cmi.core.lesson_status =
|
|
318
411
|
parseFloat(this.cmi.core.score.raw) >=
|
|
319
412
|
parseFloat(this.cmi.student_data.mastery_score)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
} else {
|
|
323
|
-
this.cmi.core.lesson_status = "failed";
|
|
324
|
-
}
|
|
413
|
+
? "passed"
|
|
414
|
+
: "failed";
|
|
325
415
|
}
|
|
326
416
|
}
|
|
327
417
|
} else if (this.cmi.core.lesson_mode === "browse") {
|
|
@@ -334,25 +424,27 @@ export default class Scorm12API extends BaseAPI {
|
|
|
334
424
|
}
|
|
335
425
|
}
|
|
336
426
|
|
|
337
|
-
const
|
|
338
|
-
terminateCommit || this.settings.alwaysSendTotalTime
|
|
339
|
-
|
|
427
|
+
const shouldTerminateCommit =
|
|
428
|
+
terminateCommit || this.settings.alwaysSendTotalTime;
|
|
429
|
+
const commitObject = this.settings.renderCommonCommitFields
|
|
430
|
+
? this.renderCommitObject(shouldTerminateCommit)
|
|
431
|
+
: this.renderCommitCMI(shouldTerminateCommit);
|
|
340
432
|
|
|
341
|
-
if (this.apiLogLevel ===
|
|
433
|
+
if (this.apiLogLevel === APIConstants.global.LOG_LEVEL_DEBUG) {
|
|
342
434
|
console.debug(
|
|
343
435
|
"Commit (terminated: " + (terminateCommit ? "yes" : "no") + "): ",
|
|
344
436
|
);
|
|
345
437
|
console.debug(commitObject);
|
|
346
438
|
}
|
|
347
439
|
if (typeof this.settings.lmsCommitUrl === "string") {
|
|
348
|
-
return this.processHttpRequest(
|
|
440
|
+
return await this.processHttpRequest(
|
|
349
441
|
this.settings.lmsCommitUrl,
|
|
350
442
|
commitObject,
|
|
351
443
|
terminateCommit,
|
|
352
444
|
);
|
|
353
445
|
} else {
|
|
354
446
|
return {
|
|
355
|
-
result:
|
|
447
|
+
result: APIConstants.global.SCORM_TRUE,
|
|
356
448
|
errorCode: 0,
|
|
357
449
|
};
|
|
358
450
|
}
|