2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 require_once($CFG->dirroot.'/mod/scorm/locallib.php');
19 if (isset($userdata->status)) {
20 if ($userdata->status == '') {
21 $userdata->entry = 'ab-initio';
23 if (isset($userdata->{'cmi.core.exit'}) && ($userdata->{'cmi.core.exit'} == 'suspend')) {
24 $userdata->entry = 'resume';
26 $userdata->entry = '';
30 if (!isset($currentorg)) {
35 // SCORM 1.2 API Implementation
37 function SCORMapi1_2() {
38 // Standard Data Type Definition
39 CMIString256 = '^[\\u0000-\\uffff]{0,255}$';
40 CMIString4096 = '^[\\u0000-\\uffff]{0,4096}$';
41 CMITime = '^([0-2]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})(\.[0-9]{1,2})?$';
42 CMITimespan = '^([0-9]{2,4}):([0-9]{2}):([0-9]{2})(\.[0-9]{1,2})?$';
43 CMIInteger = '^\\d+$';
44 CMISInteger = '^-?([0-9]+)$';
45 CMIDecimal = '^-?([0-9]{0,3})(\.[0-9]{1,2})?$';
46 CMIIdentifier = '^[\\u0021-\\u007E]{0,255}$';
47 CMIFeedback = CMIString256; // This must be redefined
48 CMIIndex = '[._](\\d+).';
49 // Vocabulary Data Type Definition
50 CMIStatus = '^passed$|^completed$|^failed$|^incomplete$|^browsed$';
51 CMIStatus2 = '^passed$|^completed$|^failed$|^incomplete$|^browsed$|^not attempted$';
52 CMIExit = '^time-out$|^suspend$|^logout$|^$';
53 CMIType = '^true-false$|^choice$|^fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$';
54 CMIResult = '^correct$|^wrong$|^unanticipated$|^neutral$|^([0-9]{0,3})?(\.[0-9]{1,2})?$';
55 NAVEvent = '^previous$|^continue$';
57 cmi_children = 'core,suspend_data,launch_data,comments,objectives,student_data,student_preference,interactions';
58 core_children = 'student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,lesson_mode,exit,session_time';
59 score_children = 'raw,min,max';
60 comments_children = 'content,location,time';
61 objectives_children = 'id,score,status';
62 correct_responses_children = 'pattern';
63 student_data_children = 'mastery_score,max_time_allowed,time_limit_action';
64 student_preference_children = 'audio,language,speed,text';
65 interactions_children = 'id,objectives,time,type,correct_responses,weighting,student_response,result,latency';
67 score_range = '0#100';
68 audio_range = '-1#100';
69 speed_range = '-100#100';
70 weighting_range = '-100#100';
72 // The SCORM 1.2 data model
74 'cmi._children':{'defaultvalue':cmi_children, 'mod':'r', 'writeerror':'402'},
75 'cmi._version':{'defaultvalue':'3.4', 'mod':'r', 'writeerror':'402'},
76 'cmi.core._children':{'defaultvalue':core_children, 'mod':'r', 'writeerror':'402'},
77 'cmi.core.student_id':{'defaultvalue':'<?php echo $userdata->student_id ?>', 'mod':'r', 'writeerror':'403'},
78 'cmi.core.student_name':{'defaultvalue':'<?php echo $userdata->student_name ?>', 'mod':'r', 'writeerror':'403'},
79 'cmi.core.lesson_location':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_location'})?$userdata->{'cmi.core.lesson_location'}:'' ?>', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
80 'cmi.core.credit':{'defaultvalue':'<?php echo $userdata->credit ?>', 'mod':'r', 'writeerror':'403'},
81 'cmi.core.lesson_status':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_status'})?$userdata->{'cmi.core.lesson_status'}:'' ?>', 'format':CMIStatus, 'mod':'rw', 'writeerror':'405'},
82 'cmi.core.entry':{'defaultvalue':'<?php echo $userdata->entry ?>', 'mod':'r', 'writeerror':'403'},
83 'cmi.core.score._children':{'defaultvalue':score_children, 'mod':'r', 'writeerror':'402'},
84 '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'},
85 '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'},
86 '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'},
87 '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'},
88 'cmi.core.lesson_mode':{'defaultvalue':'<?php echo $userdata->mode ?>', 'mod':'r', 'writeerror':'403'},
89 'cmi.core.exit':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.exit'})?$userdata->{'cmi.core.exit'}:'' ?>', 'format':CMIExit, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
90 'cmi.core.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'00:00:00', 'readerror':'404', 'writeerror':'405'},
91 'cmi.suspend_data':{'defaultvalue':'<?php echo isset($userdata->{'cmi.suspend_data'})?$userdata->{'cmi.suspend_data'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
92 'cmi.launch_data':{'defaultvalue':'<?php echo isset($userdata->datafromlms)?$userdata->datafromlms:'' ?>', 'mod':'r', 'writeerror':'403'},
93 'cmi.comments':{'defaultvalue':'<?php echo isset($userdata->{'cmi.comments'})?$userdata->{'cmi.comments'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
94 // deprecated evaluation attributes
95 'cmi.evaluation.comments._count':{'defaultvalue':'0', 'mod':'r', 'writeerror':'402'},
96 'cmi.evaluation.comments._children':{'defaultvalue':comments_children, 'mod':'r', 'writeerror':'402'},
97 'cmi.evaluation.comments.n.content':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
98 'cmi.evaluation.comments.n.location':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
99 'cmi.evaluation.comments.n.time':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMITime, 'mod':'rw', 'writeerror':'405'},
100 'cmi.comments_from_lms':{'mod':'r', 'writeerror':'403'},
101 'cmi.objectives._children':{'defaultvalue':objectives_children, 'mod':'r', 'writeerror':'402'},
102 'cmi.objectives._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
103 'cmi.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'rw', 'writeerror':'405'},
104 'cmi.objectives.n.score._children':{'pattern':CMIIndex, 'mod':'r', 'writeerror':'402'},
105 'cmi.objectives.n.score.raw':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
106 'cmi.objectives.n.score.min':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
107 'cmi.objectives.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
108 'cmi.objectives.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'},
109 'cmi.student_data._children':{'defaultvalue':student_data_children, 'mod':'r', 'writeerror':'402'},
110 'cmi.student_data.mastery_score':{'defaultvalue':'<?php echo isset($userdata->masteryscore)?$userdata->masteryscore:'' ?>', 'mod':'r', 'writeerror':'403'},
111 'cmi.student_data.max_time_allowed':{'defaultvalue':'<?php echo isset($userdata->maxtimeallowed)?$userdata->maxtimeallowed:'' ?>', 'mod':'r', 'writeerror':'403'},
112 'cmi.student_data.time_limit_action':{'defaultvalue':'<?php echo isset($userdata->timelimitaction)?$userdata->timelimitaction:'' ?>', 'mod':'r', 'writeerror':'403'},
113 'cmi.student_preference._children':{'defaultvalue':student_preference_children, 'mod':'r', 'writeerror':'402'},
114 'cmi.student_preference.audio':{'defaultvalue':'0', 'format':CMISInteger, 'range':audio_range, 'mod':'rw', 'writeerror':'405'},
115 'cmi.student_preference.language':{'defaultvalue':'', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
116 'cmi.student_preference.speed':{'defaultvalue':'0', 'format':CMISInteger, 'range':speed_range, 'mod':'rw', 'writeerror':'405'},
117 'cmi.student_preference.text':{'defaultvalue':'0', 'format':CMISInteger, 'range':text_range, 'mod':'rw', 'writeerror':'405'},
118 'cmi.interactions._children':{'defaultvalue':interactions_children, 'mod':'r', 'writeerror':'402'},
119 'cmi.interactions._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
120 'cmi.interactions.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
121 'cmi.interactions.n.objectives._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
122 'cmi.interactions.n.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
123 'cmi.interactions.n.time':{'pattern':CMIIndex, 'format':CMITime, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
124 'cmi.interactions.n.type':{'pattern':CMIIndex, 'format':CMIType, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
125 'cmi.interactions.n.correct_responses._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
126 'cmi.interactions.n.correct_responses.n.pattern':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
127 'cmi.interactions.n.weighting':{'pattern':CMIIndex, 'format':CMIDecimal, 'range':weighting_range, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
128 'cmi.interactions.n.student_response':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
129 'cmi.interactions.n.result':{'pattern':CMIIndex, 'format':CMIResult, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
130 'cmi.interactions.n.latency':{'pattern':CMIIndex, 'format':CMITimespan, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
131 'nav.event':{'defaultvalue':'', 'format':NAVEvent, 'mod':'w', 'readerror':'404', 'writeerror':'405'}
134 // Datamodel inizialization
136 var cmi = new Object();
137 cmi.core = new Object();
138 cmi.core.score = new Object();
139 cmi.objectives = new Object();
140 cmi.student_data = new Object();
141 cmi.student_preference = new Object();
142 cmi.interactions = new Object();
143 // deprecated evaluation attributes
144 cmi.evaluation = new Object();
145 cmi.evaluation.comments = new Object();
148 var nav = new Object();
150 for (element in datamodel) {
151 if (element.match(/\.n\./) == null) {
152 if ((typeof eval('datamodel["'+element+'"].defaultvalue')) != 'undefined') {
153 eval(element+' = datamodel["'+element+'"].defaultvalue;');
155 eval(element+' = "";');
161 // reconstitute objectives
162 scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.objectives', array('score'));
163 scorm_reconstitute_array_element($scorm->version, $userdata, 'cmi.interactions', array('objectives', 'correct_responses'));
166 if (cmi.core.lesson_status == '') {
167 cmi.core.lesson_status = 'not attempted';
171 // API Methods definition
173 var Initialized = false;
175 function LMSInitialize (param) {
182 if (scorm_debugging($scorm)) {
183 echo 'LogAPICall("LMSInitialize", param, "", errorCode);';
194 if (scorm_debugging($scorm)) {
195 echo 'LogAPICall("LMSInitialize", param, "", errorCode);';
202 // pull in the TOC callback
203 require_once($CFG->dirroot.'/mod/scorm/datamodels/callback.js.php');
206 function LMSFinish (param) {
211 result = StoreData(cmi,true);
212 if (nav.event != '') {
213 if (nav.event == 'continue') {
214 setTimeout('scorm_get_next();',500);
216 setTimeout('scorm_get_prev();',500);
219 if (<?php echo $scorm->auto ?> == 1) {
220 setTimeout('scorm_get_next();',500);
224 if (scorm_debugging($scorm)) {
225 echo 'LogAPICall("LMSFinish", "AJAXResult", result, 0);';
228 result = ('true' == result) ? 'true' : 'false';
229 errorCode = (result == 'true')? '0' : '101';
231 if (scorm_debugging($scorm)) {
232 echo 'LogAPICall("LMSFinish", "result", result, 0);';
233 echo 'LogAPICall("LMSFinish", param, "", 0);';
236 // trigger TOC update
237 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 ?>¤torg=<?php echo $currentorg ?>&sesskey=<?php echo sesskey(); ?>";
238 YAHOO.util.Connect.asyncRequest('GET', sURL, this.connectPrereqCallback, null);
247 if (scorm_debugging($scorm)) {
248 echo 'LogAPICall("LMSFinish", param, "", errorCode);';
254 function LMSGetValue (element) {
258 expression = new RegExp(CMIIndex,'g');
259 elementmodel = String(element).replace(expression,'.n.');
260 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
261 if (eval('datamodel["'+elementmodel+'"].mod') != 'w') {
262 element = String(element).replace(expression, "_$1.");
263 elementIndexes = element.split('.');
266 while ((i < elementIndexes.length) && (typeof eval(subelement) != "undefined")) {
267 subelement += '.'+elementIndexes[i++];
269 if (subelement == element) {
272 if (scorm_debugging($scorm)) {
273 echo 'LogAPICall("LMSGetValue", element, eval(element), 0);';
276 return eval(element);
278 errorCode = "0"; // Need to check if it is the right errorCode
281 errorCode = eval('datamodel["'+elementmodel+'"].readerror');
284 childrenstr = '._children';
285 countstr = '._count';
286 if (elementmodel.substr(elementmodel.length-childrenstr.length,elementmodel.length) == childrenstr) {
287 parentmodel = elementmodel.substr(0,elementmodel.length-childrenstr.length);
288 if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
293 } else if (elementmodel.substr(elementmodel.length-countstr.length,elementmodel.length) == countstr) {
294 parentmodel = elementmodel.substr(0,elementmodel.length-countstr.length);
295 if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
311 if (scorm_debugging($scorm)) {
312 echo 'LogAPICall("LMSGetValue", element, "", errorCode);';
318 function LMSSetValue (element,value) {
322 expression = new RegExp(CMIIndex,'g');
323 elementmodel = String(element).replace(expression,'.n.');
324 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
325 if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
326 expression = new RegExp(eval('datamodel["'+elementmodel+'"].format'));
328 matches = value.match(expression);
329 if (matches != null) {
330 //Create dynamic data model element
331 if (element != elementmodel) {
332 elementIndexes = element.split('.');
334 for (i=1;i < elementIndexes.length-1;i++) {
335 elementIndex = elementIndexes[i];
336 if (elementIndexes[i+1].match(/^\d+$/)) {
337 if ((typeof eval(subelement+'.'+elementIndex)) == "undefined") {
338 eval(subelement+'.'+elementIndex+' = new Object();');
339 eval(subelement+'.'+elementIndex+'._count = 0;');
341 if (elementIndexes[i+1] == eval(subelement+'.'+elementIndex+'._count')) {
342 eval(subelement+'.'+elementIndex+'._count++;');
344 if (elementIndexes[i+1] > eval(subelement+'.'+elementIndex+'._count')) {
347 subelement = subelement.concat('.'+elementIndex+'_'+elementIndexes[i+1]);
350 subelement = subelement.concat('.'+elementIndex);
352 if ((typeof eval(subelement)) == "undefined") {
353 eval(subelement+' = new Object();');
354 if (subelement.substr(0,14) == 'cmi.objectives') {
355 eval(subelement+'.score = new Object();');
356 eval(subelement+'.score._children = score_children;');
357 eval(subelement+'.score.raw = "";');
358 eval(subelement+'.score.min = "";');
359 eval(subelement+'.score.max = "";');
361 if (subelement.substr(0,16) == 'cmi.interactions') {
362 eval(subelement+'.objectives = new Object();');
363 eval(subelement+'.objectives._count = 0;');
364 eval(subelement+'.correct_responses = new Object();');
365 eval(subelement+'.correct_responses._count = 0;');
369 element = subelement.concat('.'+elementIndexes[elementIndexes.length-1]);
372 if (errorCode == "0") {
373 if ((typeof eval('datamodel["'+elementmodel+'"].range')) != "undefined") {
374 range = eval('datamodel["'+elementmodel+'"].range');
375 ranges = range.split('#');
377 if ((value >= ranges[0]) && (value <= ranges[1])) {
378 eval(element+'=value;');
381 if (scorm_debugging($scorm)) {
382 echo 'LogAPICall("LMSSetValue", element, value, errorCode);';
387 errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
390 if (element == 'cmi.comments') {
391 cmi.comments = cmi.comments + value;
393 eval(element+'=value;');
397 if (scorm_debugging($scorm)) {
398 echo 'LogAPICall("LMSSetValue", element, value, errorCode);';
405 errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
408 errorCode = eval('datamodel["'+elementmodel+'"].writeerror');
420 if (scorm_debugging($scorm)) {
421 echo 'LogAPICall("LMSSetValue", element, value, errorCode);';
427 function LMSCommit (param) {
431 result = StoreData(cmi,false);
433 if (scorm_debugging($scorm)) {
434 echo 'LogAPICall("Commit", param, "", 0);';
438 if (scorm_debugging($scorm)) {
439 echo 'LogAPICall("LMSCommit", "AJAXResult", result, 0);';
442 result = ('true' == result) ? 'true' : 'false';
443 errorCode = (result =='true')? '0' : '101';
445 if (scorm_debugging($scorm)) {
446 echo 'LogAPICall("LMSCommit", "result", result, 0);';
447 echo 'LogAPICall("LMSCommit", "errorCode", errorCode, 0);';
458 if (scorm_debugging($scorm)) {
459 echo 'LogAPICall("LMSCommit", param, "", 0);';
465 function LMSGetLastError () {
467 if (scorm_debugging($scorm)) {
468 echo 'LogAPICall("LMSGetLastError", "", "", errorCode);';
474 function LMSGetErrorString (param) {
476 var errorString = new Array();
477 errorString["0"] = "No error";
478 errorString["101"] = "General exception";
479 errorString["201"] = "Invalid argument error";
480 errorString["202"] = "Element cannot have children";
481 errorString["203"] = "Element not an array - cannot have count";
482 errorString["301"] = "Not initialized";
483 errorString["401"] = "Not implemented error";
484 errorString["402"] = "Invalid set value, element is a keyword";
485 errorString["403"] = "Element is read only";
486 errorString["404"] = "Element is write only";
487 errorString["405"] = "Incorrect data type";
489 if (scorm_debugging($scorm)) {
490 echo 'LogAPICall("LMSGetErrorString", param, errorString[param], 0);';
493 return errorString[param];
496 if (scorm_debugging($scorm)) {
497 echo 'LogAPICall("LMSGetErrorString", param, "No error string found!", 0);';
504 function LMSGetDiagnostic (param) {
509 if (scorm_debugging($scorm)) {
510 echo 'LogAPICall("LMSGetDiagnostic", param, param, 0);';
516 function AddTime (first, second) {
517 var sFirst = first.split(":");
518 var sSecond = second.split(":");
519 var cFirst = sFirst[2].split(".");
520 var cSecond = sSecond[2].split(".");
523 FirstCents = 0; //Cents
524 if (cFirst.length > 1) {
525 FirstCents = parseInt(cFirst[1],10);
528 if (cSecond.length > 1) {
529 SecondCents = parseInt(cSecond[1],10);
531 var cents = FirstCents + SecondCents;
532 change = Math.floor(cents / 100);
533 cents = cents - (change * 100);
534 if (Math.floor(cents) < 10) {
535 cents = "0" + cents.toString();
538 var secs = parseInt(cFirst[0],10)+parseInt(cSecond[0],10)+change; //Seconds
539 change = Math.floor(secs / 60);
540 secs = secs - (change * 60);
541 if (Math.floor(secs) < 10) {
542 secs = "0" + secs.toString();
545 mins = parseInt(sFirst[1],10)+parseInt(sSecond[1],10)+change; //Minutes
546 change = Math.floor(mins / 60);
547 mins = mins - (change * 60);
549 mins = "0" + mins.toString();
552 hours = parseInt(sFirst[0],10)+parseInt(sSecond[0],10)+change; //Hours
554 hours = "0" + hours.toString();
558 return hours + ":" + mins + ":" + secs + '.' + cents;
560 return hours + ":" + mins + ":" + secs;
564 function TotalTime() {
565 total_time = AddTime(cmi.core.total_time, cmi.core.session_time);
566 return '&'+underscore('cmi.core.total_time')+'='+encodeURIComponent(total_time);
569 function CollectData(data,parent) {
571 for (property in data) {
572 if (typeof data[property] == 'object') {
573 datastring += CollectData(data[property],parent+'.'+property);
575 element = parent+'.'+property;
576 expression = new RegExp(CMIIndex,'g');
577 elementmodel = String(element).replace(expression,'.n.');
578 if (elementmodel != "cmi.core.session_time") {
579 if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
580 if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
581 elementstring = '&'+underscore(element)+'='+encodeURIComponent(data[property]);
582 if ((typeof eval('datamodel["'+elementmodel+'"].defaultvalue')) != "undefined") {
583 if (eval('datamodel["'+elementmodel+'"].defaultvalue') != data[property] || eval('typeof(datamodel["'+elementmodel+'"].defaultvalue)') != typeof(data[property])) {
584 datastring += elementstring;
585 eval('datamodel["'+elementmodel+'"].defaultvalue=data[property];');
588 datastring += elementstring;
589 eval('datamodel["'+elementmodel+'"].defaultvalue=data[property];');
599 function StoreData(data,storetotaltime) {
600 if (storetotaltime) {
601 if (cmi.core.lesson_status == 'not attempted') {
602 cmi.core.lesson_status = 'completed';
604 if (cmi.core.lesson_mode == 'normal') {
605 if (cmi.core.credit == 'credit') {
606 if (cmi.student_data.mastery_score != '' && cmi.core.score.raw != '') {
607 if (parseFloat(cmi.core.score.raw) >= parseFloat(cmi.student_data.mastery_score)) {
608 cmi.core.lesson_status = 'passed';
610 cmi.core.lesson_status = 'failed';
615 if (cmi.core.lesson_mode == 'browse') {
616 if (datamodel['cmi.core.lesson_status'].defaultvalue == '' && cmi.core.lesson_status == 'not attempted') {
617 cmi.core.lesson_status = 'browsed';
620 datastring = CollectData(data,'cmi');
621 datastring += TotalTime();
623 datastring = CollectData(data,'cmi');
625 datastring += '&attempt=<?php echo $attempt ?>';
626 datastring += '&scoid=<?php echo $scoid ?>';
628 var myRequest = NewHttpReq();
629 //alert('going to:' + "<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php" + "id=<?php p($id) ?>&a=<?php p($a) ?>&sesskey=<?php echo sesskey() ?>"+datastring);
630 result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&a=<?php p($a) ?>&sesskey=<?php echo sesskey() ?>"+datastring);
631 results = String(result).split('\n');
632 errorCode = results[1];
636 this.LMSInitialize = LMSInitialize;
637 this.LMSFinish = LMSFinish;
638 this.LMSGetValue = LMSGetValue;
639 this.LMSSetValue = LMSSetValue;
640 this.LMSCommit = LMSCommit;
641 this.LMSGetLastError = LMSGetLastError;
642 this.LMSGetErrorString = LMSGetErrorString;
643 this.LMSGetDiagnostic = LMSGetDiagnostic;
646 var API = new SCORMapi1_2();
649 // pull in the debugging utilities
650 if (scorm_debugging($scorm)) {
651 include_once($CFG->dirroot.'/mod/scorm/datamodels/debug.js.php');
652 echo 'AppendToLog("Moodle SCORM 1.2 API Loaded, Activity: '.$scorm->name.', SCO: '.$sco->identifier.'", 0);';