PageRenderTime 45ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/mod/scorm/datamodels/aicc.js.php

https://bitbucket.org/synergylearning/campusconnect
PHP | 573 lines | 519 code | 25 blank | 29 comment | 82 complexity | a3a86d9609caf1a00e7331b93aa08aaa MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, LGPL-2.1, Apache-2.0, BSD-3-Clause, AGPL-3.0
  1. <?php
  2. // This file is part of Moodle - http://moodle.org/
  3. //
  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.
  8. //
  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.
  13. //
  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/>.
  16. if (isset($userdata->status)) {
  17. if ($userdata->status == '') {
  18. $userdata->entry = 'ab-initio';
  19. } else {
  20. if (isset($userdata->{'cmi.core.exit'}) && ($userdata->{'cmi.core.exit'} == 'suspend')) {
  21. $userdata->entry = 'resume';
  22. } else {
  23. $userdata->entry = '';
  24. }
  25. }
  26. }
  27. if (!isset($currentorg)) {
  28. $currentorg = '';
  29. }
  30. ?>
  31. //
  32. // SCORM 1.2 API Implementation
  33. //
  34. function AICCapi() {
  35. // Standard Data Type Definition
  36. CMIString256 = '^.{0,255}$';
  37. CMIString4096 = '^.{0,4096}$';
  38. CMITime = '^([0-2]{1}[0-9]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})(\.[0-9]{1,2})?$';
  39. CMITimespan = '^([0-9]{2,4}):([0-9]{2}):([0-9]{2})(\.[0-9]{1,2})?$';
  40. CMIInteger = '^\\d+$';
  41. CMISInteger = '^-?([0-9]+)$';
  42. CMIDecimal = '^-?([0-9]{0,3})(\.[0-9]{1,2})?$';
  43. CMIIdentifier = '^\\w{1,255}$';
  44. CMIFeedback = CMIString256; // This must be redefined
  45. CMIIndex = '[._](\\d+).';
  46. // Vocabulary Data Type Definition
  47. CMIStatus = '^passed$|^completed$|^failed$|^incomplete$|^browsed$';
  48. CMIStatus2 = '^passed$|^completed$|^failed$|^incomplete$|^browsed$|^not attempted$';
  49. CMIExit = '^time-out$|^suspend$|^logout$|^$';
  50. CMIType = '^true-false$|^choice$|^fill-in$|^matching$|^performance$|^sequencing$|^likert$|^numeric$';
  51. CMIResult = '^correct$|^wrong$|^unanticipated$|^neutral$|^([0-9]{0,3})?(\.[0-9]{1,2})?$';
  52. NAVEvent = '^previous$|^continue$';
  53. // Children lists
  54. cmi_children = 'core, suspend_data, launch_data, comments, objectives, student_data, student_preference, interactions';
  55. core_children = 'student_id, student_name, lesson_location, credit, lesson_status, entry, score, total_time, lesson_mode, exit, session_time';
  56. score_children = 'raw, min, max';
  57. comments_children = 'content, location, time';
  58. objectives_children = 'id, score, status';
  59. student_data_children = 'attempt_number, tries, mastery_score, max_time_allowed, time_limit_action';
  60. student_preference_children = 'audio, language, speed, text';
  61. interactions_children = 'id, objectives, time, type, correct_responses, weighting, student_response, result, latency';
  62. // Data ranges
  63. score_range = '0#100';
  64. audio_range = '-1#100';
  65. speed_range = '-100#100';
  66. weighting_range = '-100#100';
  67. text_range = '-1#1';
  68. // The AICC data model
  69. var datamodel = {
  70. 'cmi._children':{'defaultvalue':cmi_children, 'mod':'r', 'writeerror':'402'},
  71. 'cmi._version':{'defaultvalue':'3.4', 'mod':'r', 'writeerror':'402'},
  72. 'cmi.core._children':{'defaultvalue':core_children, 'mod':'r', 'writeerror':'402'},
  73. 'cmi.core.student_id':{'defaultvalue':'<?php echo $userdata->student_id ?>', 'mod':'r', 'writeerror':'403'},
  74. 'cmi.core.student_name':{'defaultvalue':'<?php echo $userdata->student_name ?>', 'mod':'r', 'writeerror':'403'},
  75. 'cmi.core.lesson_location':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_location'})?$userdata->{'cmi.core.lesson_location'}:'' ?>', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
  76. 'cmi.core.credit':{'defaultvalue':'<?php echo $userdata->credit ?>', 'mod':'r', 'writeerror':'403'},
  77. 'cmi.core.lesson_status':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.lesson_status'})?$userdata->{'cmi.core.lesson_status'}:'' ?>', 'format':CMIStatus, 'mod':'rw', 'writeerror':'405'},
  78. 'cmi.core.exit':{'defaultvalue':'<?php echo isset($userdata->{'cmi.core.exit'})?$userdata->{'cmi.core.exit'}:'' ?>', 'format':CMIExit, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  79. 'cmi.core.entry':{'defaultvalue':'<?php echo $userdata->entry ?>', 'mod':'r', 'writeerror':'403'},
  80. 'cmi.core.score._children':{'defaultvalue':score_children, 'mod':'r', 'writeerror':'402'},
  81. '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'},
  82. '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'},
  83. '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'},
  84. 'cmi.core.session_time':{'format':CMITimespan, 'mod':'w', 'defaultvalue':'00:00:00', 'readerror':'404', 'writeerror':'405'},
  85. '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'},
  86. 'cmi.core.lesson_mode':{'defaultvalue':'<?php echo $userdata->mode ?>', 'mod':'r', 'writeerror':'403'},
  87. 'cmi.suspend_data':{'defaultvalue':'<?php echo isset($userdata->{'cmi.suspend_data'})?$userdata->{'cmi.suspend_data'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
  88. 'cmi.launch_data':{'defaultvalue':'<?php echo isset($userdata->datafromlms)?$userdata->datafromlms:'' ?>', 'mod':'r', 'writeerror':'403'},
  89. 'cmi.comments':{'defaultvalue':'<?php echo isset($userdata->{'cmi.comments'})?$userdata->{'cmi.comments'}:'' ?>', 'format':CMIString4096, 'mod':'rw', 'writeerror':'405'},
  90. // deprecated evaluation attributes
  91. 'cmi.evaluation.comments._count':{'defaultvalue':'0', 'mod':'r', 'writeerror':'402'},
  92. 'cmi.evaluation.comments._children':{'defaultvalue':comments_children, 'mod':'r', 'writeerror':'402'},
  93. 'cmi.evaluation.comments.n.content':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
  94. 'cmi.evaluation.comments.n.location':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
  95. 'cmi.evaluation.comments.n.time':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMITime, 'mod':'rw', 'writeerror':'405'},
  96. 'cmi.comments_from_lms':{'mod':'r', 'writeerror':'403'},
  97. 'cmi.objectives._children':{'defaultvalue':objectives_children, 'mod':'r', 'writeerror':'402'},
  98. 'cmi.objectives._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
  99. 'cmi.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'rw', 'writeerror':'405'},
  100. 'cmi.objectives.n.score._children':{'pattern':CMIIndex, 'mod':'r', 'writeerror':'402'},
  101. 'cmi.objectives.n.score.raw':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
  102. 'cmi.objectives.n.score.min':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
  103. 'cmi.objectives.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
  104. 'cmi.objectives.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'},
  105. 'cmi.student_data._children':{'defaultvalue':student_data_children, 'mod':'r', 'writeerror':'402'},
  106. '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'},
  107. 'cmi.student_data.tries.n.score.raw':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
  108. 'cmi.student_data.tries.n.score.min':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
  109. 'cmi.student_data.tries.n.score.max':{'defaultvalue':'', 'pattern':CMIIndex, 'format':CMIDecimal, 'range':score_range, 'mod':'rw', 'writeerror':'405'},
  110. 'cmi.student_data.tries.n.status':{'pattern':CMIIndex, 'format':CMIStatus2, 'mod':'rw', 'writeerror':'405'},
  111. 'cmi.student_data.tries.n.time':{'pattern':CMIIndex, 'format':CMITime, 'mod':'rw', 'writeerror':'405'},
  112. 'cmi.student_data.mastery_score':{'defaultvalue':'<?php echo isset($userdata->mastery_score)?$userdata->mastery_score:'' ?>', 'mod':'r', 'writeerror':'403'},
  113. 'cmi.student_data.max_time_allowed':{'defaultvalue':'<?php echo isset($userdata->max_time_allowed)?$userdata->max_time_allowed:'' ?>', 'mod':'r', 'writeerror':'403'},
  114. 'cmi.student_data.time_limit_action':{'defaultvalue':'<?php echo isset($userdata->time_limit_action)?$userdata->time_limit_action:'' ?>', 'mod':'r', 'writeerror':'403'},
  115. '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'},
  116. 'cmi.student_preference._children':{'defaultvalue':student_preference_children, 'mod':'r', 'writeerror':'402'},
  117. 'cmi.student_preference.audio':{'defaultvalue':'0', 'format':CMISInteger, 'range':audio_range, 'mod':'rw', 'writeerror':'405'},
  118. 'cmi.student_preference.language':{'defaultvalue':'', 'format':CMIString256, 'mod':'rw', 'writeerror':'405'},
  119. 'cmi.student_preference.speed':{'defaultvalue':'0', 'format':CMISInteger, 'range':speed_range, 'mod':'rw', 'writeerror':'405'},
  120. 'cmi.student_preference.text':{'defaultvalue':'0', 'format':CMISInteger, 'range':text_range, 'mod':'rw', 'writeerror':'405'},
  121. 'cmi.interactions._children':{'defaultvalue':interactions_children, 'mod':'r', 'writeerror':'402'},
  122. 'cmi.interactions._count':{'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
  123. 'cmi.interactions.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  124. 'cmi.interactions.n.objectives._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
  125. 'cmi.interactions.n.objectives.n.id':{'pattern':CMIIndex, 'format':CMIIdentifier, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  126. 'cmi.interactions.n.time':{'pattern':CMIIndex, 'format':CMITime, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  127. 'cmi.interactions.n.type':{'pattern':CMIIndex, 'format':CMIType, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  128. 'cmi.interactions.n.correct_responses._count':{'pattern':CMIIndex, 'mod':'r', 'defaultvalue':'0', 'writeerror':'402'},
  129. 'cmi.interactions.n.correct_responses.n.pattern':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  130. 'cmi.interactions.n.weighting':{'pattern':CMIIndex, 'format':CMIDecimal, 'range':weighting_range, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  131. 'cmi.interactions.n.student_response':{'pattern':CMIIndex, 'format':CMIFeedback, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  132. 'cmi.interactions.n.result':{'pattern':CMIIndex, 'format':CMIResult, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  133. 'cmi.interactions.n.latency':{'pattern':CMIIndex, 'format':CMITimespan, 'mod':'w', 'readerror':'404', 'writeerror':'405'},
  134. 'nav.event':{'defaultvalue':'', 'format':NAVEvent, 'mod':'w', 'readerror':'404', 'writeerror':'405'}
  135. };
  136. //
  137. // Datamodel inizialization
  138. //
  139. var cmi = new Object();
  140. cmi.core = new Object();
  141. cmi.core.score = new Object();
  142. cmi.objectives = new Object();
  143. cmi.student_data = new Object();
  144. cmi.student_preference = new Object();
  145. cmi.interactions = new Object();
  146. // deprecated evaluation attributes
  147. cmi.evaluation = new Object();
  148. cmi.evaluation.comments = new Object();
  149. // Navigation Object
  150. var nav = new Object();
  151. for (element in datamodel) {
  152. if (element.match(/\.n\./) == null) {
  153. if ((typeof eval('datamodel["'+element+'"].defaultvalue')) != 'undefined') {
  154. eval(element+' = datamodel["'+element+'"].defaultvalue;');
  155. } else {
  156. eval(element+' = "";');
  157. }
  158. }
  159. }
  160. <?php
  161. $current_objective = '';
  162. $count = 0;
  163. $objectives = '';
  164. foreach ($userdata as $element => $value) {
  165. if (substr($element, 0, 14) == 'cmi.objectives') {
  166. $element = preg_replace('/\.(\d+)\./', "_\$1.", $element);
  167. preg_match('/\_(\d+)\./', $element, $matches);
  168. if (count($matches) > 0 && $current_objective != $matches[1]) {
  169. $current_objective = $matches[1];
  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. echo ' '.$subelement.".score.raw = '';\n";
  177. echo ' '.$subelement.".score.min = '';\n";
  178. echo ' '.$subelement.".score.max = '';\n";
  179. }
  180. echo ' '.$element.' = \''.$value."';\n";
  181. }
  182. }
  183. if ($count > 0) {
  184. echo ' cmi.objectives._count = '.$count.";\n";
  185. }
  186. ?>
  187. if (cmi.core.lesson_status == '') {
  188. cmi.core.lesson_status = 'not attempted';
  189. }
  190. //
  191. // API Methods definition
  192. //
  193. var Initialized = false;
  194. function LMSInitialize (param) {
  195. errorCode = "0";
  196. if (param == "") {
  197. if (!Initialized) {
  198. Initialized = true;
  199. errorCode = "0";
  200. return "true";
  201. } else {
  202. errorCode = "101";
  203. }
  204. } else {
  205. errorCode = "201";
  206. }
  207. return "false";
  208. }
  209. function LMSFinish (param) {
  210. errorCode = "0";
  211. if (param == "") {
  212. if (Initialized) {
  213. Initialized = false;
  214. result = StoreData(cmi,true);
  215. if (nav.event != '') {
  216. if (nav.event == 'continue') {
  217. setTimeout('mod_scorm_launch_next_sco();',500);
  218. } else {
  219. setTimeout('mod_scorm_launch_prev_sco();',500);
  220. }
  221. } else {
  222. if (<?php echo $scorm->auto ?> == 1) {
  223. setTimeout('mod_scorm_launch_next_sco();',500);
  224. }
  225. }
  226. // trigger TOC update
  227. 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(); ?>";
  228. var callback = M.mod_scorm.connectPrereqCallback;
  229. YUI().use('io-base', function(Y) {
  230. Y.on('io:complete', callback.success, Y);
  231. Y.io(sURL);
  232. });
  233. return "true";
  234. } else {
  235. errorCode = "301";
  236. }
  237. } else {
  238. errorCode = "201";
  239. }
  240. return "false";
  241. }
  242. function LMSGetValue (element) {
  243. errorCode = "0";
  244. if (Initialized) {
  245. if (element !="") {
  246. expression = new RegExp(CMIIndex,'g');
  247. elementmodel = String(element).replace(expression,'.n.');
  248. if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
  249. if (eval('datamodel["'+elementmodel+'"].mod') != 'w') {
  250. element = String(element).replace(expression, "_$1.");
  251. elementIndexes = element.split('.');
  252. subelement = 'cmi';
  253. i = 1;
  254. while ((i < elementIndexes.length) && (typeof eval(subelement) != "undefined")) {
  255. subelement += '.'+elementIndexes[i++];
  256. }
  257. if (subelement == element) {
  258. errorCode = "0";
  259. return eval(element);
  260. } else {
  261. errorCode = "0"; // Need to check if it is the right errorCode
  262. }
  263. } else {
  264. errorCode = eval('datamodel["'+elementmodel+'"].readerror');
  265. }
  266. } else {
  267. childrenstr = '._children';
  268. countstr = '._count';
  269. if (elementmodel.substr(elementmodel.length-childrenstr.length,elementmodel.length) == childrenstr) {
  270. parentmodel = elementmodel.substr(0,elementmodel.length-childrenstr.length);
  271. if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
  272. errorCode = "202";
  273. } else {
  274. errorCode = "201";
  275. }
  276. } else if (elementmodel.substr(elementmodel.length-countstr.length,elementmodel.length) == countstr) {
  277. parentmodel = elementmodel.substr(0,elementmodel.length-countstr.length);
  278. if ((typeof eval('datamodel["'+parentmodel+'"]')) != "undefined") {
  279. errorCode = "203";
  280. } else {
  281. errorCode = "201";
  282. }
  283. } else {
  284. errorCode = "201";
  285. }
  286. }
  287. } else {
  288. errorCode = "201";
  289. }
  290. } else {
  291. errorCode = "301";
  292. }
  293. return "";
  294. }
  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. }
  388. function LMSCommit (param) {
  389. errorCode = "0";
  390. if (param == "") {
  391. if (Initialized) {
  392. result = StoreData(cmi,false);
  393. return "true";
  394. } else {
  395. errorCode = "301";
  396. }
  397. } else {
  398. errorCode = "201";
  399. }
  400. return "false";
  401. }
  402. function LMSGetLastError () {
  403. return errorCode;
  404. }
  405. function LMSGetErrorString (param) {
  406. if (param != "") {
  407. var errorString = new Array();
  408. errorString["0"] = "No error";
  409. errorString["101"] = "General exception";
  410. errorString["201"] = "Invalid argument error";
  411. errorString["202"] = "Element cannot have children";
  412. errorString["203"] = "Element not an array - cannot have count";
  413. errorString["301"] = "Not initialized";
  414. errorString["401"] = "Not implemented error";
  415. errorString["402"] = "Invalid set value, element is a keyword";
  416. errorString["403"] = "Element is read only";
  417. errorString["404"] = "Element is write only";
  418. errorString["405"] = "Incorrect data type";
  419. return errorString[param];
  420. } else {
  421. return "";
  422. }
  423. }
  424. function LMSGetDiagnostic (param) {
  425. if (param == "") {
  426. param = errorCode;
  427. }
  428. return param;
  429. }
  430. function AddTime (first, second) {
  431. var sFirst = first.split(":");
  432. var sSecond = second.split(":");
  433. var cFirst = sFirst[2].split(".");
  434. var cSecond = sSecond[2].split(".");
  435. var change = 0;
  436. FirstCents = 0; //Cents
  437. if (cFirst.length > 1) {
  438. FirstCents = parseInt(cFirst[1],10);
  439. }
  440. SecondCents = 0;
  441. if (cSecond.length > 1) {
  442. SecondCents = parseInt(cSecond[1],10);
  443. }
  444. var cents = FirstCents + SecondCents;
  445. change = Math.floor(cents / 100);
  446. cents = cents - (change * 100);
  447. if (Math.floor(cents) < 10) {
  448. cents = "0" + cents.toString();
  449. }
  450. var secs = parseInt(cFirst[0],10)+parseInt(cSecond[0],10)+change; //Seconds
  451. change = Math.floor(secs / 60);
  452. secs = secs - (change * 60);
  453. if (Math.floor(secs) < 10) {
  454. secs = "0" + secs.toString();
  455. }
  456. mins = parseInt(sFirst[1],10)+parseInt(sSecond[1],10)+change; //Minutes
  457. change = Math.floor(mins / 60);
  458. mins = mins - (change * 60);
  459. if (mins < 10) {
  460. mins = "0" + mins.toString();
  461. }
  462. hours = parseInt(sFirst[0],10)+parseInt(sSecond[0],10)+change; //Hours
  463. if (hours < 10) {
  464. hours = "0" + hours.toString();
  465. }
  466. if (cents != '0') {
  467. return hours + ":" + mins + ":" + secs + '.' + cents;
  468. } else {
  469. return hours + ":" + mins + ":" + secs;
  470. }
  471. }
  472. function TotalTime() {
  473. total_time = AddTime(cmi.core.total_time, cmi.core.session_time);
  474. return '&'+underscore('cmi.core.total_time')+'='+escape(total_time);
  475. }
  476. function CollectData(data,parent) {
  477. var datastring = '';
  478. for (property in data) {
  479. if (typeof data[property] == 'object') {
  480. datastring += CollectData(data[property],parent+'.'+property);
  481. } else {
  482. element = parent+'.'+property;
  483. expression = new RegExp(CMIIndex,'g');
  484. elementmodel = String(element).replace(expression,'.n.');
  485. if ((typeof eval('datamodel["'+elementmodel+'"]')) != "undefined") {
  486. if (eval('datamodel["'+elementmodel+'"].mod') != 'r') {
  487. elementstring = '&'+underscore(element)+'='+escape(data[property]);
  488. if ((typeof eval('datamodel["'+elementmodel+'"].defaultvalue')) != "undefined") {
  489. if (eval('datamodel["'+elementmodel+'"].defaultvalue') != data[property]) {
  490. datastring += elementstring;
  491. }
  492. } else {
  493. datastring += elementstring;
  494. }
  495. }
  496. }
  497. }
  498. }
  499. return datastring;
  500. }
  501. function StoreData(data,storetotaltime) {
  502. if (storetotaltime) {
  503. if (cmi.core.lesson_mode == 'normal') {
  504. if (cmi.core.credit == 'credit') {
  505. if (cmi.student_data.mastery_score != '' && cmi.core.score.raw != '') {
  506. if (cmi.core.score.raw >= cmi.student_data.mastery_score) {
  507. cmi.core.lesson_status = 'passed';
  508. } else {
  509. cmi.core.lesson_status = 'failed';
  510. }
  511. }
  512. }
  513. }
  514. if (cmi.core.lesson_mode == 'browse') {
  515. if (datamodel['cmi.core.lesson_status'].defaultvalue == '' && cmi.core.lesson_status == 'not attempted') {
  516. cmi.core.lesson_status = 'browsed';
  517. }
  518. }
  519. datastring = CollectData(data,'cmi');
  520. datastring += TotalTime();
  521. } else {
  522. datastring = CollectData(data,'cmi');
  523. }
  524. datastring += '&attempt=<?php echo $attempt ?>';
  525. datastring += '&scoid=<?php echo $scoid ?>';
  526. //popupwin(datastring);
  527. var myRequest = NewHttpReq();
  528. result = DoRequest(myRequest,"<?php p($CFG->wwwroot) ?>/mod/scorm/datamodel.php","id=<?php p($id) ?>&sesskey=<?php echo sesskey() ?>"+datastring);
  529. results = String(result).split('\n');
  530. errorCode = results[1];
  531. return results[0];
  532. }
  533. this.LMSInitialize = LMSInitialize;
  534. this.LMSFinish = LMSFinish;
  535. this.LMSGetValue = LMSGetValue;
  536. this.LMSSetValue = LMSSetValue;
  537. this.LMSCommit = LMSCommit;
  538. this.LMSGetLastError = LMSGetLastError;
  539. this.LMSGetErrorString = LMSGetErrorString;
  540. this.LMSGetDiagnostic = LMSGetDiagnostic;
  541. }
  542. var API = new AICCapi();