Fixed a problem with double indexed elements in the GetValue method
[moodle.git] / mod / scorm / datamodels / scorm_13.js.php
1 <?php
2     if (isset($userdata->status)) {
3         if ($userdata->status == ''&& (!(($userdata->{'cmi.exit'} == 'suspend') || ($userdata->{'cmi.exit'} == 'logout'))&& !($userdata->{'adl.nav.request'} == 'suspendAll'))||($userdata->{'cmi.exit'} == 'normal')) {      //antes solo llegaba esta lĂ­nea hasta el &&
4                 $userdata->entry = 'ab-initio';
5         } else {
6             if ((isset($userdata->{'cmi.exit'}) && (($userdata->{'cmi.exit'} == 'suspend') || ($userdata->{'cmi.exit'} == 'logout')))||(($userdata->{'adl.nav.request'} == 'suspendAll')&& isset($userdata->{'adl.nav.request'}) )) {
7                 $userdata->entry = 'resume';
8             } else {
9                 $userdata->entry = '';
10             }
11         }
12     }
13     $userdata->threshold = '0.8';
14 ?>
15     var cmi = new Object();
17 //
18 // SCORM 1.3 API Implementation
19 //
20 function SCORMapi1_3() {
21     // Standard Data Type Definition
22     CMIString200 = '^.{0,200}$';
23     CMIString250 = '^.{0,250}$';
24     CMILangString250 = '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,250}$)?';
25     CMIString1000 = '^.{0,1500}$';
26     CMIString4000 = '^.{0,4000}$';
27     CMILangString4000 = '^(\{lang=([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?\})?([^\{].{0,4000}$)?';
28     CMIString64000 = '^.{0,64000}$';
29     CMILang = '^([a-zA-Z]{2,3}|i|x)(\-[a-zA-Z0-9\-]{2,8})?$|^$';
30     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})?)?)?)?)?)?)?)?$';
31     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))))?$';
32     CMIInteger = '^\\d+$';
33     CMISInteger = '^-?([0-9]+)$';
34     CMIDecimal = '^-?([0-9]{1,4})(\\.[0-9]{1,18})?$';
35     CMIIdentifier = '^\\S{0,200}[a-zA-Z0-9]$';
36     CMILongIdentifier = '^\\S{0,4000}[a-zA-Z0-9]$';
37     CMIFeedback = CMIString200; // This must be redefined
38     CMIIndex = '[._](\\d+).';
39     CMIIndexStore = '.N(\\d+).';
40     // Vocabulary Data Type Definition
41     CMICStatus = '^completed$|^incomplete$|^not attempted$|^unknown$';
42     CMISStatus = '^passed$|^failed$|^unknown$';
43     CMIExit = '^time-out$|^suspend$|^logout$|^normal$|^$';
44     CMIType = '^true-false$|^choice$|^(long-)?fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$|^other$';
45     CMIResult = '^correct$|^incorrect$|^unanticipated$|^neutral$|^-?([0-9]{1,4})(\\.[0-9]{1,18})?$';
46     NAVEvent = '^previous$|^continue$|^exit$|^exitAll$|^abandon$|^abandonAll$|^suspendAll$|^{target=\\S{0,200}[a-zA-Z0-9]}choice$';
47     NAVBoolean = '^unknown$|^true$|^false$';
48     NAVTarget = '^previous$|^continue$|^choice.{target=\\S{0,200}[a-zA-Z0-9]}$'
49     // Children lists
50     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';
51     comments_children = 'comment, timestamp, location';
52     score_children = 'max, raw, scaled, min';
53     objectives_children = 'progress_measure, completion_status, success_status, description, score, id';
54     student_data_children = 'mastery_score, max_time_allowed, time_limit_action';
55     student_preference_children = 'audio_level, audio_captioning, delivery_speed, language';
56     interactions_children = 'id, type, objectives, timestamp, correct_responses, weighting, learner_response, result, latency, description';
57     // Data ranges
58     scaled_range = '-1#1';
59     audio_range = '0#*';
60     speed_range = '0#*';
61     text_range = '-1#1';
62     progress_range = '0#1';
63     // The SCORM 1.3 data model
64     var datamodel =  {
65         'cmi._children':{'defaultvalue':cmi_children, 'mod':'r'},
66         'cmi._version':{'defaultvalue':'1.0', 'mod':'r'},
67         'cmi.comments_from_learner._children':{'defaultvalue':comments_children, 'mod':'r'},
68         'cmi.comments_from_learner._count':{'mod':'r', 'defaultvalue':'0'},
69         'cmi.comments_from_learner.n.comment':{'format':CMILangString4000, 'mod':'rw'},
70         'cmi.comments_from_learner.n.location':{'format':CMIString250, 'mod':'rw'},
71         'cmi.comments_from_learner.n.timestamp':{'format':CMITime, 'mod':'rw'},
72         'cmi.comments_from_lms._children':{'defaultvalue':comments_children, 'mod':'r'},
73         'cmi.comments_from_lms._count':{'mod':'r', 'defaultvalue':'0'},
74         'cmi.comments_from_lms.n.comment':{'format':CMILangString4000, 'mod':'r'},
75         'cmi.comments_from_lms.n.location':{'format':CMIString250, 'mod':'r'},
76         'cmi.comments_from_lms.n.timestamp':{'format':CMITime, 'mod':'r'},
77         'cmi.completion_status':{'defaultvalue':'<?php echo isset($userdata->{'cmi.completion_status'})?$userdata->{'cmi.completion_status'}:'unknown' ?>', 'format':CMICStatus, 'mod':'rw'},
78         'cmi.completion_threshold':{'defaultvalue':<?php echo isset($userdata->threshold)?'\''.$userdata->threshold.'\'':'null' ?>, 'mod':'r'},
79         'cmi.credit':{'defaultvalue':'<?php echo isset($userdata->credit)?$userdata->credit:'' ?>', 'mod':'r'},
80         'cmi.entry':{'defaultvalue':'<?php echo $userdata->entry ?>', 'mod':'r'},
81         'cmi.exit':{'defaultvalue':'<?php echo isset($userdata->{'cmi.exit'})?$userdata->{'cmi.exit'}:'' ?>', 'format':CMIExit, 'mod':'w'},
82         'cmi.interactions._children':{'defaultvalue':interactions_children, 'mod':'r'},
83         'cmi.interactions._count':{'mod':'r', 'defaultvalue':'0'},
84         'cmi.interactions.n.id':{'pattern':CMIIndex, 'format':CMILongIdentifier, 'mod':'rw'},
85         'cmi.interactions.n.type':{'pattern':CMIIndex, 'format':CMIType, 'mod':'rw'},
86         'cmi.interactions.n.objectives._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0'},
87         'cmi.interactions.n.objectives.n.id':{'pattern':CMIIndex, 'format':CMILongIdentifier, 'mod':'rw'},
88         'cmi.interactions.n.timestamp':{'pattern':CMIIndex, 'format':CMITime, 'mod':'rw'},
89         'cmi.interactions.n.correct_responses._count':{'defaultvalue':'0', 'pattern':CMIIndex, 'mod':'r'},
90         'cmi.interactions.n.correct_responses.n.pattern':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'rw'},
91         'cmi.interactions.n.weighting':{'pattern':CMIIndex, 'format':CMIDecimal, 'mod':'rw'},
92         'cmi.interactions.n.learner_response':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'rw'},
93         'cmi.interactions.n.result':{'pattern':CMIIndex, 'format':CMIResult, 'mod':'rw'},
94         'cmi.interactions.n.latency':{'pattern':CMIIndex, 'format':CMITimespan, 'mod':'rw'},
95         'cmi.interactions.n.description':{'pattern':CMIIndex, 'format':CMILangString250, 'mod':'rw'},
96         'cmi.launch_data':{'defaultvalue':<?php echo isset($userdata->datafromlms)?'\''.$userdata->datafromlms.'\'':'null' ?>, 'mod':'r'},
97         'cmi.learner_id':{'defaultvalue':'<?php echo $userdata->student_id ?>', 'mod':'r'},
98         'cmi.learner_name':{'defaultvalue':'<?php echo addslashes($userdata->student_name) ?>', 'mod':'r'},
99         'cmi.learner_preference._children':{'defaultvalue':student_preference_children, 'mod':'r'},
100         'cmi.learner_preference.audio_level':{'defaultvalue':'1', 'format':CMIDecimal, 'range':audio_range, 'mod':'rw'},
101         'cmi.learner_preference.language':{'defaultvalue':'', 'format':CMILang, 'mod':'rw'},
102         'cmi.learner_preference.delivery_speed':{'defaultvalue':'1', 'format':CMIDecimal, 'range':speed_range, 'mod':'rw'},
103         'cmi.learner_preference.audio_captioning':{'defaultvalue':'0', 'format':CMISInteger, 'range':text_range, 'mod':'rw'},
104         'cmi.location':{'defaultvalue':<?php echo isset($userdata->{'cmi.location'})?'\''.$userdata->{'cmi.location'}.'\'':'null' ?>, 'format':CMIString1000, 'mod':'rw'},
105         'cmi.max_time_allowed':{'defaultvalue':<?php echo isset($userdata->maxtimeallowed)?'\''.$userdata->maxtimeallowed.'\'':'null' ?>, 'mod':'r'},
106         'cmi.mode':{'defaultvalue':'<?php echo $userdata->mode ?>', 'mod':'r'},
107         'cmi.objectives._children':{'defaultvalue':objectives_children, 'mod':'r'},
108         'cmi.objectives._count':{'mod':'r', 'defaultvalue':'0'},
109         'cmi.objectives.n.id':{'pattern':CMIIndex, 'format':CMILongIdentifier, 'mod':'rw'},
110         'cmi.objectives.n.score._children':{'defaultvalue':score_children, 'pattern':CMIIndex, 'mod':'r'},
111         'cmi.objectives.n.score.scaled':{'defaultvalue':null, 'pattern':CMIIndex, 'format':CMIDecimal, 'range':scaled_range, 'mod':'rw'},
112         'cmi.objectives.n.score.raw':{'defaultvalue':null, 'pattern':CMIIndex, 'format':CMIDecimal, 'mod':'rw'},
113         'cmi.objectives.n.score.min':{'defaultvalue':null, 'pattern':CMIIndex, 'format':CMIDecimal, 'mod':'rw'},
114         'cmi.objectives.n.score.max':{'defaultvalue':null, 'pattern':CMIIndex, 'format':CMIDecimal, 'mod':'rw'},
115         'cmi.objectives.n.success_status':{'defaultvalue':'unknown', 'pattern':CMIIndex, 'format':CMISStatus, 'mod':'rw'},
116         'cmi.objectives.n.completion_status':{'defaultvalue':'unknown', 'pattern':CMIIndex, 'format':CMICStatus, 'mod':'rw'},
117         'cmi.objectives.n.progress_measure':{'defaultvalue':null, 'format':CMIDecimal, 'range':progress_range, 'mod':'rw'},
118         'cmi.objectives.n.description':{'pattern':CMIIndex, 'format':CMILangString250, 'mod':'rw'},
119         'cmi.progress_measure':{'defaultvalue':<?php echo isset($userdata->{'cmi.progess_measure'})?'\''.$userdata->{'cmi.progress_measure'}.'\'':'null' ?>, 'format':CMIDecimal, 'range':progress_range, 'mod':'rw'},
120         'cmi.scaled_passing_score':{'defaultvalue':<?php echo isset($userdata->{'cmi.scaled_passing_score'})?'\''.$userdata->{'cmi.scaled_passing_score'}.'\'':'null' ?>, 'format':CMIDecimal, 'range':scaled_range, 'mod':'r'},
121         'cmi.score._children':{'defaultvalue':score_children, 'mod':'r'},
122         'cmi.score.scaled':{'defaultvalue':<?php echo isset($userdata->{'cmi.score.scaled'})?'\''.$userdata->{'cmi.score.scaled'}.'\'':'null' ?>, 'format':CMIDecimal, 'range':scaled_range, 'mod':'rw'},
123         'cmi.score.raw':{'defaultvalue':<?php echo isset($userdata->{'cmi.score.raw'})?'\''.$userdata->{'cmi.score.raw'}.'\'':'null' ?>, 'format':CMIDecimal, 'mod':'rw'},
124         'cmi.score.min':{'defaultvalue':<?php echo isset($userdata->{'cmi.score.min'})?'\''.$userdata->{'cmi.score.min'}.'\'':'null' ?>, 'format':CMIDecimal, 'mod':'rw'},
125         'cmi.score.max':{'defaultvalue':<?php echo isset($userdata->{'cmi.score.max'})?'\''.$userdata->{'cmi.score.max'}.'\'':'null' ?>, 'format':CMIDecimal, 'mod':'rw'},
126         'cmi.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'PT0H0M0S'},
127         'cmi.success_status':{'defaultvalue':'<?php echo isset($userdata->{'cmi.success_status'})?$userdata->{'cmi.success_status'}:'unknown' ?>', 'format':CMISStatus, 'mod':'rw'},
128         'cmi.suspend_data':{'defaultvalue':<?php echo isset($userdata->{'cmi.suspend_data'})?'\''.$userdata->{'cmi.suspend_data'}.'\'':'null' ?>, 'format':CMIString64000, 'mod':'rw'},
129         'cmi.time_limit_action':{'defaultvalue':<?php echo isset($userdata->timelimitaction)?'\''.$userdata->timelimitaction.'\'':'null' ?>, 'mod':'r'},
130         'cmi.total_time':{'defaultvalue':'<?php echo isset($userdata->{'cmi.total_time'})?$userdata->{'cmi.total_time'}:'PT0H0M0S' ?>', 'mod':'r'},
131         'adl.nav.request':{'defaultvalue':'_none_', 'format':NAVEvent, 'mod':'rw'}
132     };
133     //
134     // Datamodel inizialization
135     //
136 //    var cmi = new Object();
137         cmi.comments_from_learner = new Object();
138         cmi.comments_from_learner._count = 0;
139         cmi.comments_from_lms = new Object();
140         cmi.comments_from_lms._count = 0;
141         cmi.interactions = new Object();
142         cmi.interactions._count = 0;
143         cmi.learner_preference = new Object();
144         cmi.objectives = new Object();
145         cmi.objectives._count = 0;
146         cmi.score = new Object();
148     // Navigation Object
149     var adl = new Object();
150         adl.nav = new Object();
152     for (element in datamodel) {
153         if (element.match(/\.n\./) == null) {
154             if ((typeof eval('datamodel["'+element+'"].defaultvalue')) != 'undefined') {
155                 eval(element+' = datamodel["'+element+'"].defaultvalue;');
156             } else {
157                 eval(element+' = "";');
158             }
159         }
160     }
162 <?php
163     $count = 0;
164     $objectives = '';
165     foreach($userdata as $element => $value){
166         if (substr($element,0,14) == 'cmi.objectives') {
167             preg_match('/.(\d+)./',$element,$matches);
168             $element = preg_replace('/.(\d+)./',".N\$1.",$element);
169             if ($matches[1] == $count) {
170                 $count++;
171                 $end = strpos($element,$matches[1])+strlen($matches[1]);
172                 $subelement = substr($element,0,$end);
173                 echo '    '.$subelement." = new Object();\n";
174                 echo '    '.$subelement.".score = new Object();\n";
175                 echo '    '.$subelement.".score._children = score_children;\n";
176             }
177             echo '    '.$element.' = \''.$value."';\n";
178         }
179     }
180     if ($count > 0) {
181         echo '    cmi.objectives._count = '.$count.";\n";
182     }
183 ?>
185     if (cmi.completion_status == '') {
186         cmi.completion_status = 'not attempted';
187     } 
188     
189     //
190     // API Methods definition
191     //
192     var Initialized = false;
193     var Terminated = false;
194     var diagnostic = "";
196     function Initialize (param) {
197         errorCode = "0";
198         if (param == "") {
199             if ((!Initialized) && (!Terminated)) {
200                 <?php 
201                     if (debugging('',DEBUG_DEVELOPER)) {
202                         echo 'alert("Initialized SCORM 1.3");';
203                     }
204                 ?>
205                 Initialized = true;
206                 errorCode = "0";
207                 return "true";
208             } else {
209                 if (Initialized) {
210                     errorCode = "103";
211                 } else {
212                     errorCode = "104";
213                 }
214             }
215         } else {
216             errorCode = "201";
217         }
218         <?php 
219             if (debugging('',DEBUG_DEVELOPER)) {
220                 echo 'alert("Initialize: "+GetErrorString(errorCode));';
221             }
222         ?>
223         return "false";
224     }
225     
226     function Terminate (param) {
227         errorCode = "0";
228         if (param == "") {
229             if ((Initialized) && (!Terminated)) {
230                 <?php 
231                     if (debugging('',DEBUG_DEVELOPER)) {
232                         echo 'alert("Terminated SCORM 1.3");';
233                     }
234                 ?>
235                 Initialized = false;
236                 Terminated = true;
237                 result = StoreData(cmi,true);
238                 if (nav.event != '') {
239                     if (nav.event == 'continue') {
240                         setTimeout('top.nextSCO();',500);
241                     } else {
242                         setTimeout('top.prevSCO();',500);
243                     }
244                 } else {
245                     if (<?php echo $scorm->auto ?> == 1) {
246                         setTimeout('top.nextSCO();',500);
247                     }
248                 }    
249                 return "true";
250             } else {
251                 if (Terminated) {
252                     errorCode = "113";
253                 } else {
254                     errorCode = "112";
255                 }
256             }
257         } else {
258             errorCode = "201";
259         }
260         <?php 
261             if (debugging('',DEBUG_DEVELOPER)) {
262                 echo 'alert("Terminate: "+GetErrorString(errorCode));';
263             }
264         ?>
265         return "false";
266     }
267     
268     function GetValue (element) {
269         errorCode = "0";
270         diagnostic = "";
271         if ((Initialized) && (!Terminated)) {
272             if (element !="") {
273                 expression = new RegExp(CMIIndex,'g');
274                 elementmodel = element.replace(expression,'.n.');
275                                 
276                 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
277                     if (eval('datamodel["'+elementmodel+'"].mod') != 'w') {
278                                         
279                         element = element.replace(/\.(\d+)\./, ".N$1.");
280                                                 element = element.replace(/\.(\d+)\./, ".N$1.");
282                         elementIndexes = element.split('.');
283                         subelement = element.substr(0,3);
284                         i = 1;
285                                                 
286                         while ((i < elementIndexes.length) && (typeof eval(subelement) != "undefined")) {
287                             subelement += '.'+elementIndexes[i++];
288                                                 
289                         }
290                                                 
291                         if (subelement == element) {
293                             if ((typeof eval(subelement) != "undefined") && (eval(subelement) != null)) {
294                                 errorCode = "0";
295                                 <?php 
296                                     if (debugging('',DEBUG_DEVELOPER)) {
297                                         echo 'alert("GetValue("+element+") -> "+eval(element));';
298                                     }
299                                 ?>
300                                 return eval(element);
301                             } else {
302                                 errorCode = "403";
303                             }
304                         } else {
305                             errorCode = "301";
306                         }
307                     } else {
308                         //errorCode = eval('datamodel["'+elementmodel+'"].readerror');
309                         errorCode = "405";
310                     }
311                 } else {
312                     childrenstr = '._children';
313                     countstr = '._count';
314                     if (elementmodel.substr(elementmodel.length-childrenstr.length,elementmodel.length) == childrenstr) {
315                         parentmodel = elementmodel.substr(0,elementmodel.length-childrenstr.length);
316                         if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
317                             errorCode = "301";
318                             diagnostic = "Data Model Element Does Not Have Children";
319                         } else {
320                             errorCode = "401";
321                         }
322                     } else if (elementmodel.substr(elementmodel.length-countstr.length,elementmodel.length) == countstr) {
323                         parentmodel = elementmodel.substr(0,elementmodel.length-countstr.length);
324                         if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
325                             errorCode = "301";
326                             diagnostic = "Data Model Element Cannot Have Count";
327                         } else {
328                             errorCode = "401";
329                         }
330                     } else {
331                         parentmodel = 'adl.nav.request_valid.';
332                         if (element.substr(0,parentmodel.length) == parentmodel) {
333                             if (element.substr(parentmodel.length).match(NAVTarget) == null) {
334                                 errorCode = "301";
335                             } else {
336                                 if (adl.nav.request == element.substr(parentmodel.length)) {
337                                     return "true";
338                                 } else if (adl.nav.request == '_none_') {
339                                     return "unknown";
340                                 } else {
341                                     return "false";
342                                 }
343                             }
344                         } else {
345                             errorCode = "401";
346                         }
347                     }
348                 }
349             } else {
350                 errorCode = "301";
351             }
352         } else {
353             if (Terminated) {                
354                 errorCode = "123";
355             } else {
356                 errorCode = "122";
357             }
358         }
359         <?php 
360             if (debugging('',DEBUG_DEVELOPER)) {
361                 echo 'alert("GetValue("+element+") -> "+GetErrorString(errorCode));';
362             }
363         ?>
364         return "";
365     }
366     
367     function SetValue (element,value) {
368         errorCode = "0";
369         diagnostic = "";
370                 if (element== 'cmi.interactions.0.learner_response' && value=='Dependency on cmi.interaction.n.type not established'){
371                         
372                         errorCode="408";
373                 }
374         if ((Initialized) && (!Terminated)) {
375             if (element != "") {
376                 expression = new RegExp(CMIIndex,'g');
377                 elementmodel = element.replace(expression,'.n.');
378                 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
379                     if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
380                         expression = new RegExp(eval('datamodel["'+elementmodel+'"].format'));
381                         value = value+'';
382                         matches = value.match(expression);
383                         if ((matches != null) && ((matches.join('').length > 0) || (value.length == 0))) {
384                                                 
385                             //Create dynamic data model element
387                             if (element != elementmodel) {
388                                 elementIndexes = element.split('.');
389                                 subelement = 'cmi';
390                                 parentelement = 'cmi';
391                                 for (i=1;(i < elementIndexes.length-1) && (errorCode=="0");i++) {
392                                     elementIndex = elementIndexes[i];
393                                     if (elementIndexes[i+1].match(/^\d+$/)) {
394                                         if ((parseInt(elementIndexes[i+1]) > 0) && (elementIndexes[i+1].charAt(0) == 0)) {
395                                             // Index has a leading 0 (zero), this is not a number
396                                             errorCode = "351";
397                                         }
398                                         parentelement = subelement+'.'+elementIndex;
399                                         if (elementIndexes[i+1] > eval(parentelement+'._count')) {
400                                                                         
401                                             errorCode = "351";
402                                             diagnostic = "Data Model Element Collection Set Out Of Order";
403                                         }
404                                         subelement = subelement.concat('.'+elementIndex+'.N'+elementIndexes[i+1]);
405                                         i++;
406                                                                                 
407                                         if (((typeof eval(subelement)) == "undefined") && (i < elementIndexes.length-2)) {
408                                             errorCode="408";
409                                         }
410                                     } else {
411                                         subelement = subelement.concat('.'+elementIndex);
412                                     }
413                                 }
415                                                         
417                                 if (errorCode == "0") {
418                                                                         
419                                     element = subelement.concat('.'+elementIndexes[elementIndexes.length-1]);
420                                     elemlen = element.length;
421                                                                         
422                                     if (((typeof eval(subelement)) == "undefined") && (errorCode == "0")) {
423                                         parentmodel = 'cmi.objectives';
424                                         maxmodel = 'cmi.objectives.Nxxx.id';
425                                         if (subelement.substr(0,parentmodel.length) == parentmodel) {
426                                                                                 
427                                              if ((elemlen <= maxmodel.length) && (element.substr(elemlen-2) == 'id') && (errorCode=="0")) { 
428                                                                                 
429                                                 //This is a parentmodel.n.id element
430                                                 if (!duplicatedID(parentmodel,value)) {
431                                                     if (elementIndexes[elementIndexes.length-2] == eval(parentmodel+'._count')) {
432                                                         eval(parentmodel+'._count++;');
433                                                         eval(subelement+' = new Object();');
434                                                         subobject = eval(subelement);
435                                                         subobject.success_status = datamodel["cmi.objectives.n.success_status"].defaultvalue;
436                                                         subobject.completion_status = datamodel["cmi.objectives.n.completion_status"].defaultvalue;
437                                                         subobject.progress_measure = datamodel["cmi.objectives.n.progress_measure"].defaultvalue;
438                                                         subobject.score = new Object();
439                                                         subobject.score._children = score_children;
440                                                         subobject.score.scaled = datamodel["cmi.objectives.n.score.scaled"].defaultvalue;
441                                                         subobject.score.raw = datamodel["cmi.objectives.n.score.raw"].defaultvalue;
442                                                         subobject.score.min = datamodel["cmi.objectives.n.score.min"].defaultvalue;
443                                                         subobject.score.max = datamodel["cmi.objectives.n.score.max"].defaultvalue;
444                                                     }
445                                                 } else {
446                                                     errorCode="351";
447                                                     diagnostic = "Data Model Element ID Already Exists";
448                                                 }
449                                             } else {
450                                                                                         
451                                                                                         
452                                                 if (typeof eval(subelement) == "undefined") {
453                                                     errorCode="408";
454                                                 } else {
455                                                     if (duplicatedID(parentmodel,value)) {
456                                                         errorCode="351";
457                                                         diagnostic = "Data Model Element ID Already Exists";
458                                                     }
459                                                 }
460                                             }
461                                         } else {
462                                                                                         
464                                                                 
465                                             parentmodel = 'cmi.interactions';
466                                             maxmodel = 'cmi.interactions.Nxxx.id';
467                                                                                         
468                                             if (subelement.substr(0,parentmodel.length) == parentmodel) {
469                                                                                         
470                                                 if ((elemlen <= maxmodel.length) && (element.substr(elemlen-2) == 'id') && (errorCode=="0")) { 
471                                                                                                 
472                                                     //This is a parentmodel.n.id element
473                                                     if (!duplicatedID(parentmodel,value)) {
474                                                                                                         
475                                                         if (elementIndexes[elementIndexes.length-2] == eval(parentmodel+'._count')) {
476                                                                                                                 
477                                                             eval(parentmodel+'._count++;');
478                                                                                                                         
479                                                             eval(subelement+' = new Object();');
480                                                                                                                         
481                                                             subobject = eval(subelement);
482                                                             subobject.objectives = new Object();
483                                                             subobject.objectives._count = 0;
484                                                                                                                         subobject.correct_responses = new Object();
485                                                             subobject.correct_responses._count = 0;
486                                                                                                                         
487                                                             
488                                                         } 
489                                                     } else {
490                                                                                                 
491                                                         errorCode="351";
492                                                         diagnostic = "Data Model Element ID Already Exists";
493                                                     }
494                                                 } else {
495                                                                                                 
496                                                     if (typeof eval(subelement) == "undefined") {
497                                                                                                         
498                                                         errorCode="408";
499                                                     } else {
500                                                         maxmodel = 'cmi.interactions.Nxxx.type';
501                                                         if ((elemlen <= maxmodel.length) && (element.substr(elemlen-4) == 'type') && (errorCode=="0")) { 
502                                                             subobject = eval(subelement);
503                                                            //subobject.correct_responses = new Object();
504                                                            //subobject.correct_responses._count = 0;
505                                                                                                                   subobject.learner_response = new Object();
506                                                         } 
507                                                     }
508                                                 }
509                                             } else {
510                                                                                         
511                                                                                         
512                                                 if (errorCode == "0") {
513                                                     if (elementIndexes[elementIndexes.length-2] == eval(parentelement+'._count')) {
514                                                         eval(parentelement+'._count++;');
515                                                         eval(subelement+' = new Object();');
516                                                     } 
517                                                 }
518                                             }
519                                         }
520                                      } else {
522                                          parentmodel = 'cmi.objectives';
523                                          maxmodel = 'cmi.objectives.Nxxx.id';
524                                          if (subelement.substr(0,parentmodel.length) == parentmodel) {
525                                              if ((elemlen <= maxmodel.length) && (element.substr(elemlen-2) == 'id') && (errorCode=="0")) {
526                                                                                                 
527                                                  if (eval(element) != value) {
528                                                      errorCode = "351";
529                                                      diagnostic = "Write Once Violation";
530                                                  }
531                                              }
532                                          } else {
533                                                                                 
534                                              parentmodel = 'cmi.interactions';
535                                              maxmodel = 'cmi.interactions.Nxxx.id';
536                                              if (subelement.substr(0,parentmodel.length) == parentmodel) {
537                                                  if ((elemlen <= maxmodel.length) && (element.substr(elemlen-2) == 'id') && (errorCode=="0")) { 
538                                                      if (eval(element) != value) {
539                                                          errorCode = "351";
540                                                          diagnostic = "Write Once Violation";
541                                                      }
542                                                  }
543                                              }
544                                          }
545                                      }
546                                 }
547                             }
548                             //Store data
549                             if (errorCode == "0") {
550                                                         
551                                 if ((typeof eval('datamodel["'+elementmodel+'"].range')) != "undefined") {
552                                     range = eval('datamodel["'+elementmodel+'"].range');
553                                     ranges = range.split('#');
554                                     value = value*1.0;
555                                     if (value >= ranges[0]) {
556                                         if ((ranges[1] == '*') || (value <= ranges[1])) {
557                                             eval(element+'="'+value+'";');
558                                             errorCode = "0";
559                                             <?php 
560                                                 if (debugging('',DEBUG_DEVELOPER)) {
561                                                     echo 'alert("SetValue("+element+","+value+") -> OK");';
562                                                 }
563                                             ?>
564                                             return "true";
565                                         } else {
566                                             errorCode = '407';
567                                         }
568                                     } else {
569                                         errorCode = '407';
570                                     }
571                                 } else {
572                                     eval(element+'="'+value+'";');
573                                     errorCode = "0"; 
574                                     <?php 
575                                         if (debugging('',DEBUG_DEVELOPER)) {
576                                             echo 'alert("SetValue("+element+","+value+") -> OK");';
577                                         }
578                                     ?>
579                                     return "true";
580                                 }
581                             }
582                         } else {
583                             //errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
584                             errorCode = "406";
585                         }
586                     } else {
587                         //errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
588                         errorCode = "404";
589                     }
590                 } else {
591                     errorCode = "401"
592                 }
593             } else {
594                 errorCode = "351";
595             }
596         }
598                 else {
599             if (Terminated) {
600                 errorCode = "133";
601             } else {
602                 errorCode = "132";
603             }
604         }
605         <?php 
606             if (debugging('',DEBUG_DEVELOPER)) {
607                 echo 'alert("SetValue("+element+","+value+") -> "+GetErrorString(errorCode));';
608             }
609         ?>
610         return "false";
611     }
612     
613     function Commit (param) {
614         errorCode = "0";
615         if (param == "") {
616             if ((Initialized) && (!Terminated)) {
617                 result = StoreData(cmi,false);
618                 <?php 
619                     if (debugging('',DEBUG_DEVELOPER)) {
620                         echo 'alert("Data Commited");';
621                     }
622                 ?>
623                 return "true";
624             } else {
625                 if (Terminated) {
626                     errorCode = "143";
627                 } else {
628                     errorCode = "142";
629                 }
630             }
631         } else {
632             errorCode = "201";
633         }
634         <?php 
635             if (debugging('',DEBUG_DEVELOPER)) {
636                 echo 'alert("Commit: "+GetErrorString(errorCode));';
637             }
638         ?>
639         return "false";
640     }
641     
642     function GetLastError () {
643         return errorCode;
644     }
645     
646     function GetErrorString (param) {
647         if (param != "") {
648             var errorString = "";
649             switch(param) {
650                 case "0":
651                     errorString = "No error";
652                 break;
653                 case "101":
654                     errorString = "General exception";
655                 break;
656                 case "102":
657                     errorString = "General Inizialization Failure";
658                 break;
659                 case "103":
660                     errorString = "Already Initialized";
661                 break;
662                 case "104":
663                     errorString = "Content Instance Terminated";
664                 break;
665                 case "111":
666                     errorString = "General Termination Failure";
667                 break;
668                 case "112":
669                     errorString = "Termination Before Inizialization";
670                 break;
671                 case "113":
672                     errorString = "Termination After Termination";
673                 break;
674                 case "122":
675                     errorString = "Retrieve Data Before Initialization";
676                 break;
677                 case "123":
678                     errorString = "Retrieve Data After Termination";
679                 break;
680                 case "132":
681                     errorString = "Store Data Before Inizialization";
682                 break;
683                 case "133":
684                     errorString = "Store Data After Termination";
685                 break;
686                 case "142":
687                     errorString = "Commit Before Inizialization";
688                 break;
689                 case "143":
690                     errorString = "Commit After Termination";
691                 break;
692                 case "201":
693                     errorString = "General Argument Error";
694                 break;
695                 case "301":
696                     errorString = "General Get Failure";
697                 break;
698                 case "351":
699                     errorString = "General Set Failure";
700                 break;
701                 case "391":
702                     errorString = "General Commit Failure";
703                 break;
704                 case "401":
705                     errorString = "Undefinited Data Model";
706                 break;
707                 case "402":
708                     errorString = "Unimplemented Data Model Element";
709                 break;
710                 case "403":
711                     errorString = "Data Model Element Value Not Initialized";
712                 break;
713                 case "404":
714                     errorString = "Data Model Element Is Read Only";
715                 break;
716                 case "405":
717                     errorString = "Data Model Element Is Write Only";
718                 break;
719                 case "406":
720                     errorString = "Data Model Element Type Mismatch";
721                 break;
722                 case "407":
723                     errorString = "Data Model Element Value Out Of Range";
724                 break;
725                 case "408":
726                     errorString = "Data Model Dependency Not Established";
727                 break;
728             }
729             return errorString;
730         } else {
731            return "";
732         }
733     }
734     
735     function GetDiagnostic (param) {
736         if (diagnostic != "") {
737             return diagnostic;
738         }
739         return param;
740     }
742     function duplicatedID (element, value) {
743         var found = false;
744         var elements = eval(element+'._count');
745         for (n=0;(n<elements) && (!found);n++) {
746             if (eval(element+'.N'+n+'.id') == value) {
747                 found = true;
748             }
749         } 
750         return found;
751     }
753     function getElementModel(element) {
754         if (typeof datamodel[element] != "undefined") {
755             return element;
756         } else {
757             expression = new RegExp(CMIIndex,'g');
758             elementmodel = element.replace(expression,'.n.');
759             if (typeof datamodel[elementmodel] != "undefined") {
760                 return elementmodel;
761             }
762         }
763     }
765     function AddTime (first, second) {
766         <?php 
767             if (debugging('',DEBUG_DEVELOPER)) {
768                 echo 'alert("AddTime: "+first+" + "+second);';
769             }
770         ?>
771         var timestring = 'P';
772         var matchexpr = /^P((\d+)Y)?((\d+)M)?((\d+)D)?(T((\d+)H)?((\d+)M)?((\d+(\.\d{1,2})?)S)?)?$/;
773         var firstarray = first.match(matchexpr);
774         var secondarray = second.match(matchexpr);
775         if ((firstarray != null) && (secondarray != null)) {
776             var secs = parseFloat(firstarray[13],10)+parseFloat(secondarray[13],10);  //Seconds
777             change = Math.floor(secs / 60);
778             secs = secs - (change * 60);
779             mins = parseInt(firstarray[11],10)+parseInt(secondarray[11],10)+change;   //Minutes
780             change = Math.floor(mins / 60);
781             mins = mins - (change * 60);
782             hours = parseInt(firstarray[10],10)+parseInt(secondarray[10],10)+change;  //Hours
783             change = Math.floor(hours / 24);
784             hours = hours - (change * 24);
785             days = parseInt(firstarray[6],10)+parseInt(secondarray[6],10)+change; // Days
786             months = parseInt(firstarray[4],10)+parseInt(secondarray[4],10)
787             years = parseInt(firstarray[2],10)+parseInt(secondarray[2],10)
788         }
789         if (years > 0) {
790             timestring += years + 'Y';
791         }
792         if (months > 0) {
793             timestring += months + 'M';
794         }
795         if (days > 0) {
796             timestring += days + 'D';
797         }
798         if ((hours > 0) || (mins > 0) || (secs > 0)) {
799             timestring += 'T';
800             if (hours > 0) {
801                 timestring += hours + 'H';
802             }
803             if (mins > 0) {
804                 timestring += mins + 'M';
805             }
806             if (secs > 0) {
807                 timestring += secs + 'S';
808             }
809         }
810         return timestring;
811     }
813     function TotalTime() {
814         total_time = AddTime(cmi.total_time, cmi.session_time);
815         return '&'+underscore('cmi.total_time')+'='+escape(total_time);
816     }
818     function CollectData(data,parent) {
819         var datastring = '';
820         for (property in data) {
821             if (typeof data[property] == 'object') {
822                 datastring += CollectData(data[property],parent+'.'+property);
823             } else {
824                 element = parent+'.'+property;
825                 expression = new RegExp(CMIIndexStore,'g');
826                 elementmodel = element.replace(expression,'.n.');
827                 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
828                     if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
829                         elementstring = '&'+underscore(element)+'='+escape(data[property]);
830                         if ((typeof eval('datamodel["'+elementmodel+'"].defaultvalue')) != "undefined") {
831                             if (eval('datamodel["'+elementmodel+'"].defaultvalue') != data[property]) {
832                                 datastring += elementstring;
833                             }
834                         } else {
835                             datastring += elementstring;
836                         }
837                     }
838                 }
839             }
840         }
841         return datastring;
842     }
844     function StoreData(data,storetotaltime) {
845         if (storetotaltime) {
846             if (cmi.mode == 'normal') {
847                 if (cmi.credit == 'credit') {
848                     if ((cmi.completion_threshold != null) && (cmi.progress_measure != null)) {
849                         if (cmi.progress_measure >= cmi.completion_threshold) {
850                             cmi.completion_status = 'completed';
851                         } else {
852                             cmi.completion_status = 'incomplete';
853                         }
854                     }
855                     if ((cmi.scaled_passed_score != null) && (cmi.score.scaled != '')) {
856                         if (cmi.score.scaled >= cmi.scaled_passed_score) {
857                             cmi.success_status = 'passed';
858                         } else {
859                             cmi.success_status = 'failed';
860                         }
861                     }
862                 }
863             }
864             datastring = CollectData(data,'cmi');
865             datastring += TotalTime();
866         } else {
867             datastring = CollectData(data,'cmi');
868         }
869         datastring += '&attempt=<?php echo $attempt ?>';
870         datastring += '&scoid=<?php echo $sco->id ?>';
871         <?php
872             if (debugging('',DEBUG_DEVELOPER)) {
873                 echo 'popupwin(datastring);';
874             }
875         ?>
876         var myRequest = NewHttpReq();
877         result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&sesskey=<?php p($USER->sesskey) ?>"+datastring);
878         results = result.split('\n');
879         errorCode = results[1];
880         return results[0];
881     }
882     
883     this.Initialize = Initialize;
884     this.Terminate = Terminate;
885     this.GetValue = GetValue;
886     this.SetValue = SetValue;
887     this.Commit = Commit;
888     this.GetLastError = GetLastError;
889     this.GetErrorString = GetErrorString;
890     this.GetDiagnostic = GetDiagnostic;
891     this.version = '1.0';
894 var API_1484_11 = new SCORMapi1_3();