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.
Files changed (77) hide show
  1. package/.github/workflows/stale.yml +14 -0
  2. package/.run/{Mocha Unit Tests.run.xml → Mocha Unit Tests (watch).run.xml } +1 -1
  3. package/.run/Template Mocha.run.xml +17 -0
  4. package/README.md +171 -72
  5. package/dist/aicc.js +1441 -1140
  6. package/dist/aicc.js.map +1 -1
  7. package/dist/aicc.min.js +1 -1
  8. package/dist/aicc.min.js.map +1 -1
  9. package/dist/scorm-again.js +2703 -2212
  10. package/dist/scorm-again.js.map +1 -1
  11. package/dist/scorm-again.min.js +1 -1
  12. package/dist/scorm-again.min.js.map +1 -1
  13. package/dist/scorm12.js +1069 -852
  14. package/dist/scorm12.js.map +1 -1
  15. package/dist/scorm12.min.js +1 -1
  16. package/dist/scorm12.min.js.map +1 -1
  17. package/dist/scorm2004.js +1861 -1571
  18. package/dist/scorm2004.js.map +1 -1
  19. package/dist/scorm2004.min.js +1 -1
  20. package/dist/scorm2004.min.js.map +1 -1
  21. package/package.json +10 -6
  22. package/src/AICC.ts +15 -17
  23. package/src/BaseAPI.ts +268 -417
  24. package/src/Scorm12API.ts +65 -38
  25. package/src/Scorm2004API.ts +151 -117
  26. package/src/cmi/aicc/attempts.ts +94 -0
  27. package/src/cmi/aicc/cmi.ts +100 -0
  28. package/src/cmi/aicc/core.ts +360 -0
  29. package/src/cmi/aicc/evaluation.ts +157 -0
  30. package/src/cmi/aicc/paths.ts +180 -0
  31. package/src/cmi/aicc/student_data.ts +86 -0
  32. package/src/cmi/aicc/student_demographics.ts +367 -0
  33. package/src/cmi/aicc/student_preferences.ts +176 -0
  34. package/src/cmi/aicc/tries.ts +116 -0
  35. package/src/cmi/aicc/validation.ts +25 -0
  36. package/src/cmi/common/array.ts +77 -0
  37. package/src/cmi/common/base_cmi.ts +46 -0
  38. package/src/cmi/common/score.ts +203 -0
  39. package/src/cmi/common/validation.ts +60 -0
  40. package/src/cmi/scorm12/cmi.ts +224 -0
  41. package/src/cmi/scorm12/interactions.ts +368 -0
  42. package/src/cmi/scorm12/nav.ts +54 -0
  43. package/src/cmi/scorm12/objectives.ts +112 -0
  44. package/src/cmi/scorm12/student_data.ts +130 -0
  45. package/src/cmi/scorm12/student_preference.ts +158 -0
  46. package/src/cmi/scorm12/validation.ts +48 -0
  47. package/src/cmi/scorm2004/adl.ts +272 -0
  48. package/src/cmi/scorm2004/cmi.ts +599 -0
  49. package/src/cmi/scorm2004/comments.ts +163 -0
  50. package/src/cmi/scorm2004/interactions.ts +466 -0
  51. package/src/cmi/scorm2004/learner_preference.ts +152 -0
  52. package/src/cmi/scorm2004/objectives.ts +212 -0
  53. package/src/cmi/scorm2004/score.ts +78 -0
  54. package/src/cmi/scorm2004/validation.ts +42 -0
  55. package/src/constants/default_settings.ts +81 -0
  56. package/src/constants/enums.ts +5 -0
  57. package/src/constants/regex.ts +2 -2
  58. package/src/constants/response_constants.ts +2 -0
  59. package/src/exceptions.ts +22 -1
  60. package/src/helpers/scheduled_commit.ts +42 -0
  61. package/src/interfaces/IBaseAPI.ts +35 -0
  62. package/src/types/api_types.ts +32 -0
  63. package/src/utilities/debounce.ts +31 -0
  64. package/src/utilities.ts +56 -0
  65. package/test/AICC.spec.ts +11 -1
  66. package/test/Scorm12API.spec.ts +262 -9
  67. package/test/Scorm2004API.spec.ts +488 -2
  68. package/test/cmi/aicc_cmi.spec.ts +188 -11
  69. package/test/cmi/scorm12_cmi.spec.ts +5 -5
  70. package/test/cmi/scorm2004_cmi.spec.ts +8 -8
  71. package/test/cmi_helpers.ts +1 -1
  72. package/test/types/api_types.spec.ts +126 -0
  73. package/test/utilities/debounce.spec.ts +56 -0
  74. package/src/cmi/aicc_cmi.ts +0 -1248
  75. package/src/cmi/common.ts +0 -411
  76. package/src/cmi/scorm12_cmi.ts +0 -1426
  77. package/src/cmi/scorm2004_cmi.ts +0 -1874
@@ -0,0 +1,224 @@
1
+ import APIConstants from "../../constants/api_constants";
2
+ import ErrorCodes from "../../constants/error_codes";
3
+ import Regex from "../../constants/regex";
4
+ import { Scorm12ValidationError } from "../../exceptions";
5
+ import { BaseRootCMI } from "../common/base_cmi";
6
+ import { check12ValidFormat } from "./validation";
7
+ import { CMICore } from "../aicc/core";
8
+ import { CMIObjectives } from "./objectives";
9
+ import { CMIStudentData } from "./student_data";
10
+ import { CMIStudentPreference } from "./student_preference";
11
+ import { CMIInteractions } from "./interactions";
12
+
13
+ /**
14
+ * Class representing the cmi object for SCORM 1.2
15
+ */
16
+ export class CMI extends BaseRootCMI {
17
+ private readonly __children: string = "";
18
+ private __version: string = "3.4";
19
+ private _launch_data: string = "";
20
+ private _comments: string = "";
21
+ private _comments_from_lms: string = "";
22
+
23
+ /**
24
+ * Constructor for the SCORM 1.2 cmi object
25
+ * @param {string} cmi_children
26
+ * @param {(CMIStudentData|AICCCMIStudentData)} student_data
27
+ * @param {boolean} initialized
28
+ */
29
+ constructor(
30
+ cmi_children?: string,
31
+ student_data?: CMIStudentData,
32
+ initialized?: boolean,
33
+ ) {
34
+ super();
35
+ if (initialized) this.initialize();
36
+ this.__children = cmi_children
37
+ ? cmi_children
38
+ : APIConstants.scorm12.cmi_children;
39
+ this.core = new CMICore();
40
+ this.objectives = new CMIObjectives();
41
+ this.student_data = student_data ? student_data : new CMIStudentData();
42
+ this.student_preference = new CMIStudentPreference();
43
+ this.interactions = new CMIInteractions();
44
+ }
45
+
46
+ public core: CMICore;
47
+ public objectives: CMIObjectives;
48
+ public student_data: CMIStudentData;
49
+ public student_preference: CMIStudentPreference;
50
+ public interactions: CMIInteractions;
51
+
52
+ /**
53
+ * Called when the API has been initialized after the CMI has been created
54
+ */
55
+ initialize() {
56
+ super.initialize();
57
+ this.core?.initialize();
58
+ this.objectives?.initialize();
59
+ this.student_data?.initialize();
60
+ this.student_preference?.initialize();
61
+ this.interactions?.initialize();
62
+ }
63
+
64
+ /**
65
+ * toJSON for cmi
66
+ *
67
+ * @return {
68
+ * {
69
+ * suspend_data: string,
70
+ * launch_data: string,
71
+ * comments: string,
72
+ * comments_from_lms: string,
73
+ * core: CMICore,
74
+ * objectives: CMIObjectives,
75
+ * student_data: CMIStudentData,
76
+ * student_preference: CMIStudentPreference,
77
+ * interactions: CMIInteractions
78
+ * }
79
+ * }
80
+ */
81
+ toJSON(): {
82
+ suspend_data: string;
83
+ launch_data: string;
84
+ comments: string;
85
+ comments_from_lms: string;
86
+ core: CMICore;
87
+ objectives: CMIObjectives;
88
+ student_data: CMIStudentData;
89
+ student_preference: CMIStudentPreference;
90
+ interactions: CMIInteractions;
91
+ } {
92
+ this.jsonString = true;
93
+ const result = {
94
+ suspend_data: this.suspend_data,
95
+ launch_data: this.launch_data,
96
+ comments: this.comments,
97
+ comments_from_lms: this.comments_from_lms,
98
+ core: this.core,
99
+ objectives: this.objectives,
100
+ student_data: this.student_data,
101
+ student_preference: this.student_preference,
102
+ interactions: this.interactions,
103
+ };
104
+ delete this.jsonString;
105
+ return result;
106
+ }
107
+
108
+ /**
109
+ * Getter for __version
110
+ * @return {string}
111
+ */
112
+ get _version(): string {
113
+ return this.__version;
114
+ }
115
+
116
+ /**
117
+ * Setter for __version. Just throws an error.
118
+ * @param {string} _version
119
+ */
120
+ set _version(_version: string) {
121
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.INVALID_SET_VALUE);
122
+ }
123
+
124
+ /**
125
+ * Getter for __children
126
+ * @return {string}
127
+ */
128
+ get _children(): string {
129
+ return this.__children;
130
+ }
131
+
132
+ /**
133
+ * Setter for __version. Just throws an error.
134
+ * @param {string} _children
135
+ */
136
+ set _children(_children: string) {
137
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.INVALID_SET_VALUE);
138
+ }
139
+
140
+ /**
141
+ * Getter for _suspend_data
142
+ * @return {string}
143
+ */
144
+ get suspend_data(): string {
145
+ return this.core?.suspend_data;
146
+ }
147
+
148
+ /**
149
+ * Setter for _suspend_data
150
+ * @param {string} suspend_data
151
+ */
152
+ set suspend_data(suspend_data: string) {
153
+ if (this.core) {
154
+ this.core.suspend_data = suspend_data;
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Getter for _launch_data
160
+ * @return {string}
161
+ */
162
+ get launch_data(): string {
163
+ return this._launch_data;
164
+ }
165
+
166
+ /**
167
+ * Setter for _launch_data. Can only be called before initialization.
168
+ * @param {string} launch_data
169
+ */
170
+ set launch_data(launch_data: string) {
171
+ if (this.initialized) {
172
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
173
+ } else {
174
+ this._launch_data = launch_data;
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Getter for _comments
180
+ * @return {string}
181
+ */
182
+ get comments(): string {
183
+ return this._comments;
184
+ }
185
+
186
+ /**
187
+ * Setter for _comments
188
+ * @param {string} comments
189
+ */
190
+ set comments(comments: string) {
191
+ if (check12ValidFormat(comments, Regex.scorm12.CMIString4096, true)) {
192
+ this._comments = comments;
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Getter for _comments_from_lms
198
+ * @return {string}
199
+ */
200
+ get comments_from_lms(): string {
201
+ return this._comments_from_lms;
202
+ }
203
+
204
+ /**
205
+ * Setter for _comments_from_lms. Can only be called before initialization.
206
+ * @param {string} comments_from_lms
207
+ */
208
+ set comments_from_lms(comments_from_lms: string) {
209
+ if (this.initialized) {
210
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
211
+ } else {
212
+ this._comments_from_lms = comments_from_lms;
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Adds the current session time to the existing total time.
218
+ *
219
+ * @return {string}
220
+ */
221
+ getCurrentTotalTime(): string {
222
+ return this.core.getCurrentTotalTime(this.start_time);
223
+ }
224
+ }
@@ -0,0 +1,368 @@
1
+ import { CMIArray } from "../common/array";
2
+ import APIConstants from "../../constants/api_constants";
3
+ import ErrorCodes from "../../constants/error_codes";
4
+ import { Scorm12ValidationError } from "../../exceptions";
5
+ import { BaseCMI } from "../common/base_cmi";
6
+ import { check12ValidFormat, check12ValidRange } from "./validation";
7
+ import Regex from "../../constants/regex";
8
+
9
+ /**
10
+ * Class representing the SCORM 1.2 `cmi.interactions`
11
+ * @extends CMIArray
12
+ */
13
+ export class CMIInteractions extends CMIArray {
14
+ /**
15
+ * Constructor for `cmi.interactions`
16
+ */
17
+ constructor() {
18
+ super({
19
+ children: APIConstants.scorm12.interactions_children,
20
+ errorCode: ErrorCodes.scorm12.INVALID_SET_VALUE,
21
+ errorClass: Scorm12ValidationError,
22
+ });
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Class representing SCORM 1.2's cmi.interactions.n object
28
+ * @extends BaseCMI
29
+ */
30
+ export class CMIInteractionsObject extends BaseCMI {
31
+ /**
32
+ * Constructor for cmi.interactions.n object
33
+ */
34
+ constructor() {
35
+ super();
36
+ this.objectives = new CMIArray({
37
+ errorCode: ErrorCodes.scorm12.INVALID_SET_VALUE,
38
+ errorClass: Scorm12ValidationError,
39
+ children: APIConstants.scorm12.objectives_children,
40
+ });
41
+ this.correct_responses = new CMIArray({
42
+ errorCode: ErrorCodes.scorm12.INVALID_SET_VALUE,
43
+ errorClass: Scorm12ValidationError,
44
+ children: APIConstants.scorm12.correct_responses_children,
45
+ });
46
+ }
47
+
48
+ public readonly objectives: CMIArray;
49
+ public readonly correct_responses: CMIArray;
50
+
51
+ /**
52
+ * Called when the API has been initialized after the CMI has been created
53
+ */
54
+ initialize() {
55
+ super.initialize();
56
+ this.objectives?.initialize();
57
+ this.correct_responses?.initialize();
58
+ }
59
+
60
+ private _id = "";
61
+ private _time = "";
62
+ private _type = "";
63
+ private _weighting = "";
64
+ private _student_response = "";
65
+ private _result = "";
66
+ private _latency = "";
67
+
68
+ /**
69
+ * Getter for _id. Should only be called during JSON export.
70
+ * @return {string}
71
+ */
72
+ get id(): string {
73
+ if (!this.jsonString) {
74
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
75
+ }
76
+ return this._id;
77
+ }
78
+
79
+ /**
80
+ * Setter for _id
81
+ * @param {string} id
82
+ */
83
+ set id(id: string) {
84
+ if (check12ValidFormat(id, Regex.scorm12.CMIIdentifier)) {
85
+ this._id = id;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Getter for _time. Should only be called during JSON export.
91
+ * @return {string}
92
+ */
93
+ get time(): string {
94
+ if (!this.jsonString) {
95
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
96
+ }
97
+ return this._time;
98
+ }
99
+
100
+ /**
101
+ * Setter for _time
102
+ * @param {string} time
103
+ */
104
+ set time(time: string) {
105
+ if (check12ValidFormat(time, Regex.scorm12.CMITime)) {
106
+ this._time = time;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Getter for _type. Should only be called during JSON export.
112
+ * @return {string}
113
+ */
114
+ get type(): string {
115
+ if (!this.jsonString) {
116
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
117
+ }
118
+ return this._type;
119
+ }
120
+
121
+ /**
122
+ * Setter for _type
123
+ * @param {string} type
124
+ */
125
+ set type(type: string) {
126
+ if (check12ValidFormat(type, Regex.scorm12.CMIType)) {
127
+ this._type = type;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Getter for _weighting. Should only be called during JSON export.
133
+ * @return {string}
134
+ */
135
+ get weighting(): string {
136
+ if (!this.jsonString) {
137
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
138
+ }
139
+ return this._weighting;
140
+ }
141
+
142
+ /**
143
+ * Setter for _weighting
144
+ * @param {string} weighting
145
+ */
146
+ set weighting(weighting: string) {
147
+ if (
148
+ check12ValidFormat(weighting, Regex.scorm12.CMIDecimal) &&
149
+ check12ValidRange(weighting, Regex.scorm12.weighting_range)
150
+ ) {
151
+ this._weighting = weighting;
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Getter for _student_response. Should only be called during JSON export.
157
+ * @return {string}
158
+ */
159
+ get student_response(): string {
160
+ if (!this.jsonString) {
161
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
162
+ }
163
+ return this._student_response;
164
+ }
165
+
166
+ /**
167
+ * Setter for _student_response
168
+ * @param {string} student_response
169
+ */
170
+ set student_response(student_response: string) {
171
+ if (check12ValidFormat(student_response, Regex.scorm12.CMIFeedback, true)) {
172
+ this._student_response = student_response;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Getter for _result. Should only be called during JSON export.
178
+ * @return {string}
179
+ */
180
+ get result(): string {
181
+ if (!this.jsonString) {
182
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
183
+ }
184
+ return this._result;
185
+ }
186
+
187
+ /**
188
+ * Setter for _result
189
+ * @param {string} result
190
+ */
191
+ set result(result: string) {
192
+ if (check12ValidFormat(result, Regex.scorm12.CMIResult)) {
193
+ this._result = result;
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Getter for _latency. Should only be called during JSON export.
199
+ * @return {string}
200
+ */
201
+ get latency(): string {
202
+ if (!this.jsonString) {
203
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
204
+ }
205
+ return this._latency;
206
+ }
207
+
208
+ /**
209
+ * Setter for _latency
210
+ * @param {string} latency
211
+ */
212
+ set latency(latency: string) {
213
+ if (check12ValidFormat(latency, Regex.scorm12.CMITimespan)) {
214
+ this._latency = latency;
215
+ }
216
+ }
217
+
218
+ /**
219
+ * toJSON for cmi.interactions.n
220
+ *
221
+ * @return {
222
+ * {
223
+ * id: string,
224
+ * time: string,
225
+ * type: string,
226
+ * weighting: string,
227
+ * student_response: string,
228
+ * result: string,
229
+ * latency: string,
230
+ * objectives: CMIArray,
231
+ * correct_responses: CMIArray
232
+ * }
233
+ * }
234
+ */
235
+ toJSON(): {
236
+ id: string;
237
+ time: string;
238
+ type: string;
239
+ weighting: string;
240
+ student_response: string;
241
+ result: string;
242
+ latency: string;
243
+ objectives: CMIArray;
244
+ correct_responses: CMIArray;
245
+ } {
246
+ this.jsonString = true;
247
+ const result = {
248
+ id: this.id,
249
+ time: this.time,
250
+ type: this.type,
251
+ weighting: this.weighting,
252
+ student_response: this.student_response,
253
+ result: this.result,
254
+ latency: this.latency,
255
+ objectives: this.objectives,
256
+ correct_responses: this.correct_responses,
257
+ };
258
+ delete this.jsonString;
259
+ return result;
260
+ }
261
+ }
262
+
263
+ /**
264
+ * Class representing SCORM 1.2's cmi.interactions.n.objectives.n object
265
+ * @extends BaseCMI
266
+ */
267
+ export class CMIInteractionsObjectivesObject extends BaseCMI {
268
+ /**
269
+ * Constructor for cmi.interactions.n.objectives.n
270
+ */
271
+ constructor() {
272
+ super();
273
+ }
274
+
275
+ private _id = "";
276
+
277
+ /**
278
+ * Getter for _id
279
+ * @return {string}
280
+ */
281
+ get id(): string {
282
+ return this._id;
283
+ }
284
+
285
+ /**
286
+ * Setter for _id
287
+ * @param {string} id
288
+ */
289
+ set id(id: string) {
290
+ if (check12ValidFormat(id, Regex.scorm12.CMIIdentifier)) {
291
+ this._id = id;
292
+ }
293
+ }
294
+
295
+ /**
296
+ * toJSON for cmi.interactions.n.objectives.n
297
+ * @return {
298
+ * {
299
+ * id: string
300
+ * }
301
+ * }
302
+ */
303
+ toJSON(): {
304
+ id: string;
305
+ } {
306
+ this.jsonString = true;
307
+ const result = {
308
+ id: this.id,
309
+ };
310
+ delete this.jsonString;
311
+ return result;
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Class representing SCORM 1.2's cmi.interactions.correct_responses.n object
317
+ * @extends BaseCMI
318
+ */
319
+ export class CMIInteractionsCorrectResponsesObject extends BaseCMI {
320
+ /**
321
+ * Constructor for cmi.interactions.correct_responses.n
322
+ */
323
+ constructor() {
324
+ super();
325
+ }
326
+
327
+ private _pattern = "";
328
+
329
+ /**
330
+ * Getter for _pattern
331
+ * @return {string}
332
+ */
333
+ get pattern(): string {
334
+ if (!this.jsonString) {
335
+ throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
336
+ }
337
+ return this._pattern;
338
+ }
339
+
340
+ /**
341
+ * Setter for _pattern
342
+ * @param {string} pattern
343
+ */
344
+ set pattern(pattern: string) {
345
+ if (check12ValidFormat(pattern, Regex.scorm12.CMIFeedback, true)) {
346
+ this._pattern = pattern;
347
+ }
348
+ }
349
+
350
+ /**
351
+ * toJSON for cmi.interactions.correct_responses.n
352
+ * @return {
353
+ * {
354
+ * pattern: string
355
+ * }
356
+ * }
357
+ */
358
+ toJSON(): {
359
+ pattern: string;
360
+ } {
361
+ this.jsonString = true;
362
+ const result = {
363
+ pattern: this._pattern,
364
+ };
365
+ delete this.jsonString;
366
+ return result;
367
+ }
368
+ }
@@ -0,0 +1,54 @@
1
+ import {BaseCMI} from "../common/base_cmi";
2
+ import {check12ValidFormat} from "./validation";
3
+ import Regex from "../../constants/regex";
4
+
5
+ /**
6
+ * Class for AICC Navigation object
7
+ */
8
+ export class NAV extends BaseCMI {
9
+ /**
10
+ * Constructor for NAV object
11
+ */
12
+ constructor() {
13
+ super();
14
+ }
15
+
16
+ private _event = "";
17
+
18
+ /**
19
+ * Getter for _event
20
+ * @return {string}
21
+ */
22
+ get event(): string {
23
+ return this._event;
24
+ }
25
+
26
+ /**
27
+ * Setter for _event
28
+ * @param {string} event
29
+ */
30
+ set event(event: string) {
31
+ if (check12ValidFormat(event, Regex.scorm12.NAVEvent)) {
32
+ this._event = event;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * toJSON for nav object
38
+ * @return {
39
+ * {
40
+ * event: string
41
+ * }
42
+ * }
43
+ */
44
+ toJSON(): {
45
+ event: string;
46
+ } {
47
+ this.jsonString = true;
48
+ const result = {
49
+ event: this.event,
50
+ };
51
+ delete this.jsonString;
52
+ return result;
53
+ }
54
+ }