[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 // This file is part of Moodle - http://moodle.org/ 2 // 3 // Moodle is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // Moodle is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 15 16 // 17 // SCORM 1.2 API Implementation 18 // 19 function SCORMapi1_2(def, cmiobj, cmiint, cmistring256, cmistring4096, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg, autocommit, masteryoverride) { 20 21 var prerequrl = cfgwwwroot + "/mod/scorm/prereqs.php?a=" + scormid + "&scoid=" + scoid + "&attempt=" + attempt + "&mode=" + viewmode + "¤torg=" + currentorg + "&sesskey=" + sesskey; 22 var datamodelurl = cfgwwwroot + "/mod/scorm/datamodel.php"; 23 var datamodelurlparams = "id=" + cmid + "&a=" + scormid + "&sesskey=" + sesskey + "&attempt=" + attempt + "&scoid=" + scoid; 24 25 // Standard Data Type Definition 26 CMIString256 = cmistring256; 27 CMIString4096 = cmistring4096; 28 CMITime = '^([0-2]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})(\.[0-9]{1,2})?$'; 29 CMITimespan = '^([0-9]{2,4}):([0-9]{2}):([0-9]{2})(\.[0-9]{1,2})?$'; 30 CMIInteger = '^\\d+$'; 31 CMISInteger = '^-?([0-9]+)$'; 32 CMIDecimal = '^-?([0-9]{0,3})(\.[0-9]*)?$'; 33 CMIIdentifier = '^[\\u0021-\\u007E]{0,255}$'; 34 CMIFeedback = CMIString256; // This must be redefined 35 CMIIndex = '[._](\\d+).'; 36 // Vocabulary Data Type Definition 37 CMIStatus = '^passed$|^completed$|^failed$|^incomplete$|^browsed$'; 38 CMIStatus2 = '^passed$|^completed$|^failed$|^incomplete$|^browsed$|^not attempted$'; 39 CMIExit = '^time-out$|^suspend$|^logout$|^$'; 40 CMIType = '^true-false$|^choice$|^fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$'; 41 CMIResult = '^correct$|^wrong$|^unanticipated$|^neutral$|^([0-9]{0,3})?(\.[0-9]*)?$'; 42 NAVEvent = '^previous$|^continue$'; 43 // Children lists 44 cmi_children = 'core,suspend_data,launch_data,comments,objectives,student_data,student_preference,interactions'; 45 core_children = 'student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,lesson_mode,exit,session_time'; 46 score_children = 'raw,min,max'; 47 comments_children = 'content,location,time'; 48 objectives_children = 'id,score,status'; 49 correct_responses_children = 'pattern'; 50 student_data_children = 'mastery_score,max_time_allowed,time_limit_action'; 51 student_preference_children = 'audio,language,speed,text'; 52 interactions_children = 'id,objectives,time,type,correct_responses,weighting,student_response,result,latency'; 53 // Data ranges 54 score_range = '0#100'; 55 audio_range = '-1#100'; 56 speed_range = '-100#100'; 57 weighting_range = '-100#100'; 58 text_range = '-1#1'; 59 60 // The SCORM 1.2 data model 61 // Set up data model for each sco 62 var datamodel = {}; 63 for(scoid in def){ 64 datamodel[scoid] = { 65 'cmi._children':{'defaultvalue':cmi_children, 'mod':'r', 'writeerror':'402'}, 66 'cmi._version':{'defaultvalue':'3.4', 'mod':'r', 'writeerror':'402'}, 67 'cmi.core._children':{'defaultvalue':core_children, 'mod':'r', 'writeerror':'402'}, 68 'cmi.core.student_id':{'defaultvalue':def[scoid]['cmi.core.student_id'], 'mod':'r', 'writeerror':'403'}, 69 'cmi.core.student_name':{'defaultvalue':def[scoid]['cmi.core.student_name'], 'mod':'r', 'writeerror':'403'}, 70 'cmi.core.lesson_location':{'defaultvalue':def[scoid]['cmi.core.lesson_location'], 'format':CMIString256, 'mod':'rw', 'writeerror':'405'}, 71 'cmi.core.credit':{'defaultvalue':def[scoid]['cmi.core.credit'], 'mod':'r', 'writeerror':'403'}, 72 'cmi.core.lesson_status':{'defaultvalue':def[scoid]['cmi.core.lesson_status'], 'format':CMIStatus, 'mod':'rw', 'writeerror':'405'}, 73 'cmi.core.entry':{'defaultvalue':def[scoid]['cmi.core.entry'], 'mod':'r', 'writeerror':'403'}, 74 'cmi.core.score._children':{'defaultvalue':score_children, 'mod':'r', 'writeerror':'402'}, 75 'cmi.core.score.raw':{'defaultvalue':def[scoid]['cmi.core.score.raw'], 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'}, 76 'cmi.core.score.max':{'defaultvalue':def[scoid]['cmi.core.score.max'], 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'}, 77 'cmi.core.score.min':{'defaultvalue':def[scoid]['cmi.core.score.min'], 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'}, 78 'cmi.core.total_time':{'defaultvalue':def[scoid]['cmi.core.total_time'], 'mod':'r', 'writeerror':'403'}, 79 'cmi.core.lesson_mode':{'defaultvalue':def[scoid]['cmi.core.lesson_mode'], 'mod':'r', 'writeerror':'403'}, 80 'cmi.core.exit':{'defaultvalue':def[scoid]['cmi.core.exit'], 'format':CMIExit, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 81 'cmi.core.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'00:00:00', 'readerror':'404', 'writeerror':'405'}, 82 'cmi.suspend_data':{'defaultvalue':def[scoid]['cmi.suspend_data'], 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'}, 83 'cmi.launch_data':{'defaultvalue':def[scoid]['cmi.launch_data'], 'mod':'r', 'writeerror':'403'}, 84 'cmi.comments':{'defaultvalue':def[scoid]['cmi.comments'], 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'}, 85 // deprecated evaluation attributes 86 'cmi.evaluation.comments._count':{'defaultvalue':'0', 'mod':'r', 'writeerror':'402'}, 87 'cmi.evaluation.comments._children':{'defaultvalue':comments_children, 'mod':'r', 'writeerror':'402'}, 88 'cmi.evaluation.comments.n.content':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'}, 89 'cmi.evaluation.comments.n.location':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'}, 90 'cmi.evaluation.comments.n.time':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMITime, 'mod':'rw', 'writeerror':'405'}, 91 'cmi.comments_from_lms':{'mod':'r', 'writeerror':'403'}, 92 'cmi.objectives._children':{'defaultvalue':objectives_children, 'mod':'r', 'writeerror':'402'}, 93 'cmi.objectives._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'}, 94 'cmi.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'rw', 'writeerror':'405'}, 95 'cmi.objectives.n.score._children':{'pattern':CMIIndex, 'mod':'r', 'writeerror':'402'}, 96 'cmi.objectives.n.score.raw':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'}, 97 'cmi.objectives.n.score.min':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'}, 98 'cmi.objectives.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'}, 99 'cmi.objectives.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'}, 100 'cmi.student_data._children':{'defaultvalue':student_data_children, 'mod':'r', 'writeerror':'402'}, 101 'cmi.student_data.mastery_score':{'defaultvalue':def[scoid]['cmi.student_data.mastery_score'], 'mod':'r', 'writeerror':'403'}, 102 'cmi.student_data.max_time_allowed':{'defaultvalue':def[scoid]['cmi.student_data.max_time_allowed'], 'mod':'r', 'writeerror':'403'}, 103 'cmi.student_data.time_limit_action':{'defaultvalue':def[scoid]['cmi.student_data.time_limit_action'], 'mod':'r', 'writeerror':'403'}, 104 'cmi.student_preference._children':{'defaultvalue':student_preference_children, 'mod':'r', 'writeerror':'402'}, 105 'cmi.student_preference.audio':{'defaultvalue':def[scoid]['cmi.student_preference.audio'], 'format':CMISInteger, 'range':audio_range, 'mod':'rw', 'writeerror':'405'}, 106 'cmi.student_preference.language':{'defaultvalue':def[scoid]['cmi.student_preference.language'], 'format':CMIString256, 'mod':'rw', 'writeerror':'405'}, 107 'cmi.student_preference.speed':{'defaultvalue':def[scoid]['cmi.student_preference.speed'], 'format':CMISInteger, 'range':speed_range, 'mod':'rw', 'writeerror':'405'}, 108 'cmi.student_preference.text':{'defaultvalue':def[scoid]['cmi.student_preference.text'], 'format':CMISInteger, 'range':text_range, 'mod':'rw', 'writeerror':'405'}, 109 'cmi.interactions._children':{'defaultvalue':interactions_children, 'mod':'r', 'writeerror':'402'}, 110 'cmi.interactions._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'}, 111 'cmi.interactions.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 112 'cmi.interactions.n.objectives._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'}, 113 'cmi.interactions.n.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 114 'cmi.interactions.n.time':{'pattern':CMIIndex, 'format':CMITime, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 115 'cmi.interactions.n.type':{'pattern':CMIIndex, 'format':CMIType, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 116 'cmi.interactions.n.correct_responses._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'}, 117 'cmi.interactions.n.correct_responses.n.pattern':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 118 'cmi.interactions.n.weighting':{'pattern':CMIIndex, 'format':CMIDecimal, 'range':weighting_range, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 119 'cmi.interactions.n.student_response':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 120 'cmi.interactions.n.result':{'pattern':CMIIndex, 'format':CMIResult, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 121 'cmi.interactions.n.latency':{'pattern':CMIIndex, 'format':CMITimespan, 'mod':'w', 'readerror':'404', 'writeerror':'405'}, 122 'nav.event':{'defaultvalue':'', 'format':NAVEvent, 'mod':'w', 'readerror':'404', 'writeerror':'405'} 123 }; 124 } 125 126 var cmi, nav; 127 function initdatamodel(scoid){ 128 prerequrl = cfgwwwroot + "/mod/scorm/prereqs.php?a=" + scormid + "&scoid=" + scoid + "&attempt=" + attempt + "&mode=" + viewmode + "¤torg=" + currentorg + "&sesskey=" + sesskey; 129 datamodelurlparams = "id=" + cmid + "&a=" + scormid + "&sesskey=" + sesskey + "&attempt=" + attempt + "&scoid=" + scoid; 130 131 // 132 // Datamodel inizialization 133 // 134 cmi = new Object(); 135 cmi.core = new Object(); 136 cmi.core.score = new Object(); 137 cmi.objectives = new Object(); 138 cmi.student_data = new Object(); 139 cmi.student_preference = new Object(); 140 cmi.interactions = new Object(); 141 // deprecated evaluation attributes 142 cmi.evaluation = new Object(); 143 cmi.evaluation.comments = new Object(); 144 145 // Navigation Object 146 nav = new Object(); 147 148 for (element in datamodel[scoid]) { 149 if (element.match(/\.n\./) == null) { 150 if ((typeof eval('datamodel["' + scoid + '"]["' + element + '"].defaultvalue')) != 'undefined') { 151 eval(element + ' = datamodel["' + scoid + '"]["' + element + '"].defaultvalue;'); 152 } else { 153 eval(element + ' = "";'); 154 } 155 } 156 } 157 158 eval(cmiobj[scoid]); 159 eval(cmiint[scoid]); 160 161 if (cmi.core.lesson_status == '') { 162 cmi.core.lesson_status = 'not attempted'; 163 } 164 } 165 166 // 167 // API Methods definition 168 // 169 var Initialized = false; 170 171 function LMSInitialize (param) { 172 scoid = scorm_current_node ? scorm_current_node.scoid : scoid; 173 initdatamodel(scoid); 174 175 errorCode = "0"; 176 if (param == "") { 177 if (!Initialized) { 178 Initialized = true; 179 errorCode = "0"; 180 if (scormdebugging) { 181 LogAPICall("LMSInitialize", param, "", errorCode); 182 } 183 return "true"; 184 } else { 185 errorCode = "101"; 186 } 187 } else { 188 errorCode = "201"; 189 } 190 if (scormdebugging) { 191 LogAPICall("LMSInitialize", param, "", errorCode); 192 } 193 return "false"; 194 } 195 196 function LMSFinish (param) { 197 errorCode = "0"; 198 if (param == "") { 199 if (Initialized) { 200 Initialized = false; 201 result = StoreData(cmi,true); 202 if (nav.event != '') { 203 if (nav.event == 'continue') { 204 setTimeout('mod_scorm_launch_next_sco();',500); 205 } else { 206 setTimeout('mod_scorm_launch_prev_sco();',500); 207 } 208 } else { 209 if (scormauto == 1) { 210 setTimeout('mod_scorm_launch_next_sco();',500); 211 } 212 } 213 if (scormdebugging) { 214 LogAPICall("LMSFinish", "AJAXResult", result, 0); 215 } 216 result = ('true' == result) ? 'true' : 'false'; 217 errorCode = (result == 'true') ? '0' : '101'; 218 if (scormdebugging) { 219 LogAPICall("LMSFinish", "result", result, 0); 220 LogAPICall("LMSFinish", param, "", 0); 221 } 222 // trigger TOC update 223 var callback = M.mod_scorm.connectPrereqCallback; 224 YUI().use('io-base', function(Y) { 225 Y.on('io:complete', callback.success, Y); 226 Y.io(prerequrl); 227 }); 228 return result; 229 } else { 230 errorCode = "301"; 231 } 232 } else { 233 errorCode = "201"; 234 } 235 if (scormdebugging) { 236 LogAPICall("LMSFinish", param, "", errorCode); 237 } 238 return "false"; 239 } 240 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["' + scoid + '"]["' + elementmodel + '"]')) != "undefined") { 248 if (eval('datamodel["' + scoid + '"]["' + 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 if (scormdebugging) { 259 LogAPICall("LMSGetValue", element, eval(element), 0); 260 } 261 return eval(element); 262 } else { 263 errorCode = "0"; // Need to check if it is the right errorCode 264 } 265 } else { 266 errorCode = eval('datamodel["' + scoid + '"]["' + elementmodel + '"].readerror'); 267 } 268 } else { 269 childrenstr = '._children'; 270 countstr = '._count'; 271 if (elementmodel.substr(elementmodel.length - childrenstr.length,elementmodel.length) == childrenstr) { 272 parentmodel = elementmodel.substr(0,elementmodel.length - childrenstr.length); 273 if ((typeof eval('datamodel["' + scoid + '"]["' + parentmodel + '"]')) != "undefined") { 274 errorCode = "202"; 275 } else { 276 errorCode = "201"; 277 } 278 } else if (elementmodel.substr(elementmodel.length - countstr.length,elementmodel.length) == countstr) { 279 parentmodel = elementmodel.substr(0,elementmodel.length - countstr.length); 280 if ((typeof eval('datamodel["' + scoid + '"]["' + parentmodel + '"]')) != "undefined") { 281 errorCode = "203"; 282 } else { 283 errorCode = "201"; 284 } 285 } else { 286 errorCode = "201"; 287 } 288 } 289 } else { 290 errorCode = "201"; 291 } 292 } else { 293 errorCode = "301"; 294 } 295 if (scormdebugging) { 296 LogAPICall("LMSGetValue", element, "", errorCode); 297 } 298 return ""; 299 } 300 301 function LMSSetValue (element,value) { 302 errorCode = "0"; 303 if (Initialized) { 304 if (element != "") { 305 expression = new RegExp(CMIIndex,'g'); 306 elementmodel = String(element).replace(expression,'.n.'); 307 if ((typeof eval('datamodel["' + scoid + '"]["' + elementmodel + '"]')) != "undefined") { 308 if (eval('datamodel["' + scoid + '"]["' + elementmodel + '"].mod') != 'r') { 309 expression = new RegExp(eval('datamodel["' + scoid + '"]["' + elementmodel + '"].format')); 310 value = value + ''; 311 matches = value.match(expression); 312 if (matches != null) { 313 //Create dynamic data model element 314 if (element != elementmodel) { 315 elementIndexes = element.split('.'); 316 subelement = 'cmi'; 317 for (i = 1; i < elementIndexes.length - 1; i++) { 318 elementIndex = elementIndexes[i]; 319 if (elementIndexes[i + 1].match(/^\d+$/)) { 320 if ((typeof eval(subelement + '.' + elementIndex)) == "undefined") { 321 eval(subelement + '.' + elementIndex + ' = new Object();'); 322 eval(subelement + '.' + elementIndex + '._count = 0;'); 323 } 324 if (elementIndexes[i + 1] == eval(subelement + '.' + elementIndex + '._count')) { 325 eval(subelement + '.' + elementIndex + '._count++;'); 326 } 327 if (elementIndexes[i + 1] > eval(subelement + '.' + elementIndex + '._count')) { 328 errorCode = "201"; 329 } 330 subelement = subelement.concat('.' + elementIndex + '_' + elementIndexes[i + 1]); 331 i++; 332 } else { 333 subelement = subelement.concat('.' + elementIndex); 334 } 335 if ((typeof eval(subelement)) == "undefined") { 336 eval(subelement + ' = new Object();'); 337 if (subelement.substr(0,14) == 'cmi.objectives') { 338 eval(subelement + '.score = new Object();'); 339 eval(subelement + '.score._children = score_children;'); 340 eval(subelement + '.score.raw = "";'); 341 eval(subelement + '.score.min = "";'); 342 eval(subelement + '.score.max = "";'); 343 } 344 if (subelement.substr(0,16) == 'cmi.interactions') { 345 eval(subelement + '.objectives = new Object();'); 346 eval(subelement + '.objectives._count = 0;'); 347 eval(subelement + '.correct_responses = new Object();'); 348 eval(subelement + '.correct_responses._count = 0;'); 349 } 350 } 351 } 352 element = subelement.concat('.' + elementIndexes[elementIndexes.length - 1]); 353 } 354 //Store data 355 if (errorCode == "0") { 356 if (autocommit && !(SCORMapi1_2.timeout)) { 357 SCORMapi1_2.timeout = Y.later(60000, API, 'LMSCommit', [""], false); 358 } 359 if ((typeof eval('datamodel["' + scoid + '"]["' + elementmodel + '"].range')) != "undefined") { 360 range = eval('datamodel["' + scoid + '"]["' + elementmodel + '"].range'); 361 ranges = range.split('#'); 362 value = value * 1.0; 363 if ((value >= ranges[0]) && (value <= ranges[1])) { 364 eval(element + '=value;'); 365 errorCode = "0"; 366 if (scormdebugging) { 367 LogAPICall("LMSSetValue", element, value, errorCode); 368 } 369 return "true"; 370 } else { 371 errorCode = eval('datamodel["' + scoid + '"]["' + elementmodel + '"].writeerror'); 372 } 373 } else { 374 if (element == 'cmi.comments') { 375 cmi.comments = cmi.comments + value; 376 } else { 377 eval(element + '=value;'); 378 } 379 errorCode = "0"; 380 if (scormdebugging) { 381 LogAPICall("LMSSetValue", element, value, errorCode); 382 } 383 return "true"; 384 } 385 } 386 } else { 387 errorCode = eval('datamodel["' + scoid + '"]["' + elementmodel + '"].writeerror'); 388 } 389 } else { 390 errorCode = eval('datamodel["' + scoid + '"]["' + elementmodel + '"].writeerror'); 391 } 392 } else { 393 errorCode = "201" 394 } 395 } else { 396 errorCode = "201"; 397 } 398 } else { 399 errorCode = "301"; 400 } 401 if (scormdebugging) { 402 LogAPICall("LMSSetValue", element, value, errorCode); 403 } 404 return "false"; 405 } 406 407 function LMSCommit (param) { 408 if (SCORMapi1_2.timeout) { 409 SCORMapi1_2.timeout.cancel(); 410 SCORMapi1_2.timeout = null; 411 } 412 errorCode = "0"; 413 if (param == "") { 414 if (Initialized) { 415 result = StoreData(cmi,false); 416 // trigger TOC update 417 var callback = M.mod_scorm.connectPrereqCallback; 418 YUI().use('io-base', function(Y) { 419 Y.on('io:complete', callback.success, Y); 420 Y.io(prerequrl); 421 }); 422 if (scormdebugging) { 423 LogAPICall("Commit", param, "", 0); 424 } 425 if (scormdebugging) { 426 LogAPICall("LMSCommit", "AJAXResult", result, 0); 427 } 428 result = ('true' == result) ? 'true' : 'false'; 429 errorCode = (result == 'true') ? '0' : '101'; 430 if (scormdebugging) { 431 LogAPICall("LMSCommit", "result", result, 0); 432 LogAPICall("LMSCommit", "errorCode", errorCode, 0); 433 } 434 return result; 435 } else { 436 errorCode = "301"; 437 } 438 } else { 439 errorCode = "201"; 440 } 441 if (scormdebugging) { 442 LogAPICall("LMSCommit", param, "", 0); 443 } 444 return "false"; 445 } 446 447 function LMSGetLastError () { 448 if (scormdebugging) { 449 LogAPICall("LMSGetLastError", "", "", errorCode); 450 } 451 return errorCode; 452 } 453 454 function LMSGetErrorString (param) { 455 if (param != "") { 456 var errorString = new Array(); 457 errorString["0"] = "No error"; 458 errorString["101"] = "General exception"; 459 errorString["201"] = "Invalid argument error"; 460 errorString["202"] = "Element cannot have children"; 461 errorString["203"] = "Element not an array - cannot have count"; 462 errorString["301"] = "Not initialized"; 463 errorString["401"] = "Not implemented error"; 464 errorString["402"] = "Invalid set value, element is a keyword"; 465 errorString["403"] = "Element is read only"; 466 errorString["404"] = "Element is write only"; 467 errorString["405"] = "Incorrect data type"; 468 if (scormdebugging) { 469 LogAPICall("LMSGetErrorString", param, errorString[param], 0); 470 } 471 return errorString[param]; 472 } else { 473 if (scormdebugging) { 474 LogAPICall("LMSGetErrorString", param, "No error string found!", 0); 475 } 476 return ""; 477 } 478 } 479 480 function LMSGetDiagnostic (param) { 481 if (param == "") { 482 param = errorCode; 483 } 484 if (scormdebugging) { 485 LogAPICall("LMSGetDiagnostic", param, param, 0); 486 } 487 return param; 488 } 489 490 function AddTime (first, second) { 491 var sFirst = first.split(":"); 492 var sSecond = second.split(":"); 493 var cFirst = sFirst[2].split("."); 494 var cSecond = sSecond[2].split("."); 495 var change = 0; 496 497 FirstCents = 0; //Cents 498 if (cFirst.length > 1) { 499 FirstCents = parseInt(cFirst[1],10); 500 } 501 SecondCents = 0; 502 if (cSecond.length > 1) { 503 SecondCents = parseInt(cSecond[1],10); 504 } 505 var cents = FirstCents + SecondCents; 506 change = Math.floor(cents / 100); 507 cents = cents - (change * 100); 508 if (Math.floor(cents) < 10) { 509 cents = "0" + cents.toString(); 510 } 511 512 var secs = parseInt(cFirst[0],10) + parseInt(cSecond[0],10) + change; //Seconds 513 change = Math.floor(secs / 60); 514 secs = secs - (change * 60); 515 if (Math.floor(secs) < 10) { 516 secs = "0" + secs.toString(); 517 } 518 519 mins = parseInt(sFirst[1],10) + parseInt(sSecond[1],10) + change; //Minutes 520 change = Math.floor(mins / 60); 521 mins = mins - (change * 60); 522 if (mins < 10) { 523 mins = "0" + mins.toString(); 524 } 525 526 hours = parseInt(sFirst[0],10) + parseInt(sSecond[0],10) + change; //Hours 527 if (hours < 10) { 528 hours = "0" + hours.toString(); 529 } 530 531 if (cents != '0') { 532 return hours + ":" + mins + ":" + secs + '.' + cents; 533 } else { 534 return hours + ":" + mins + ":" + secs; 535 } 536 } 537 538 function TotalTime() { 539 total_time = AddTime(cmi.core.total_time, cmi.core.session_time); 540 return '&' + underscore('cmi.core.total_time') + '=' + encodeURIComponent(total_time); 541 } 542 543 function CollectData(data,parent) { 544 var datastring = ''; 545 for (property in data) { 546 if (typeof data[property] == 'object') { 547 datastring += CollectData(data[property],parent + '.' + property); 548 } else { 549 element = parent + '.' + property; 550 expression = new RegExp(CMIIndex,'g'); 551 552 // get the generic name for this element (e.g. convert 'cmi.interactions.1.id' to 'cmi.interactions.n.id') 553 elementmodel = String(element).replace(expression,'.n.'); 554 555 // ignore the session time element 556 if (element != "cmi.core.session_time") { 557 558 // check if this specific element is not defined in the datamodel, 559 // but the generic element name is 560 if ((eval('typeof datamodel["' + scoid + '"]["' + element + '"]')) == "undefined" 561 && (eval('typeof datamodel["' + scoid + '"]["' + elementmodel + '"]')) != "undefined") { 562 563 // add this specific element to the data model (by cloning 564 // the generic element) so we can track changes to it 565 eval('datamodel["' + scoid + '"]["' + element + '"]=CloneObj(datamodel["' + scoid + '"]["' + elementmodel + '"]);'); 566 } 567 568 // check if the current element exists in the datamodel 569 if ((typeof eval('datamodel["' + scoid + '"]["' + element + '"]')) != "undefined") { 570 571 // make sure this is not a read only element 572 if (eval('datamodel["' + scoid + '"]["' + element + '"].mod') != 'r') { 573 574 elementstring = '&' + underscore(element) + '=' + encodeURIComponent(data[property]); 575 576 // check if the element has a default value 577 if ((typeof eval('datamodel["' + scoid + '"]["' + element + '"].defaultvalue')) != "undefined") { 578 579 // check if the default value is different from the current value 580 if (eval('datamodel["' + scoid + '"]["' + element + '"].defaultvalue') != data[property] 581 || eval('typeof(datamodel["' + scoid + '"]["' + element + '"].defaultvalue)') != typeof(data[property])) { 582 583 // append the URI fragment to the string we plan to commit 584 datastring += elementstring; 585 586 // update the element default to reflect the current committed value 587 eval('datamodel["' + scoid + '"]["' + element + '"].defaultvalue=data[property];'); 588 } 589 } else { 590 // append the URI fragment to the string we plan to commit 591 datastring += elementstring; 592 // no default value for the element, so set it now 593 eval('datamodel["' + scoid + '"]["' + element + '"].defaultvalue=data[property];'); 594 } 595 } 596 } 597 } 598 } 599 } 600 return datastring; 601 } 602 603 function CloneObj(obj){ 604 if(obj == null || typeof(obj) != 'object') { 605 return obj; 606 } 607 608 var temp = new obj.constructor(); // changed (twice) 609 for(var key in obj) { 610 temp[key] = CloneObj(obj[key]); 611 } 612 613 return temp; 614 } 615 616 function StoreData(data,storetotaltime) { 617 if (storetotaltime) { 618 if (cmi.core.lesson_status == 'not attempted') { 619 cmi.core.lesson_status = 'completed'; 620 } 621 if (cmi.core.lesson_mode == 'normal') { 622 if (cmi.core.credit == 'credit') { 623 if (masteryoverride && cmi.student_data.mastery_score !== '' && cmi.core.score.raw !== '') { 624 if (parseFloat(cmi.core.score.raw) >= parseFloat(cmi.student_data.mastery_score)) { 625 cmi.core.lesson_status = 'passed'; 626 } else { 627 cmi.core.lesson_status = 'failed'; 628 } 629 } 630 } 631 } 632 if (cmi.core.lesson_mode == 'browse') { 633 if (datamodel[scoid]['cmi.core.lesson_status'].defaultvalue == '' && cmi.core.lesson_status == 'not attempted') { 634 cmi.core.lesson_status = 'browsed'; 635 } 636 } 637 datastring = CollectData(data,'cmi'); 638 datastring += TotalTime(); 639 } else { 640 datastring = CollectData(data,'cmi'); 641 } 642 643 var myRequest = NewHttpReq(); 644 //alert('going to:' + "<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php" + "id=<?php p($id) ?>&a=<?php p($a) ?>&sesskey=<?php echo sesskey() ?>"+datastring); 645 result = DoRequest(myRequest,datamodelurl,datamodelurlparams + datastring); 646 results = String(result).split('\n'); 647 errorCode = results[1]; 648 return results[0]; 649 } 650 651 this.LMSInitialize = LMSInitialize; 652 this.LMSFinish = LMSFinish; 653 this.LMSGetValue = LMSGetValue; 654 this.LMSSetValue = LMSSetValue; 655 this.LMSCommit = LMSCommit; 656 this.LMSGetLastError = LMSGetLastError; 657 this.LMSGetErrorString = LMSGetErrorString; 658 this.LMSGetDiagnostic = LMSGetDiagnostic; 659 } 660 661 M.scorm_api = {}; 662 663 M.scorm_api.init = function(Y, def, cmiobj, cmiint, cmistring256, cmistring4096, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg, autocommit, masteryoverride) { 664 window.API = new SCORMapi1_2(def, cmiobj, cmiint, cmistring256, cmistring4096, scormdebugging, scormauto, scormid, cfgwwwroot, sesskey, scoid, attempt, viewmode, cmid, currentorg, autocommit, masteryoverride); 665 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |