api_wrapper.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. /**
  2. * Wrapper to the SCORM API provided by Chamilo
  3. * The complete set of functions and variables are in this file to avoid unnecessary file
  4. * accesses.
  5. * Only event triggers and answer data are inserted into the final document.
  6. * @author Yannick Warnier - inspired by the ADLNet documentation on SCORM content-side API
  7. * @package scorm.js
  8. */
  9. /**
  10. * Initialisation of the SCORM API section.
  11. * Find the SCO functions (startTimer, computeTime, etc in the second section)
  12. * Find the Chamilo-proper functions (checkAnswers, etc in the third section)
  13. */
  14. var _debug = false;
  15. var findAPITries = 0;
  16. var _apiHandle = null; //private variable
  17. var errMsgLocate = "Unable to locate the LMS's API implementation";
  18. var _NoError = 0;
  19. var _GeneralException = 101;
  20. var _ServerBusy = 102;
  21. var _InvalidArgumentError = 201;
  22. var _ElementCannotHaveChildren = 202;
  23. var _ElementIsNotAnArray = 203;
  24. var _NotInitialized = 301;
  25. var _NotImplementedError = 401;
  26. var _InvalidSetValue = 402;
  27. var _ElementIsReadOnly = 403;
  28. var _ElementIsWriteOnly = 404;
  29. var _IncorrectDataType = 405;
  30. /**
  31. * Gets the API handle right into the local API object and ensure there is only one.
  32. * Using the singleton pattern to ensure there's only one API object.
  33. * @return object The API object as given by the LMS
  34. */
  35. var API = new function ()
  36. {
  37. if (_apiHandle == null)
  38. {
  39. _apiHandle = getAPI();
  40. }
  41. return _apiHandle;
  42. }
  43. /**
  44. * Finds the API on the LMS side or gives up giving an error message
  45. * @param object The window/frame object in which we are searching for the SCORM API
  46. * @return object The API object recovered from the LMS's implementation of the SCORM API
  47. */
  48. function findAPI(win)
  49. {
  50. while((win.API == null) && (win.parent != null) && (win.parent != win))
  51. {
  52. findAPITries++;
  53. if(findAPITries>10)
  54. {
  55. alert("Error finding API - too deeply nested");
  56. return null;
  57. }
  58. win = win.parent
  59. }
  60. return win.API;
  61. }
  62. /**
  63. * Gets the API from the current window/frame or from parent objects if not found
  64. * @return object The API object recovered from the LMS's implementation of the SCORM API
  65. */
  66. function getAPI()
  67. {
  68. //window is the global/root object of the current window/frame
  69. var MyAPI = findAPI(window);
  70. //look through parents if any
  71. if((MyAPI == null) && (window.opener != null) && (typeof(window.opener) != "undefined"))
  72. {
  73. MyAPI = findAPI(window.opener);
  74. }
  75. //still not found? error message
  76. if(MyAPI == null)
  77. {
  78. alert("Unable to find SCORM API adapter.\nPlease check your LMS is considering this page as SCORM and providing the right JavaScript interface.")
  79. }
  80. return MyAPI;
  81. }
  82. /**
  83. * Handles error codes (prints the error if it has a description)
  84. * @return int Error code from LMS's API
  85. */
  86. function ErrorHandler()
  87. {
  88. if(API == null)
  89. {
  90. alert("Unable to locate the LMS's API. Cannot determine LMS error code");
  91. return;
  92. }
  93. var errCode = API.LMSGetLastError().toString();
  94. if(errCode != _NoError)
  95. {
  96. if(errCode == _NotImplementedError)
  97. {
  98. var errDescription = "The LMS doesn't support this feature";
  99. if(_debug)
  100. {
  101. errDescription += "\n";
  102. errDescription += api.LMSGetDiagnostic(null);
  103. }
  104. alert (errDescription);
  105. }
  106. else
  107. {
  108. var errDescription = API.LMSGetErrorString(errCode);
  109. if(_debug)
  110. {
  111. errDescription += "\n";
  112. errDescription += api.LMSGetDiagnostic(null);
  113. }
  114. alert (errDescription);
  115. }
  116. }
  117. return errCode;
  118. }
  119. /**
  120. * Calls the LMSInitialize method of the LMS's API object
  121. * @return string The string value of the LMS returned value or false if error (should be "true" otherwise)
  122. */
  123. function doLMSInitialize()
  124. {
  125. if(API == null)
  126. {
  127. alert(errMsgLocate + "\nLMSInitialize failed");
  128. return false;
  129. }
  130. var result = API.LMSInitialize("");
  131. if(result.toString() != "true")
  132. {
  133. var err = ErrorHandler();
  134. }
  135. return result.toString();
  136. }
  137. /**
  138. * Calls the LMSFinish method of the LMS's API object
  139. * @return string The string value of the LMS return value, or false if error (should be "true" otherwise)
  140. */
  141. function doLMSFinish()
  142. {
  143. if(API == null)
  144. {
  145. alert(errMsgLocate + "\nLMSFinish failed");
  146. return false;
  147. }
  148. else
  149. {
  150. var result = API.LMSFinish('');
  151. if(result.toString() != "true")
  152. {
  153. var err = ErrorHandler();
  154. }
  155. }
  156. return result.toString();
  157. }
  158. /**
  159. * Calls the LMSGetValue method
  160. * @param string The name of the SCORM parameter to get
  161. * @return string The value returned by the LMS
  162. */
  163. function doLMSGetValue(name)
  164. {
  165. if (API == null)
  166. {
  167. alert(errMsgLocate + "\nLMSGetValue was not successful.");
  168. return "";
  169. }
  170. else
  171. {
  172. var value = API.LMSGetValue(name);
  173. var errCode = API.LMSGetLastError().toString();
  174. if (errCode != _NoError)
  175. {
  176. // an error was encountered so display the error description
  177. var errDescription = API.LMSGetErrorString(errCode);
  178. alert("LMSGetValue("+name+") failed. \n"+ errDescription);
  179. return "";
  180. }
  181. else
  182. {
  183. return value.toString();
  184. }
  185. }
  186. }
  187. /**
  188. * Calls the LMSSetValue method of the API object
  189. * @param string The name of the SCORM parameter to set
  190. * @param string The value to set the parameter to
  191. * @return void
  192. */
  193. function doLMSSetValue(name, value)
  194. {
  195. if (API == null)
  196. {
  197. alert("Unable to locate the LMS's API Implementation.\nLMSSetValue was not successful.");
  198. return;
  199. }
  200. else
  201. {
  202. var result = API.LMSSetValue(name, value);
  203. if (result.toString() != "true")
  204. {
  205. var err = ErrorHandler();
  206. }
  207. }
  208. return;
  209. }
  210. /**
  211. * Calls the LMSCommit method
  212. */
  213. function doLMSCommit()
  214. {
  215. if(API == null)
  216. {
  217. alert(errMsgLocate +"\nLMSCommit was not successful.");
  218. return "false";
  219. }
  220. else
  221. {
  222. var result = API.LMSCommit("");
  223. if (result != "true")
  224. {
  225. var err = ErrorHandler();
  226. }
  227. }
  228. return result.toString();
  229. }
  230. /**
  231. * Calls GetLastError()
  232. */
  233. function doLMSGetLastError()
  234. {
  235. if (API == null)
  236. {
  237. alert(errMsgLocate + "\nLMSGetLastError was not successful."); //since we can't get the error code from the LMS, return a general error
  238. return _GeneralError;
  239. }
  240. return API.LMSGetLastError().toString();
  241. }
  242. /**
  243. * Calls LMSGetErrorString()
  244. */
  245. function doLMSGetErrorString(errorCode)
  246. {
  247. if (API == null)
  248. {
  249. alert(errMsgLocate + "\nLMSGetErrorString was not successful.");
  250. }
  251. return API.LMSGetErrorString(errorCode).toString();
  252. }
  253. /**
  254. * Calls LMSGetDiagnostic()
  255. */
  256. function doLMSGetDiagnostic(errorCode)
  257. {
  258. if (API == null)
  259. {
  260. alert(errMsgLocate + "\nLMSGetDiagnostic was not successful.");
  261. }
  262. return API.LMSGetDiagnostic(errorCode).toString();
  263. }
  264. /**
  265. * Second section. The SCO functions are located here (handle time and score messaging to SCORM API)
  266. * Initialisation
  267. */
  268. var startTime;
  269. var exitPageStatus;
  270. /**
  271. * Initialise page values
  272. */
  273. function loadPage()
  274. {
  275. var result = doLMSInitialize();
  276. if(result)
  277. {
  278. var status = doLMSGetValue("cmi.core.lesson_status");
  279. if(status == "not attempted")
  280. {
  281. doLMSSetValue("cmi.core.lesson_status","incomplete");
  282. }
  283. exitPageStatus = false;
  284. startTimer();
  285. }
  286. }
  287. /**
  288. * Starts the local timer
  289. */
  290. function startTimer()
  291. {
  292. startTime = new Date().getTime();
  293. }
  294. /**
  295. * Calculates the total time and sends the result to the LMS
  296. */
  297. function computeTime()
  298. {
  299. if ( startTime != 0 )
  300. {
  301. var currentDate = new Date().getTime();
  302. var elapsedSeconds = ( (currentDate - startTime) / 1000 );
  303. var formattedTime = convertTotalSeconds( elapsedSeconds );
  304. }
  305. else
  306. {
  307. formattedTime = "00:00:00.0";
  308. }
  309. doLMSSetValue( "cmi.core.session_time", formattedTime );
  310. }
  311. /**
  312. * Formats the time in a SCORM time format
  313. */
  314. function convertTotalSeconds(ts)
  315. {
  316. var sec = (ts % 60);
  317. ts -= sec;
  318. var tmp = (ts % 3600); //# of seconds in the total # of minutes
  319. ts -= tmp; //# of seconds in the total # of hours
  320. // convert seconds to conform to CMITimespan type (e.g. SS.00)
  321. sec = Math.round(sec*100)/100;
  322. var strSec = new String(sec);
  323. var strWholeSec = strSec;
  324. var strFractionSec = "";
  325. if (strSec.indexOf(".") != -1)
  326. {
  327. strWholeSec = strSec.substring(0, strSec.indexOf("."));
  328. strFractionSec = strSec.substring(strSec.indexOf(".")+1, strSec.length);
  329. }
  330. if (strWholeSec.length < 2)
  331. {
  332. strWholeSec = "0" + strWholeSec;
  333. }
  334. strSec = strWholeSec;
  335. if (strFractionSec.length)
  336. {
  337. strSec = strSec+ "." + strFractionSec;
  338. }
  339. if ((ts % 3600) != 0 )
  340. var hour = 0;
  341. else var hour = (ts / 3600);
  342. if ( (tmp % 60) != 0 )
  343. var min = 0;
  344. else var min = (tmp / 60);
  345. if ((new String(hour)).length < 2)
  346. hour = "0"+hour;
  347. if ((new String(min)).length < 2)
  348. min = "0"+min;
  349. var rtnVal = hour+":"+min+":"+strSec;
  350. return rtnVal
  351. }
  352. /**
  353. * Handles the use of the back button (saves data and closes SCO)
  354. */
  355. function doBack()
  356. {
  357. checkAnswers(true);
  358. doLMSSetValue( "cmi.core.exit", "suspend" );
  359. computeTime();
  360. exitPageStatus = true;
  361. var result;
  362. result = doLMSCommit();
  363. result = doLMSFinish();
  364. }
  365. /**
  366. * Handles the closure of the current SCO before an interruption. This is only useful if the LMS
  367. * deals with the cmi.core.exit, cmi.core.lesson_status and cmi.core.lesson_mode *and* the SCO
  368. * sends some kind of value for cmi.core.exit, which is not the case here (yet).
  369. */
  370. function doContinue(status)
  371. {
  372. // Reinitialize Exit to blank
  373. doLMSSetValue( "cmi.core.exit", "" );
  374. var mode = doLMSGetValue( "cmi.core.lesson_mode" );
  375. if ( mode != "review" && mode != "browse" )
  376. {
  377. doLMSSetValue( "cmi.core.lesson_status", status );
  378. }
  379. computeTime();
  380. exitPageStatus = true;
  381. var result;
  382. result = doLMSCommit();
  383. result = doLMSFinish();
  384. }
  385. /**
  386. * handles the recording of everything on a normal shutdown
  387. */
  388. function doQuit()
  389. {
  390. checkAnswers();
  391. computeTime();
  392. exitPageStatus = true;
  393. var result;
  394. result = doLMSCommit();
  395. result = doLMSFinish();
  396. }
  397. /**
  398. * Called upon unload event from body element
  399. */
  400. function unloadPage(status)
  401. {
  402. if (!exitPageStatus)
  403. {
  404. // doQuit( status );
  405. }
  406. }
  407. /**
  408. * Third section - depending on Chamilo - check answers and set score
  409. */
  410. var questions = new Array();
  411. var questions_answers = new Array();
  412. var questions_answers_correct = new Array();
  413. var questions_types = new Array();
  414. var questions_score_max = new Array();
  415. var questions_answers_ponderation = new Array();
  416. /**
  417. * Checks the answers on the test formular page
  418. */
  419. function checkAnswers(interrupted)
  420. {
  421. var tmpScore = 0;
  422. var status = 'not attempted';
  423. var scoreMax = 0;
  424. for(var i=0; i<questions.length;i++) {
  425. if(questions[i] != undefined && questions[i] != null){
  426. var idQuestion = questions[i];
  427. var type = questions_types[idQuestion];
  428. var interactionScore = 0;
  429. var interactionAnswers = '';
  430. var interactionCorrectResponses = '';
  431. var interactionType = '';
  432. if (type == 'mcma') {
  433. var interactionType = 'choice';
  434. var myScore = 0;
  435. for(var j=0; j<questions_answers[idQuestion].length;j++)
  436. {
  437. var idAnswer = questions_answers[idQuestion][j];
  438. var answer = document.getElementById('question_'+(idQuestion)+'_multiple_'+(idAnswer));
  439. if(answer.checked)
  440. {
  441. interactionAnswers += idAnswer+'__|';// changed by isaac flores
  442. myScore +=questions_answers_ponderation[idQuestion][idAnswer];
  443. /*for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  444. {
  445. if(questions_answers_correct[idQuestion][k] == idAnswer)
  446. {
  447. if(questions_answers_ponderation[idQuestion][idAnswer])
  448. {
  449. myScore += questions_answers_ponderation[idQuestion][idAnswer];
  450. }
  451. else
  452. {
  453. myScore ++;
  454. }
  455. }
  456. }*/
  457. }
  458. }
  459. interactionScore = myScore;
  460. //correct responses work by pattern, see SCORM Runtime Env Doc
  461. //for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  462. //{
  463. // interactionCorrectResponses += questions_answers_correct[idQuestion][k].toString()+',';
  464. //}
  465. scoreMax += questions_score_max[idQuestion];
  466. }
  467. else if(type == 'mcua')
  468. {
  469. var interactionType = 'choice';
  470. var myScore = 0;
  471. for(var j=0; j<questions_answers[idQuestion].length;j++)
  472. {
  473. var idAnswer = questions_answers[idQuestion][j];
  474. var answer = document.getElementById('question_'+(idQuestion)+'_unique_'+(idAnswer));
  475. if(answer.checked)
  476. {
  477. interactionAnswers += idAnswer;
  478. if(questions_answers_correct[idQuestion] == idAnswer)
  479. {
  480. if(questions_answers_ponderation[idQuestion][idAnswer])
  481. {
  482. myScore += questions_answers_ponderation[idQuestion][idAnswer];
  483. }
  484. else
  485. {
  486. myScore ++;
  487. }
  488. }
  489. }
  490. }
  491. interactionScore = myScore;
  492. //correct responses work by pattern, see SCORM Runtime Env Doc
  493. //interactionCorrectResponses += questions_answers_correct[idQuestion].toString();
  494. scoreMax += questions_score_max[idQuestion];
  495. }
  496. else if(type == 'tf')
  497. {
  498. var interactionType = 'true-false';
  499. var myScore = 0;
  500. for(var j=0; j<questions_answers[idQuestion].length;j++)
  501. {
  502. var idAnswer = questions_answers[idQuestion][j];
  503. var answer = document.getElementById('question_'+(idQuestion)+'_tf_'+(idAnswer));
  504. if(answer.checked.value)
  505. {
  506. interactionAnswers += idAnswer;
  507. for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  508. {
  509. if(questions_answers_correct[idQuestion][k] == idAnswer)
  510. {
  511. if(questions_answers_ponderation[idQuestion][idAnswer])
  512. {
  513. myScore += questions_answers_ponderation[idQuestion][idAnswer];
  514. }
  515. else
  516. {
  517. myScore ++;
  518. }
  519. }
  520. }
  521. }
  522. }
  523. interactionScore = myScore;
  524. //correct responses work by pattern, see SCORM Runtime Env Doc
  525. //interactionCorrectResponses += questions_answers_correct[idQuestion].toString();
  526. scoreMax += questions_score_max[idQuestion];
  527. }
  528. else if(type == 'fib')
  529. {
  530. var interactionType = 'fill-in';
  531. var myScore = 0;
  532. for(var j=0; j<questions_answers[idQuestion].length;j++)
  533. {
  534. var idAnswer = questions_answers[idQuestion][j];
  535. var answer = document.getElementById('question_'+(idQuestion)+'_fib_'+(idAnswer));
  536. if(answer.value)
  537. {
  538. interactionAnswers += answer.value+'__|';//changed by isaac flores
  539. for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  540. {
  541. if(questions_answers_correct[idQuestion][k] == answer.value)
  542. {
  543. if(questions_answers_ponderation[idQuestion][idAnswer])
  544. {
  545. myScore += questions_answers_ponderation[idQuestion][idAnswer];
  546. }
  547. else
  548. {
  549. myScore ++;
  550. }
  551. }
  552. }
  553. }
  554. }
  555. interactionScore = myScore;
  556. //correct responses work by pattern, see SCORM Runtime Env Doc
  557. //for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  558. //{
  559. // interactionCorrectResponses += questions_answers_correct[idQuestion][k].toString()+',';
  560. //}
  561. scoreMax += questions_score_max[idQuestion];
  562. }
  563. else if(type == 'matching')
  564. {
  565. var interactionType = 'matching';
  566. var myScore = 0;
  567. for(var j=0; j<questions_answers[idQuestion].length;j++)
  568. {
  569. var idAnswer = questions_answers[idQuestion][j];
  570. var answer = document.getElementById('question_'+(idQuestion)+'_matching_'+(idAnswer));
  571. if(answer && answer.value)
  572. {
  573. interactionAnswers += answer.value+'__|';//changed by isaac flores
  574. for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  575. {
  576. var left = questions_answers_correct[idQuestion][k][0];
  577. var right = questions_answers_correct[idQuestion][k][1];
  578. if(left == idAnswer && right == answer.value)
  579. {
  580. if(questions_answers_ponderation[idQuestion][idAnswer])
  581. {
  582. myScore += questions_answers_ponderation[idQuestion][idAnswer];
  583. }
  584. else
  585. {
  586. myScore ++;
  587. }
  588. }
  589. }
  590. }
  591. }
  592. interactionScore = myScore;
  593. //correct responses work by pattern, see SCORM Runtime Env Doc
  594. //for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  595. //{
  596. // interactionCorrectResponses += questions_answers_correct[idQuestion][k].toString()+',';
  597. //}
  598. scoreMax += questions_score_max[idQuestion];
  599. } else if(type == 'free') {
  600. //ignore for now as a score cannot be given
  601. var interactionType = 'likert';
  602. interactionScore = 0;
  603. //interactionAnswers = document.getElementById('question_'+(idQuestion)+'_free').value;
  604. //correct responses work by pattern, see SCORM Runtime Env Doc
  605. //interactionCorrectResponses += questions_answers_correct[idQuestion].toString();
  606. } else if(type == 'hotspot') {
  607. var interactionType = 'sequencing';
  608. interactionScore = 0;
  609. //if(question_score && question_score[idQuestion]){
  610. // interactionScore = question_score[idQuestion];
  611. //} //else, 0
  612. //interactionAnswers = document.getElementById('question_'+(idQuestion)+'_free').innerHTML;
  613. //correct responses work by pattern, see SCORM Runtime Env Doc
  614. //for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  615. //{
  616. // interactionCorrectResponses += questions_answers_correct[idQuestion][k].toString()+',';
  617. //}
  618. } else if(type == 'exact') {
  619. var interactionType = 'exact';
  620. interactionScore = 0;
  621. // not yet implemented see scorm_classes.php ScormAnswerMultipleChoice::export() function
  622. /*
  623. var myScore = 0;
  624. var real_answers = new Array();
  625. for(var j=0; j<questions_answers[idQuestion].length;j++) {
  626. var idAnswer = questions_answers[idQuestion][j];
  627. var answer = document.getElementById('question_'+(idQuestion)+'_multiple_'+(idAnswer));
  628. if (answer.checked) {
  629. if(questions_answers_ponderation[idQuestion][idAnswer] != 0 ) {
  630. real_answers[j] = true;
  631. } else {
  632. real_answers[j] = false;
  633. }
  634. } else {
  635. if(questions_answers_ponderation[idQuestion][idAnswer] != 0) {
  636. real_answers[j] = false;
  637. } else {
  638. real_answers[j] = true;
  639. }
  640. }
  641. //alert(real_answers[j] +' ' + answer.checked + ' ' + questions_answers_ponderation[idQuestion][idAnswer]);
  642. }
  643. var final_answer = true;
  644. for(var z=0; z<real_answers.length ;z++) {
  645. if (!real_answers[z]) {
  646. final_answer = false;
  647. }
  648. }
  649. if (final_answer) {
  650. //getting only the first score where we save the weight of all the question
  651. myScore += questions_answers_ponderation[idQuestion][1];
  652. }
  653. interactionScore = myScore;
  654. //correct responses work by pattern, see SCORM Runtime Env Doc
  655. //for(k=0;k<questions_answers_correct[idQuestion].length;k++)
  656. //{
  657. // interactionCorrectResponses += questions_answers_correct[idQuestion][k].toString()+',';
  658. //}
  659. scoreMax += questions_score_max[idQuestion];
  660. */
  661. }
  662. else
  663. {
  664. //
  665. }
  666. tmpScore += interactionScore;
  667. doLMSSetValue('cmi.interactions.'+idQuestion+'.id','Q'+idQuestion);
  668. doLMSSetValue('cmi.interactions.'+idQuestion+'.type',interactionType);
  669. doLMSSetValue('cmi.interactions.'+idQuestion+'.student_response',interactionAnswers);
  670. doLMSSetValue('cmi.interactions.'+idQuestion+'.result',interactionScore);
  671. //correct responses work by pattern, see SCORM Runtime Env Doc
  672. //doLMSSetValue('cmi.interactions.'+idQuestion+'.correct_responses',questions_answers_correct[idQuestion]);
  673. //doLMSSetValue('cmi.interactions.'+idQuestion+'.correct_responses',interactionCorrectResponses);
  674. }
  675. }
  676. doLMSSetValue('cmi.core.score.min',0);
  677. doLMSSetValue('cmi.core.score.max',scoreMax);
  678. doLMSSetValue('cmi.core.score.raw',tmpScore);
  679. //doLMSSetValue('cmi.student_data.mastery_score',(scoreMax*0.7));
  680. //get status
  681. var mastery_score = doLMSGetValue('cmi.student_data.mastery_score');
  682. if(mastery_score <= 0)
  683. {
  684. mastery_score = (scoreMax*0.80);
  685. }
  686. if(tmpScore > mastery_score)
  687. {
  688. status = 'passed';
  689. }
  690. else
  691. {
  692. status = 'failed';
  693. }
  694. doLMSSetValue('cmi.core.lesson_status',status);
  695. if (interrupted && (status != 'completed') && (status != 'passed'))
  696. {
  697. doLMSSetValue('cmi.core.exit','suspended');
  698. }
  699. else
  700. {
  701. }
  702. return false; //do not submit the form
  703. }