329 lines
7.1 KiB
JavaScript
329 lines
7.1 KiB
JavaScript
// @flow
|
|
import APIConstants from '../constants/api_constants';
|
|
import ErrorCodes from '../constants/error_codes';
|
|
import Regex from '../constants/regex';
|
|
|
|
const scorm12_constants = APIConstants.scorm12;
|
|
const scorm12_regex = Regex.scorm12;
|
|
const scorm12_error_codes = ErrorCodes.scorm12;
|
|
|
|
/**
|
|
* Check if the value matches the proper format. If not, throw proper error code.
|
|
*
|
|
* @param {string} value
|
|
* @param {string} regexPattern
|
|
* @param {number} errorCode
|
|
* @param {class} errorClass
|
|
* @param {boolean} allowEmptyString
|
|
* @return {boolean}
|
|
*/
|
|
export function checkValidFormat(
|
|
value: String,
|
|
regexPattern: String,
|
|
errorCode: number,
|
|
errorClass: function,
|
|
allowEmptyString?: boolean) {
|
|
const formatRegex = new RegExp(regexPattern);
|
|
const matches = value.match(formatRegex);
|
|
if (allowEmptyString && value === '') {
|
|
return true;
|
|
}
|
|
if (value === undefined || !matches || matches[0] === '') {
|
|
throw new errorClass.prototype.constructor(errorCode);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check if the value matches the proper range. If not, throw proper error code.
|
|
*
|
|
* @param {*} value
|
|
* @param {string} rangePattern
|
|
* @param {number} errorCode
|
|
* @param {class} errorClass
|
|
* @return {boolean}
|
|
*/
|
|
export function checkValidRange(
|
|
value: any,
|
|
rangePattern: String,
|
|
errorCode: number,
|
|
errorClass: function) {
|
|
const ranges = rangePattern.split('#');
|
|
value = value * 1.0;
|
|
if (value >= ranges[0]) {
|
|
if ((ranges[1] === '*') || (value <= ranges[1])) {
|
|
return true;
|
|
} else {
|
|
throw new errorClass.prototype.constructor(errorCode);
|
|
}
|
|
} else {
|
|
throw new errorClass.prototype.constructor(errorCode);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Base class for API cmi objects
|
|
*/
|
|
export class BaseCMI {
|
|
jsonString = false;
|
|
#initialized = false;
|
|
#start_time;
|
|
|
|
/**
|
|
* Constructor for BaseCMI, just marks the class as abstract
|
|
*/
|
|
constructor() {
|
|
if (new.target === BaseCMI) {
|
|
throw new TypeError('Cannot construct BaseCMI instances directly');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Getter for #initialized
|
|
* @return {boolean}
|
|
*/
|
|
get initialized() {
|
|
return this.#initialized;
|
|
}
|
|
|
|
/**
|
|
* Getter for #start_time
|
|
* @return {Number}
|
|
*/
|
|
get start_time() {
|
|
return this.#start_time;
|
|
}
|
|
|
|
/**
|
|
* Called when the API has been initialized after the CMI has been created
|
|
*/
|
|
initialize() {
|
|
this.#initialized = true;
|
|
}
|
|
|
|
/**
|
|
* Called when the player should override the 'session_time' provided by
|
|
* the module
|
|
*/
|
|
setStartTime() {
|
|
this.#start_time = new Date().getTime();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Base class for cmi *.score objects
|
|
*/
|
|
export class CMIScore extends BaseCMI {
|
|
/**
|
|
* Constructor for *.score
|
|
* @param {string} score_children
|
|
* @param {string} score_range
|
|
* @param {string} max
|
|
* @param {number} invalidErrorCode
|
|
* @param {number} invalidTypeCode
|
|
* @param {number} invalidRangeCode
|
|
* @param {string} decimalRegex
|
|
* @param {class} errorClass
|
|
*/
|
|
constructor(
|
|
{
|
|
score_children,
|
|
score_range,
|
|
max,
|
|
invalidErrorCode,
|
|
invalidTypeCode,
|
|
invalidRangeCode,
|
|
decimalRegex,
|
|
errorClass,
|
|
}) {
|
|
super();
|
|
|
|
this.#_children = score_children ||
|
|
scorm12_constants.score_children;
|
|
this.#_score_range = !score_range ? false : scorm12_regex.score_range;
|
|
this.#max = (max || max === '') ? max : '100';
|
|
this.#_invalid_error_code = invalidErrorCode ||
|
|
scorm12_error_codes.INVALID_SET_VALUE;
|
|
this.#_invalid_type_code = invalidTypeCode ||
|
|
scorm12_error_codes.TYPE_MISMATCH;
|
|
this.#_invalid_range_code = invalidRangeCode ||
|
|
scorm12_error_codes.VALUE_OUT_OF_RANGE;
|
|
this.#_decimal_regex = decimalRegex ||
|
|
scorm12_regex.CMIDecimal;
|
|
this.#_error_class = errorClass;
|
|
}
|
|
|
|
#_children;
|
|
#_score_range;
|
|
#_invalid_error_code;
|
|
#_invalid_type_code;
|
|
#_invalid_range_code;
|
|
#_decimal_regex;
|
|
#_error_class;
|
|
#raw = '';
|
|
#min = '';
|
|
#max;
|
|
|
|
/**
|
|
* Getter for _children
|
|
* @return {string}
|
|
* @private
|
|
*/
|
|
get _children() {
|
|
return this.#_children;
|
|
}
|
|
|
|
/**
|
|
* Setter for _children. Just throws an error.
|
|
* @param {string} _children
|
|
* @private
|
|
*/
|
|
set _children(_children) {
|
|
throw new this.#_error_class.prototype.constructor(this.#_invalid_error_code);
|
|
}
|
|
|
|
/**
|
|
* Getter for #raw
|
|
* @return {string}
|
|
*/
|
|
get raw() {
|
|
return this.#raw;
|
|
}
|
|
|
|
/**
|
|
* Setter for #raw
|
|
* @param {string} raw
|
|
*/
|
|
set raw(raw) {
|
|
if (checkValidFormat(raw, this.#_decimal_regex, this.#_invalid_type_code, this.#_error_class) &&
|
|
(!this.#_score_range ||
|
|
checkValidRange(raw, this.#_score_range, this.#_invalid_range_code, this.#_error_class))) {
|
|
this.#raw = raw;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Getter for #min
|
|
* @return {string}
|
|
*/
|
|
get min() {
|
|
return this.#min;
|
|
}
|
|
|
|
/**
|
|
* Setter for #min
|
|
* @param {string} min
|
|
*/
|
|
set min(min) {
|
|
if (checkValidFormat(min, this.#_decimal_regex, this.#_invalid_type_code, this.#_error_class) &&
|
|
(!this.#_score_range ||
|
|
checkValidRange(min, this.#_score_range, this.#_invalid_range_code, this.#_error_class))) {
|
|
this.#min = min;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Getter for #max
|
|
* @return {string}
|
|
*/
|
|
get max() {
|
|
return this.#max;
|
|
}
|
|
|
|
/**
|
|
* Setter for #max
|
|
* @param {string} max
|
|
*/
|
|
set max(max) {
|
|
if (checkValidFormat(max, this.#_decimal_regex, this.#_invalid_type_code, this.#_error_class) &&
|
|
(!this.#_score_range ||
|
|
checkValidRange(max, this.#_score_range, this.#_invalid_range_code, this.#_error_class))) {
|
|
this.#max = max;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* toJSON for *.score
|
|
* @return {{min: string, max: string, raw: string}}
|
|
*/
|
|
toJSON() {
|
|
this.jsonString = true;
|
|
const result = {
|
|
'raw': this.raw,
|
|
'min': this.min,
|
|
'max': this.max,
|
|
};
|
|
delete this.jsonString;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Base class for cmi *.n objects
|
|
*/
|
|
export class CMIArray extends BaseCMI {
|
|
/**
|
|
* Constructor cmi *.n arrays
|
|
* @param {string} children
|
|
* @param {number} errorCode
|
|
* @param {class} errorClass
|
|
*/
|
|
constructor({children, errorCode, errorClass}) {
|
|
super();
|
|
this.#_children = children;
|
|
this.#errorCode = errorCode;
|
|
this.#errorClass = errorClass;
|
|
this.childArray = [];
|
|
}
|
|
|
|
#errorCode;
|
|
#errorClass;
|
|
#_children;
|
|
|
|
/**
|
|
* Getter for _children
|
|
* @return {*}
|
|
*/
|
|
get _children() {
|
|
return this.#_children;
|
|
}
|
|
|
|
/**
|
|
* Setter for _children. Just throws an error.
|
|
* @param {string} _children
|
|
*/
|
|
set _children(_children) {
|
|
throw new this.#errorClass.prototype.constructor(this.#errorCode);
|
|
}
|
|
|
|
/**
|
|
* Getter for _count
|
|
* @return {number}
|
|
*/
|
|
get _count() {
|
|
return this.childArray.length;
|
|
}
|
|
|
|
/**
|
|
* Setter for _count. Just throws an error.
|
|
* @param {number} _count
|
|
*/
|
|
set _count(_count) {
|
|
throw new this.#errorClass.prototype.constructor(this.#errorCode);
|
|
}
|
|
|
|
/**
|
|
* toJSON for *.n arrays
|
|
* @return {object}
|
|
*/
|
|
toJSON() {
|
|
this.jsonString = true;
|
|
const result = {};
|
|
for (let i = 0; i < this.childArray.length; i++) {
|
|
result[i + ''] = this.childArray[i];
|
|
}
|
|
delete this.jsonString;
|
|
return result;
|
|
}
|
|
}
|