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.
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 +180 -72
  5. package/dist/aicc.js +1520 -1149
  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 +2812 -2205
  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 +1129 -842
  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 +1921 -1564
  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 +20 -17
  22. package/src/AICC.ts +15 -17
  23. package/src/BaseAPI.ts +283 -420
  24. package/src/Scorm12API.ts +133 -41
  25. package/src/Scorm2004API.ts +224 -120
  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 +82 -0
  56. package/src/constants/enums.ts +17 -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 +50 -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 +372 -9
  67. package/test/Scorm2004API.spec.ts +558 -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,176 @@
1
+ import { CMIArray } from "../common/array";
2
+ import { AICCValidationError } from "../../exceptions";
3
+ import { checkAICCValidFormat } from "./validation";
4
+ import ErrorCodes from "../../constants/error_codes";
5
+ import Regex from "../../constants/regex";
6
+ import APIConstants from "../../constants/api_constants";
7
+ import { CMIStudentPreference } from "../scorm12/student_preference";
8
+
9
+ /**
10
+ * StudentPreferences class for AICC
11
+ */
12
+ export class AICCStudentPreferences extends CMIStudentPreference {
13
+ /**
14
+ * Constructor for AICC Student Preferences object
15
+ */
16
+ constructor() {
17
+ super(APIConstants.aicc.student_preference_children);
18
+ this.windows = new CMIArray({
19
+ errorCode: ErrorCodes.scorm12.INVALID_SET_VALUE,
20
+ errorClass: AICCValidationError,
21
+ children: "",
22
+ });
23
+ }
24
+
25
+ public windows: CMIArray;
26
+
27
+ /**
28
+ * Called when the API has been initialized after the CMI has been created
29
+ */
30
+ initialize() {
31
+ super.initialize();
32
+ this.windows?.initialize();
33
+ }
34
+
35
+ private _lesson_type = "";
36
+ private _text_color = "";
37
+ private _text_location = "";
38
+ private _text_size = "";
39
+ private _video = "";
40
+
41
+ /**
42
+ * Getter for _lesson_type
43
+ * @return {string}
44
+ */
45
+ get lesson_type(): string {
46
+ return this._lesson_type;
47
+ }
48
+
49
+ /**
50
+ * Setter for _lesson_type
51
+ * @param {string} lesson_type
52
+ */
53
+ set lesson_type(lesson_type: string) {
54
+ if (checkAICCValidFormat(lesson_type, Regex.aicc.CMIString256)) {
55
+ this._lesson_type = lesson_type;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Getter for _text_color
61
+ * @return {string}
62
+ */
63
+ get text_color(): string {
64
+ return this._text_color;
65
+ }
66
+
67
+ /**
68
+ * Setter for _text_color
69
+ * @param {string} text_color
70
+ */
71
+ set text_color(text_color: string) {
72
+ if (checkAICCValidFormat(text_color, Regex.aicc.CMIString256)) {
73
+ this._text_color = text_color;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Getter for _text_location
79
+ * @return {string}
80
+ */
81
+ get text_location(): string {
82
+ return this._text_location;
83
+ }
84
+
85
+ /**
86
+ * Setter for _text_location
87
+ * @param {string} text_location
88
+ */
89
+ set text_location(text_location: string) {
90
+ if (checkAICCValidFormat(text_location, Regex.aicc.CMIString256)) {
91
+ this._text_location = text_location;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Getter for _text_size
97
+ * @return {string}
98
+ */
99
+ get text_size(): string {
100
+ return this._text_size;
101
+ }
102
+
103
+ /**
104
+ * Setter for _text_size
105
+ * @param {string} text_size
106
+ */
107
+ set text_size(text_size: string) {
108
+ if (checkAICCValidFormat(text_size, Regex.aicc.CMIString256)) {
109
+ this._text_size = text_size;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Getter for _video
115
+ * @return {string}
116
+ */
117
+ get video(): string {
118
+ return this._video;
119
+ }
120
+
121
+ /**
122
+ * Setter for _video
123
+ * @param {string} video
124
+ */
125
+ set video(video: string) {
126
+ if (checkAICCValidFormat(video, Regex.aicc.CMIString256)) {
127
+ this._video = video;
128
+ }
129
+ }
130
+
131
+ /**
132
+ * toJSON for cmi.student_preference
133
+ *
134
+ * @return {
135
+ * {
136
+ * audio: string,
137
+ * language: string,
138
+ * speed: string,
139
+ * text: string,
140
+ * text_color: string,
141
+ * text_location: string,
142
+ * text_size: string,
143
+ * video: string,
144
+ * windows: CMIArray
145
+ * }
146
+ * }
147
+ */
148
+ toJSON(): {
149
+ audio: string;
150
+ language: string;
151
+ lesson_type: string;
152
+ speed: string;
153
+ text: string;
154
+ text_color: string;
155
+ text_location: string;
156
+ text_size: string;
157
+ video: string;
158
+ windows: CMIArray;
159
+ } {
160
+ this.jsonString = true;
161
+ const result = {
162
+ audio: this.audio,
163
+ language: this.language,
164
+ lesson_type: this.lesson_type,
165
+ speed: this.speed,
166
+ text: this.text,
167
+ text_color: this.text_color,
168
+ text_location: this.text_location,
169
+ text_size: this.text_size,
170
+ video: this.video,
171
+ windows: this.windows,
172
+ };
173
+ delete this.jsonString;
174
+ return result;
175
+ }
176
+ }
@@ -0,0 +1,116 @@
1
+ import {CMIArray} from "../common/array";
2
+ import APIConstants from "../../constants/api_constants";
3
+ import {BaseCMI} from "../common/base_cmi";
4
+ import {CMIScore} from "../common/score";
5
+ import Regex from "../../constants/regex";
6
+ import ErrorCodes from "../../constants/error_codes";
7
+ import {AICCValidationError} from "../../exceptions";
8
+ import {checkAICCValidFormat} from "./validation";
9
+
10
+ /**
11
+ * Class representing the AICC cmi.student_data.tries object
12
+ */
13
+ export class CMITries extends CMIArray {
14
+ /**
15
+ * Constructor for inline Tries Array class
16
+ */
17
+ constructor() {
18
+ super({
19
+ children: APIConstants.aicc.tries_children,
20
+ });
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Class for AICC Tries
26
+ */
27
+ export class CMITriesObject extends BaseCMI {
28
+ /**
29
+ * Constructor for AICC Tries object
30
+ */
31
+ constructor() {
32
+ super();
33
+ 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,
39
+ errorClass: AICCValidationError,
40
+ });
41
+ }
42
+
43
+ public score: CMIScore;
44
+
45
+ /**
46
+ * Called when the API has been initialized after the CMI has been created
47
+ */
48
+ initialize() {
49
+ super.initialize();
50
+ this.score?.initialize();
51
+ }
52
+
53
+ private _status = "";
54
+ private _time = "";
55
+
56
+ /**
57
+ * Getter for _status
58
+ * @return {string}
59
+ */
60
+ get status(): string {
61
+ return this._status;
62
+ }
63
+
64
+ /**
65
+ * Setter for _status
66
+ * @param {string} status
67
+ */
68
+ set status(status: string) {
69
+ if (checkAICCValidFormat(status, Regex.aicc.CMIStatus2)) {
70
+ this._status = status;
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Getter for _time
76
+ * @return {string}
77
+ */
78
+ get time(): string {
79
+ return this._time;
80
+ }
81
+
82
+ /**
83
+ * Setter for _time
84
+ * @param {string} time
85
+ */
86
+ set time(time: string) {
87
+ if (checkAICCValidFormat(time, Regex.aicc.CMITime)) {
88
+ this._time = time;
89
+ }
90
+ }
91
+
92
+ /**
93
+ * toJSON for cmi.student_data.tries.n object
94
+ * @return {
95
+ * {
96
+ * status: string,
97
+ * time: string,
98
+ * score: CMIScore
99
+ * }
100
+ * }
101
+ */
102
+ toJSON(): {
103
+ status: string;
104
+ time: string;
105
+ score: CMIScore;
106
+ } {
107
+ this.jsonString = true;
108
+ const result = {
109
+ status: this.status,
110
+ time: this.time,
111
+ score: this.score,
112
+ };
113
+ delete this.jsonString;
114
+ return result;
115
+ }
116
+ }
@@ -0,0 +1,25 @@
1
+ import { checkValidFormat } from "../common/validation";
2
+ import { AICCValidationError } from "../../exceptions";
3
+ import ErrorCodes from "../../constants/error_codes";
4
+ const aicc_error_codes = ErrorCodes.scorm12;
5
+
6
+ /**
7
+ * Helper method, no reason to have to pass the same error codes every time
8
+ * @param {string} value
9
+ * @param {string} regexPattern
10
+ * @param {boolean} allowEmptyString
11
+ * @return {boolean}
12
+ */
13
+ export function checkAICCValidFormat(
14
+ value: string,
15
+ regexPattern: string,
16
+ allowEmptyString?: boolean,
17
+ ): boolean {
18
+ return checkValidFormat(
19
+ value,
20
+ regexPattern,
21
+ aicc_error_codes.TYPE_MISMATCH,
22
+ AICCValidationError,
23
+ allowEmptyString,
24
+ );
25
+ }
@@ -0,0 +1,77 @@
1
+ import { BaseCMI } from "./base_cmi";
2
+ import ErrorCodes from "../../constants/error_codes";
3
+ import { BaseScormValidationError } from "../../exceptions";
4
+
5
+ export const scorm12_error_codes = ErrorCodes.scorm12;
6
+
7
+ /**
8
+ * Base class for cmi *.n objects
9
+ */
10
+ export class CMIArray extends BaseCMI {
11
+ private readonly _errorCode: number;
12
+ private readonly _errorClass: typeof BaseScormValidationError;
13
+ private readonly __children: string;
14
+ childArray: any[];
15
+
16
+ /**
17
+ * Constructor cmi *.n arrays
18
+ * @param {object} params
19
+ */
20
+ constructor(params: {
21
+ children: string;
22
+ errorCode?: number;
23
+ errorClass?: typeof BaseScormValidationError;
24
+ }) {
25
+ super();
26
+ this.__children = params.children;
27
+ this._errorCode = params.errorCode || scorm12_error_codes.GENERAL;
28
+ this._errorClass = params.errorClass || BaseScormValidationError;
29
+ this.childArray = [];
30
+ }
31
+
32
+ /**
33
+ * Getter for _children
34
+ * @return {string}
35
+ */
36
+ get _children(): string {
37
+ return this.__children;
38
+ }
39
+
40
+ /**
41
+ * Setter for _children. Just throws an error.
42
+ * @param {string} _children
43
+ */
44
+ set _children(_children: string) {
45
+ throw new this._errorClass(this._errorCode);
46
+ }
47
+
48
+ /**
49
+ * Getter for _count
50
+ * @return {number}
51
+ */
52
+ get _count(): number {
53
+ return this.childArray.length;
54
+ }
55
+
56
+ /**
57
+ * Setter for _count. Just throws an error.
58
+ * @param {number} _count
59
+ */
60
+ set _count(_count: number) {
61
+ throw new this._errorClass(this._errorCode);
62
+ }
63
+
64
+ /**
65
+ * toJSON for *.n arrays
66
+ * @return {object}
67
+ */
68
+ toJSON(): object {
69
+ this.jsonString = true;
70
+ const result: { [key: string]: any } = {};
71
+ for (let i = 0; i < this.childArray.length; i++) {
72
+ result[i + ""] = this.childArray[i];
73
+ }
74
+ delete this.jsonString;
75
+ return result;
76
+ }
77
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Base class for API cmi objects
3
+ */
4
+ export abstract class BaseCMI {
5
+ jsonString? = false;
6
+ private _initialized = false;
7
+ private _start_time: number | undefined;
8
+
9
+ /**
10
+ * Getter for _initialized
11
+ * @return {boolean}
12
+ */
13
+ get initialized(): boolean {
14
+ return this._initialized;
15
+ }
16
+
17
+ /**
18
+ * Getter for _start_time
19
+ * @return {number | undefined}
20
+ */
21
+ get start_time(): number | undefined {
22
+ return this._start_time;
23
+ }
24
+
25
+ /**
26
+ * Called when the API has been initialized after the CMI has been created
27
+ */
28
+ initialize(): void {
29
+ this._initialized = true;
30
+ }
31
+
32
+ /**
33
+ * Called when the player should override the 'session_time' provided by
34
+ * the module
35
+ */
36
+ setStartTime(): void {
37
+ this._start_time = new Date().getTime();
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Base class for cmi root objects
43
+ */
44
+ export abstract class BaseRootCMI extends BaseCMI {
45
+ abstract getCurrentTotalTime(): string;
46
+ }
@@ -0,0 +1,203 @@
1
+ import APIConstants from "../../constants/api_constants";
2
+ import Regex from "../../constants/regex";
3
+ import { BaseCMI } from "./base_cmi";
4
+ import { checkValidFormat, checkValidRange } from "./validation";
5
+ import ErrorCodes from "../../constants/error_codes";
6
+ import { BaseScormValidationError } from "../../exceptions";
7
+
8
+ const scorm12_constants = APIConstants.scorm12;
9
+ const scorm12_regex = Regex.scorm12;
10
+ export const scorm12_error_codes = ErrorCodes.scorm12;
11
+
12
+ /**
13
+ * Base class for cmi *.score objects
14
+ */
15
+ export class CMIScore extends BaseCMI {
16
+ private readonly __children: string;
17
+ private readonly __score_range: string | false;
18
+ private readonly __invalid_error_code: number;
19
+ private readonly __invalid_type_code: number;
20
+ private readonly __invalid_range_code: number;
21
+ private readonly __decimal_regex: string;
22
+ private readonly __error_class: typeof BaseScormValidationError;
23
+ private _raw = "";
24
+ private _min = "";
25
+ private _max: string;
26
+
27
+ /**
28
+ * Constructor for *.score
29
+ * @param {
30
+ * score_children: string,
31
+ * score_range: string,
32
+ * max: string,
33
+ * invalidErrorCode: number,
34
+ * invalidTypeCode: number,
35
+ * invalidRangeCode: number,
36
+ * decimalRegex: string,
37
+ * errorClass: typeof BaseScormValidationError
38
+ * } params
39
+ */
40
+ constructor(params: {
41
+ score_children?: string;
42
+ score_range?: string;
43
+ max?: string;
44
+ invalidErrorCode?: number;
45
+ invalidTypeCode?: number;
46
+ invalidRangeCode?: number;
47
+ decimalRegex?: string;
48
+ errorClass: typeof BaseScormValidationError;
49
+ }) {
50
+ super();
51
+
52
+ this.__children = params.score_children || scorm12_constants.score_children;
53
+ this.__score_range = !params.score_range
54
+ ? false
55
+ : scorm12_regex.score_range;
56
+ this._max = params.max || params.max === "" ? params.max : "100";
57
+ this.__invalid_error_code =
58
+ params.invalidErrorCode || scorm12_error_codes.INVALID_SET_VALUE;
59
+ this.__invalid_type_code =
60
+ params.invalidTypeCode || scorm12_error_codes.TYPE_MISMATCH;
61
+ this.__invalid_range_code =
62
+ params.invalidRangeCode || scorm12_error_codes.VALUE_OUT_OF_RANGE;
63
+ this.__decimal_regex = params.decimalRegex || scorm12_regex.CMIDecimal;
64
+ this.__error_class = params.errorClass;
65
+ }
66
+
67
+ /**
68
+ * Getter for _children
69
+ * @return {string}
70
+ */
71
+ get _children(): string {
72
+ return this.__children;
73
+ }
74
+
75
+ /**
76
+ * Setter for _children. Just throws an error.
77
+ * @param {string} _children
78
+ */
79
+ set _children(_children: string) {
80
+ throw new this.__error_class(this.__invalid_error_code);
81
+ }
82
+
83
+ /**
84
+ * Getter for _raw
85
+ * @return {string}
86
+ */
87
+ get raw(): string {
88
+ return this._raw;
89
+ }
90
+
91
+ /**
92
+ * Setter for _raw
93
+ * @param {string} raw
94
+ */
95
+ set raw(raw: string) {
96
+ if (
97
+ checkValidFormat(
98
+ raw,
99
+ this.__decimal_regex,
100
+ this.__invalid_type_code,
101
+ this.__error_class,
102
+ ) &&
103
+ (!this.__score_range ||
104
+ checkValidRange(
105
+ raw,
106
+ this.__score_range,
107
+ this.__invalid_range_code,
108
+ this.__error_class,
109
+ ))
110
+ ) {
111
+ this._raw = raw;
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Getter for _min
117
+ * @return {string}
118
+ */
119
+ get min(): string {
120
+ return this._min;
121
+ }
122
+
123
+ /**
124
+ * Setter for _min
125
+ * @param {string} min
126
+ */
127
+ set min(min: string) {
128
+ if (
129
+ checkValidFormat(
130
+ min,
131
+ this.__decimal_regex,
132
+ this.__invalid_type_code,
133
+ this.__error_class,
134
+ ) &&
135
+ (!this.__score_range ||
136
+ checkValidRange(
137
+ min,
138
+ this.__score_range,
139
+ this.__invalid_range_code,
140
+ this.__error_class,
141
+ ))
142
+ ) {
143
+ this._min = min;
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Getter for _max
149
+ * @return {string}
150
+ */
151
+ get max(): string {
152
+ return this._max;
153
+ }
154
+
155
+ /**
156
+ * Setter for _max
157
+ * @param {string} max
158
+ */
159
+ set max(max: string) {
160
+ if (
161
+ checkValidFormat(
162
+ max,
163
+ this.__decimal_regex,
164
+ this.__invalid_type_code,
165
+ this.__error_class,
166
+ ) &&
167
+ (!this.__score_range ||
168
+ checkValidRange(
169
+ max,
170
+ this.__score_range,
171
+ this.__invalid_range_code,
172
+ this.__error_class,
173
+ ))
174
+ ) {
175
+ this._max = max;
176
+ }
177
+ }
178
+
179
+ /**
180
+ * toJSON for *.score
181
+ * @return {
182
+ * {
183
+ * min: string,
184
+ * max: string,
185
+ * raw: string
186
+ * }
187
+ * }
188
+ */
189
+ toJSON(): {
190
+ min: string;
191
+ max: string;
192
+ raw: string;
193
+ } {
194
+ this.jsonString = true;
195
+ const result = {
196
+ raw: this.raw,
197
+ min: this.min,
198
+ max: this.max,
199
+ };
200
+ delete this.jsonString;
201
+ return result;
202
+ }
203
+ }
@@ -0,0 +1,60 @@
1
+ import { BaseScormValidationError } from "../../exceptions";
2
+
3
+ /**
4
+ * Check if the value matches the proper format. If not, throw proper error code.
5
+ *
6
+ * @param {string} value
7
+ * @param {string} regexPattern
8
+ * @param {number} errorCode
9
+ * @param {typeof BaseScormValidationError} errorClass
10
+ * @param {boolean} [allowEmptyString]
11
+ * @return {boolean}
12
+ */
13
+ export function checkValidFormat(
14
+ value: string,
15
+ regexPattern: string,
16
+ errorCode: number,
17
+ errorClass: typeof BaseScormValidationError,
18
+ allowEmptyString?: boolean,
19
+ ): boolean {
20
+ if (typeof value !== "string") {
21
+ return false;
22
+ }
23
+ const formatRegex = new RegExp(regexPattern);
24
+ const matches = value.match(formatRegex);
25
+ if (allowEmptyString && value === "") {
26
+ return true;
27
+ }
28
+ if (value === undefined || !matches || matches[0] === "") {
29
+ throw new errorClass(errorCode);
30
+ }
31
+ return true;
32
+ }
33
+
34
+ /**
35
+ * Check if the value matches the proper range. If not, throw proper error code.
36
+ *
37
+ * @param {any} value
38
+ * @param {string} rangePattern
39
+ * @param {number} errorCode
40
+ * @param {typeof BaseScormValidationError} errorClass
41
+ * @return {boolean}
42
+ */
43
+ export function checkValidRange(
44
+ value: any,
45
+ rangePattern: string,
46
+ errorCode: number,
47
+ errorClass: typeof BaseScormValidationError,
48
+ ): boolean {
49
+ const ranges = rangePattern.split("#");
50
+ value = value * 1.0;
51
+ if (value >= ranges[0]) {
52
+ if (ranges[1] === "*" || value <= ranges[1]) {
53
+ return true;
54
+ } else {
55
+ throw new errorClass(errorCode);
56
+ }
57
+ } else {
58
+ throw new errorClass(errorCode);
59
+ }
60
+ }