]> git.mjollnir.org Git - moodle.git/commitdiff
General cleaning of function SetValue
authorbobopinna <bobopinna>
Mon, 4 Jun 2007 07:26:00 +0000 (07:26 +0000)
committerbobopinna <bobopinna>
Mon, 4 Jun 2007 07:26:00 +0000 (07:26 +0000)
First step for solving CMIFeedback pattern matching

mod/scorm/datamodels/scorm_13.js.php

index 46c496812574e6cf623c35da4ce4f4b41f8d2815..12a1ee9938bfc890b1d67c8df96991552feec377 100644 (file)
         }
     }
 ?>
-    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<parseInt(ind)){
-                                                               elem = 'cmi.interactions.N'+ind+'.id';
-                                                               if (eval(elem)==value){
-                                                                   errorCode = "351";
-                                                            diagnostic = "Write Once Violation";
-                                                               }
-                                                                                                               else{
-                                                           i++;
-                                                                                                               }
-                                                       }
-                                                 }
-                                                 
-                                                 if (elementmodel=='cmi.interactions.n.objectives.n.id') {
-                                                    elementIndexesSubindexes = element.split('.');
-                                                    elementFirstindex = elementIndexesSubindexes [2];
-                                                       longit = elementFirstindex.length;
-       
-                                                       longit--;
-                                                       if (longit == 1){
-        
-                                                           ind = elementFirstindex.substring(1);
-                                                       }
-                                                    else{
-                                                           ind = elementFirstindex.substring(1,longit);
-                                                       }
-       
-                                                       elementSubindex = elementIndexesSubindexes [4];
-                                                       longit2 = elementSubindex.length;
-        
-                                                       longit2--;
-                                                       if (longit2 == 1){
-            
-                                                              subind = elementSubindex.substring(1);
-               
-                                                           }
-                                                           else{
-    
-                                                          subind = elementSubindex.substring(1,longit2);
-                                                       }
-       
-                                                       i=0;
-                                                       while (i<parseInt(subind)){
-                                                               elem = 'cmi.interactions.N'+ind+'.objectives.N'+i+'.id';
-                                                               if (eval(elem)==value){
-                                                                   errorCode = "351";
-                                                            diagnostic = "Write Once Violation";
-                                                               }
-                                                           i++;
-                                                       }
-                      
-  
-                                                                                               
-
-                                                                                               }
-                                                 
-                                                if (elementmodel=='cmi.interactions.n.learner_response') {
-                                                    if (typeof eval(subelement+'.type') == "undefined") {
-                                                        errorCode="408";
-                                                    } else {
-                                                        // Use cmi.interactions.n.type value to check the right dataelement format
+                                    } else {
+                                        switch (elementmodel) {
+                                            case 'cmi.objectives.n.id':
+                                                if (eval(element) != value) {
+                                                    errorCode = "351";
+                                                    diagnostic = "Write Once Violation";
+                                                }
+                                            break; 
+                                            case 'cmi.interactions.n.id':
+                                            case 'cmi.interactions.n.objectives.n.id':
+                                                if (duplicatedID(element,parentelement,value)) {
+                                                    errorCode = "351";
+                                                    diagnostic = "Data Model Element ID Already Exists";
+                                                }
+                                            break;
+                                            case 'cmi.interactions.n.type':
+                                                var subobject = eval(subelement);
+                                                subobject.correct_responses = new Object();
+                                                subobject.correct_responses._count = 0;
+                                            break;
+                                            case 'cmi.interactions.n.learner_response':
+                                                if (typeof eval(subelement+'.type') == "undefined") {
+                                                    errorCode="408";
+                                                } else {
+                                                    // Use cmi.interactions.n.type value to check the right dataelement format
+                                                    interactiontype = eval(subelement+'.type');
+                                                    expression = new RegExp(learner_response[interactiontype]);
+                                                    matches = value.match(expression);
+                                                    if ((matches == null) || (matches.join('').length == 0)) {
+                                                        errorCode = "406";
                                                     }
                                                 }
-                                                if ((elementmodel==parentmodel+'.n.type') && (errorCode=="0")) { 
-                                                    subobject = eval(subelement);
-                                                    subobject.correct_responses = new Object();
-                                                    subobject.correct_responses._count = 0;
-                                                } 
-                                             }
-                                         }
-                                     }
+                                             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
+                                                     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 ((correct_responses[interactiontype].unique == true) && 
+                                                         (duplicatedPA(element,parentelement,value))) {
+                                                         errorCode="351";
+                                                         diagnostic = "Data Model Element Pattern Already Exists";
+                                                     } else {
+                                                         if ((matches == null) || (matches.join('').length == 0)) {
+                                                             errorCode = "406";
+                                                         }
+                                                     }
+                                                 } else {
+                                                     errorCode="408";
+                                                 }
+                                             break;
+                                        } 
+                                    }
                                 }
                             }
                             //Store data
@@ -833,11 +814,22 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
         return param;
     }
 
-    function duplicatedID (element, value) {
+    function duplicatedID (element, parent, value) {
         var found = false;
-        var elements = eval(element+'._count');
-        for (n=0;(n<elements) && (!found);n++) {
-            if (eval(element+'.N'+n+'.id') == value) {
+        var elements = eval(parent+'._count');
+        for (var n=0;(n<elements) && (!found);n++) {
+            if ((parent+'.N'+n+'.id' != element) && (eval(parent+'.N'+n+'.id') == value)) {
+                found = true;
+            }
+        } 
+        return found;
+    }
+
+    function duplicatedPA (element, parent, value) {
+        var found = false;
+        var elements = eval(parent+'._count');
+        for (var n=0;(n<elements) && (!found);n++) {
+            if ((parent+'.N'+n+'.pattern' != element) && (eval(parent+'.N'+n+'.pattern') == value)) {
                 found = true;
             }
         } 
@@ -848,12 +840,13 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
         if (typeof datamodel[element] != "undefined") {
             return element;
         } else {
-            expression = new RegExp(CMIIndex,'g');
-            elementmodel = element.replace(expression,'.n.');
+            var expression = new RegExp(CMIIndex,'g');
+            var elementmodel = element.replace(expression,'.n.');
             if (typeof datamodel[elementmodel] != "undefined") {
                 return elementmodel;
             }
         }
+        return false;
     }
 
     function AddTime (first, second) {
@@ -868,17 +861,17 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
         var secondarray = second.match(matchexpr);
         if ((firstarray != null) && (secondarray != null)) {
             var secs = parseFloat(firstarray[13],10)+parseFloat(secondarray[13],10);  //Seconds
-            change = Math.floor(secs / 60);
+            var change = Math.floor(secs / 60);
             secs = secs - (change * 60);
-            mins = parseInt(firstarray[11],10)+parseInt(secondarray[11],10)+change;   //Minutes
+            var mins = parseInt(firstarray[11],10)+parseInt(secondarray[11],10)+change;   //Minutes
             change = Math.floor(mins / 60);
             mins = mins - (change * 60);
-            hours = parseInt(firstarray[10],10)+parseInt(secondarray[10],10)+change;  //Hours
+            var hours = parseInt(firstarray[10],10)+parseInt(secondarray[10],10)+change;  //Hours
             change = Math.floor(hours / 24);
             hours = hours - (change * 24);
-            days = parseInt(firstarray[6],10)+parseInt(secondarray[6],10)+change; // Days
-            months = parseInt(firstarray[4],10)+parseInt(secondarray[4],10)
-            years = parseInt(firstarray[2],10)+parseInt(secondarray[2],10)
+            var days = parseInt(firstarray[6],10)+parseInt(secondarray[6],10)+change; // Days
+            var months = parseInt(firstarray[4],10)+parseInt(secondarray[4],10)
+            var years = parseInt(firstarray[2],10)+parseInt(secondarray[2],10)
         }
         if (years > 0) {
             timestring += years + 'Y';
@@ -905,7 +898,7 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
     }
 
     function TotalTime() {
-        total_time = AddTime(cmi.total_time, cmi.session_time);
+        var total_time = AddTime(cmi.total_time, cmi.session_time);
         return '&'+underscore('cmi.total_time')+'='+encodeURIComponent(total_time);
     }
 
@@ -915,12 +908,12 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
             if (typeof data[property] == 'object') {
                 datastring += CollectData(data[property],parent+'.'+property);
             } else {
-                element = parent+'.'+property;
-                expression = new RegExp(CMIIndexStore,'g');
-                elementmodel = element.replace(expression,'.n.');
+                var element = parent+'.'+property;
+                var expression = new RegExp(CMIIndexStore,'g');
+                var elementmodel = element.replace(expression,'.n.');
                 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
                     if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
-                        elementstring = '&'+underscore(element)+'='+encodeURIComponent(data[property]);
+                        var elementstring = '&'+underscore(element)+'='+encodeURIComponent(data[property]);
                         if ((typeof eval('datamodel["'+elementmodel+'"].defaultvalue')) != "undefined") {
                             if (eval('datamodel["'+elementmodel+'"].defaultvalue') != data[property]) {
                                 datastring += elementstring;
@@ -936,7 +929,7 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
     }
 
     function StoreData(data,storetotaltime) {
-        datastring = '';
+        var datastring = '';
         if (storetotaltime) {
             if (cmi.mode == 'normal') {
                 if (cmi.credit == 'credit') {
@@ -959,8 +952,8 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
             datastring += TotalTime();
         }
         datastring += CollectData(data,'cmi');
-        element = 'adl.nav.request';
-        navrequest = eval(element) != datamodel[element].defaultvalue ? '&'+underscore(element)+'='+encodeURIComponent(eval(element)) : '';
+        var element = 'adl.nav.request';
+        var navrequest = eval(element) != datamodel[element].defaultvalue ? '&'+underscore(element)+'='+encodeURIComponent(eval(element)) : '';
         datastring += navrequest;
         datastring += '&attempt=<?php echo $attempt ?>';
         datastring += '&scoid=<?php echo $scoid ?>';
@@ -970,13 +963,13 @@ alert('element = '+element+"\nsubelement = "+subelement+"\nparentmodel = "+paren
             }
         ?>
         var myRequest = NewHttpReq();
-        result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&sesskey=<?php p($USER->sesskey) ?>"+datastring);
+        var result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&sesskey=<?php p($USER->sesskey) ?>"+datastring);
         <?php
             if (debugging('',DEBUG_DEVELOPER)) {
                 echo 'popupwin(result);';
             }
         ?>
-        results = result.split('\n');
+        var results = result.split('\n');
         if ((results.length > 2) && (navrequest != '')) {
             eval(results[2]);
         }