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
*/
loadFromFlattenedJSON(json, CMIElement) {
console.clear();
if (!this.isNotInitialized()) {
console.error(
'loadFromFlattenedJSON can only be called before the call to lmsInitialize.');
@@ -866,39 +865,23 @@ export default class BaseAPI {
function testPattern(a, c, a_pattern) {
const a_match = a.match(a_pattern);
if (a_match !== null) {
let c_match = c.match(
new RegExp(a_match[1] + Number(a_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);
}
let c_match;
if (a_match !== null && (c_match = c.match(a_pattern)) !== null) {
return Number(a_match[2]) - Number(c_match[2]);
}
return null;
}
/**
* Function to sort the array, which we'll call until we're done.
*
* @param {string} a
* @param {string} b
* @param {string} c
* @param {string} d
* @return {number}
*/
function resultSort([a, b], [c, d]) {
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
result.sort(function([a, b], [c, d]) {
let test;
if ((test = testPattern(a, c, int_pattern)) !== null) {
return test;
@@ -914,25 +897,10 @@ export default class BaseAPI {
return 1;
}
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;
sorted_result.forEach((element) => {
result.forEach((element) => {
obj = {};
obj[element[0]] = element[1];
this.loadFromJSON(unflatten(obj), CMIElement);

View File

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

View File

@@ -819,7 +819,7 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} type
*/
set type(type) {
if (typeof this.id === 'undefined') {
if (this.initialized && typeof this.id === 'undefined') {
throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
@@ -842,8 +842,13 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} timestamp
*/
set timestamp(timestamp) {
if (check2004ValidFormat(timestamp, scorm2004_regex.CMITime)) {
this.#timestamp = timestamp;
if (this.initialized && typeof this.id === 'undefined') {
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
*/
set weighting(weighting) {
if (check2004ValidFormat(weighting, scorm2004_regex.CMIDecimal)) {
this.#weighting = weighting;
if (this.initialized && typeof this.id === 'undefined') {
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
*/
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(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
@@ -962,8 +973,13 @@ export class CMIInteractionsObject extends BaseCMI {
* @param {string} latency
*/
set latency(latency) {
if (check2004ValidFormat(latency, scorm2004_regex.CMITimespan)) {
this.#latency = latency;
if (this.initialized && typeof this.id === 'undefined') {
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
*/
set description(description) {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
true)) {
this.#description = description;
if (this.initialized && typeof this.id === 'undefined') {
throw new ValidationError(
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
*/
set success_status(success_status) {
if (check2004ValidFormat(success_status, scorm2004_regex.CMISStatus)) {
this.#success_status = success_status;
if (this.initialized && typeof this.id === 'undefined') {
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
*/
set completion_status(completion_status) {
if (check2004ValidFormat(completion_status, scorm2004_regex.CMICStatus)) {
this.#completion_status = completion_status;
if (this.initialized && typeof this.id === 'undefined') {
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
*/
set progress_measure(progress_measure) {
if (check2004ValidFormat(progress_measure, scorm2004_regex.CMIDecimal) &&
check2004ValidRange(progress_measure, scorm2004_regex.progress_range)) {
this.#progress_measure = progress_measure;
if (this.initialized && typeof this.id === 'undefined') {
throw new ValidationError(
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
*/
set description(description) {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
true)) {
this.#description = description;
if (this.initialized && typeof this.id === 'undefined') {
throw new ValidationError(
scorm2004_error_codes.DEPENDENCY_NOT_ESTABLISHED);
} else {
if (check2004ValidFormat(description, scorm2004_regex.CMILangString250,
true)) {
this.#description = description;
}
}
}