scorm-again 2.0.0 → 2.1.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 +171 -72
- package/dist/aicc.js +1441 -1140
- 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 +2703 -2212
- 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 +1069 -852
- 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 +1861 -1571
- 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 +10 -6
- package/src/AICC.ts +15 -17
- package/src/BaseAPI.ts +268 -417
- package/src/Scorm12API.ts +65 -38
- package/src/Scorm2004API.ts +151 -117
- 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 +81 -0
- package/src/constants/enums.ts +5 -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 +32 -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 +262 -9
- package/test/Scorm2004API.spec.ts +488 -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,19 @@
|
|
|
1
|
-
import BaseAPI
|
|
1
|
+
import BaseAPI from "./BaseAPI";
|
|
2
|
+
import { CMI } from "./cmi/scorm12/cmi";
|
|
3
|
+
import * as Utilities from "./utilities";
|
|
4
|
+
import APIConstants from "./constants/api_constants";
|
|
5
|
+
import ErrorCodes from "./constants/error_codes";
|
|
6
|
+
|
|
7
|
+
import { BaseCMI } from "./cmi/common/base_cmi";
|
|
8
|
+
import { CMIObjectivesObject } from "./cmi/scorm12/objectives";
|
|
2
9
|
import {
|
|
3
|
-
CMI,
|
|
4
10
|
CMIInteractionsCorrectResponsesObject,
|
|
5
11
|
CMIInteractionsObject,
|
|
6
12
|
CMIInteractionsObjectivesObject,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./
|
|
10
|
-
import
|
|
11
|
-
import APIConstants from "./constants/api_constants";
|
|
12
|
-
import ErrorCodes, { ErrorCode } from "./constants/error_codes";
|
|
13
|
-
import { BaseCMI } from "./cmi/common";
|
|
14
|
-
|
|
15
|
-
const scorm12_constants = APIConstants.scorm12;
|
|
16
|
-
const global_constants = APIConstants.global;
|
|
17
|
-
const scorm12_error_codes: ErrorCode = ErrorCodes.scorm12;
|
|
13
|
+
} from "./cmi/scorm12/interactions";
|
|
14
|
+
import { NAV } from "./cmi/scorm12/nav";
|
|
15
|
+
import { RefObject, ResultObject, Settings } from "./types/api_types";
|
|
16
|
+
import { stringMatches } from "./utilities";
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
19
|
* API class for SCORM 1.2
|
|
@@ -31,7 +30,7 @@ export default class Scorm12API extends BaseAPI {
|
|
|
31
30
|
}
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
super(
|
|
33
|
+
super(ErrorCodes.scorm12, settings);
|
|
35
34
|
|
|
36
35
|
this.cmi = new CMI();
|
|
37
36
|
this.nav = new NAV();
|
|
@@ -47,6 +46,8 @@ export default class Scorm12API extends BaseAPI {
|
|
|
47
46
|
this.LMSGetDiagnostic = this.lmsGetDiagnostic;
|
|
48
47
|
}
|
|
49
48
|
|
|
49
|
+
public statusSetByModule = false;
|
|
50
|
+
|
|
50
51
|
public cmi: CMI;
|
|
51
52
|
public nav: NAV;
|
|
52
53
|
|
|
@@ -59,6 +60,16 @@ export default class Scorm12API extends BaseAPI {
|
|
|
59
60
|
public LMSGetErrorString: (CMIErrorCode: string) => string;
|
|
60
61
|
public LMSGetDiagnostic: (CMIErrorCode: string) => string;
|
|
61
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Called when the API needs to be reset
|
|
65
|
+
*/
|
|
66
|
+
reset(settings?: Settings) {
|
|
67
|
+
this.commonReset(settings);
|
|
68
|
+
|
|
69
|
+
this.cmi = new CMI();
|
|
70
|
+
this.nav = new NAV();
|
|
71
|
+
}
|
|
72
|
+
|
|
62
73
|
/**
|
|
63
74
|
* lmsInitialize function from SCORM 1.2 Spec
|
|
64
75
|
*
|
|
@@ -66,6 +77,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
66
77
|
*/
|
|
67
78
|
lmsInitialize(): string {
|
|
68
79
|
this.cmi.initialize();
|
|
80
|
+
if (this.cmi.core.lesson_status) {
|
|
81
|
+
this.statusSetByModule = true;
|
|
82
|
+
} else {
|
|
83
|
+
this.cmi.core.lesson_status = "not attempted";
|
|
84
|
+
}
|
|
69
85
|
return this.initialize(
|
|
70
86
|
"LMSInitialize",
|
|
71
87
|
"LMS was already initialized!",
|
|
@@ -79,9 +95,16 @@ export default class Scorm12API extends BaseAPI {
|
|
|
79
95
|
* @return {string} bool
|
|
80
96
|
*/
|
|
81
97
|
lmsFinish(): string {
|
|
82
|
-
|
|
98
|
+
(async () => {
|
|
99
|
+
await this.internalFinish();
|
|
100
|
+
})();
|
|
101
|
+
return APIConstants.global.SCORM_TRUE;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async internalFinish(): Promise<string> {
|
|
105
|
+
const result = await this.terminate("LMSFinish", true);
|
|
83
106
|
|
|
84
|
-
if (result ===
|
|
107
|
+
if (result === APIConstants.global.SCORM_TRUE) {
|
|
85
108
|
if (this.nav.event !== "") {
|
|
86
109
|
if (this.nav.event === "continue") {
|
|
87
110
|
this.processListeners("SequenceNext");
|
|
@@ -114,6 +137,9 @@ export default class Scorm12API extends BaseAPI {
|
|
|
114
137
|
* @return {string}
|
|
115
138
|
*/
|
|
116
139
|
lmsSetValue(CMIElement: string, value: any): string {
|
|
140
|
+
if (CMIElement === "cmi.core.lesson_status") {
|
|
141
|
+
this.statusSetByModule = true;
|
|
142
|
+
}
|
|
117
143
|
return this.setValue("LMSSetValue", "LMSCommit", false, CMIElement, value);
|
|
118
144
|
}
|
|
119
145
|
|
|
@@ -123,7 +149,10 @@ export default class Scorm12API extends BaseAPI {
|
|
|
123
149
|
* @return {string} bool
|
|
124
150
|
*/
|
|
125
151
|
lmsCommit(): string {
|
|
126
|
-
|
|
152
|
+
(async () => {
|
|
153
|
+
await this.commit("LMSCommit", false);
|
|
154
|
+
})();
|
|
155
|
+
return APIConstants.global.SCORM_TRUE;
|
|
127
156
|
}
|
|
128
157
|
|
|
129
158
|
/**
|
|
@@ -189,11 +218,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
189
218
|
_value: any,
|
|
190
219
|
foundFirstIndex: boolean,
|
|
191
220
|
): BaseCMI | null {
|
|
192
|
-
if (
|
|
221
|
+
if (stringMatches(CMIElement, "cmi\\.objectives\\.\\d+")) {
|
|
193
222
|
return new CMIObjectivesObject();
|
|
194
223
|
} else if (
|
|
195
224
|
foundFirstIndex &&
|
|
196
|
-
|
|
225
|
+
stringMatches(
|
|
197
226
|
CMIElement,
|
|
198
227
|
"cmi\\.interactions\\.\\d+\\.correct_responses\\.\\d+",
|
|
199
228
|
)
|
|
@@ -201,15 +230,12 @@ export default class Scorm12API extends BaseAPI {
|
|
|
201
230
|
return new CMIInteractionsCorrectResponsesObject();
|
|
202
231
|
} else if (
|
|
203
232
|
foundFirstIndex &&
|
|
204
|
-
|
|
205
|
-
CMIElement,
|
|
206
|
-
"cmi\\.interactions\\.\\d+\\.objectives\\.\\d+",
|
|
207
|
-
)
|
|
233
|
+
stringMatches(CMIElement, "cmi\\.interactions\\.\\d+\\.objectives\\.\\d+")
|
|
208
234
|
) {
|
|
209
235
|
return new CMIInteractionsObjectivesObject();
|
|
210
236
|
} else if (
|
|
211
237
|
!foundFirstIndex &&
|
|
212
|
-
|
|
238
|
+
stringMatches(CMIElement, "cmi\\.interactions\\.\\d+")
|
|
213
239
|
) {
|
|
214
240
|
return new CMIInteractionsObject();
|
|
215
241
|
}
|
|
@@ -243,11 +269,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
243
269
|
|
|
244
270
|
// Set error number to string since inconsistent from modules if string or number
|
|
245
271
|
errorNumber = String(errorNumber);
|
|
246
|
-
if (
|
|
272
|
+
if (APIConstants.scorm12.error_descriptions[errorNumber]) {
|
|
247
273
|
basicMessage =
|
|
248
|
-
|
|
274
|
+
APIConstants.scorm12.error_descriptions[errorNumber].basicMessage;
|
|
249
275
|
detailMessage =
|
|
250
|
-
|
|
276
|
+
APIConstants.scorm12.error_descriptions[errorNumber].detailMessage;
|
|
251
277
|
}
|
|
252
278
|
|
|
253
279
|
return detail ? detailMessage : basicMessage;
|
|
@@ -300,10 +326,14 @@ export default class Scorm12API extends BaseAPI {
|
|
|
300
326
|
* @param {boolean} terminateCommit
|
|
301
327
|
* @return {ResultObject}
|
|
302
328
|
*/
|
|
303
|
-
storeData(terminateCommit: boolean): ResultObject {
|
|
329
|
+
async storeData(terminateCommit: boolean): Promise<ResultObject> {
|
|
304
330
|
if (terminateCommit) {
|
|
305
331
|
const originalStatus = this.cmi.core.lesson_status;
|
|
306
|
-
if (
|
|
332
|
+
if (
|
|
333
|
+
!this.cmi.core.lesson_status ||
|
|
334
|
+
(!this.statusSetByModule &&
|
|
335
|
+
this.cmi.core.lesson_status === "not attempted")
|
|
336
|
+
) {
|
|
307
337
|
this.cmi.core.lesson_status = "completed";
|
|
308
338
|
}
|
|
309
339
|
|
|
@@ -314,14 +344,11 @@ export default class Scorm12API extends BaseAPI {
|
|
|
314
344
|
this.cmi.student_data.mastery_score !== "" &&
|
|
315
345
|
this.cmi.core.score.raw !== ""
|
|
316
346
|
) {
|
|
317
|
-
|
|
347
|
+
this.cmi.core.lesson_status =
|
|
318
348
|
parseFloat(this.cmi.core.score.raw) >=
|
|
319
349
|
parseFloat(this.cmi.student_data.mastery_score)
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
} else {
|
|
323
|
-
this.cmi.core.lesson_status = "failed";
|
|
324
|
-
}
|
|
350
|
+
? "passed"
|
|
351
|
+
: "failed";
|
|
325
352
|
}
|
|
326
353
|
}
|
|
327
354
|
} else if (this.cmi.core.lesson_mode === "browse") {
|
|
@@ -338,21 +365,21 @@ export default class Scorm12API extends BaseAPI {
|
|
|
338
365
|
terminateCommit || this.settings.alwaysSendTotalTime,
|
|
339
366
|
);
|
|
340
367
|
|
|
341
|
-
if (this.apiLogLevel ===
|
|
368
|
+
if (this.apiLogLevel === APIConstants.global.LOG_LEVEL_DEBUG) {
|
|
342
369
|
console.debug(
|
|
343
370
|
"Commit (terminated: " + (terminateCommit ? "yes" : "no") + "): ",
|
|
344
371
|
);
|
|
345
372
|
console.debug(commitObject);
|
|
346
373
|
}
|
|
347
374
|
if (typeof this.settings.lmsCommitUrl === "string") {
|
|
348
|
-
return this.processHttpRequest(
|
|
375
|
+
return await this.processHttpRequest(
|
|
349
376
|
this.settings.lmsCommitUrl,
|
|
350
377
|
commitObject,
|
|
351
378
|
terminateCommit,
|
|
352
379
|
);
|
|
353
380
|
} else {
|
|
354
381
|
return {
|
|
355
|
-
result:
|
|
382
|
+
result: APIConstants.global.SCORM_TRUE,
|
|
356
383
|
errorCode: 0,
|
|
357
384
|
};
|
|
358
385
|
}
|
package/src/Scorm2004API.ts
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
|
-
import BaseAPI
|
|
2
|
-
import {
|
|
3
|
-
ADL,
|
|
4
|
-
CMI,
|
|
5
|
-
CMICommentsObject,
|
|
6
|
-
CMIInteractionsCorrectResponsesObject,
|
|
7
|
-
CMIInteractionsObject,
|
|
8
|
-
CMIInteractionsObjectivesObject,
|
|
9
|
-
CMIObjectivesObject,
|
|
10
|
-
} from "./cmi/scorm2004_cmi";
|
|
1
|
+
import BaseAPI from "./BaseAPI";
|
|
2
|
+
import { CMI } from "./cmi/scorm2004/cmi";
|
|
11
3
|
import * as Utilities from "./utilities";
|
|
4
|
+
import { stringMatches } from "./utilities";
|
|
12
5
|
import APIConstants from "./constants/api_constants";
|
|
13
6
|
import ErrorCodes from "./constants/error_codes";
|
|
14
7
|
import { CorrectResponses, ResponseType } from "./constants/response_constants";
|
|
15
8
|
import ValidLanguages from "./constants/language_constants";
|
|
16
9
|
import Regex from "./constants/regex";
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
import regex from "./constants/regex";
|
|
11
|
+
import { CMIArray } from "./cmi/common/array";
|
|
12
|
+
import { BaseCMI } from "./cmi/common/base_cmi";
|
|
13
|
+
import {
|
|
14
|
+
CMIInteractionsCorrectResponsesObject,
|
|
15
|
+
CMIInteractionsObject,
|
|
16
|
+
CMIInteractionsObjectivesObject,
|
|
17
|
+
} from "./cmi/scorm2004/interactions";
|
|
18
|
+
import { CMICommentsObject } from "./cmi/scorm2004/comments";
|
|
19
|
+
import { CMIObjectivesObject } from "./cmi/scorm2004/objectives";
|
|
20
|
+
import { ADL } from "./cmi/scorm2004/adl";
|
|
21
|
+
import { RefObject, ResultObject, Settings } from "./types/api_types";
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* API class for SCORM 2004
|
|
@@ -39,7 +37,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
39
37
|
}
|
|
40
38
|
}
|
|
41
39
|
|
|
42
|
-
super(
|
|
40
|
+
super(ErrorCodes.scorm2004, settings);
|
|
43
41
|
|
|
44
42
|
this.cmi = new CMI();
|
|
45
43
|
this.adl = new ADL();
|
|
@@ -67,6 +65,16 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
67
65
|
public GetErrorString: (CMIErrorCode: string | number) => string;
|
|
68
66
|
public GetDiagnostic: (CMIErrorCode: string | number) => string;
|
|
69
67
|
|
|
68
|
+
/**
|
|
69
|
+
* Called when the API needs to be reset
|
|
70
|
+
*/
|
|
71
|
+
reset(settings?: Settings) {
|
|
72
|
+
this.commonReset(settings);
|
|
73
|
+
|
|
74
|
+
this.cmi = new CMI();
|
|
75
|
+
this.adl = new ADL();
|
|
76
|
+
}
|
|
77
|
+
|
|
70
78
|
/**
|
|
71
79
|
* Getter for _version
|
|
72
80
|
* @return {string}
|
|
@@ -87,32 +95,39 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
87
95
|
* @return {string} bool
|
|
88
96
|
*/
|
|
89
97
|
lmsFinish(): string {
|
|
90
|
-
|
|
98
|
+
(async () => {
|
|
99
|
+
await this.internalFinish();
|
|
100
|
+
})();
|
|
101
|
+
return APIConstants.global.SCORM_TRUE;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async internalFinish(): Promise<string> {
|
|
105
|
+
const result = await this.terminate("Terminate", true);
|
|
91
106
|
|
|
92
|
-
if (result ===
|
|
107
|
+
if (result === APIConstants.global.SCORM_TRUE) {
|
|
93
108
|
if (this.adl.nav.request !== "_none_") {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
const navActions: { [key: string]: string } = {
|
|
110
|
+
continue: "SequenceNext",
|
|
111
|
+
previous: "SequencePrevious",
|
|
112
|
+
choice: "SequenceChoice",
|
|
113
|
+
jump: "SequenceJump",
|
|
114
|
+
exit: "SequenceExit",
|
|
115
|
+
exitAll: "SequenceExitAll",
|
|
116
|
+
abandon: "SequenceAbandon",
|
|
117
|
+
abandonAll: "SequenceAbandonAll",
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
let request = this.adl.nav.request;
|
|
121
|
+
const choiceJumpRegex = new RegExp(regex.scorm2004.NAVEvent);
|
|
122
|
+
const matches = request.match(choiceJumpRegex);
|
|
123
|
+
let target = "";
|
|
124
|
+
if (matches && matches.length > 2) {
|
|
125
|
+
target = matches[2];
|
|
126
|
+
request = matches[1].replace(target, "");
|
|
127
|
+
}
|
|
128
|
+
const action = navActions[request];
|
|
129
|
+
if (action) {
|
|
130
|
+
this.processListeners(action, "adl.nav.request", target);
|
|
116
131
|
}
|
|
117
132
|
} else if (this.settings.autoProgress) {
|
|
118
133
|
this.processListeners("SequenceNext");
|
|
@@ -127,6 +142,19 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
127
142
|
* @return {string}
|
|
128
143
|
*/
|
|
129
144
|
lmsGetValue(CMIElement: string): string {
|
|
145
|
+
const adlNavRequestRegex =
|
|
146
|
+
"^adl\\.nav\\.request_valid\\.(choice|jump)\\.{target=\\S{0,}([a-zA-Z0-9-_]+)}$";
|
|
147
|
+
if (stringMatches(CMIElement, adlNavRequestRegex)) {
|
|
148
|
+
const matches = CMIElement.match(adlNavRequestRegex);
|
|
149
|
+
const request = matches[1];
|
|
150
|
+
const target = matches[2].replace("{target=", "").replace("}", "");
|
|
151
|
+
if (request === "choice" || request === "jump") {
|
|
152
|
+
if (this.settings.scoItemIdValidator) {
|
|
153
|
+
return String(this.settings.scoItemIdValidator(target));
|
|
154
|
+
}
|
|
155
|
+
return String(this.settings.scoItemIds.includes(target));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
130
158
|
return this.getValue("GetValue", true, CMIElement);
|
|
131
159
|
}
|
|
132
160
|
|
|
@@ -145,7 +173,10 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
145
173
|
* @return {string} bool
|
|
146
174
|
*/
|
|
147
175
|
lmsCommit(): string {
|
|
148
|
-
|
|
176
|
+
(async () => {
|
|
177
|
+
await this.commit("Commit");
|
|
178
|
+
})();
|
|
179
|
+
return APIConstants.global.SCORM_TRUE;
|
|
149
180
|
}
|
|
150
181
|
|
|
151
182
|
/**
|
|
@@ -201,66 +232,71 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
201
232
|
value: any,
|
|
202
233
|
foundFirstIndex: boolean,
|
|
203
234
|
): BaseCMI | null {
|
|
204
|
-
if (
|
|
235
|
+
if (stringMatches(CMIElement, "cmi\\.objectives\\.\\d+")) {
|
|
205
236
|
return new CMIObjectivesObject();
|
|
206
|
-
}
|
|
207
|
-
foundFirstIndex &&
|
|
208
|
-
this.stringMatches(
|
|
209
|
-
CMIElement,
|
|
210
|
-
"cmi\\.interactions\\.\\d+\\.correct_responses\\.\\d+",
|
|
211
|
-
)
|
|
212
|
-
) {
|
|
213
|
-
const parts = CMIElement.split(".");
|
|
214
|
-
const index = Number(parts[2]);
|
|
215
|
-
const interaction = this.cmi.interactions.childArray[index];
|
|
216
|
-
if (this.isInitialized()) {
|
|
217
|
-
if (!interaction.type) {
|
|
218
|
-
this.throwSCORMError(
|
|
219
|
-
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED,
|
|
220
|
-
);
|
|
221
|
-
} else {
|
|
222
|
-
this.checkDuplicateChoiceResponse(interaction, value);
|
|
237
|
+
}
|
|
223
238
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
239
|
+
if (foundFirstIndex) {
|
|
240
|
+
if (
|
|
241
|
+
stringMatches(
|
|
242
|
+
CMIElement,
|
|
243
|
+
"cmi\\.interactions\\.\\d+\\.correct_responses\\.\\d+",
|
|
244
|
+
)
|
|
245
|
+
) {
|
|
246
|
+
return this.createCorrectResponsesObject(CMIElement, value);
|
|
247
|
+
} else if (
|
|
248
|
+
stringMatches(
|
|
249
|
+
CMIElement,
|
|
250
|
+
"cmi\\.interactions\\.\\d+\\.objectives\\.\\d+",
|
|
251
|
+
)
|
|
252
|
+
) {
|
|
253
|
+
return new CMIInteractionsObjectivesObject();
|
|
237
254
|
}
|
|
238
|
-
} else if (
|
|
239
|
-
foundFirstIndex &&
|
|
240
|
-
this.stringMatches(
|
|
241
|
-
CMIElement,
|
|
242
|
-
"cmi\\.interactions\\.\\d+\\.objectives\\.\\d+",
|
|
243
|
-
)
|
|
244
|
-
) {
|
|
245
|
-
return new CMIInteractionsObjectivesObject();
|
|
246
|
-
} else if (
|
|
247
|
-
!foundFirstIndex &&
|
|
248
|
-
this.stringMatches(CMIElement, "cmi\\.interactions\\.\\d+")
|
|
249
|
-
) {
|
|
255
|
+
} else if (stringMatches(CMIElement, "cmi\\.interactions\\.\\d+")) {
|
|
250
256
|
return new CMIInteractionsObject();
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
) {
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (stringMatches(CMIElement, "cmi\\.comments_from_learner\\.\\d+")) {
|
|
254
260
|
return new CMICommentsObject();
|
|
255
|
-
} else if (
|
|
256
|
-
this.stringMatches(CMIElement, "cmi\\.comments_from_lms\\.\\d+")
|
|
257
|
-
) {
|
|
261
|
+
} else if (stringMatches(CMIElement, "cmi\\.comments_from_lms\\.\\d+")) {
|
|
258
262
|
return new CMICommentsObject(true);
|
|
259
263
|
}
|
|
260
264
|
|
|
261
265
|
return null;
|
|
262
266
|
}
|
|
263
267
|
|
|
268
|
+
private createCorrectResponsesObject(
|
|
269
|
+
CMIElement: string,
|
|
270
|
+
value: any,
|
|
271
|
+
): BaseCMI | null {
|
|
272
|
+
const parts = CMIElement.split(".");
|
|
273
|
+
const index = Number(parts[2]);
|
|
274
|
+
const interaction = this.cmi.interactions.childArray[index];
|
|
275
|
+
|
|
276
|
+
if (this.isInitialized()) {
|
|
277
|
+
if (!interaction.type) {
|
|
278
|
+
this.throwSCORMError(ErrorCodes.scorm2004.DEPENDENCY_NOT_ESTABLISHED);
|
|
279
|
+
} else {
|
|
280
|
+
this.checkDuplicateChoiceResponse(interaction, value);
|
|
281
|
+
const response_type = CorrectResponses[interaction.type];
|
|
282
|
+
if (response_type) {
|
|
283
|
+
this.checkValidResponseType(response_type, value, interaction.type);
|
|
284
|
+
} else {
|
|
285
|
+
this.throwSCORMError(
|
|
286
|
+
ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
|
|
287
|
+
"Incorrect Response Type: " + interaction.type,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (this.lastErrorCode === "0") {
|
|
294
|
+
return new CMIInteractionsCorrectResponsesObject();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
|
|
264
300
|
/**
|
|
265
301
|
* Checks for valid response types
|
|
266
302
|
* @param {object} response_type
|
|
@@ -283,7 +319,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
283
319
|
this.checkCorrectResponseValue(interaction_type, nodes, value);
|
|
284
320
|
} else if (nodes.length > response_type.max) {
|
|
285
321
|
this.throwSCORMError(
|
|
286
|
-
|
|
322
|
+
ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
|
|
287
323
|
"Data Model Element Pattern Too Long",
|
|
288
324
|
);
|
|
289
325
|
}
|
|
@@ -304,7 +340,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
304
340
|
) {
|
|
305
341
|
const response = interaction.correct_responses.childArray[i];
|
|
306
342
|
if (response.pattern === value) {
|
|
307
|
-
this.throwSCORMError(
|
|
343
|
+
this.throwSCORMError(ErrorCodes.scorm2004.GENERAL_SET_FAILURE);
|
|
308
344
|
}
|
|
309
345
|
}
|
|
310
346
|
}
|
|
@@ -324,7 +360,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
324
360
|
const interaction_count = interaction.correct_responses._count;
|
|
325
361
|
this.checkDuplicateChoiceResponse(interaction, value);
|
|
326
362
|
|
|
327
|
-
const response_type =
|
|
363
|
+
const response_type = CorrectResponses[interaction.type];
|
|
328
364
|
if (
|
|
329
365
|
typeof response_type.limit === "undefined" ||
|
|
330
366
|
interaction_count <= response_type.limit
|
|
@@ -345,14 +381,14 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
345
381
|
} else {
|
|
346
382
|
if (this.lastErrorCode === "0") {
|
|
347
383
|
this.throwSCORMError(
|
|
348
|
-
|
|
384
|
+
ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
|
|
349
385
|
"Data Model Element Pattern Already Exists",
|
|
350
386
|
);
|
|
351
387
|
}
|
|
352
388
|
}
|
|
353
389
|
} else {
|
|
354
390
|
this.throwSCORMError(
|
|
355
|
-
|
|
391
|
+
ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
|
|
356
392
|
"Data Model Element Collection Limit Reached",
|
|
357
393
|
);
|
|
358
394
|
}
|
|
@@ -384,11 +420,11 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
384
420
|
|
|
385
421
|
// Set error number to string since inconsistent from modules if string or number
|
|
386
422
|
errorNumber = String(errorNumber);
|
|
387
|
-
if (
|
|
423
|
+
if (APIConstants.scorm2004.error_descriptions[errorNumber]) {
|
|
388
424
|
basicMessage =
|
|
389
|
-
|
|
425
|
+
APIConstants.scorm2004.error_descriptions[errorNumber].basicMessage;
|
|
390
426
|
detailMessage =
|
|
391
|
-
|
|
427
|
+
APIConstants.scorm2004.error_descriptions[errorNumber].detailMessage;
|
|
392
428
|
}
|
|
393
429
|
|
|
394
430
|
return detail ? detailMessage : basicMessage;
|
|
@@ -427,7 +463,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
427
463
|
nodes: Array<any>,
|
|
428
464
|
value: any,
|
|
429
465
|
) {
|
|
430
|
-
const response =
|
|
466
|
+
const response = CorrectResponses[interaction_type];
|
|
431
467
|
const formatRegex = new RegExp(response.format);
|
|
432
468
|
for (let i = 0; i < nodes.length && this.lastErrorCode === "0"; i++) {
|
|
433
469
|
if (
|
|
@@ -443,17 +479,17 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
443
479
|
if (values.length === 2) {
|
|
444
480
|
const matches = values[0].match(formatRegex);
|
|
445
481
|
if (!matches) {
|
|
446
|
-
this.throwSCORMError(
|
|
482
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
447
483
|
} else {
|
|
448
484
|
if (
|
|
449
485
|
!response.format2 ||
|
|
450
486
|
!values[1].match(new RegExp(response.format2))
|
|
451
487
|
) {
|
|
452
|
-
this.throwSCORMError(
|
|
488
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
453
489
|
}
|
|
454
490
|
}
|
|
455
491
|
} else {
|
|
456
|
-
this.throwSCORMError(
|
|
492
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
457
493
|
}
|
|
458
494
|
} else {
|
|
459
495
|
const matches = nodes[i].match(formatRegex);
|
|
@@ -461,17 +497,17 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
461
497
|
(!matches && value !== "") ||
|
|
462
498
|
(!matches && interaction_type === "true-false")
|
|
463
499
|
) {
|
|
464
|
-
this.throwSCORMError(
|
|
500
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
465
501
|
} else {
|
|
466
502
|
if (interaction_type === "numeric" && nodes.length > 1) {
|
|
467
503
|
if (Number(nodes[0]) > Number(nodes[1])) {
|
|
468
|
-
this.throwSCORMError(
|
|
504
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
469
505
|
}
|
|
470
506
|
} else {
|
|
471
507
|
if (nodes[i] !== "" && response.unique) {
|
|
472
508
|
for (let j = 0; j < i && this.lastErrorCode === "0"; j++) {
|
|
473
509
|
if (nodes[i] === nodes[j]) {
|
|
474
|
-
this.throwSCORMError(
|
|
510
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
475
511
|
}
|
|
476
512
|
}
|
|
477
513
|
}
|
|
@@ -499,12 +535,12 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
499
535
|
while (matches) {
|
|
500
536
|
switch (matches[2]) {
|
|
501
537
|
case "lang":
|
|
502
|
-
langMatches = node.match(
|
|
538
|
+
langMatches = node.match(Regex.scorm2004.CMILangcr);
|
|
503
539
|
if (langMatches) {
|
|
504
540
|
const lang = langMatches[3];
|
|
505
541
|
if (lang !== undefined && lang.length > 0) {
|
|
506
542
|
if (!ValidLanguages.includes(lang.toLowerCase())) {
|
|
507
|
-
this.throwSCORMError(
|
|
543
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
508
544
|
}
|
|
509
545
|
}
|
|
510
546
|
}
|
|
@@ -513,7 +549,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
513
549
|
case "case_matters":
|
|
514
550
|
if (!seenLang && !seenOrder && !seenCase) {
|
|
515
551
|
if (matches[3] !== "true" && matches[3] !== "false") {
|
|
516
|
-
this.throwSCORMError(
|
|
552
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
517
553
|
}
|
|
518
554
|
}
|
|
519
555
|
|
|
@@ -522,14 +558,12 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
522
558
|
case "order_matters":
|
|
523
559
|
if (!seenCase && !seenLang && !seenOrder) {
|
|
524
560
|
if (matches[3] !== "true" && matches[3] !== "false") {
|
|
525
|
-
this.throwSCORMError(
|
|
561
|
+
this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
|
|
526
562
|
}
|
|
527
563
|
}
|
|
528
564
|
|
|
529
565
|
seenOrder = true;
|
|
530
566
|
break;
|
|
531
|
-
default:
|
|
532
|
-
break;
|
|
533
567
|
}
|
|
534
568
|
node = node.substring(matches[1].length);
|
|
535
569
|
matches = node.match(prefixRegex);
|
|
@@ -585,7 +619,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
585
619
|
* @param {boolean} terminateCommit
|
|
586
620
|
* @return {ResultObject}
|
|
587
621
|
*/
|
|
588
|
-
storeData(terminateCommit: boolean): ResultObject {
|
|
622
|
+
async storeData(terminateCommit: boolean): Promise<ResultObject> {
|
|
589
623
|
if (terminateCommit) {
|
|
590
624
|
if (this.cmi.mode === "normal") {
|
|
591
625
|
if (this.cmi.credit === "credit") {
|
|
@@ -620,14 +654,14 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
620
654
|
terminateCommit || this.settings.alwaysSendTotalTime,
|
|
621
655
|
);
|
|
622
656
|
|
|
623
|
-
if (this.apiLogLevel ===
|
|
657
|
+
if (this.apiLogLevel === APIConstants.global.LOG_LEVEL_DEBUG) {
|
|
624
658
|
console.debug(
|
|
625
659
|
"Commit (terminated: " + (terminateCommit ? "yes" : "no") + "): ",
|
|
626
660
|
);
|
|
627
661
|
console.debug(commitObject);
|
|
628
662
|
}
|
|
629
663
|
if (typeof this.settings.lmsCommitUrl === "string") {
|
|
630
|
-
const result = this.processHttpRequest(
|
|
664
|
+
const result = await this.processHttpRequest(
|
|
631
665
|
this.settings.lmsCommitUrl,
|
|
632
666
|
commitObject,
|
|
633
667
|
terminateCommit,
|
|
@@ -646,7 +680,7 @@ export default class Scorm2004API extends BaseAPI {
|
|
|
646
680
|
return result;
|
|
647
681
|
} else {
|
|
648
682
|
return {
|
|
649
|
-
result:
|
|
683
|
+
result: APIConstants.global.SCORM_TRUE,
|
|
650
684
|
errorCode: 0,
|
|
651
685
|
};
|
|
652
686
|
}
|