scorm-again 2.4.1 → 2.6.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 (87) hide show
  1. package/README.md +23 -23
  2. package/dist/aicc.js +676 -493
  3. package/dist/aicc.js.map +1 -1
  4. package/dist/aicc.min.js +1 -1
  5. package/dist/aicc.min.js.map +1 -1
  6. package/dist/esm/aicc.js +692 -496
  7. package/dist/esm/aicc.js.map +1 -1
  8. package/dist/esm/aicc.min.js +1 -1
  9. package/dist/esm/aicc.min.js.map +1 -1
  10. package/dist/esm/scorm-again.js +1151 -743
  11. package/dist/esm/scorm-again.js.map +1 -1
  12. package/dist/esm/scorm-again.min.js +1 -1
  13. package/dist/esm/scorm-again.min.js.map +1 -1
  14. package/dist/esm/scorm12.js +534 -401
  15. package/dist/esm/scorm12.js.map +1 -1
  16. package/dist/esm/scorm12.min.js +1 -1
  17. package/dist/esm/scorm12.min.js.map +1 -1
  18. package/dist/esm/scorm2004.js +712 -465
  19. package/dist/esm/scorm2004.js.map +1 -1
  20. package/dist/esm/scorm2004.min.js +1 -1
  21. package/dist/esm/scorm2004.min.js.map +1 -1
  22. package/dist/scorm-again.js +1127 -731
  23. package/dist/scorm-again.js.map +1 -1
  24. package/dist/scorm-again.min.js +1 -1
  25. package/dist/scorm-again.min.js.map +1 -1
  26. package/dist/scorm12.js +521 -400
  27. package/dist/scorm12.js.map +1 -1
  28. package/dist/scorm12.min.js +1 -1
  29. package/dist/scorm12.min.js.map +1 -1
  30. package/dist/scorm2004.js +698 -464
  31. package/dist/scorm2004.js.map +1 -1
  32. package/dist/scorm2004.min.js +1 -1
  33. package/dist/scorm2004.min.js.map +1 -1
  34. package/package.json +15 -15
  35. package/src/AICC.ts +3 -0
  36. package/src/BaseAPI.ts +60 -95
  37. package/src/Scorm12API.ts +14 -14
  38. package/src/Scorm2004API.ts +107 -37
  39. package/src/cmi/aicc/attempts.ts +22 -12
  40. package/src/cmi/aicc/cmi.ts +2 -2
  41. package/src/cmi/aicc/core.ts +44 -26
  42. package/src/cmi/aicc/evaluation.ts +31 -12
  43. package/src/cmi/aicc/paths.ts +29 -15
  44. package/src/cmi/aicc/student_data.ts +14 -5
  45. package/src/cmi/aicc/student_demographics.ts +31 -24
  46. package/src/cmi/aicc/student_preferences.ts +11 -11
  47. package/src/cmi/aicc/tries.ts +24 -14
  48. package/src/cmi/aicc/validation.ts +3 -4
  49. package/src/cmi/common/array.ts +17 -5
  50. package/src/cmi/common/base_cmi.ts +3 -1
  51. package/src/cmi/common/score.ts +16 -13
  52. package/src/cmi/scorm12/cmi.ts +25 -10
  53. package/src/cmi/scorm12/interactions.ts +62 -28
  54. package/src/cmi/scorm12/nav.ts +13 -5
  55. package/src/cmi/scorm12/objectives.ts +28 -18
  56. package/src/cmi/scorm12/student_data.ts +15 -8
  57. package/src/cmi/scorm12/student_preference.ts +20 -13
  58. package/src/cmi/scorm12/validation.ts +7 -7
  59. package/src/cmi/scorm2004/adl.ts +141 -25
  60. package/src/cmi/scorm2004/cmi.ts +50 -55
  61. package/src/cmi/scorm2004/comments.ts +21 -20
  62. package/src/cmi/scorm2004/interactions.ts +73 -32
  63. package/src/cmi/scorm2004/learner_preference.ts +20 -13
  64. package/src/cmi/scorm2004/objectives.ts +41 -16
  65. package/src/cmi/scorm2004/score.ts +22 -11
  66. package/src/cmi/scorm2004/validation.ts +4 -4
  67. package/src/constants/api_constants.ts +8 -29
  68. package/src/constants/default_settings.ts +26 -12
  69. package/src/constants/enums.ts +9 -0
  70. package/src/constants/error_codes.ts +5 -12
  71. package/src/constants/regex.ts +5 -11
  72. package/src/constants/response_constants.ts +1 -2
  73. package/src/exceptions/aicc_exceptions.ts +29 -0
  74. package/src/exceptions/scorm12_exceptions.ts +29 -0
  75. package/src/exceptions/scorm2004_exceptions.ts +29 -0
  76. package/src/exceptions.ts +1 -86
  77. package/src/types/api_types.ts +29 -5
  78. package/test/AICC.spec.ts +114 -43
  79. package/test/Scorm12API.spec.ts +37 -39
  80. package/test/Scorm2004API.spec.ts +165 -80
  81. package/test/cmi/aicc_cmi.spec.ts +6 -9
  82. package/test/cmi/scorm12_cmi.spec.ts +8 -8
  83. package/test/cmi/scorm2004_cmi.spec.ts +8 -9
  84. package/test/exceptions.spec.ts +11 -9
  85. package/test/types/api_types.spec.ts +40 -47
  86. package/test/utilities.spec.ts +1 -4
  87. package/webpack.config.js +4 -0
@@ -2,12 +2,13 @@ import BaseAPI from "./BaseAPI";
2
2
  import { CMI } from "./cmi/scorm2004/cmi";
3
3
  import * as Utilities from "./utilities";
4
4
  import { stringMatches } from "./utilities";
5
- import APIConstants from "./constants/api_constants";
6
- import ErrorCodes from "./constants/error_codes";
5
+ import {
6
+ global_constants,
7
+ scorm2004_constants,
8
+ } from "./constants/api_constants";
9
+ import { scorm2004_errors } from "./constants/error_codes";
7
10
  import { CorrectResponses, ResponseType } from "./constants/response_constants";
8
11
  import ValidLanguages from "./constants/language_constants";
9
- import Regex from "./constants/regex";
10
- import regex from "./constants/regex";
11
12
  import { CMIArray } from "./cmi/common/array";
12
13
  import { BaseCMI } from "./cmi/common/base_cmi";
13
14
  import {
@@ -17,7 +18,7 @@ import {
17
18
  } from "./cmi/scorm2004/interactions";
18
19
  import { CMICommentsObject } from "./cmi/scorm2004/comments";
19
20
  import { CMIObjectivesObject } from "./cmi/scorm2004/objectives";
20
- import { ADL } from "./cmi/scorm2004/adl";
21
+ import { ADL, ADLDataObject } from "./cmi/scorm2004/adl";
21
22
  import {
22
23
  CommitObject,
23
24
  RefObject,
@@ -26,12 +27,14 @@ import {
26
27
  Settings,
27
28
  } from "./types/api_types";
28
29
  import { CompletionStatus, SuccessStatus } from "./constants/enums";
30
+ import { scorm2004_regex } from "./constants/regex";
29
31
 
30
32
  /**
31
33
  * API class for SCORM 2004
32
34
  */
33
35
  class Scorm2004Impl extends BaseAPI {
34
36
  private _version: string = "1.0";
37
+ private _globalObjectives: CMIObjectivesObject[] = [];
35
38
 
36
39
  /**
37
40
  * Constructor for SCORM 2004 API
@@ -44,7 +47,7 @@ class Scorm2004Impl extends BaseAPI {
44
47
  }
45
48
  }
46
49
 
47
- super(ErrorCodes.scorm2004, settings);
50
+ super(scorm2004_errors, settings);
48
51
 
49
52
  this.cmi = new CMI();
50
53
  this.adl = new ADL();
@@ -78,8 +81,8 @@ class Scorm2004Impl extends BaseAPI {
78
81
  reset(settings?: Settings) {
79
82
  this.commonReset(settings);
80
83
 
81
- this.cmi = new CMI();
82
- this.adl = new ADL();
84
+ this.cmi?.reset();
85
+ this.adl?.reset();
83
86
  }
84
87
 
85
88
  /**
@@ -90,6 +93,13 @@ class Scorm2004Impl extends BaseAPI {
90
93
  return this._version;
91
94
  }
92
95
 
96
+ /**
97
+ * Getter for _globalObjectives
98
+ */
99
+ get globalObjectives(): CMIObjectivesObject[] {
100
+ return this._globalObjectives;
101
+ }
102
+
93
103
  /**
94
104
  * @return {string} bool
95
105
  */
@@ -105,13 +115,13 @@ class Scorm2004Impl extends BaseAPI {
105
115
  (async () => {
106
116
  await this.internalFinish();
107
117
  })();
108
- return APIConstants.global.SCORM_TRUE;
118
+ return global_constants.SCORM_TRUE;
109
119
  }
110
120
 
111
121
  async internalFinish(): Promise<string> {
112
122
  const result = await this.terminate("Terminate", true);
113
123
 
114
- if (result === APIConstants.global.SCORM_TRUE) {
124
+ if (result === global_constants.SCORM_TRUE) {
115
125
  if (this.adl.nav.request !== "_none_") {
116
126
  const navActions: { [key: string]: string } = {
117
127
  continue: "SequenceNext",
@@ -125,12 +135,17 @@ class Scorm2004Impl extends BaseAPI {
125
135
  };
126
136
 
127
137
  let request = this.adl.nav.request;
128
- const choiceJumpRegex = new RegExp(regex.scorm2004.NAVEvent);
138
+ const choiceJumpRegex = new RegExp(scorm2004_regex.NAVEvent);
129
139
  const matches = request.match(choiceJumpRegex);
130
140
  let target = "";
131
- if (matches && matches.length > 2) {
132
- target = matches[2];
133
- request = matches[1].replace(target, "");
141
+ if (matches) {
142
+ if (matches.groups?.choice_target) {
143
+ target = matches.groups?.choice_target;
144
+ request = "choice";
145
+ } else if (matches.groups?.jump_target) {
146
+ target = matches.groups?.jump_target;
147
+ request = "jump";
148
+ }
134
149
  }
135
150
  const action = navActions[request];
136
151
  if (action) {
@@ -171,6 +186,7 @@ class Scorm2004Impl extends BaseAPI {
171
186
  * @return {string}
172
187
  */
173
188
  lmsSetValue(CMIElement: string, value: any): string {
189
+ // Proceed with regular setting for non-objective elements or fallback behavior
174
190
  return this.setValue("SetValue", "Commit", true, CMIElement, value);
175
191
  }
176
192
 
@@ -187,7 +203,7 @@ class Scorm2004Impl extends BaseAPI {
187
203
  await this.commit("LMSCommit", false);
188
204
  })();
189
205
  }
190
- return APIConstants.global.SCORM_TRUE;
206
+ return global_constants.SCORM_TRUE;
191
207
  }
192
208
 
193
209
  /**
@@ -227,6 +243,57 @@ class Scorm2004Impl extends BaseAPI {
227
243
  * @return {string}
228
244
  */
229
245
  override setCMIValue(CMIElement: string, value: any): string {
246
+ // Check if we're updating a global or local objective
247
+ if (stringMatches(CMIElement, "cmi\\.objectives\\.\\d+")) {
248
+ const parts = CMIElement.split(".");
249
+ const index = Number(parts[2]);
250
+ const element_base = `cmi.objectives.${index}`;
251
+
252
+ let objective_id;
253
+ const setting_id = stringMatches(
254
+ CMIElement,
255
+ "cmi\\.objectives\\.\\d+\\.id",
256
+ );
257
+
258
+ if (setting_id) {
259
+ // If we're setting the objective ID, capture it directly
260
+ objective_id = value;
261
+ } else {
262
+ // Find existing objective ID if available
263
+ const objective = this.cmi.objectives.findObjectiveByIndex(index);
264
+ objective_id = objective ? objective.id : undefined;
265
+ }
266
+
267
+ // Check if the objective ID matches a global objective
268
+ const is_global =
269
+ objective_id && this.settings.globalObjectiveIds.includes(objective_id);
270
+
271
+ if (is_global) {
272
+ // Locate or create an entry in _globalObjectives for the global objective
273
+ let global_index = this._globalObjectives.findIndex(
274
+ (obj) => obj.id === objective_id,
275
+ );
276
+
277
+ if (global_index === -1) {
278
+ global_index = this._globalObjectives.length;
279
+ const newGlobalObjective = new CMIObjectivesObject();
280
+ newGlobalObjective.id = objective_id;
281
+ this._globalObjectives.push(newGlobalObjective);
282
+ }
283
+
284
+ // Update the global objective
285
+ const global_element = CMIElement.replace(
286
+ element_base,
287
+ `_globalObjectives.${global_index}`,
288
+ );
289
+ this._commonSetCMIValue(
290
+ "SetGlobalObjectiveValue",
291
+ true,
292
+ global_element,
293
+ value,
294
+ );
295
+ }
296
+ }
230
297
  return this._commonSetCMIValue("SetValue", true, CMIElement, value);
231
298
  }
232
299
 
@@ -273,6 +340,10 @@ class Scorm2004Impl extends BaseAPI {
273
340
  return new CMICommentsObject(true);
274
341
  }
275
342
 
343
+ if (stringMatches(CMIElement, "adl\\.data\\.\\d+")) {
344
+ return new ADLDataObject();
345
+ }
346
+
276
347
  return null;
277
348
  }
278
349
 
@@ -286,7 +357,7 @@ class Scorm2004Impl extends BaseAPI {
286
357
 
287
358
  if (this.isInitialized()) {
288
359
  if (!interaction.type) {
289
- this.throwSCORMError(ErrorCodes.scorm2004.DEPENDENCY_NOT_ESTABLISHED);
360
+ this.throwSCORMError(scorm2004_errors.DEPENDENCY_NOT_ESTABLISHED);
290
361
  } else {
291
362
  this.checkDuplicateChoiceResponse(interaction, value);
292
363
  const response_type = CorrectResponses[interaction.type];
@@ -294,7 +365,7 @@ class Scorm2004Impl extends BaseAPI {
294
365
  this.checkValidResponseType(response_type, value, interaction.type);
295
366
  } else {
296
367
  this.throwSCORMError(
297
- ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
368
+ scorm2004_errors.GENERAL_SET_FAILURE,
298
369
  "Incorrect Response Type: " + interaction.type,
299
370
  );
300
371
  }
@@ -330,7 +401,7 @@ class Scorm2004Impl extends BaseAPI {
330
401
  this.checkCorrectResponseValue(interaction_type, nodes, value);
331
402
  } else if (nodes.length > response_type.max) {
332
403
  this.throwSCORMError(
333
- ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
404
+ scorm2004_errors.GENERAL_SET_FAILURE,
334
405
  "Data Model Element Pattern Too Long",
335
406
  );
336
407
  }
@@ -351,7 +422,7 @@ class Scorm2004Impl extends BaseAPI {
351
422
  ) {
352
423
  const response = interaction.correct_responses.childArray[i];
353
424
  if (response.pattern === value) {
354
- this.throwSCORMError(ErrorCodes.scorm2004.GENERAL_SET_FAILURE);
425
+ this.throwSCORMError(scorm2004_errors.GENERAL_SET_FAILURE);
355
426
  }
356
427
  }
357
428
  }
@@ -392,14 +463,14 @@ class Scorm2004Impl extends BaseAPI {
392
463
  } else {
393
464
  if (this.lastErrorCode === "0") {
394
465
  this.throwSCORMError(
395
- ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
466
+ scorm2004_errors.GENERAL_SET_FAILURE,
396
467
  "Data Model Element Pattern Already Exists",
397
468
  );
398
469
  }
399
470
  }
400
471
  } else {
401
472
  this.throwSCORMError(
402
- ErrorCodes.scorm2004.GENERAL_SET_FAILURE,
473
+ scorm2004_errors.GENERAL_SET_FAILURE,
403
474
  "Data Model Element Collection Limit Reached",
404
475
  );
405
476
  }
@@ -431,11 +502,11 @@ class Scorm2004Impl extends BaseAPI {
431
502
 
432
503
  // Set error number to string since inconsistent from modules if string or number
433
504
  errorNumber = String(errorNumber);
434
- if (APIConstants.scorm2004.error_descriptions[errorNumber]) {
505
+ if (scorm2004_constants.error_descriptions[errorNumber]) {
435
506
  basicMessage =
436
- APIConstants.scorm2004.error_descriptions[errorNumber].basicMessage;
507
+ scorm2004_constants.error_descriptions[errorNumber].basicMessage;
437
508
  detailMessage =
438
- APIConstants.scorm2004.error_descriptions[errorNumber].detailMessage;
509
+ scorm2004_constants.error_descriptions[errorNumber].detailMessage;
439
510
  }
440
511
 
441
512
  return detail ? detailMessage : basicMessage;
@@ -490,17 +561,17 @@ class Scorm2004Impl extends BaseAPI {
490
561
  if (values.length === 2) {
491
562
  const matches = values[0].match(formatRegex);
492
563
  if (!matches) {
493
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
564
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
494
565
  } else {
495
566
  if (
496
567
  !response.format2 ||
497
568
  !values[1].match(new RegExp(response.format2))
498
569
  ) {
499
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
570
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
500
571
  }
501
572
  }
502
573
  } else {
503
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
574
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
504
575
  }
505
576
  } else {
506
577
  const matches = nodes[i].match(formatRegex);
@@ -508,17 +579,17 @@ class Scorm2004Impl extends BaseAPI {
508
579
  (!matches && value !== "") ||
509
580
  (!matches && interaction_type === "true-false")
510
581
  ) {
511
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
582
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
512
583
  } else {
513
584
  if (interaction_type === "numeric" && nodes.length > 1) {
514
585
  if (Number(nodes[0]) > Number(nodes[1])) {
515
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
586
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
516
587
  }
517
588
  } else {
518
589
  if (nodes[i] !== "" && response.unique) {
519
590
  for (let j = 0; j < i && this.lastErrorCode === "0"; j++) {
520
591
  if (nodes[i] === nodes[j]) {
521
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
592
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
522
593
  }
523
594
  }
524
595
  }
@@ -546,12 +617,12 @@ class Scorm2004Impl extends BaseAPI {
546
617
  while (matches) {
547
618
  switch (matches[2]) {
548
619
  case "lang":
549
- langMatches = node.match(Regex.scorm2004.CMILangcr);
620
+ langMatches = node.match(scorm2004_regex.CMILangcr);
550
621
  if (langMatches) {
551
622
  const lang = langMatches[3];
552
623
  if (lang !== undefined && lang.length > 0) {
553
624
  if (!ValidLanguages.includes(lang.toLowerCase())) {
554
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
625
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
555
626
  }
556
627
  }
557
628
  }
@@ -560,7 +631,7 @@ class Scorm2004Impl extends BaseAPI {
560
631
  case "case_matters":
561
632
  if (!seenLang && !seenOrder && !seenCase) {
562
633
  if (matches[3] !== "true" && matches[3] !== "false") {
563
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
634
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
564
635
  }
565
636
  }
566
637
 
@@ -569,7 +640,7 @@ class Scorm2004Impl extends BaseAPI {
569
640
  case "order_matters":
570
641
  if (!seenCase && !seenLang && !seenOrder) {
571
642
  if (matches[3] !== "true" && matches[3] !== "false") {
572
- this.throwSCORMError(ErrorCodes.scorm2004.TYPE_MISMATCH);
643
+ this.throwSCORMError(scorm2004_errors.TYPE_MISMATCH);
573
644
  }
574
645
  }
575
646
 
@@ -634,7 +705,7 @@ class Scorm2004Impl extends BaseAPI {
634
705
  const totalTimeDuration = this.cmi.getCurrentTotalTime();
635
706
  const totalTimeSeconds = Utilities.getDurationAsSeconds(
636
707
  totalTimeDuration,
637
- Regex.scorm2004.CMITimespan,
708
+ scorm2004_regex.CMITimespan,
638
709
  );
639
710
 
640
711
  let completionStatus = CompletionStatus.unknown;
@@ -718,7 +789,6 @@ class Scorm2004Impl extends BaseAPI {
718
789
  this.adl.nav.request !== this.startingData?.adl?.nav?.request &&
719
790
  this.adl.nav.request !== "_none_"
720
791
  ) {
721
- this.adl.nav.request = encodeURIComponent(this.adl.nav.request);
722
792
  navRequest = true;
723
793
  }
724
794
 
@@ -743,7 +813,7 @@ class Scorm2004Impl extends BaseAPI {
743
813
  return result;
744
814
  } else {
745
815
  return {
746
- result: APIConstants.global.SCORM_TRUE,
816
+ result: global_constants.SCORM_TRUE,
747
817
  errorCode: 0,
748
818
  };
749
819
  }
@@ -1,9 +1,9 @@
1
1
  import { BaseCMI } from "../common/base_cmi";
2
2
  import { CMIScore } from "../common/score";
3
- import APIConstants from "../../constants/api_constants";
4
- import Regex from "../../constants/regex";
5
- import ErrorCodes from "../../constants/error_codes";
6
- import { AICCValidationError } from "../../exceptions";
3
+ import { aicc_constants } from "../../constants/api_constants";
4
+ import { aicc_regex } from "../../constants/regex";
5
+ import { scorm12_errors } from "../../constants/error_codes";
6
+ import { AICCValidationError } from "../../exceptions/aicc_exceptions";
7
7
  import { checkAICCValidFormat } from "./validation";
8
8
  import { CMIArray } from "../common/array";
9
9
 
@@ -16,7 +16,7 @@ export class CMIAttemptRecords extends CMIArray {
16
16
  */
17
17
  constructor() {
18
18
  super({
19
- children: APIConstants.aicc.attempt_records_children,
19
+ children: aicc_constants.attempt_records_children,
20
20
  });
21
21
  }
22
22
  }
@@ -25,17 +25,19 @@ export class CMIAttemptRecords extends CMIArray {
25
25
  * Class for AICC Attempt Records
26
26
  */
27
27
  export class CMIAttemptRecordsObject extends BaseCMI {
28
+ private _lesson_status = "";
29
+
28
30
  /**
29
31
  * Constructor for AICC Attempt Records object
30
32
  */
31
33
  constructor() {
32
34
  super();
33
35
  this.score = new CMIScore({
34
- score_children: APIConstants.aicc.score_children,
35
- score_range: Regex.aicc.score_range,
36
- invalidErrorCode: ErrorCodes.scorm12.INVALID_SET_VALUE,
37
- invalidTypeCode: ErrorCodes.scorm12.TYPE_MISMATCH,
38
- invalidRangeCode: ErrorCodes.scorm12.VALUE_OUT_OF_RANGE,
36
+ score_children: aicc_constants.score_children,
37
+ score_range: aicc_regex.score_range,
38
+ invalidErrorCode: scorm12_errors.INVALID_SET_VALUE,
39
+ invalidTypeCode: scorm12_errors.TYPE_MISMATCH,
40
+ invalidRangeCode: scorm12_errors.VALUE_OUT_OF_RANGE,
39
41
  errorClass: AICCValidationError,
40
42
  });
41
43
  }
@@ -47,10 +49,18 @@ export class CMIAttemptRecordsObject extends BaseCMI {
47
49
  */
48
50
  override initialize() {
49
51
  super.initialize();
52
+
53
+ this._lesson_status = "";
50
54
  this.score?.initialize();
51
55
  }
52
56
 
53
- private _lesson_status = "";
57
+ /**
58
+ * Called when the API has been reset
59
+ */
60
+ reset(): void {
61
+ this._initialized = false;
62
+ this.score?.reset();
63
+ }
54
64
 
55
65
  /**
56
66
  * Getter for _lesson_status
@@ -65,7 +75,7 @@ export class CMIAttemptRecordsObject extends BaseCMI {
65
75
  * @param {string} lesson_status
66
76
  */
67
77
  set lesson_status(lesson_status: string) {
68
- if (checkAICCValidFormat(lesson_status, Regex.aicc.CMIStatus2)) {
78
+ if (checkAICCValidFormat(lesson_status, aicc_regex.CMIStatus2)) {
69
79
  this._lesson_status = lesson_status;
70
80
  }
71
81
  }
@@ -1,5 +1,5 @@
1
1
  import * as Scorm12CMI from "../scorm12/cmi";
2
- import APIConstants from "../../constants/api_constants";
2
+ import { aicc_constants } from "../../constants/api_constants";
3
3
  import { CMIEvaluation } from "./evaluation";
4
4
  import { AICCStudentPreferences } from "./student_preferences";
5
5
  import { CMIStudentDemographics } from "./student_demographics";
@@ -20,7 +20,7 @@ export class CMI extends Scorm12CMI.CMI {
20
20
  * @param {boolean} initialized
21
21
  */
22
22
  constructor(initialized: boolean = false) {
23
- super(APIConstants.aicc.cmi_children);
23
+ super(aicc_constants.cmi_children);
24
24
  if (initialized) this.initialize();
25
25
  this.student_preference = new AICCStudentPreferences();
26
26
  this.student_data = new AICCCMIStudentData();
@@ -1,9 +1,9 @@
1
1
  import { BaseCMI } from "../common/base_cmi";
2
2
  import { CMIScore } from "../common/score";
3
- import APIConstants from "../../constants/api_constants";
4
- import Regex from "../../constants/regex";
5
- import ErrorCodes from "../../constants/error_codes";
6
- import { Scorm12ValidationError } from "../../exceptions";
3
+ import { scorm12_constants } from "../../constants/api_constants";
4
+ import { scorm12_regex } from "../../constants/regex";
5
+ import { scorm12_errors } from "../../constants/error_codes";
6
+ import { Scorm12ValidationError } from "../../exceptions/scorm12_exceptions";
7
7
  import { check12ValidFormat } from "../scorm12/validation";
8
8
  import * as Util from "../../utilities";
9
9
 
@@ -18,11 +18,11 @@ export class CMICore extends BaseCMI {
18
18
  constructor() {
19
19
  super();
20
20
  this.score = new CMIScore({
21
- score_children: APIConstants.scorm12.score_children,
22
- score_range: Regex.scorm12.score_range,
23
- invalidErrorCode: ErrorCodes.scorm12.INVALID_SET_VALUE,
24
- invalidTypeCode: ErrorCodes.scorm12.TYPE_MISMATCH,
25
- invalidRangeCode: ErrorCodes.scorm12.VALUE_OUT_OF_RANGE,
21
+ score_children: scorm12_constants.score_children,
22
+ score_range: scorm12_regex.score_range,
23
+ invalidErrorCode: scorm12_errors.INVALID_SET_VALUE,
24
+ invalidTypeCode: scorm12_errors.TYPE_MISMATCH,
25
+ invalidRangeCode: scorm12_errors.VALUE_OUT_OF_RANGE,
26
26
  errorClass: Scorm12ValidationError,
27
27
  });
28
28
  }
@@ -37,7 +37,7 @@ export class CMICore extends BaseCMI {
37
37
  this.score?.initialize();
38
38
  }
39
39
 
40
- private __children = APIConstants.scorm12.core_children;
40
+ private __children = scorm12_constants.core_children;
41
41
  private _student_id = "";
42
42
  private _student_name = "";
43
43
  private _lesson_location = "";
@@ -50,6 +50,24 @@ export class CMICore extends BaseCMI {
50
50
  private _session_time = "00:00:00";
51
51
  private _suspend_data = "";
52
52
 
53
+ /**
54
+ * Called when the API has been reset
55
+ */
56
+ reset(): void {
57
+ this._initialized = false;
58
+
59
+ this._exit = "";
60
+ this._entry = "";
61
+
62
+ /**
63
+ * Resetting ensures we accurately track the time spent on each individual SCO session independently. Each new
64
+ * session should start from zero, so we can reset cmi.core.session_time at the beginning of each session.
65
+ */
66
+ this._session_time = "00:00:00";
67
+
68
+ this.score?.reset();
69
+ }
70
+
53
71
  /**
54
72
  * Getter for __children
55
73
  * @return {string}
@@ -65,7 +83,7 @@ export class CMICore extends BaseCMI {
65
83
  * @private
66
84
  */
67
85
  set _children(_children: string) {
68
- throw new Scorm12ValidationError(ErrorCodes.scorm12.INVALID_SET_VALUE);
86
+ throw new Scorm12ValidationError(scorm12_errors.INVALID_SET_VALUE);
69
87
  }
70
88
 
71
89
  /**
@@ -82,7 +100,7 @@ export class CMICore extends BaseCMI {
82
100
  */
83
101
  set student_id(student_id: string) {
84
102
  if (this.initialized) {
85
- throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
103
+ throw new Scorm12ValidationError(scorm12_errors.READ_ONLY_ELEMENT);
86
104
  } else {
87
105
  this._student_id = student_id;
88
106
  }
@@ -102,7 +120,7 @@ export class CMICore extends BaseCMI {
102
120
  */
103
121
  set student_name(student_name: string) {
104
122
  if (this.initialized) {
105
- throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
123
+ throw new Scorm12ValidationError(scorm12_errors.READ_ONLY_ELEMENT);
106
124
  } else {
107
125
  this._student_name = student_name;
108
126
  }
@@ -121,7 +139,7 @@ export class CMICore extends BaseCMI {
121
139
  * @param {string} lesson_location
122
140
  */
123
141
  set lesson_location(lesson_location: string) {
124
- if (check12ValidFormat(lesson_location, Regex.scorm12.CMIString256, true)) {
142
+ if (check12ValidFormat(lesson_location, scorm12_regex.CMIString256, true)) {
125
143
  this._lesson_location = lesson_location;
126
144
  }
127
145
  }
@@ -140,7 +158,7 @@ export class CMICore extends BaseCMI {
140
158
  */
141
159
  set credit(credit: string) {
142
160
  if (this.initialized) {
143
- throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
161
+ throw new Scorm12ValidationError(scorm12_errors.READ_ONLY_ELEMENT);
144
162
  } else {
145
163
  this._credit = credit;
146
164
  }
@@ -160,11 +178,11 @@ export class CMICore extends BaseCMI {
160
178
  */
161
179
  set lesson_status(lesson_status: string) {
162
180
  if (this.initialized) {
163
- if (check12ValidFormat(lesson_status, Regex.scorm12.CMIStatus)) {
181
+ if (check12ValidFormat(lesson_status, scorm12_regex.CMIStatus)) {
164
182
  this._lesson_status = lesson_status;
165
183
  }
166
184
  } else {
167
- if (check12ValidFormat(lesson_status, Regex.scorm12.CMIStatus2)) {
185
+ if (check12ValidFormat(lesson_status, scorm12_regex.CMIStatus2)) {
168
186
  this._lesson_status = lesson_status;
169
187
  }
170
188
  }
@@ -184,7 +202,7 @@ export class CMICore extends BaseCMI {
184
202
  */
185
203
  set entry(entry: string) {
186
204
  if (this.initialized) {
187
- throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
205
+ throw new Scorm12ValidationError(scorm12_errors.READ_ONLY_ELEMENT);
188
206
  } else {
189
207
  this._entry = entry;
190
208
  }
@@ -204,7 +222,7 @@ export class CMICore extends BaseCMI {
204
222
  */
205
223
  set total_time(total_time: string) {
206
224
  if (this.initialized) {
207
- throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
225
+ throw new Scorm12ValidationError(scorm12_errors.READ_ONLY_ELEMENT);
208
226
  } else {
209
227
  this._total_time = total_time;
210
228
  }
@@ -224,7 +242,7 @@ export class CMICore extends BaseCMI {
224
242
  */
225
243
  set lesson_mode(lesson_mode: string) {
226
244
  if (this.initialized) {
227
- throw new Scorm12ValidationError(ErrorCodes.scorm12.READ_ONLY_ELEMENT);
245
+ throw new Scorm12ValidationError(scorm12_errors.READ_ONLY_ELEMENT);
228
246
  } else {
229
247
  this._lesson_mode = lesson_mode;
230
248
  }
@@ -236,7 +254,7 @@ export class CMICore extends BaseCMI {
236
254
  */
237
255
  get exit(): string {
238
256
  if (!this.jsonString) {
239
- throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
257
+ throw new Scorm12ValidationError(scorm12_errors.WRITE_ONLY_ELEMENT);
240
258
  }
241
259
  return this._exit;
242
260
  }
@@ -246,7 +264,7 @@ export class CMICore extends BaseCMI {
246
264
  * @param {string} exit
247
265
  */
248
266
  set exit(exit: string) {
249
- if (check12ValidFormat(exit, Regex.scorm12.CMIExit, true)) {
267
+ if (check12ValidFormat(exit, scorm12_regex.CMIExit, true)) {
250
268
  this._exit = exit;
251
269
  }
252
270
  }
@@ -257,7 +275,7 @@ export class CMICore extends BaseCMI {
257
275
  */
258
276
  get session_time(): string {
259
277
  if (!this.jsonString) {
260
- throw new Scorm12ValidationError(ErrorCodes.scorm12.WRITE_ONLY_ELEMENT);
278
+ throw new Scorm12ValidationError(scorm12_errors.WRITE_ONLY_ELEMENT);
261
279
  }
262
280
  return this._session_time;
263
281
  }
@@ -267,7 +285,7 @@ export class CMICore extends BaseCMI {
267
285
  * @param {string} session_time
268
286
  */
269
287
  set session_time(session_time: string) {
270
- if (check12ValidFormat(session_time, Regex.scorm12.CMITimespan)) {
288
+ if (check12ValidFormat(session_time, scorm12_regex.CMITimespan)) {
271
289
  this._session_time = session_time;
272
290
  }
273
291
  }
@@ -285,7 +303,7 @@ export class CMICore extends BaseCMI {
285
303
  * @param {string} suspend_data
286
304
  */
287
305
  set suspend_data(suspend_data: string) {
288
- if (check12ValidFormat(suspend_data, Regex.scorm12.CMIString4096, true)) {
306
+ if (check12ValidFormat(suspend_data, scorm12_regex.CMIString4096, true)) {
289
307
  this._suspend_data = suspend_data;
290
308
  }
291
309
  }
@@ -307,7 +325,7 @@ export class CMICore extends BaseCMI {
307
325
  return Util.addHHMMSSTimeStrings(
308
326
  this._total_time,
309
327
  sessionTime,
310
- new RegExp(Regex.scorm12.CMITimespan),
328
+ new RegExp(scorm12_regex.CMITimespan),
311
329
  );
312
330
  }
313
331