Not requiring fields to be previously set while loading existing data

This commit is contained in:
Jonathan Putney
2020-07-30 16:54:15 -04:00
parent dcad088b25
commit c341d3f70f
6 changed files with 199 additions and 188 deletions

180
dist/scorm-again.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -848,7 +848,6 @@ export default class BaseAPI {
* @param {string} CMIElement * @param {string} CMIElement
*/ */
loadFromFlattenedJSON(json, CMIElement) { loadFromFlattenedJSON(json, CMIElement) {
console.clear();
if (!this.isNotInitialized()) { if (!this.isNotInitialized()) {
console.error( console.error(
'loadFromFlattenedJSON can only be called before the call to lmsInitialize.'); 'loadFromFlattenedJSON can only be called before the call to lmsInitialize.');
@@ -866,39 +865,23 @@ export default class BaseAPI {
function testPattern(a, c, a_pattern) { function testPattern(a, c, a_pattern) {
const a_match = a.match(a_pattern); const a_match = a.match(a_pattern);
if (a_match !== null) { let c_match;
let c_match = c.match( if (a_match !== null && (c_match = c.match(a_pattern)) !== null) {
new RegExp(a_match[1] + Number(a_match[2]) + '.(.*)')); return Number(a_match[2]) - Number(c_match[2]);
if (c_match !== null) {
const a_int = Number(a_match[2]);
if (a_match[3] === 'id') {
return -1;
} else if (a_match[3] === 'type' && c_match[1] !== 'id') {
return -1;
} else {
return 1;
}
} else if ((c_match = c.match(a_pattern)) !== null) {
return Number(a_match[2]) - Number(c_match[2]);
} else {
return testPattern(c, a, a_pattern);
}
} }
return null; return null;
} }
/** const int_pattern = /^(cmi\.interactions\.)(\d+)\.(.*)$/;
* Function to sort the array, which we'll call until we're done. const obj_pattern = /^(cmi\.objectives\.)(\d+)\.(.*)$/;
*
* @param {string} a const result = Object.keys(json).map(function(key) {
* @param {string} b return [String(key), json[key]];
* @param {string} c });
* @param {string} d
* @return {number} // CMI interactions need to have id and type loaded before any other fields
*/ result.sort(function([a, b], [c, d]) {
function resultSort([a, b], [c, d]) {
let test; let test;
if ((test = testPattern(a, c, int_pattern)) !== null) { if ((test = testPattern(a, c, int_pattern)) !== null) {
return test; return test;
@@ -914,25 +897,10 @@ export default class BaseAPI {
return 1; return 1;
} }
return 0; return 0;
}
const int_pattern = /^(cmi\.interactions\.)(\d+)\.(.*)$/;
const obj_pattern = /^(cmi\.objectives\.)(\d+)\.(.*)$/;
const result = Object.keys(json).map(function(key) {
return [String(key), json[key]];
}); });
// CMI interactions need to have id and type loaded before any other fields
// Call the sort until everything is properly sorted.
// I must be missing an edge case in my sort?
let sorted_result = [];
while (sorted_result !== result.sort(resultSort)) {
sorted_result = result;
}
let obj; let obj;
sorted_result.forEach((element) => { result.forEach((element) => {
obj = {}; obj = {};
obj[element[0]] = element[1]; obj[element[0]] = element[1];
this.loadFromJSON(unflatten(obj), CMIElement); this.loadFromJSON(unflatten(obj), CMIElement);

View File

@@ -194,39 +194,42 @@ export default class Scorm2004API extends BaseAPI {
const parts = CMIElement.split('.'); const parts = CMIElement.split('.');
const index = Number(parts[2]); const index = Number(parts[2]);
const interaction = this.cmi.interactions.childArray[index]; const interaction = this.cmi.interactions.childArray[index];
if (!interaction.type) { if (this.isInitialized()) {
this.throwSCORMError(scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED); if (!interaction.type) {
} else { this.throwSCORMError(
const interaction_type = interaction.type; scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
const interaction_count = interaction.correct_responses._count; } else {
if (interaction_type === 'choice') { const interaction_type = interaction.type;
for (let i = 0; i < interaction_count && this.lastErrorCode === const interaction_count = interaction.correct_responses._count;
0; i++) { if (interaction_type === 'choice') {
const response = interaction.correct_responses.childArray[i]; for (let i = 0; i < interaction_count && this.lastErrorCode ===
if (response.pattern === value) { 0; i++) {
this.throwSCORMError(scorm2004_error_codes.GENERAL_SET_FAILURE); const response = interaction.correct_responses.childArray[i];
if (response.pattern === value) {
this.throwSCORMError(scorm2004_error_codes.GENERAL_SET_FAILURE);
}
} }
} }
}
const response_type = correct_responses[interaction_type]; const response_type = correct_responses[interaction_type];
if (response_type) { if (response_type) {
let nodes = []; let nodes = [];
if (response_type?.delimiter) { if (response_type?.delimiter) {
nodes = String(value).split(response_type.delimiter); nodes = String(value).split(response_type.delimiter);
} else {
nodes[0] = value;
}
if (nodes.length > 0 && nodes.length <= response_type.max) {
this.checkCorrectResponseValue(interaction_type, nodes, value);
} else if (nodes.length > response_type.max) {
this.throwSCORMError(scorm2004_error_codes.GENERAL_SET_FAILURE,
'Data Model Element Pattern Too Long');
}
} else { } else {
nodes[0] = value;
}
if (nodes.length > 0 && nodes.length <= response_type.max) {
this.checkCorrectResponseValue(interaction_type, nodes, value);
} else if (nodes.length > response_type.max) {
this.throwSCORMError(scorm2004_error_codes.GENERAL_SET_FAILURE, this.throwSCORMError(scorm2004_error_codes.GENERAL_SET_FAILURE,
'Data Model Element Pattern Too Long'); 'Incorrect Response Type: ' + interaction_type);
} }
} else {
this.throwSCORMError(scorm2004_error_codes.GENERAL_SET_FAILURE,
'Incorrect Response Type: ' + interaction_type);
} }
} }
if (this.lastErrorCode === 0) { if (this.lastErrorCode === 0) {

View File

@@ -819,7 +819,7 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} type * @param {string} type
*/ */
set type(type) { set type(type) {
if (typeof this.id === 'undefined') { if (this.initialized && typeof this.id === 'undefined') {
throw new ValidationError( throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED); scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
@@ -842,8 +842,13 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} timestamp * @param {string} timestamp
*/ */
set timestamp(timestamp) { set timestamp(timestamp) {
if (check2004ValidFormat(timestamp, scorm2004_regex.CMITime)) { if (this.initialized && typeof this.id === 'undefined') {
this.#timestamp = timestamp; throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(timestamp, scorm2004_regex.CMITime)) {
this.#timestamp = timestamp;
}
} }
} }
@@ -860,8 +865,13 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} weighting * @param {string} weighting
*/ */
set weighting(weighting) { set weighting(weighting) {
if (check2004ValidFormat(weighting, scorm2004_regex.CMIDecimal)) { if (this.initialized && typeof this.id === 'undefined') {
this.#weighting = weighting; throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(weighting, scorm2004_regex.CMIDecimal)) {
this.#weighting = weighting;
}
} }
} }
@@ -879,7 +889,8 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} learner_response * @param {string} learner_response
*/ */
set learner_response(learner_response) { set learner_response(learner_response) {
if (typeof this.type === 'undefined' || typeof this.id === 'undefined') { if (this.initialized && (typeof this.type === 'undefined' ||
typeof this.id === 'undefined')) {
throw new ValidationError( throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED); scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else { } else {
@@ -962,8 +973,13 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} latency * @param {string} latency
*/ */
set latency(latency) { set latency(latency) {
if (check2004ValidFormat(latency, scorm2004_regex.CMITimespan)) { if (this.initialized && typeof this.id === 'undefined') {
this.#latency = latency; throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(latency, scorm2004_regex.CMITimespan)) {
this.#latency = latency;
}
} }
} }
@@ -980,9 +996,14 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} description * @param {string} description
*/ */
set description(description) { set description(description) {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250, if (this.initialized && typeof this.id === 'undefined') {
true)) { throw new ValidationError(
this.#description = description; scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
true)) {
this.#description = description;
}
} }
} }
@@ -1081,8 +1102,13 @@ export class CMIObjectivesObject extends BaseCMI {
* @param {string} success_status * @param {string} success_status
*/ */
set success_status(success_status) { set success_status(success_status) {
if (check2004ValidFormat(success_status, scorm2004_regex.CMISStatus)) { if (this.initialized && typeof this.id === 'undefined') {
this.#success_status = success_status; throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(success_status, scorm2004_regex.CMISStatus)) {
this.#success_status = success_status;
}
} }
} }
@@ -1099,8 +1125,13 @@ export class CMIObjectivesObject extends BaseCMI {
* @param {string} completion_status * @param {string} completion_status
*/ */
set completion_status(completion_status) { set completion_status(completion_status) {
if (check2004ValidFormat(completion_status, scorm2004_regex.CMICStatus)) { if (this.initialized && typeof this.id === 'undefined') {
this.#completion_status = completion_status; throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(completion_status, scorm2004_regex.CMICStatus)) {
this.#completion_status = completion_status;
}
} }
} }
@@ -1117,9 +1148,15 @@ export class CMIObjectivesObject extends BaseCMI {
* @param {string} progress_measure * @param {string} progress_measure
*/ */
set progress_measure(progress_measure) { set progress_measure(progress_measure) {
if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) && if (this.initialized && typeof this.id === 'undefined') {
check2004ValidRange(progress_measure, scorm2004_regex.progress_range)) { throw new ValidationError(
this.#progress_measure = progress_measure; scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) &&
check2004ValidRange(progress_measure,
scorm2004_regex.progress_range)) {
this.#progress_measure = progress_measure;
}
} }
} }
@@ -1136,9 +1173,14 @@ export class CMIObjectivesObject extends BaseCMI {
* @param {string} description * @param {string} description
*/ */
set description(description) { set description(description) {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250, if (this.initialized && typeof this.id === 'undefined') {
true)) { throw new ValidationError(
this.#description = description; scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
true)) {
this.#description = description;
}
} }
} }