Merge branch 'm20_MDL-26176_cleanup' of github.com:danmarsden/moodle
[moodle.git] / mod / scorm / datamodels / aicc.js.php
1 <?php
2     if (isset($userdata->status)) {
3         if ($userdata->status == '') {
4             $userdata->entry = 'ab-initio';
5         } else {
6             if (isset($userdata->{'cmi.core.exit'}) && ($userdata->{'cmi.core.exit'} == 'suspend')) {
7                 $userdata->entry = 'resume';
8             } else {
9                 $userdata->entry = '';
10             }
11         }
12     }
13 ?>
14 //
15 // SCORM 1.2 API Implementation
16 //
17 function AICCapi() {
18     // Standard Data Type Definition
19     CMIString256 = '^.{0,255}$';
20     CMIString4096 = '^.{0,4096}$';
21     CMITime = '^([0-2]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})(\.[0-9]{1,2})?$';
22     CMITimespan = '^([0-9]{2,4}):([0-9]{2}):([0-9]{2})(\.[0-9]{1,2})?$';
23     CMIInteger = '^\\d+$';
24     CMISInteger = '^-?([0-9]+)$';
25     CMIDecimal = '^-?([0-9]{0,3})(\.[0-9]{1,2})?$';
26     CMIIdentifier = '^\\w{1,255}$';
27     CMIFeedback = CMIString256; // This must be redefined
28     CMIIndex = '[._](\\d+).';
30     // Vocabulary Data Type Definition
31     CMIStatus = '^passed$|^completed$|^failed$|^incomplete$|^browsed$';
32     CMIStatus2 = '^passed$|^completed$|^failed$|^incomplete$|^browsed$|^not attempted$';
33     CMIExit = '^time-out$|^suspend$|^logout$|^$';
34     CMIType = '^true-false$|^choice$|^fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$';
35     CMIResult = '^correct$|^wrong$|^unanticipated$|^neutral$|^([0-9]{0,3})?(\.[0-9]{1,2})?$';
36     NAVEvent = '^previous$|^continue$';
38     // Children lists
39     cmi_children = 'core, suspend_data, launch_data, comments, objectives, student_data, student_preference, interactions';
40     core_children = 'student_id, student_name, lesson_location, credit, lesson_status, entry, score, total_time, lesson_mode, exit, session_time';
41     score_children = 'raw, min, max';
42     comments_children = 'content, location, time';
43     objectives_children = 'id, score, status';
44     student_data_children = 'attempt_number, tries, mastery_score, max_time_allowed, time_limit_action';
45     student_preference_children = 'audio, language, speed, text';
46     interactions_children = 'id, objectives, time, type, correct_responses, weighting, student_response, result, latency';
48     // Data ranges
49     score_range = '0#100';
50     audio_range = '-1#100';
51     speed_range = '-100#100';
52     weighting_range = '-100#100';
53     text_range = '-1#1';
55     // The AICC data model
56     var datamodel =  {
57         'cmi._children':{'defaultvalue':cmi_children, 'mod':'r', 'writeerror':'402'},
58         'cmi._version':{'defaultvalue':'3.4', 'mod':'r', 'writeerror':'402'},
59         'cmi.core._children':{'defaultvalue':core_children, 'mod':'r', 'writeerror':'402'},
60         'cmi.core.student_id':{'defaultvalue':'<?php echo $userdata->student_id ?>', 'mod':'r', 'writeerror':'403'},
61         'cmi.core.student_name':{'defaultvalue':'<?php echo $userdata->student_name ?>', 'mod':'r', 'writeerror':'403'},
62         'cmi.core.lesson_location':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_location'})?$userdata->{'cmi.core.lesson_location'}:'' ?>', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
63         'cmi.core.credit':{'defaultvalue':'<?php echo $userdata->credit ?>', 'mod':'r', 'writeerror':'403'},
64         'cmi.core.lesson_status':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_status'})?$userdata->{'cmi.core.lesson_status'}:'' ?>', 'format':CMIStatus, 'mod':'rw', 'writeerror':'405'},
65         'cmi.core.exit':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.exit'})?$userdata->{'cmi.core.exit'}:'' ?>', 'format':CMIExit, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
66         'cmi.core.entry':{'defaultvalue':'<?php echo $userdata->entry ?>', 'mod':'r', 'writeerror':'403'},
67         'cmi.core.score._children':{'defaultvalue':score_children, 'mod':'r', 'writeerror':'402'},
68         'cmi.core.score.raw':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.score.raw'})?$userdata->{'cmi.core.score.raw'}:'' ?>', 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
69         'cmi.core.score.max':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.score.max'})?$userdata->{'cmi.core.score.max'}:'' ?>', 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
70         'cmi.core.score.min':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.score.min'})?$userdata->{'cmi.core.score.min'}:'' ?>', 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
71         'cmi.core.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'00:00:00', 'readerror':'404', 'writeerror':'405'},
72         'cmi.core.total_time':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.total_time'})?$userdata->{'cmi.core.total_time'}:'00:00:00' ?>', 'mod':'r', 'writeerror':'403'},
73         'cmi.core.lesson_mode':{'defaultvalue':'<?php echo $userdata->mode ?>', 'mod':'r', 'writeerror':'403'},
74         'cmi.suspend_data':{'defaultvalue':'<?php echo isset($userdata->{'cmi.suspend_data'})?$userdata->{'cmi.suspend_data'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
75         'cmi.launch_data':{'defaultvalue':'<?php echo isset($userdata->datafromlms)?$userdata->datafromlms:'' ?>', 'mod':'r', 'writeerror':'403'},
76         'cmi.comments':{'defaultvalue':'<?php echo isset($userdata->{'cmi.comments'})?$userdata->{'cmi.comments'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
77         // deprecated evaluation attributes
78         'cmi.evaluation.comments._count':{'defaultvalue':'0', 'mod':'r', 'writeerror':'402'},
79         'cmi.evaluation.comments._children':{'defaultvalue':comments_children, 'mod':'r', 'writeerror':'402'},
80         'cmi.evaluation.comments.n.content':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
81         'cmi.evaluation.comments.n.location':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
82         'cmi.evaluation.comments.n.time':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMITime, 'mod':'rw', 'writeerror':'405'},
83         'cmi.comments_from_lms':{'mod':'r', 'writeerror':'403'},
84         'cmi.objectives._children':{'defaultvalue':objectives_children, 'mod':'r', 'writeerror':'402'},
85         'cmi.objectives._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
86         'cmi.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'rw', 'writeerror':'405'},
87         'cmi.objectives.n.score._children':{'pattern':CMIIndex, 'mod':'r', 'writeerror':'402'},
88         'cmi.objectives.n.score.raw':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
89         'cmi.objectives.n.score.min':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
90         'cmi.objectives.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
91         'cmi.objectives.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'},
92         'cmi.student_data._children':{'defaultvalue':student_data_children, 'mod':'r', 'writeerror':'402'},
93         'cmi.student_data.attempt_number':{'defaultvalue':'<?php echo isset($userdata->{'cmi.student_data.attempt_number'})?$userdata->{'cmi.student_data.attempt_number'}:'' ?>', 'mod':'r', 'writeerror':'402'},
94         'cmi.student_data.tries.n.score.raw':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
95         'cmi.student_data.tries.n.score.min':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
96         'cmi.student_data.tries.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
97         'cmi.student_data.tries.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'},
98         'cmi.student_data.tries.n.time':{'pattern':CMIIndex, 'format':CMITime, 'mod':'rw', 'writeerror':'405'},
99         'cmi.student_data.mastery_score':{'defaultvalue':'<?php echo isset($userdata->mastery_score)?$userdata->mastery_score:'' ?>', 'mod':'r', 'writeerror':'403'},
100         'cmi.student_data.max_time_allowed':{'defaultvalue':'<?php echo isset($userdata->max_time_allowed)?$userdata->max_time_allowed:'' ?>', 'mod':'r', 'writeerror':'403'},
101         'cmi.student_data.time_limit_action':{'defaultvalue':'<?php echo isset($userdata->time_limit_action)?$userdata->time_limit_action:'' ?>', 'mod':'r', 'writeerror':'403'},
102         'cmi.student_data.tries_during_lesson':{'defaultvalue':'<?php echo isset($userdata->{'cmi.student_data.tries_during_lesson'})?$userdata->{'cmi.student_data.tries_during_lesson'}:'' ?>', 'mod':'r', 'writeerror':'402'},
103         'cmi.student_preference._children':{'defaultvalue':student_preference_children, 'mod':'r', 'writeerror':'402'},
104         'cmi.student_preference.audio':{'defaultvalue':'0', 'format':CMISInteger, 'range':audio_range, 'mod':'rw', 'writeerror':'405'},
105         'cmi.student_preference.language':{'defaultvalue':'', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
106         'cmi.student_preference.speed':{'defaultvalue':'0', 'format':CMISInteger, 'range':speed_range, 'mod':'rw', 'writeerror':'405'},
107         'cmi.student_preference.text':{'defaultvalue':'0', 'format':CMISInteger, 'range':text_range, 'mod':'rw', 'writeerror':'405'},
108         'cmi.interactions._children':{'defaultvalue':interactions_children, 'mod':'r', 'writeerror':'402'},
109         'cmi.interactions._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
110         'cmi.interactions.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
111         'cmi.interactions.n.objectives._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
112         'cmi.interactions.n.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
113         'cmi.interactions.n.time':{'pattern':CMIIndex, 'format':CMITime, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
114         'cmi.interactions.n.type':{'pattern':CMIIndex, 'format':CMIType, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
115         'cmi.interactions.n.correct_responses._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
116         'cmi.interactions.n.correct_responses.n.pattern':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
117         'cmi.interactions.n.weighting':{'pattern':CMIIndex, 'format':CMIDecimal, 'range':weighting_range, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
118         'cmi.interactions.n.student_response':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
119         'cmi.interactions.n.result':{'pattern':CMIIndex, 'format':CMIResult, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
120         'cmi.interactions.n.latency':{'pattern':CMIIndex, 'format':CMITimespan, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
121         'nav.event':{'defaultvalue':'', 'format':NAVEvent, 'mod':'w', 'readerror':'404', 'writeerror':'405'}
122     };
124     //
125     // Datamodel inizialization
126     //
127     var cmi = new Object();
128         cmi.core = new Object();
129         cmi.core.score = new Object();
130         cmi.objectives = new Object();
131         cmi.student_data = new Object();
132         cmi.student_preference = new Object();
133         cmi.interactions = new Object();
134         // deprecated evaluation attributes
135         cmi.evaluation = new Object();
136         cmi.evaluation.comments = new Object();
138     // Navigation Object
139     var nav = new Object();
141     for (element in datamodel) {
142         if (element.match(/\.n\./) == null) {
143             if ((typeof eval('datamodel["'+element+'"].defaultvalue')) != 'undefined') {
144                 eval(element+' = datamodel["'+element+'"].defaultvalue;');
145             } else {
146                 eval(element+' = "";');
147             }
148         }
149     }
151 <?php
152     $current_objective = '';
153     $count = 0;
154     $objectives = '';
155     foreach($userdata as $element => $value){
156         if (substr($element,0,14) == 'cmi.objectives') {
157             $element = preg_replace('/\.(\d+)\./', "_\$1.", $element);
158             preg_match('/\_(\d+)\./', $element, $matches);
159             if (count($matches) > 0 && $current_objective != $matches[1]) {
160                 $current_objective = $matches[1];
161                 $count++;
162                 $end = strpos($element,$matches[1])+strlen($matches[1]);
163                 $subelement = substr($element,0,$end);
164                 echo '    '.$subelement." = new Object();\n";
165                 echo '    '.$subelement.".score = new Object();\n";
166                 echo '    '.$subelement.".score._children = score_children;\n";
167                 echo '    '.$subelement.".score.raw = '';\n";
168                 echo '    '.$subelement.".score.min = '';\n";
169                 echo '    '.$subelement.".score.max = '';\n";
170             }
171             echo '    '.$element.' = \''.$value."';\n";
172         }
173     }
174     if ($count > 0) {
175         echo '    cmi.objectives._count = '.$count.";\n";
176     }
177 ?>
179     if (cmi.core.lesson_status == '') {
180         cmi.core.lesson_status = 'not attempted';
181     }
183     //
184     // API Methods definition
185     //
186     var Initialized = false;
188     function LMSInitialize (param) {
189         errorCode = "0";
190         if (param == "") {
191             if (!Initialized) {
192                 Initialized = true;
193                 errorCode = "0";
194                 return "true";
195             } else {
196                 errorCode = "101";
197             }
198         } else {
199             errorCode = "201";
200         }
201         return "false";
202     }
205 <?php
206     // pull in the TOC callback
207     include_once($CFG->dirroot.'/mod/scorm/datamodels/callback.js.php');
208  ?>
211     function LMSFinish (param) {
212         errorCode = "0";
213         if (param == "") {
214             if (Initialized) {
215                 Initialized = false;
216                 result = StoreData(cmi,true);
217                 if (nav.event != '') {
218                     if (nav.event == 'continue') {
219                         setTimeout('scorm_get_next();',500);
220                     } else {
221                         setTimeout('scorm_get_prev();',500);
222                     }
223                 } else {
224                     if (<?php echo $scorm->auto ?> == 1) {
225                         setTimeout('scorm_get_next();',500);
226                     }
227                 }
228                 // trigger TOC update
229                 var sURL = "<?php echo $CFG->wwwroot; ?>" + "/mod/scorm/prereqs.php?a=<?php echo $scorm->id ?>&scoid=<?php echo $scoid ?>&attempt=<?php echo $attempt ?>&mode=<?php echo $mode ?>&currentorg=<?php echo $currentorg ?>&sesskey=<?php echo sesskey(); ?>";
230                 YAHOO.util.Connect.asyncRequest('GET', sURL, this.connectPrereqCallback, null);
231                 return "true";
232             } else {
233                 errorCode = "301";
234             }
235         } else {
236             errorCode = "201";
237         }
238         return "false";
239     }
241     function LMSGetValue (element) {
242         errorCode = "0";
243         if (Initialized) {
244             if (element !="") {
245                 expression = new RegExp(CMIIndex,'g');
246                 elementmodel = String(element).replace(expression,'.n.');
247                 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
248                     if (eval('datamodel["'+elementmodel+'"].mod') != 'w') {
249                             element = String(element).replace(expression, "_$1.");
250                             elementIndexes = element.split('.');
251                         subelement = 'cmi';
252                         i = 1;
253                         while ((i < elementIndexes.length) && (typeof eval(subelement) != "undefined")) {
254                             subelement += '.'+elementIndexes[i++];
255                         }
256                         if (subelement == element) {
257                             errorCode = "0";
258                             return eval(element);
259                         } else {
260                             errorCode = "0"; // Need to check if it is the right errorCode
261                         }
262                     } else {
263                         errorCode = eval('datamodel["'+elementmodel+'"].readerror');
264                     }
265                 } else {
266                     childrenstr = '._children';
267                     countstr = '._count';
268                     if (elementmodel.substr(elementmodel.length-childrenstr.length,elementmodel.length) == childrenstr) {
269                         parentmodel = elementmodel.substr(0,elementmodel.length-childrenstr.length);
270                         if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
271                             errorCode = "202";
272                         } else {
273                             errorCode = "201";
274                         }
275                     } else if (elementmodel.substr(elementmodel.length-countstr.length,elementmodel.length) == countstr) {
276                         parentmodel = elementmodel.substr(0,elementmodel.length-countstr.length);
277                         if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
278                             errorCode = "203";
279                         } else {
280                             errorCode = "201";
281                         }
282                     } else {
283                         errorCode = "201";
284                     }
285                 }
286             } else {
287                 errorCode = "201";
288             }
289         } else {
290             errorCode = "301";
291         }
292         return "";
293     }
295     function LMSSetValue (element,value) {
296         errorCode = "0";
297         if (Initialized) {
298             if (element != "") {
299                 expression = new RegExp(CMIIndex,'g');
300                 elementmodel = String(element).replace(expression,'.n.');
301                 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
302                     if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
303                         expression = new RegExp(eval('datamodel["'+elementmodel+'"].format'));
304                         value = value+'';
305                         matches = value.match(expression);
306                         if (matches != null) {
307                             //Create dynamic data model element
308                             if (element != elementmodel) {
309                                 elementIndexes = element.split('.');
310                                 subelement = 'cmi';
311                                 for (i=1;i < elementIndexes.length-1;i++) {
312                                     elementIndex = elementIndexes[i];
313                                     if (elementIndexes[i+1].match(/^\d+$/)) {
314                                         if ((typeof eval(subelement+'.'+elementIndex)) == "undefined") {
315                                             eval(subelement+'.'+elementIndex+' = new Object();');
316                                             eval(subelement+'.'+elementIndex+'._count = 0;');
317                                         }
318                                         if (elementIndexes[i+1] == eval(subelement+'.'+elementIndex+'._count')) {
319                                             eval(subelement+'.'+elementIndex+'._count++;');
320                                         }
321                                         if (elementIndexes[i+1] > eval(subelement+'.'+elementIndex+'._count')) {
322                                             errorCode = "201";
323                                         }
324                                         subelement = subelement.concat('.'+elementIndex+'_'+elementIndexes[i+1]);
325                                         i++;
326                                     } else {
327                                         subelement = subelement.concat('.'+elementIndex);
328                                     }
329                                     if ((typeof eval(subelement)) == "undefined") {
330                                         eval(subelement+' = new Object();');
331                                         if (subelement.substr(0,14) == 'cmi.objectives') {
332                                             eval(subelement+'.score = new Object();');
333                                             eval(subelement+'.score._children = score_children;');
334                                             eval(subelement+'.score.raw = "";');
335                                             eval(subelement+'.score.min = "";');
336                                             eval(subelement+'.score.max = "";');
337                                         }
338                                         if (subelement.substr(0,16) == 'cmi.interactions') {
339                                             eval(subelement+'.objectives = new Object();');
340                                             eval(subelement+'.objectives._count = 0;');
341                                             eval(subelement+'.correct_responses = new Object();');
342                                             eval(subelement+'.correct_responses._count = 0;');
343                                         }
344                                     }
345                                 }
346                                 element = subelement.concat('.'+elementIndexes[elementIndexes.length-1]);
347                             }
348                             //Store data
349                             if (errorCode == "0") {
350                                 if ((typeof eval('datamodel["'+elementmodel+'"].range')) != "undefined") {
351                                     range = eval('datamodel["'+elementmodel+'"].range');
352                                     ranges = range.split('#');
353                                     value = value*1.0;
354                                     if ((value >= ranges[0]) && (value <= ranges[1])) {
355                                         eval(element+'="'+value+'";');
356                                         errorCode = "0";
357                                         return "true";
358                                     } else {
359                                         errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
360                                     }
361                                 } else {
362                                     if (element == 'cmi.comments') {
363                                         eval(element+'+="'+value+'";');
364                                     } else {
365                                         eval(element+'="'+value+'";');
366                                     }
367                                     errorCode = "0";
368                                     return "true";
369                                 }
370                             }
371                         } else {
372                             errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
373                         }
374                     } else {
375                         errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
376                     }
377                 } else {
378                     errorCode = "201"
379                 }
380             } else {
381                 errorCode = "201";
382             }
383         } else {
384             errorCode = "301";
385         }
386         return "false";
387     }
389     function LMSCommit (param) {
390         errorCode = "0";
391         if (param == "") {
392             if (Initialized) {
393                 result = StoreData(cmi,false);
394                 return "true";
395             } else {
396                 errorCode = "301";
397             }
398         } else {
399             errorCode = "201";
400         }
401         return "false";
402     }
404     function LMSGetLastError () {
405         return errorCode;
406     }
408     function LMSGetErrorString (param) {
409         if (param != "") {
410             var errorString = new Array();
411             errorString["0"] = "No error";
412             errorString["101"] = "General exception";
413             errorString["201"] = "Invalid argument error";
414             errorString["202"] = "Element cannot have children";
415             errorString["203"] = "Element not an array - cannot have count";
416             errorString["301"] = "Not initialized";
417             errorString["401"] = "Not implemented error";
418             errorString["402"] = "Invalid set value, element is a keyword";
419             errorString["403"] = "Element is read only";
420             errorString["404"] = "Element is write only";
421             errorString["405"] = "Incorrect data type";
422             return errorString[param];
423         } else {
424            return "";
425         }
426     }
428     function LMSGetDiagnostic (param) {
429         if (param == "") {
430             param = errorCode;
431         }
432         return param;
433     }
435     function AddTime (first, second) {
436         var sFirst = first.split(":");
437         var sSecond = second.split(":");
438         var cFirst = sFirst[2].split(".");
439         var cSecond = sSecond[2].split(".");
440         var change = 0;
442         FirstCents = 0;  //Cents
443         if (cFirst.length > 1) {
444             FirstCents = parseInt(cFirst[1],10);
445         }
446         SecondCents = 0;
447         if (cSecond.length > 1) {
448             SecondCents = parseInt(cSecond[1],10);
449         }
450         var cents = FirstCents + SecondCents;
451         change = Math.floor(cents / 100);
452         cents = cents - (change * 100);
453         if (Math.floor(cents) < 10) {
454             cents = "0" + cents.toString();
455         }
457         var secs = parseInt(cFirst[0],10)+parseInt(cSecond[0],10)+change;  //Seconds
458         change = Math.floor(secs / 60);
459         secs = secs - (change * 60);
460         if (Math.floor(secs) < 10) {
461             secs = "0" + secs.toString();
462         }
464         mins = parseInt(sFirst[1],10)+parseInt(sSecond[1],10)+change;   //Minutes
465         change = Math.floor(mins / 60);
466         mins = mins - (change * 60);
467         if (mins < 10) {
468             mins = "0" + mins.toString();
469         }
471         hours = parseInt(sFirst[0],10)+parseInt(sSecond[0],10)+change;  //Hours
472         if (hours < 10) {
473             hours = "0" + hours.toString();
474         }
476         if (cents != '0') {
477             return hours + ":" + mins + ":" + secs + '.' + cents;
478         } else {
479             return hours + ":" + mins + ":" + secs;
480         }
481     }
483     function TotalTime() {
484         total_time = AddTime(cmi.core.total_time, cmi.core.session_time);
485         return '&'+underscore('cmi.core.total_time')+'='+escape(total_time);
486     }
488     function CollectData(data,parent) {
489         var datastring = '';
490         for (property in data) {
491             if (typeof data[property] == 'object') {
492                 datastring += CollectData(data[property],parent+'.'+property);
493             } else {
494                 element = parent+'.'+property;
495                 expression = new RegExp(CMIIndex,'g');
496                 elementmodel = String(element).replace(expression,'.n.');
497                 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
498                     if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
499                         elementstring = '&'+underscore(element)+'='+escape(data[property]);
500                         if ((typeof eval('datamodel["'+elementmodel+'"].defaultvalue')) != "undefined") {
501                             if (eval('datamodel["'+elementmodel+'"].defaultvalue') != data[property]) {
502                                 datastring += elementstring;
503                             }
504                         } else {
505                             datastring += elementstring;
506                         }
507                     }
508                 }
509             }
510         }
511         return datastring;
512     }
514     function StoreData(data,storetotaltime) {
515         if (storetotaltime) {
516             if (cmi.core.lesson_mode == 'normal') {
517                 if (cmi.core.credit == 'credit') {
518                     if (cmi.student_data.mastery_score != '' && cmi.core.score.raw != '') {
519                         if (cmi.core.score.raw >= cmi.student_data.mastery_score) {
520                             cmi.core.lesson_status = 'passed';
521                         } else {
522                             cmi.core.lesson_status = 'failed';
523                         }
524                     }
525                 }
526             }
527             if (cmi.core.lesson_mode == 'browse') {
528                 if (datamodel['cmi.core.lesson_status'].defaultvalue == '' && cmi.core.lesson_status == 'not attempted') {
529                     cmi.core.lesson_status = 'browsed';
530                 }
531             }
532             datastring = CollectData(data,'cmi');
533             datastring += TotalTime();
534         } else {
535             datastring = CollectData(data,'cmi');
536         }
537         datastring += '&attempt=<?php echo $attempt ?>';
538         datastring += '&scoid=<?php echo $scoid ?>';
540         //popupwin(datastring);
541         var myRequest = NewHttpReq();
542         result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&sesskey=<?php echo sesskey() ?>"+datastring);
543         results = String(result).split('\n');
544         errorCode = results[1];
545         return results[0];
546     }
548     this.LMSInitialize = LMSInitialize;
549     this.LMSFinish = LMSFinish;
550     this.LMSGetValue = LMSGetValue;
551     this.LMSSetValue = LMSSetValue;
552     this.LMSCommit = LMSCommit;
553     this.LMSGetLastError = LMSGetLastError;
554     this.LMSGetErrorString = LMSGetErrorString;
555     this.LMSGetDiagnostic = LMSGetDiagnostic;
558 var API = new AICCapi();