From d5f9eb42b1d3973d091f491b1f99b2232f5ccad5 Mon Sep 17 00:00:00 2001 From: bobopinna Date: Mon, 4 Jun 2007 07:26:00 +0000 Subject: [PATCH] General cleaning of function SetValue First step for solving CMIFeedback pattern matching --- mod/scorm/datamodels/scorm_13.js.php | 487 +++++++++++++-------------- 1 file changed, 240 insertions(+), 247 deletions(-) diff --git a/mod/scorm/datamodels/scorm_13.js.php b/mod/scorm/datamodels/scorm_13.js.php index 46c4968125..12a1ee9938 100644 --- a/mod/scorm/datamodels/scorm_13.js.php +++ b/mod/scorm/datamodels/scorm_13.js.php @@ -13,54 +13,80 @@ } } ?> - var cmi = new Object(); // Used need to debug cmi content (if you uncomment this, you must comment the definition inside SCORMapi1_3) + +// Used need to debug cmi content (if you uncomment this, you must comment the definition inside SCORMapi1_3) +//var cmi = new Object(); // // SCORM 1.3 API Implementation // function SCORMapi1_3() { // Standard Data Type Definition - CMIString200 = '^.{0,200}$'; - CMIString250 = '^.{0,250}$'; - CMILangString250 = '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250}$)?'; - CMIString1000 = '^.{0,1500}$'; - CMIString4000 = '^.{0,4000}$'; - CMILangString4000 = '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,4000}$)?'; - CMIString64000 = '^.{0,64000}$'; - CMILang = '^([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?$|^$'; - CMITime = '^(19[7-9]{1}[0-9]{1}|20[0-2]{1}[0-9]{1}|203[0-8]{1})((-(0[1-9]{1}|1[0-2]{1}))((-(0[1-9]{1}|[1-2]{1}[0-9]{1}|3[0-1]{1}))(T([0-1]{1}[0-9]{1}|2[0-3]{1})((:[0-5]{1}[0-9]{1})((:[0-5]{1}[0-9]{1})((\\.[0-9]{1,2})((Z|([+|-]([0-1]{1}[0-9]{1}|2[0-3]{1})))(:[0-5]{1}[0-9]{1})?)?)?)?)?)?)?)?$'; - CMITimespan = '^P(\\d+Y)?(\\d+M)?(\\d+D)?(T(((\\d+H)(\\d+M)?(\\d+(\.\\d{1,2})?S)?)|((\\d+M)(\\d+(\.\\d{1,2})?S)?)|((\\d+(\.\\d{1,2})?S))))?$'; - CMIInteger = '^\\d+$'; - CMISInteger = '^-?([0-9]+)$'; - CMIDecimal = '^-?([0-9]{1,4})(\\.[0-9]{1,18})?$'; - CMIIdentifier = '^\\S{0,200}[a-zA-Z0-9]$'; - CMILongIdentifier = '^\\S{0,4000}[a-zA-Z0-9]$'; - CMIFeedback = '^.*$'; // This must be redefined - CMIIndex = '[._](\\d+).'; - CMIIndexStore = '.N(\\d+).'; + var CMIString200 = '^.{0,200}$'; + var CMIString250 = '^.{0,250}$'; + var CMIString1000 = '^.{0,1500}$'; + var CMIString4000 = '^.{0,4000}$'; + var CMIString64000 = '^.{0,64000}$'; + var CMILang = '^([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?$|^$'; + var CMILangString250 = '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250}$)?'; + var CMILangString4000 = '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,4000}$)?'; + var CMITime = '^(19[7-9]{1}[0-9]{1}|20[0-2]{1}[0-9]{1}|203[0-8]{1})((-(0[1-9]{1}|1[0-2]{1}))((-(0[1-9]{1}|[1-2]{1}[0-9]{1}|3[0-1]{1}))(T([0-1]{1}[0-9]{1}|2[0-3]{1})((:[0-5]{1}[0-9]{1})((:[0-5]{1}[0-9]{1})((\\.[0-9]{1,2})((Z|([+|-]([0-1]{1}[0-9]{1}|2[0-3]{1})))(:[0-5]{1}[0-9]{1})?)?)?)?)?)?)?)?$'; + var CMITimespan = '^P(\\d+Y)?(\\d+M)?(\\d+D)?(T(((\\d+H)(\\d+M)?(\\d+(\.\\d{1,2})?S)?)|((\\d+M)(\\d+(\.\\d{1,2})?S)?)|((\\d+(\.\\d{1,2})?S))))?$'; + var CMIInteger = '^\\d+$'; + var CMISInteger = '^-?([0-9]+)$'; + var CMIDecimal = '^-?([0-9]{1,4})(\\.[0-9]{1,18})?$'; + var CMIIdentifier = '^\\S{0,250}[a-zA-Z0-9]$'; + var CMILongIdentifier = '^\\S{0,4000}[a-zA-Z0-9]$'; + var CMIFeedback = '^.*$'; // This must be redefined + var CMIIndex = '[._](\\d+).'; + var CMIIndexStore = '.N(\\d+).'; // Vocabulary Data Type Definition - CMICStatus = '^completed$|^incomplete$|^not attempted$|^unknown$'; - CMISStatus = '^passed$|^failed$|^unknown$'; - CMIExit = '^time-out$|^suspend$|^logout$|^normal$|^$'; - CMIType = '^true-false$|^choice$|^(long-)?fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$|^other$'; - CMIResult = '^correct$|^incorrect$|^unanticipated$|^neutral$|^-?([0-9]{1,4})(\\.[0-9]{1,18})?$'; - NAVEvent = '^previous$|^continue$|^exit$|^exitAll$|^abandon$|^abandonAll$|^suspendAll$|^{target=\\S{0,200}[a-zA-Z0-9]}choice$'; - NAVBoolean = '^unknown$|^true$|^false$'; - NAVTarget = '^previous$|^continue$|^choice.{target=\\S{0,200}[a-zA-Z0-9]}$' + var CMICStatus = '^completed$|^incomplete$|^not attempted$|^unknown$'; + var CMISStatus = '^passed$|^failed$|^unknown$'; + var CMIExit = '^time-out$|^suspend$|^logout$|^normal$|^$'; + var CMIType = '^true-false$|^choice$|^(long-)?fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$|^other$'; + var CMIResult = '^correct$|^incorrect$|^unanticipated$|^neutral$|^-?([0-9]{1,4})(\\.[0-9]{1,18})?$'; + var NAVEvent = '^previous$|^continue$|^exit$|^exitAll$|^abandon$|^abandonAll$|^suspendAll$|^{target=\\S{0,200}[a-zA-Z0-9]}choice$'; + var NAVBoolean = '^unknown$|^true$|^false$'; + var NAVTarget = '^previous$|^continue$|^choice.{target=\\S{0,200}[a-zA-Z0-9]}$' // Children lists - cmi_children = '_version, comments_from_learner, comments_from_lms, completion_status, credit, entry, exit, interactions, launch_data, learner_id, learner_name, learner_preference, location, max_time_allowed, mode, objectives, progress_measure, scaled_passing_score, score, session_time, success_status, suspend_data, time_limit_action, total_time'; - comments_children = 'comment, timestamp, location'; - score_children = 'max, raw, scaled, min'; - objectives_children = 'progress_measure, completion_status, success_status, description, score, id'; - student_data_children = 'mastery_score, max_time_allowed, time_limit_action'; - student_preference_children = 'audio_level, audio_captioning, delivery_speed, language'; - interactions_children = 'id, type, objectives, timestamp, correct_responses, weighting, learner_response, result, latency, description'; + var cmi_children = '_version, comments_from_learner, comments_from_lms, completion_status, credit, entry, exit, interactions, launch_data, learner_id, learner_name, learner_preference, location, max_time_allowed, mode, objectives, progress_measure, scaled_passing_score, score, session_time, success_status, suspend_data, time_limit_action, total_time'; + var comments_children = 'comment, timestamp, location'; + var score_children = 'max, raw, scaled, min'; + var objectives_children = 'progress_measure, completion_status, success_status, description, score, id'; + var student_data_children = 'mastery_score, max_time_allowed, time_limit_action'; + var student_preference_children = 'audio_level, audio_captioning, delivery_speed, language'; + var interactions_children = 'id, type, objectives, timestamp, correct_responses, weighting, learner_response, result, latency, description'; // Data ranges - scaled_range = '-1#1'; - audio_range = '0#*'; - speed_range = '0#*'; - text_range = '-1#1'; - progress_range = '0#1'; + var scaled_range = '-1#1'; + var audio_range = '0#*'; + var speed_range = '0#*'; + var text_range = '-1#1'; + var progress_range = '0#1'; + var learner_response = { + 'true-false':'^true$|^false$', + 'choice':'^(\\S{0,250}[a-zA-Z0-9])((\[\,\])\\S{0,250}[a-zA-Z0-9]){0,35}$', + 'fill-in':'^((\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250})?)(\[\,\]((\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250})?)){0,9}$', + 'long-fill-in':CMILangString4000, + 'matching':'^(\\S{0,250}[a-zA-Z0-9](\[\\.\])\\S{0,250}[a-zA-Z0-9])((\[\,\])\\S{0,250}[a-zA-Z0-9](\[\\.\])\\S{0,250}[a-zA-Z0-9]){0,35}$', + 'performance':'^.$', + 'sequencing':'^(\\S{0,250}[a-zA-Z0-9])((\[\,\])\\S{0,250}[a-zA-Z0-9]){0,35}$', + 'likert':CMIIdentifier, + 'numeric':CMIDecimal, + 'other':CMIString4000 + } + var correct_responses = { + 'true-false':{'format':'^true$|^false$', 'unique':false, 'limit':1}, + 'choice':{'format':'^(\\S{0,250}[a-zA-Z0-9])((\[\,\])(\\S{0,250}[a-zA-Z0-9])){0,35}$', 'unique':true}, + 'fill-in':{'format':'^(\{case_matters=(true|false)\})?(\{order_matters=(true|false)\})?((\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250})?)((\[\,\])((\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250})?)){0,9}$', 'unique':false}, + 'long-fill-in':{'format':'^(\{case_matters=(true|false)\})?(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,4000}$)?', 'unique':false}, + 'matching':{'format':'^(\\S{0,250}[a-zA-Z0-9](\[\\.\])\\S{0,250}[a-zA-Z0-9])((\[\,\])\\S{0,250}[a-zA-Z0-9](\[\\.\])\\S{0,250}[a-zA-Z0-9]){0,35}$', 'unique':false}, + 'performance':{'format':'^.$', 'unique':false}, + 'sequencing':{'format':'^(\\S{0,250}[a-zA-Z0-9])((\[\,\])\\S{0,250}[a-zA-Z0-9]){0,35}$', 'unique':true}, + 'likert':{'format':CMIIdentifier, 'unique':false, 'limit':1}, + 'numeric':{'format':'^(-?([0-9]{1,4})(\\.[0-9]{1,18})?)?(\[\:\])(-?([0-9]{1,4})(\\.[0-9]{1,18})?)?$', 'unique':false, 'limit':1}, + 'other':{'format':CMIString4000, 'unique':false, 'limit':1} + } // The SCORM 1.3 data model var datamodel = { 'cmi._children':{'defaultvalue':cmi_children, 'mod':'r'}, @@ -134,7 +160,7 @@ function SCORMapi1_3() { // // Datamodel inizialization // -// var cmi = new Object(); + var cmi = new Object(); cmi.comments_from_learner = new Object(); cmi.comments_from_learner._count = 0; cmi.comments_from_lms = new Object(); @@ -236,7 +262,7 @@ function SCORMapi1_3() { ?> Initialized = false; Terminated = true; - result = StoreData(cmi,true); + var result = StoreData(cmi,true); if (adl.nav.request != '_none_') { switch (adl.nav.request) { case 'continue': @@ -285,8 +311,8 @@ function SCORMapi1_3() { diagnostic = ""; if ((Initialized) && (!Terminated)) { if (element !="") { - expression = new RegExp(CMIIndex,'g'); - elementmodel = element.replace(expression,'.n.'); + var expression = new RegExp(CMIIndex,'g'); + var elementmodel = element.replace(expression,'.n.'); if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") { if (eval('datamodel["'+elementmodel+'"].mod') != 'w') { @@ -294,9 +320,9 @@ function SCORMapi1_3() { element = element.replace(/\.(\d+)\./, ".N$1."); element = element.replace(/\.(\d+)\./, ".N$1."); - elementIndexes = element.split('.'); - subelement = element.substr(0,3); - i = 1; + var elementIndexes = element.split('.'); + var subelement = element.substr(0,3); + var i = 1; while ((i < elementIndexes.length) && (typeof eval(subelement) != "undefined")) { subelement += '.'+elementIndexes[i++]; @@ -323,8 +349,9 @@ function SCORMapi1_3() { errorCode = "405"; } } else { - childrenstr = '._children'; - countstr = '._count'; + var childrenstr = '._children'; + var countstr = '._count'; + var parentmodel = ''; if (elementmodel.substr(elementmodel.length-childrenstr.length,elementmodel.length) == childrenstr) { parentmodel = elementmodel.substr(0,elementmodel.length-childrenstr.length); if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") { @@ -383,8 +410,8 @@ function SCORMapi1_3() { diagnostic = ""; if ((Initialized) && (!Terminated)) { if (element != "") { - expression = new RegExp(CMIIndex,'g'); - elementmodel = element.replace(expression,'.n.'); + var expression = new RegExp(CMIIndex,'g'); + var elementmodel = element.replace(expression,'.n.'); if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") { if (eval('datamodel["'+elementmodel+'"].mod') != 'r') { if (eval('datamodel["'+elementmodel+'"].format') != 'CMIFeedback') { @@ -394,17 +421,18 @@ function SCORMapi1_3() { expression = new RegExp(CMIFeedback); } value = value+''; - matches = value.match(expression); + var matches = value.match(expression); if ((matches != null) && ((matches.join('').length > 0) || (value.length == 0))) { - - //Create dynamic data model element + // Value match dataelement format if (element != elementmodel) { - elementIndexes = element.split('.'); - subelement = 'cmi'; - parentelement = 'cmi'; - for (i=1;(i < elementIndexes.length-1) && (errorCode=="0");i++) { - elementIndex = elementIndexes[i]; + //This is a dynamic datamodel element + + var elementIndexes = element.split('.'); + var subelement = 'cmi'; + var parentelement = 'cmi'; + for (var i=1;(i < elementIndexes.length-1) && (errorCode=="0");i++) { + var elementIndex = elementIndexes[i]; if (elementIndexes[i+1].match(/^\d+$/)) { if ((parseInt(elementIndexes[i+1]) > 0) && (elementIndexes[i+1].charAt(0) == 0)) { // Index has a leading 0 (zero), this is not a number @@ -415,7 +443,6 @@ function SCORMapi1_3() { errorCode="408"; } else { if (elementIndexes[i+1] > eval(parentelement+'._count')) { - errorCode = "351"; diagnostic = "Data Model Element Collection Set Out Of Order"; } @@ -432,22 +459,18 @@ function SCORMapi1_3() { } if (errorCode == "0") { + // Till now it's a real datamodel element element = subelement.concat('.'+elementIndexes[elementIndexes.length-1]); - elemlen = element.length; - - if (((typeof eval(subelement)) == "undefined") && (errorCode == "0")) { - parentmodel = 'cmi.objectives'; - if (subelement.substr(0,parentmodel.length) == parentmodel) { - - if ((elementmodel==parentmodel+'.n.id') && (errorCode=="0")) { - //This is a cmi.objectives.n.id element - if (!duplicatedID(parentmodel,value)) { - if (elementIndexes[elementIndexes.length-2] == eval(parentmodel+'._count')) { - eval(parentmodel+'._count++;'); + if ((typeof eval(subelement)) == "undefined") { + switch (elementmodel) { + case 'cmi.objectives.n.id': + if (!duplicatedID(element,parentelement,value)) { + if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) { + eval(parentelement+'._count++;'); eval(subelement+' = new Object();'); - subobject = eval(subelement); + var subobject = eval(subelement); subobject.success_status = datamodel["cmi.objectives.n.success_status"].defaultvalue; subobject.completion_status = datamodel["cmi.objectives.n.completion_status"].defaultvalue; subobject.progress_measure = datamodel["cmi.objectives.n.progress_measure"].defaultvalue; @@ -462,185 +485,143 @@ function SCORMapi1_3() { errorCode="351"; diagnostic = "Data Model Element ID Already Exists"; } - } else { - - - if (typeof eval(subelement) == "undefined") { - errorCode="408"; + break; + case 'cmi.interactions.n.id': + if (!duplicatedID(element,parentelement,value)) { + if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) { + eval(parentelement+'._count++;'); + eval(subelement+' = new Object();'); + var subobject = eval(subelement); + subobject.objectives = new Object(); + subobject.objectives._count = 0; + } } else { - if (duplicatedID(parentmodel,value)) { - errorCode="351"; - diagnostic = "Data Model Element ID Already Exists"; - } + errorCode="351"; + diagnostic = "Data Model Element ID Already Exists"; } - } - } else { - - parentmodel = 'cmi.interactions'; - - if (subelement.substr(0,parentmodel.length) == parentmodel) { - - if ((elementmodel==parentmodel+'.n.id') && (errorCode=="0")) { - - //This is a cmi.interactions.n.id element - if (!duplicatedID(parentmodel,value)) { - - if (elementIndexes[elementIndexes.length-2] == eval(parentmodel+'._count')) { - - eval(parentmodel+'._count++;'); - + break; + case 'cmi.interactions.n.objectives.n.id': + if (typeof eval(parentelement) != "undefined") { + if (!duplicatedID(element,parentelement,value)) { + if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) { + eval(parentelement+'._count++;'); eval(subelement+' = new Object();'); - - subobject = eval(subelement); - subobject.objectives = new Object(); - subobject.objectives._count = 0; - } + } } else { errorCode="351"; diagnostic = "Data Model Element ID Already Exists"; } } else { -alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+parentmodel+"\nparentelement = "+parentelement+"\nvalue = "+value); - if (typeof eval(subelement) == "undefined") { - if ((elementmodel=='cmi.interactions.n.objectives.n.id') && (typeof eval(parentelement) != "undefined")) { - if (!duplicatedID(parentelement,value)) { - if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) { - eval(parentelement+'._count++;'); - - eval(subelement+' = new Object();'); - } - } else { - - errorCode="351"; - diagnostic = "Data Model Element ID Already Exists"; - } - } else if (elementmodel=='cmi.interactions.n.correct_responses.n.pattern') { - if (typeof eval(parentelement) != "undefined") { - if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) { + errorCode="408"; + } + break; + case 'cmi.interactions.n.correct_responses.n.pattern': + if (typeof eval(parentelement) != "undefined") { + // Use cmi.interactions.n.type value to check the right dataelement format + var interactiontype = eval(parentelement.replace('correct_responses','type')); +//alert('type = '+interactiontype+"\nvalue = "+value); + expression = new RegExp(correct_responses[interactiontype].format); +//alert('type = '+interactiontype+"\nexpression = "+expression+"\nvalue = "+value); + matches = value.match(expression); +//alert('type = '+interactiontype+"\nexpression = "+expression+"\nmatches = "+matches.join("\n")+"\nvalue = "+value); + if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) { + if ((typeof correct_responses[interactiontype].limit == 'undefined') || + (eval(parentelement+'._count') < correct_responses[interactiontype].limit)) { + if ((correct_responses[interactiontype].unique == false) || + (!duplicatedPA(element,parentelement,value))) { + if ((matches == null) || (matches.join('').length == 0)) { + errorCode = "406"; + } else { eval(parentelement+'._count++;'); eval(subelement+' = new Object();'); } + } else { + errorCode="351"; + diagnostic = "Data Model Element Pattern Already Exists"; } - // Use cmi.interactions.n.type value to check the right dataelement format - } else { - errorCode="408"; + errorCode="351"; + diagnostic = "Data Model Element Collection Limit Reached"; } } else { - errorCode="408"; + errorCode="351"; + diagnostic = "Data Model Element Collection Set Out Of Order"; } + } else { + errorCode="408"; } - } else { - - if (errorCode == "0") { + break; + default: + if ((parentelement != 'cmi.objectives') && (parentelement != 'cmi.interactions') && (typeof eval(parentelement) != "undefined")) { if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) { eval(parentelement+'._count++;'); eval(subelement+' = new Object();'); + } else { + errorCode="351"; + diagnostic = "Data Model Element Collection Set Out Of Order"; } + } else { + errorCode="408"; } - } + break; } - } else { - - parentmodel = 'cmi.objectives'; - if (subelement.substr(0,parentmodel.length) == parentmodel) { - if ((elementmodel==parentmodel+'.n.id') && (errorCode=="0")) { - - if (eval(element) != value) { - errorCode = "351"; - diagnostic = "Write Once Violation"; - } - } - } else { - - parentmodel = 'cmi.interactions'; - if (subelement.substr(0,parentmodel.length) == parentmodel) { - if ((elementmodel==parentmodel+'.n.id') && (errorCode=="0")) { - elementIndexesSubindex = element.split('.'); - elementFirstind = elementIndexesSubindex [2]; - len = elementFirstind.length; - - len--; - if (len == 1){ - - ind = elementFirstind.substring(1); - } - else{ - ind = elementFirstind.substring(1,len); - } - - i=0; - while (i - results = result.split('\n'); + var results = result.split('\n'); if ((results.length > 2) && (navrequest != '')) { eval(results[2]); } -- 2.39.5