exercice_submit.php 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233
  1. <?php
  2. /* For licensing terms, see /chamilo_license.txt */
  3. /**
  4. * Exercise submission
  5. * This script allows to run an exercise. According to the exercise type, questions
  6. * can be on an unique page, or one per page with a Next button.
  7. *
  8. * One exercise may contain different types of answers (unique or multiple selection,
  9. * matching, fill in blanks, free answer, hot-spot).
  10. *
  11. * Questions are selected randomly or not.
  12. *
  13. * When the user has answered all questions and clicks on the button "Ok",
  14. * it goes to exercise_result.php
  15. *
  16. * Notice : This script is also used to show a question before modifying it by
  17. * the administrator
  18. * @package dokeos.exercise
  19. * @author Olivier Brouckaert
  20. * @author Julio Montoya multiple fill in blank option added
  21. * @version $Id: exercice_submit.php 22201 2009-07-17 19:57:03Z cfasanando $
  22. */
  23. require_once 'exercise.class.php';
  24. require_once 'question.class.php';
  25. require_once 'answer.class.php';
  26. require_once 'exercise.lib.php';
  27. // debug var. Set to 0 to hide all debug display. Set to 1 to display debug messages.
  28. $debug = 0;
  29. /*
  30. // answer types
  31. define('UNIQUE_ANSWER', 1);
  32. define('MULTIPLE_ANSWER', 2);
  33. define('FILL_IN_BLANKS', 3);
  34. define('MATCHING', 4);
  35. define('FREE_ANSWER', 5);
  36. define('HOT_SPOT', 6);
  37. define('HOT_SPOT_ORDER', 7);
  38. */
  39. // name of the language file that needs to be included
  40. $language_file = 'exercice';
  41. require_once '../inc/global.inc.php';
  42. $this_section = SECTION_COURSES;
  43. $htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery.js" type="text/javascript" language="javascript"></script>'; //jQuery
  44. $htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery.corners.min.js" type="text/javascript"></script>';
  45. if (api_get_setting('show_glossary_in_extra_tools') == 'true') {
  46. $htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/glossary.js" type="text/javascript" language="javascript"></script>'; //Glossary
  47. $htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery.highlight.js" type="text/javascript" language="javascript"></script>';
  48. }
  49. //This library is necessary for the time control feature
  50. $htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery.epiclock.min.js" type="text/javascript" language="javascript"></script>'; //jQuery
  51. if (!ereg("MSIE",$_SERVER["HTTP_USER_AGENT"])) {
  52. $htmlHeadXtra[] = "<script type='text/javascript' language='javascript'>
  53. $(document).ready( function(){
  54. $('.rounded').corners();
  55. $('.exercise_options').corners();
  56. });</script>";
  57. }
  58. /* ------------ ACCESS RIGHTS ------------ */
  59. // notice for unauthorized people.
  60. api_protect_course_script(true);
  61. require_once api_get_path(LIBRARY_PATH) . 'text.lib.php';
  62. $is_allowedToEdit = api_is_allowed_to_edit(null,true);
  63. $_configuration['live_exercise_tracking'] = true;
  64. $stat_table = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
  65. $exercice_attemp_table = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
  66. $TBL_EXERCICE_QUESTION = Database :: get_course_table(TABLE_QUIZ_TEST_QUESTION);
  67. $TBL_EXERCICES = Database :: get_course_table(TABLE_QUIZ_TEST);
  68. $TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
  69. $TBL_REPONSES = Database :: get_course_table(TABLE_QUIZ_ANSWER);
  70. // general parameters passed via POST/GET
  71. if (empty ($origin)) {
  72. $origin = $_REQUEST['origin'];
  73. }
  74. if (empty ($learnpath_id)) {
  75. $learnpath_id = Security::remove_XSS($_REQUEST['learnpath_id']);
  76. }
  77. if (empty ($learnpath_item_id)) {
  78. $learnpath_item_id = Security::remove_XSS($_REQUEST['learnpath_item_id']);
  79. }
  80. if (empty ($formSent)) {
  81. $formSent = $_REQUEST['formSent'];
  82. }
  83. if (empty ($exerciseResult)) {
  84. $exerciseResult = $_REQUEST['exerciseResult'];
  85. }
  86. if (empty ($exerciseResultCoordinates)) {
  87. $exerciseResultCoordinates = $_REQUEST['exerciseResultCoordinates'];
  88. }
  89. if (empty ($exerciseType)) {
  90. $exerciseType = $_REQUEST['exerciseType'];
  91. }
  92. if (empty ($exerciseId)) {
  93. $exerciseId = Database::escape_string(intval($_REQUEST['exerciseId']));
  94. }
  95. if (empty ($choice)) {
  96. $choice = $_REQUEST['choice'];
  97. }
  98. if (empty ($_REQUEST['choice'])) {
  99. $choice = $_REQUEST['choice2'];
  100. }
  101. if (empty ($questionNum)) {
  102. $questionNum = Database :: escape_string($_REQUEST['questionNum']);
  103. }
  104. if (empty ($nbrQuestions)) {
  105. $nbrQuestions = Database :: escape_string($_REQUEST['nbrQuestions']);
  106. }
  107. if (empty ($buttonCancel)) {
  108. $buttonCancel = $_REQUEST['buttonCancel'];
  109. }
  110. $error = '';
  111. if (!isset ($exerciseType)) {
  112. $exe_start_date = time();
  113. $_SESSION['exercice_start_date'] = $exe_start_date;
  114. }
  115. // if the user has clicked on the "Cancel" button
  116. if ($buttonCancel) {
  117. // returns to the exercise list
  118. header("Location: exercice.php?origin=$origin&learnpath_id=$learnpath_id&learnpath_item_id=$learnpath_item_id");
  119. exit ();
  120. }
  121. if ($origin == 'learnpath' && isset ($_GET['not_multiple_attempt']) && $_GET['not_multiple_attempt'] == strval(intval($_GET['not_multiple_attempt']))) {
  122. $not_multiple_attempt = (int) $_GET['not_multiple_attempt'];
  123. if ($not_multiple_attempt === 1) {
  124. require_once '../inc/reduced_header.inc.php';
  125. echo '<div style="height:10px">&nbsp;</div>';
  126. Display :: display_warning_message(get_lang('ReachedOneAttempt'));
  127. exit;
  128. }
  129. }
  130. if ($origin == 'builder') {
  131. /*******************************/
  132. /* Clears the exercise session */
  133. /*******************************/
  134. if (isset ($_SESSION['objExercise'])) {
  135. api_session_unregister('objExercise');
  136. unset ($objExercise);
  137. }
  138. if (isset ($_SESSION['objQuestion'])) {
  139. api_session_unregister('objQuestion');
  140. unset ($objQuestion);
  141. }
  142. if (isset ($_SESSION['objAnswer'])) {
  143. api_session_unregister('objAnswer');
  144. unset ($objAnswer);
  145. }
  146. if (isset ($_SESSION['questionList'])) {
  147. api_session_unregister('questionList');
  148. unset ($questionList);
  149. }
  150. if (isset ($_SESSION['newquestionList'])) {
  151. api_session_unregister('newquestionList');
  152. unset ($newquestionList);
  153. }
  154. if (isset ($_SESSION['exerciseResult'])) {
  155. api_session_unregister('exerciseResult');
  156. unset ($exerciseResult);
  157. }
  158. if (isset ($_SESSION['exerciseResultCoordinates'])) {
  159. api_session_unregister('exerciseResultCoordinates');
  160. unset ($exerciseResultCoordinates);
  161. }
  162. }
  163. $safe_lp_id = ($learnpath_id == '') ? 0 : (int) $learnpath_id;
  164. $safe_lp_item_id = ($learnpath_item_id == '') ? 0 : (int) $learnpath_item_id;
  165. $condition = ' WHERE ' .
  166. 'exe_exo_id = ' . "'" . $exerciseId . "'" . ' AND ' .
  167. 'exe_user_id = ' . "'" . api_get_user_id() . "'" . ' AND ' .
  168. 'exe_cours_id = ' . "'" . $_course['id'] . "'" . ' AND ' .
  169. 'status = ' . "'incomplete'" . ' AND ' .
  170. 'orig_lp_id = ' . "'" . $safe_lp_id . "'" . ' AND ' .
  171. 'orig_lp_item_id = ' . "'" . $safe_lp_item_id . "'" . ' AND ' .
  172. 'session_id = ' . "'" . (int) $_SESSION['id_session'] . "'";
  173. $TBL_EXERCICES = Database :: get_course_table(TABLE_QUIZ_TEST);
  174. $sql_track_exercice = "SELECT type,feedback_type,expired_time FROM $TBL_EXERCICES WHERE id=$exerciseId";
  175. $result = Database::query($sql_track_exercice, __FILE__, __LINE__);
  176. $exercise_row = Database :: fetch_array($result);
  177. $exerciseType = $exercise_row['type'];
  178. $exerciseFeedbackType = $exercise_row['feedback_type'];
  179. //Get the expired time of the current exercice in track_e_exercices
  180. $total_minutes = $exercise_row["expired_time"];
  181. $total_seconds = $total_minutes*60;
  182. $current_timestamp = time();
  183. if ($exercise_row['expired_time'] != 0) {
  184. if (!isset($_SESSION['expired_time'])) {
  185. //In case that the current session php is broken
  186. //Timer - Get expired_time for a student
  187. $condition = ' WHERE ' .
  188. 'exe_exo_id = '."'".Database::escape_string($exerciseId)."'".' AND ' .
  189. 'exe_user_id = '."'".api_get_user_id()."'".' AND ' .
  190. 'exe_cours_id = '."'".api_get_course_id()."'".' AND ' .
  191. 'status = '."'incomplete'".' AND '.
  192. 'session_id = '."'".api_get_session_id()."'";
  193. $sql_track = 'SELECT exe_id,expired_time_control FROM '.$stat_table.$condition;
  194. $rs_sql = Database::query($sql_track,__FILE__,__LINE__);
  195. $exists_into_database = Database::num_rows($rs_sql);
  196. $track_exercice_row = Database::fetch_array($rs_sql);
  197. $expired_time_of_this_attempt = $track_exercice_row['expired_time_control'];
  198. //Get the last attempt of an exercice
  199. $sql_track_attempt = 'SELECT max(tms) as last_attempt_date FROM '.$exercice_attemp_table.' WHERE exe_id="'.$track_exercice_row['exe_id'].'"';
  200. $rs_last_attempt = Database::query($sql_track_attempt,__FILE__,__LINE__);
  201. $row_last_attempt = Database::fetch_array($rs_last_attempt);
  202. $my_last_attempt_date = $row_last_attempt['last_attempt_date'];
  203. //change the date format
  204. $my_last_attempt_date = strtotime($my_last_attempt_date);
  205. $expired_time_of_this_attempt = strtotime($expired_time_of_this_attempt);
  206. //New expired time
  207. $new_expired_time_in_seconds = $expired_time_of_this_attempt - $my_last_attempt_date;
  208. if ($exists_into_database == 1) {
  209. $expected_time = $current_timestamp + $new_expired_time_in_seconds;
  210. $plugin_expired_time = date('M d, Y H:i:s',$expected_time);
  211. $clock_expired_time = date('Y-m-d H:i:s',$expected_time);
  212. //We modify the "expired_time_control" field in track_e_exercices for this attempt
  213. $sql_track_e_exe = "UPDATE $stat_table SET expired_time_control = '".$clock_expired_time."' WHERE exe_id = '".$track_exercice_row['exe_id']."'";
  214. Database::query($sql_track_e_exe,__FILE__,__LINE__);
  215. //Sessions that contain the expired time
  216. $_SESSION['expired_time'] = $clock_expired_time;
  217. $_SESSION['end_expired_time'] = date('M d, Y H:i:s',$expected_time);
  218. } else {
  219. $expected_time = $current_timestamp + $total_seconds;
  220. $plugin_expired_time = date('M d, Y H:i:s',$expected_time);
  221. $clock_expired_time = date('Y-m-d H:i:s',$expected_time);
  222. //Sessions that contain the expired time
  223. $_SESSION['expired_time'] = $clock_expired_time;
  224. $_SESSION['end_expired_time'] = date('M d, Y H:i:s',$expected_time);
  225. }
  226. } else {
  227. $plugin_expired_time = $_SESSION['end_expired_time'];
  228. }
  229. }
  230. if ($exercise_row['expired_time'] != 0) { //Sends the exercice form when the expired time is finished
  231. $htmlHeadXtra[] = "<script type=\"text/javascript\">
  232. $(document).ready(function(){
  233. $('#text-content').epiclock({
  234. mode: EC_COUNTDOWN,
  235. format: 'x{ : } i{ : } s{}',
  236. target: '".$plugin_expired_time."',
  237. onTimer: function(){ $('form#my_frm_exercise').submit() }
  238. }).clocks(EC_RUN);
  239. $('.rounded').corners('transparent');
  240. $('#submit_save').click(function () {
  241. });
  242. });
  243. </script>";
  244. }
  245. if ($_configuration['live_exercise_tracking'] == true && $exerciseType == 2 && $exerciseFeedbackType != 1) {
  246. $query = 'SELECT * FROM ' . $stat_table . $condition;
  247. $result_select = Database::query($query, __FILE__, __LINE__);
  248. if (Database :: num_rows($result_select) > 0) {
  249. $getIncomplete = Database :: fetch_array($result_select);
  250. $exe_id = $getIncomplete['exe_id'];
  251. if ($_SERVER['REQUEST_METHOD'] != 'POST') {
  252. define('QUESTION_LIST_ALREADY_LOGGED', 1);
  253. $recorded['questionList'] = explode(',', $getIncomplete['data_tracking']);
  254. $query = 'SELECT * FROM ' . $exercice_attemp_table . ' WHERE exe_id = ' . $getIncomplete['exe_id'] . ' ORDER BY tms ASC';
  255. $result = Database::query($query, __FILE__, __LINE__);
  256. while ($row = Database :: fetch_array($result)) {
  257. $recorded['exerciseResult'][$row['question_id']] = 1;
  258. }
  259. $exerciseResult = $_SESSION['exerciseResult'] = $recorded['exerciseResult'];
  260. $exerciseType = 2;
  261. $questionNum = count($recorded['exerciseResult']);
  262. $questionNum++;
  263. $questionList = $_SESSION['questionList'] = $recorded['questionList'];
  264. }
  265. } else {
  266. $table_recorded_not_exist = true;
  267. }
  268. }
  269. // if the user has submitted the form
  270. if ($formSent) {
  271. if ($debug > 0) {
  272. echo str_repeat('&nbsp;', 0) . '$formSent was set' . "<br />\n";
  273. }
  274. // initializing
  275. if (!is_array($exerciseResult)) {
  276. $exerciseResult = array ();
  277. $exerciseResultCoordinates = array ();
  278. }
  279. //Only for hotspot
  280. if (!isset($choice) && isset($_REQUEST['hidden_hotspot_id'])) {
  281. $hotspot_id = (int)($_REQUEST['hidden_hotspot_id']);
  282. $choice = array($hotspot_id => '');
  283. }
  284. // if the user has answered at least one question
  285. if (is_array($choice)) {
  286. if ($debug > 0) {
  287. echo str_repeat('&nbsp;', 0) . '$choice is an array' . "<br />\n";
  288. }
  289. if ($exerciseType == 1)
  290. {
  291. // $exerciseResult receives the content of the form.
  292. // Each choice of the student is stored into the array $choice
  293. $exerciseResult = $choice;
  294. // Also store hotspot spots in the session ($exerciseResultCoordinates
  295. // will be stored in the session at the end of this script)
  296. // The results will be stored by exercise_result.php if we are in
  297. // an exercise of type 1 (=all on one page)
  298. if (isset ($_POST['hotspot'])) {
  299. $exerciseResultCoordinates = $_POST['hotspot'];
  300. }
  301. } else {
  302. // gets the question ID from $choice. It is the key of the array
  303. list ($key) = array_keys($choice);
  304. // if the user didn't already answer this question
  305. if (!isset ($exerciseResult[$key])) {
  306. // stores the user answer into the array
  307. $exerciseResult[$key] = $choice[$key];
  308. //saving each question
  309. if ($_configuration['live_exercise_tracking'] == true && $exerciseType == 2 && $exerciseFeedbackType != 1) {
  310. $nro_question = $questionNum; // - 1;
  311. //START of saving and qualifying each question submitted
  312. //------------------------------------------------------------------------------------------
  313. //
  314. define('ENABLED_LIVE_EXERCISE_TRACKING', 1);
  315. require_once 'question.class.php';
  316. require_once 'answer.class.php';
  317. $counter = 0;
  318. $main_course_user_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  319. $table_ans = Database :: get_course_table(TABLE_QUIZ_ANSWER);
  320. //foreach($questionList as $questionId)
  321. if (true) {
  322. $exeId = $exe_id;
  323. $questionId = $key;
  324. $counter++;
  325. // gets the student choice for this question
  326. $choice = $exerciseResult[$questionId];
  327. // creates a temporary Question object
  328. $objQuestionTmp = Question :: read($questionId);
  329. $questionName = $objQuestionTmp->selectTitle();
  330. $questionDescription = $objQuestionTmp->selectDescription();
  331. $questionWeighting = $objQuestionTmp->selectWeighting();
  332. $answerType = $objQuestionTmp->selectType();
  333. $quesId = $objQuestionTmp->selectId(); //added by priya saini
  334. // destruction of the Question object
  335. unset ($objQuestionTmp);
  336. if (isset ($_POST['hotspot']) && isset($_POST['hotspot'][$key])) {
  337. $exerciseResultCoordinates[$key] = $_POST['hotspot'][$key];
  338. }
  339. // construction of the Answer object
  340. $objAnswerTmp = new Answer($questionId);
  341. $nbrAnswers = $objAnswerTmp->selectNbrAnswers();
  342. $questionScore = 0;
  343. if ($answerType == FREE_ANSWER) {
  344. $nbrAnswers = 1;
  345. }
  346. for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
  347. $answer = $objAnswerTmp->selectAnswer($answerId);
  348. $answerComment = $objAnswerTmp->selectComment($answerId);
  349. $answerCorrect = $objAnswerTmp->isCorrect($answerId);
  350. $answerWeighting = $objAnswerTmp->selectWeighting($answerId);
  351. switch ($answerType) {
  352. // for unique answer
  353. case UNIQUE_ANSWER :
  354. $studentChoice = ($choice == $answerId) ? 1 : 0;
  355. if ($studentChoice) {
  356. $questionScore += $answerWeighting;
  357. $totalScore += $answerWeighting;
  358. }
  359. break;
  360. // for multiple answers
  361. case MULTIPLE_ANSWER :
  362. $studentChoice = $choice[$answerId];
  363. if ($studentChoice) {
  364. $questionScore += $answerWeighting;
  365. $totalScore += $answerWeighting;
  366. }
  367. break;
  368. // for fill in the blanks
  369. case FILL_IN_BLANKS :
  370. // the question is encoded like this
  371. // [A] B [C] D [E] F::10,10,10@1
  372. // number 1 before the "@" means that is a switchable fill in blank question
  373. // [A] B [C] D [E] F::10,10,10@ or [A] B [C] D [E] F::10,10,10
  374. // means that is a normal fill blank question
  375. // first we explode the "::"
  376. $pre_array = explode('::', $answer);
  377. // is switchable fill blank or not
  378. $last = count($pre_array) - 1;
  379. $is_set_switchable = explode('@', $pre_array[$last]);
  380. $switchable_answer_set = false;
  381. if (isset ($is_set_switchable[1]) && $is_set_switchable[1] == 1) {
  382. $switchable_answer_set = true;
  383. }
  384. $answer = '';
  385. for ($k = 0; $k < $last; $k++) {
  386. $answer .= $pre_array[$k];
  387. }
  388. // splits weightings that are joined with a comma
  389. $answerWeighting = explode(',', $is_set_switchable[0]);
  390. // we save the answer because it will be modified
  391. $temp = $answer;
  392. // TeX parsing
  393. // 1. find everything between the [tex] and [/tex] tags
  394. $startlocations = strpos($temp, '[tex]');
  395. $endlocations = strpos($temp, '[/tex]');
  396. if ($startlocations !== false && $endlocations !== false) {
  397. $texstring = substr($temp, $startlocations, $endlocations - $startlocations +6);
  398. // 2. replace this by {texcode}
  399. $temp = str_replace($texstring, '{texcode}', $temp);
  400. }
  401. $answer = '';
  402. $j = 0;
  403. //initialise answer tags
  404. $user_tags = array ();
  405. $correct_tags = array ();
  406. $real_text = array ();
  407. // the loop will stop at the end of the text
  408. while (1) {
  409. // quits the loop if there are no more blanks (detect '[')
  410. if (($pos = strpos($temp, '[')) === false) {
  411. // adds the end of the text
  412. $answer = $temp;
  413. // TeX parsing - replacement of texcode tags
  414. $texstring = api_parse_tex($texstring);
  415. $answer = str_replace("{texcode}", $texstring, $answer);
  416. $real_text[] = $answer;
  417. break; //no more "blanks", quit the loop
  418. }
  419. // adds the piece of text that is before the blank
  420. //and ends with '[' into a general storage array
  421. $real_text[] = substr($temp, 0, $pos +1);
  422. $answer .= substr($temp, 0, $pos +1);
  423. //take the string remaining (after the last "[" we found)
  424. $temp = substr($temp, $pos +1);
  425. // quit the loop if there are no more blanks, and update $pos to the position of next ']'
  426. if (($pos = strpos($temp, ']')) === false) {
  427. // adds the end of the text
  428. $answer .= $temp;
  429. break;
  430. }
  431. $choice[$j] = trim($choice[$j]);
  432. $user_tags[] = strtolower($choice[$j]);
  433. //put the contents of the [] answer tag into correct_tags[]
  434. $correct_tags[] = strtolower(substr($temp, 0, $pos));
  435. $j++;
  436. $temp = substr($temp, $pos +1);
  437. //$answer .= ']';
  438. }
  439. $answer = '';
  440. $real_correct_tags = $correct_tags;
  441. $chosen_list = array ();
  442. for ($i = 0; $i < count($real_correct_tags); $i++) {
  443. if ($i == 0) {
  444. $answer .= $real_text[0];
  445. }
  446. if (!$switchable_answer_set) {
  447. if ($correct_tags[$i] == $user_tags[$i]) {
  448. // gives the related weighting to the student
  449. $questionScore += $answerWeighting[$i];
  450. // increments total score
  451. $totalScore += $answerWeighting[$i];
  452. // adds the word in green at the end of the string
  453. $answer .= $correct_tags[$i];
  454. }
  455. // else if the word entered by the student IS NOT the same as the one defined by the professor
  456. elseif (!empty ($user_tags[$i])) {
  457. // adds the word in red at the end of the string, and strikes it
  458. $answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>';
  459. } else {
  460. // adds a tabulation if no word has been typed by the student
  461. $answer .= '&nbsp;&nbsp;&nbsp;';
  462. }
  463. } else {
  464. // switchable fill in the blanks
  465. if (in_array($user_tags[$i], $correct_tags)) {
  466. $chosen_list[] = $user_tags[$i];
  467. $correct_tags = array_diff($correct_tags, $chosen_list);
  468. // gives the related weighting to the student
  469. $questionScore += $answerWeighting[$i];
  470. // increments total score
  471. $totalScore += $answerWeighting[$i];
  472. // adds the word in green at the end of the string
  473. $answer .= $user_tags[$i];
  474. }
  475. elseif (!empty ($user_tags[$i])) {
  476. // else if the word entered by the student IS NOT the same as the one defined by the professor
  477. // adds the word in red at the end of the string, and strikes it
  478. $answer .= '<font color="red"><s>' . $user_tags[$i] . '</s></font>';
  479. } else {
  480. // adds a tabulation if no word has been typed by the student
  481. $answer .= '&nbsp;&nbsp;&nbsp;';
  482. }
  483. }
  484. // adds the correct word, followed by ] to close the blank
  485. $answer .= ' / <font color="green"><b>' . $real_correct_tags[$i] . '</b></font>]';
  486. if (isset ($real_text[$i +1])) {
  487. $answer .= $real_text[$i +1];
  488. }
  489. }
  490. break;
  491. // for free answer
  492. case FREE_ANSWER :
  493. $studentChoice = $choice;
  494. if ($studentChoice) {
  495. //Score is at -1 because the question has'nt been corected
  496. $questionScore = -1;
  497. $totalScore += 0;
  498. }
  499. break;
  500. // for matching
  501. case MATCHING :
  502. $numAnswer=$objAnswerTmp->selectAutoId($answerId);
  503. if ($answerCorrect) {
  504. if ($answerCorrect == $choice[$numAnswer]) {
  505. $questionScore+=$answerWeighting;
  506. $totalScore+=$answerWeighting;
  507. }
  508. $matching[$numAnswer] = $choice[$numAnswer];
  509. }
  510. break;
  511. // for hotspot with no order
  512. case HOT_SPOT :
  513. $studentChoice = $choice[$answerId];
  514. if ($studentChoice) {
  515. $questionScore += $answerWeighting;
  516. $totalScore += $answerWeighting;
  517. }
  518. break;
  519. // for hotspot with fixed order
  520. case HOT_SPOT_ORDER :
  521. $studentChoice = $choice['order'][$answerId];
  522. if ($studentChoice == $answerId) {
  523. $questionScore += $answerWeighting;
  524. $totalScore += $answerWeighting;
  525. $studentChoice = true;
  526. } else {
  527. $studentChoice = false;
  528. }
  529. break;
  530. } // end switch Answertype
  531. } // end for that loops over all answers of the current question
  532. // destruction of Answer
  533. unset ($objAnswerTmp);
  534. $i++;
  535. $totalWeighting += $questionWeighting;
  536. //added by priya saini
  537. // Store results directly in the database
  538. // For all in one page exercises, the results will be
  539. // stored by exercise_results.php (using the session)
  540. if ($_configuration['tracking_enabled']) {
  541. if (empty ($choice)) {
  542. $choice = 0;
  543. }
  544. if ($answerType == MULTIPLE_ANSWER) {
  545. if ($choice != 0) {
  546. $reply = array_keys($choice);
  547. for ($i = 0; $i < sizeof($reply); $i++) {
  548. $ans = $reply[$i];
  549. exercise_attempt($questionScore, $ans, $quesId, $exeId, $i);
  550. }
  551. } else {
  552. exercise_attempt($questionScore, 0, $quesId, $exeId, 0);
  553. }
  554. }
  555. elseif ($answerType == MATCHING) {
  556. foreach ($matching as $j => $val) {
  557. exercise_attempt($questionScore, $val, $quesId, $exeId, $j);
  558. }
  559. } elseif ($answerType == FREE_ANSWER) {
  560. $answer = $choice;
  561. exercise_attempt($questionScore, $answer, $quesId, $exeId, 0);
  562. } elseif ($answerType == UNIQUE_ANSWER) {
  563. $answer = $choice;
  564. exercise_attempt($questionScore, $answer, $quesId, $exeId, 0);
  565. } elseif ($answerType == HOT_SPOT) {
  566. exercise_attempt($questionScore, $answer, $quesId, $exeId, 0);
  567. if (is_array($exerciseResultCoordinates[$key])) {
  568. foreach($exerciseResultCoordinates[$key] as $idx => $val) {
  569. exercise_attempt_hotspot($exeId,$quesId,$idx,$choice[$idx],$val);
  570. }
  571. }
  572. } else {
  573. exercise_attempt($questionScore, $answer, $quesId, $exeId, 0);
  574. }
  575. }
  576. }
  577. // end huge foreach() block that loops over all questions
  578. //at loops over all questions
  579. if (isset($exe_id)) {
  580. $sql_update = 'UPDATE ' . $stat_table . ' SET exe_result = exe_result + ' . (int) $totalScore . ',exe_weighting = exe_weighting + ' . (int) $totalWeighting . ' WHERE exe_id = ' . Database::escape_string($exe_id);
  581. Database::query($sql_update, __FILE__, __LINE__);
  582. }
  583. //END of saving and qualifying
  584. //------------------------------------------------------------------------------------------
  585. //
  586. }
  587. }
  588. }
  589. if ($debug > 0) {
  590. echo str_repeat('&nbsp;', 0) . '$choice is an array - end' . "<br />\n";
  591. }
  592. }
  593. // the script "exercise_result.php" will take the variable $exerciseResult from the session
  594. api_session_register('exerciseResult');
  595. api_session_register('exerciseResultCoordinates');
  596. define('ALL_ON_ONE_PAGE',1);
  597. define('ONE_PER_PAGE',2);
  598. // if all questions on one page OR if it is the last question (only for an exercise with one question per page)
  599. if ($exerciseType == ALL_ON_ONE_PAGE || $questionNum >= $nbrQuestions) {
  600. if ($debug > 0) {
  601. echo str_repeat('&nbsp;', 0) . 'Redirecting to exercise_result.php - Remove debug option to let this happen' . "<br />\n";
  602. }
  603. if ( api_is_allowed_to_session_edit() ) {
  604. // goes to the script that will show the result of the exercise
  605. if ($exerciseType == ALL_ON_ONE_PAGE) {
  606. header("Location: exercise_result.php?id=$exe_id&exerciseType=$exerciseType&origin=$origin&learnpath_id=$learnpath_id&learnpath_item_id=$learnpath_item_id");
  607. } else {
  608. if ($exe_id != '') {
  609. //Verify if the current test is fraudulent
  610. $current_time = time();
  611. if (isset($_SESSION['expired_time']) && $exercise_row['expired_time'] != 0) {
  612. $expired_date = $_SESSION['expired_time'];
  613. $expired_time = strtotime($expired_date);
  614. //Validation in case of fraud
  615. $total_time_allowed = $expired_time + 30;
  616. if ($total_time_allowed < $current_time) {
  617. $sql_exe_result = ",exe_result = 0";
  618. }
  619. } else {
  620. $sql_exe_result = "";
  621. }
  622. //clean incomplete
  623. $update_query = 'UPDATE ' . $stat_table . ' SET ' . "status = '', data_tracking='', exe_date = '" . date('Y-m-d H:i:s') . "' $sql_exe_result " . ' WHERE exe_id = ' . Database::escape_string($exe_id);
  624. Database::query($update_query, __FILE__, __LINE__);
  625. }
  626. header("Location: exercise_show.php?id=$exe_id&exerciseType=$exerciseType&origin=$origin&learnpath_id=$learnpath_id&learnpath_item_id=$learnpath_item_id");
  627. }
  628. exit ();
  629. } else {
  630. header("Location: exercice_submit.php?exerciseId=$exerciseId");
  631. exit;
  632. }
  633. }
  634. if ($debug > 0) {
  635. echo str_repeat('&nbsp;', 0) . '$formSent was set - end' . "<br />\n";
  636. }
  637. }
  638. // if the object is not in the session
  639. //why destroying the exercise when a LP is loaded ?
  640. //if (!isset($_SESSION['objExercise']) || $origin == 'learnpath' || $_SESSION['objExercise']->id != $_REQUEST['exerciseId']) {
  641. if (!isset ($_SESSION['objExercise']) || $_SESSION['objExercise']->id != $_REQUEST['exerciseId']) {
  642. if ($debug > 0) {
  643. echo str_repeat('&nbsp;', 0) . '$_SESSION[objExercise] was unset' . "<br />\n";
  644. }
  645. // construction of Exercise
  646. $objExercise = new Exercise();
  647. unset ($_SESSION['questionList']);
  648. // if the specified exercise doesn't exist or is disabled
  649. if (!$objExercise->read($exerciseId) || (!$objExercise->selectStatus() && !$is_allowedToEdit && ($origin != 'learnpath'))) {
  650. unset ($objExercise);
  651. $error = get_lang('ExerciseNotFound');
  652. //die(get_lang('ExerciseNotFound'));
  653. } else {
  654. // saves the object into the session
  655. api_session_register('objExercise');
  656. if ($debug > 0) {
  657. echo str_repeat('&nbsp;', 0) . '$_SESSION[objExercise] was unset - set now - end' . "<br />\n";
  658. }
  659. }
  660. }
  661. if (!isset ($objExcercise) && isset ($_SESSION['objExercise'])) {
  662. $objExercise = $_SESSION['objExercise'];
  663. }
  664. if (!is_object($objExercise)) {
  665. header('Location: exercice.php');
  666. exit ();
  667. }
  668. $Exe_starttime = $objExercise->start_time;
  669. $Exe_endtime = $objExercise->end_time;
  670. $quizID = $objExercise->selectId();
  671. $exerciseAttempts = $objExercise->selectAttempts();
  672. $exerciseTitle = $objExercise->selectTitle();
  673. $exerciseDescription = $objExercise->selectDescription();
  674. $exerciseDescription = $exerciseDescription;
  675. $exerciseSound = $objExercise->selectSound();
  676. $randomQuestions = $objExercise->isRandom();
  677. $exerciseType = $objExercise->selectType();
  678. $table_quiz_test = Database :: get_course_table(TABLE_QUIZ_TEST);
  679. //if (!isset($_SESSION['questionList']) || $origin == 'learnpath') {
  680. //in LP's is enabled the "remember question" feature?
  681. $my_exe_id = Security :: remove_XSS($_GET['exerciseId']);
  682. if (!isset ($_SESSION['questionList'])) {
  683. if ($debug > 0) {
  684. echo str_repeat('&nbsp;', 0) . '$_SESSION[questionList] was unset' . "<br />\n";
  685. }
  686. // selects the list of question ID
  687. $my_question_list = array ();
  688. $questionList = ($randomQuestions ? $objExercise->selectRandomList() : $objExercise->selectQuestionList());
  689. // saves the question list into the session
  690. $sql = 'SELECT random FROM ' . $table_quiz_test . ' WHERE id="' . Database :: escape_string($my_exe_id) . '";';
  691. $rs = Database::query($sql, __FILE__, __LINE__);
  692. $row_number = Database :: fetch_array($rs);
  693. $z = 0;
  694. if ($row_number['random'] <> 0) {
  695. foreach ($questionList as $infoquestionList) {
  696. if ($z < $row_number['random']) {
  697. $my_question_list[$z] = $infoquestionList;
  698. } else {
  699. break;
  700. }
  701. $z++;
  702. }
  703. // $questionList=array();
  704. $questionList = $my_question_list;
  705. }
  706. api_session_register('questionList');
  707. if ($debug > 0) {
  708. echo str_repeat('&nbsp;', 0) . '$_SESSION[questionList] was unset - set now - end' . "<br />\n";
  709. }
  710. }
  711. if (!isset ($objExcercise) && isset ($_SESSION['objExercise'])) {
  712. $questionList = $_SESSION['questionList'];
  713. }
  714. $quizStartTime = time();
  715. api_session_register('quizStartTime');
  716. $nbrQuestions = sizeof($questionList);
  717. // if questionNum comes from POST and not from GET
  718. if (!$questionNum || $_POST['questionNum']) {
  719. // only used for sequential exercises (see $exerciseType)
  720. if (!$questionNum) {
  721. $questionNum = 1;
  722. } else {
  723. $questionNum++;
  724. }
  725. }
  726. if (!empty ($_GET['gradebook']) && $_GET['gradebook'] == 'view') {
  727. $_SESSION['gradebook'] = Security :: remove_XSS($_GET['gradebook']);
  728. $gradebook = $_SESSION['gradebook'];
  729. }
  730. elseif (empty ($_GET['gradebook'])) {
  731. unset ($_SESSION['gradebook']);
  732. $gradebook = '';
  733. }
  734. if (!empty ($gradebook) && $gradebook == 'view') {
  735. $interbreadcrumb[] = array (
  736. 'url' => '../gradebook/' . $_SESSION['gradebook_dest'],
  737. 'name' => get_lang('Gradebook')
  738. );
  739. }
  740. //$nameTools=get_lang('Exercice');
  741. $interbreadcrumb[] = array (
  742. "url" => "exercice.php?gradebook=$gradebook",
  743. "name" => get_lang('Exercices')
  744. );
  745. $interbreadcrumb[] = array (
  746. "url" => api_get_self()."?gradebook=$gradebook",
  747. "name" => $exerciseTitle
  748. );
  749. if ($origin != 'learnpath') { //so we are not in learnpath tool
  750. $htmlHeadXtra[] = "<script type=\"text/javascript\" src=\"../plugin/hotspot/JavaScriptFlashGateway.js\"></script>
  751. <script src=\"../plugin/hotspot/hotspot.js\" type=\"text/javascript\"></script>
  752. <script language=\"JavaScript\" type=\"text/javascript\">
  753. <!--
  754. // -----------------------------------------------------------------------------
  755. // Globals
  756. // Major version of Flash required
  757. var requiredMajorVersion = 7;
  758. // Minor version of Flash required
  759. var requiredMinorVersion = 0;
  760. // Minor version of Flash required
  761. var requiredRevision = 0;
  762. // the version of javascript supported
  763. var jsVersion = 1.0;
  764. // -----------------------------------------------------------------------------
  765. // -->
  766. </script>
  767. <script language=\"VBScript\" type=\"text/vbscript\">
  768. <!-- // Visual basic helper required to detect Flash Player ActiveX control version information
  769. Function VBGetSwfVer(i)
  770. on error resume next
  771. Dim swControl, swVersion
  772. swVersion = 0
  773. set swControl = CreateObject(\"ShockwaveFlash.ShockwaveFlash.\" + CStr(i))
  774. if (IsObject(swControl)) then
  775. swVersion = swControl.GetVariable(\"\$version\")
  776. end if
  777. VBGetSwfVer = swVersion
  778. End Function
  779. // -->
  780. </script>
  781. <script language=\"JavaScript1.1\" type=\"text/javascript\">
  782. <!-- // Detect Client Browser type
  783. var isIE = (navigator.appVersion.indexOf(\"MSIE\") != -1) ? true : false;
  784. var isWin = (navigator.appVersion.toLowerCase().indexOf(\"win\") != -1) ? true : false;
  785. var isOpera = (navigator.userAgent.indexOf(\"Opera\") != -1) ? true : false;
  786. jsVersion = 1.1;
  787. // JavaScript helper required to detect Flash Player PlugIn version information
  788. function JSGetSwfVer(i){
  789. // NS/Opera version >= 3 check for Flash plugin in plugin array
  790. if (navigator.plugins != null && navigator.plugins.length > 0) {
  791. if (navigator.plugins[\"Shockwave Flash 2.0\"] || navigator.plugins[\"Shockwave Flash\"]) {
  792. var swVer2 = navigator.plugins[\"Shockwave Flash 2.0\"] ? \" 2.0\" : \"\";
  793. var flashDescription = navigator.plugins[\"Shockwave Flash\" + swVer2].description;
  794. descArray = flashDescription.split(\" \");
  795. tempArrayMajor = descArray[2].split(\".\");
  796. versionMajor = tempArrayMajor[0];
  797. versionMinor = tempArrayMajor[1];
  798. if ( descArray[3] != \"\" ) {
  799. tempArrayMinor = descArray[3].split(\"r\");
  800. } else {
  801. tempArrayMinor = descArray[4].split(\"r\");
  802. }
  803. versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
  804. flashVer = versionMajor + \".\" + versionMinor + \".\" + versionRevision;
  805. } else {
  806. flashVer = -1;
  807. }
  808. }
  809. // MSN/WebTV 2.6 supports Flash 4
  810. else if (navigator.userAgent.toLowerCase().indexOf(\"webtv/2.6\") != -1) flashVer = 4;
  811. // WebTV 2.5 supports Flash 3
  812. else if (navigator.userAgent.toLowerCase().indexOf(\"webtv/2.5\") != -1) flashVer = 3;
  813. // older WebTV supports Flash 2
  814. else if (navigator.userAgent.toLowerCase().indexOf(\"webtv\") != -1) flashVer = 2;
  815. // Can't detect in all other cases
  816. else {
  817. flashVer = -1;
  818. }
  819. return flashVer;
  820. }
  821. // When called with reqMajorVer, reqMinorVer, reqRevision returns true if that version or greater is available
  822. function DetectFlashVer(reqMajorVer, reqMinorVer, reqRevision)
  823. {
  824. reqVer = parseFloat(reqMajorVer + \".\" + reqRevision);
  825. // loop backwards through the versions until we find the newest version
  826. for (i=25;i>0;i--) {
  827. if (isIE && isWin && !isOpera) {
  828. versionStr = VBGetSwfVer(i);
  829. } else {
  830. versionStr = JSGetSwfVer(i);
  831. }
  832. if (versionStr == -1 ) {
  833. return false;
  834. } else if (versionStr != 0) {
  835. if(isIE && isWin && !isOpera) {
  836. tempArray = versionStr.split(\" \");
  837. tempString = tempArray[1];
  838. versionArray = tempString .split(\",\");
  839. } else {
  840. versionArray = versionStr.split(\".\");
  841. }
  842. versionMajor = versionArray[0];
  843. versionMinor = versionArray[1];
  844. versionRevision = versionArray[2];
  845. versionString = versionMajor + \".\" + versionRevision; // 7.0r24 == 7.24
  846. versionNum = parseFloat(versionString);
  847. // is the major.revision >= requested major.revision AND the minor version >= requested minor
  848. if ( (versionMajor > reqMajorVer) && (versionNum >= reqVer) ) {
  849. return true;
  850. } else {
  851. return ((versionNum >= reqVer && versionMinor >= reqMinorVer) ? true : false );
  852. }
  853. }
  854. }
  855. }
  856. // -->
  857. </script>";
  858. Display :: display_header($nameTools, "Exercise");
  859. if (!api_is_allowed_to_session_edit() ) {
  860. Display :: display_warning_message(get_lang('SessionIsReadOnly'));
  861. }
  862. } else {
  863. if (empty ($charset)) {
  864. $charset = 'ISO-8859-15';
  865. }
  866. /*
  867. * HTML HEADER
  868. */
  869. Display::display_reduced_header();
  870. echo '<div style="height:10px">&nbsp;</div>';
  871. }
  872. // I'm in a preview mode
  873. if (api_is_course_admin() && $origin != 'learnpath') {
  874. echo '<div class="actions">';
  875. echo Display :: return_icon('quiz.gif', get_lang('GoBackToEx')) . '<a href="admin.php?' . api_get_cidreq() . '&exerciseId=' . $objExercise->id . '">' . get_lang('GoBackToEx') . '</a>';
  876. echo Display :: return_icon('edit.gif', get_lang('ModifyExercise')) . '<a href="exercise_admin.php?modifyExercise=yes&exerciseId=' . $objExercise->id . '">' . get_lang('ModifyExercise') . '</a>';
  877. echo '</div>';
  878. }
  879. //Timer control
  880. if ($exercise_row['expired_time'] != 0) {
  881. echo '<div align="right" id="wrapper-clock"><div id="square" class="rounded"><div id="text-content" align="center" class="count_down"></div></div></div>';
  882. }
  883. $exerciseTitle = api_parse_tex($exerciseTitle);
  884. echo "<h3>" . $exerciseTitle . "</h3>";
  885. if ($exerciseAttempts > 0) {
  886. $user_id = api_get_user_id();
  887. $course_code = api_get_course_id();
  888. $sql = "SELECT count(*) FROM $stat_table WHERE exe_exo_id = '$quizID'
  889. AND exe_user_id = '$user_id'
  890. AND status != 'incomplete'
  891. AND orig_lp_id = $safe_lp_id
  892. AND orig_lp_item_id = $safe_lp_item_id
  893. AND exe_cours_id = '$course_code' AND session_id = '" . (int) $_SESSION['id_session'] . "'";
  894. $aquery = Database::query($sql, __FILE__, __LINE__);
  895. $attempt = Database :: fetch_array($aquery);
  896. if ($attempt[0] >= $exerciseAttempts) {
  897. if (!api_is_allowed_to_edit(null,true)) {
  898. Display :: display_warning_message(sprintf(get_lang('ReachedMaxAttempts'), $exerciseTitle, $exerciseAttempts), false);
  899. if ($origin != 'learnpath')
  900. Display :: display_footer();
  901. exit;
  902. } else {
  903. Display :: display_warning_message(sprintf(get_lang('ReachedMaxAttemptsAdmin'), $exerciseTitle, $exerciseAttempts), false);
  904. }
  905. }
  906. }
  907. if (!function_exists('convert_date_to_number')) {
  908. function convert_date_to_number($default) {
  909. // 2008-10-12 00:00:00 ---to--> 12345672218 (timestamp)
  910. $parts = split(' ', $default);
  911. list ($d_year, $d_month, $d_day) = split('-', $parts[0]);
  912. list ($d_hour, $d_minute, $d_second) = split(':', $parts[1]);
  913. return mktime($d_hour, $d_minute, $d_second, $d_month, $d_day, $d_year);
  914. }
  915. }
  916. $limit_time_exists = (($Exe_starttime != '0000-00-00 00:00:00') || ($Exe_endtime != '0000-00-00 00:00:00')) ? true : false;
  917. if ($limit_time_exists) {
  918. $exercise_start_time = convert_date_to_number($Exe_starttime);
  919. $exercise_end_time = convert_date_to_number($Exe_endtime);
  920. $time_now = convert_date_to_number(date('Y-m-d H:i:s'));
  921. $permission_to_start = (($time_now - $exercise_start_time) > 0) ? true : false;
  922. if ($_SERVER['REQUEST_METHOD'] != 'POST')
  923. $exercise_timeover = (($time_now - $exercise_end_time) > 0) ? true : false;
  924. if ($permission_to_start == false || $exercise_timeover == true) { //
  925. if (!api_is_allowed_to_edit(null,true)) {
  926. $message_warning = ($permission_to_start == false) ? get_lang('ExerciseNoStartedYet') : get_lang('ReachedTimeLimit');
  927. Display :: display_warning_message(sprintf($message_warning, $exerciseTitle, $exerciseAttempts));
  928. Display :: display_footer();
  929. exit;
  930. } else {
  931. $message_warning = ($permission_to_start == false) ? get_lang('ExerciseNoStartedAdmin') : get_lang('ReachedTimeLimitAdmin');
  932. Display :: display_warning_message(sprintf($message_warning, $exerciseTitle, $exerciseAttempts));
  933. }
  934. }
  935. }
  936. if (!empty ($error)) {
  937. Display :: display_error_message($error, false);
  938. } else {
  939. if (!empty ($exerciseSound)) {
  940. echo "<a href=\"../document/download.php?doc_url=%2Faudio%2F" . Security::remove_XSS($exerciseSound) . "\" target=\"_blank\">", "<img src=\"../img/sound.gif\" border=\"0\" align=\"absmiddle\" alt=", get_lang('Sound') .
  941. "\" /></a>";
  942. }
  943. // Get number of hotspot questions for javascript validation
  944. $number_of_hotspot_questions = 0;
  945. $onsubmit = '';
  946. $i = 0;
  947. //i have a doubt in this line cvargas
  948. //var_dump($questionList);
  949. if (!strcmp($questionList[0], '') === 0) {
  950. foreach ($questionList as $questionId) {
  951. $i++;
  952. $objQuestionTmp = Question :: read($questionId);
  953. // for sequential exercises
  954. if ($exerciseType == 2) {
  955. // if it is not the right question, goes to the next loop iteration
  956. if ($questionNum != $i) {
  957. continue;
  958. } else {
  959. if ($objQuestionTmp->selectType() == HOT_SPOT) {
  960. $number_of_hotspot_questions++;
  961. }
  962. break;
  963. }
  964. } else {
  965. if ($objQuestionTmp->selectType() == HOT_SPOT) {
  966. $number_of_hotspot_questions++;
  967. }
  968. }
  969. }
  970. }
  971. if ($number_of_hotspot_questions > 0) {
  972. $onsubmit = "onsubmit=\"return validateFlashVar('" . $number_of_hotspot_questions . "', '" . get_lang('HotspotValidateError1') . "', '" . get_lang('HotspotValidateError2') . "');\"";
  973. }
  974. $s = "<p>$exerciseDescription</p>";
  975. if ($exerciseType == 2)
  976. {
  977. $s2 = "&exerciseId=" . $exerciseId;
  978. }
  979. $s .= " <form method='post' action='" . api_get_self() . "?autocomplete=off&gradebook=$gradebook" . $s2 . "' id='my_frm_exercise' name='frm_exercise' $onsubmit>
  980. <input type='hidden' name='formSent' value='1' />
  981. <input type='hidden' name='exerciseType' value='" . $exerciseType . "' />
  982. <input type='hidden' name='exerciseId' value='" . $exerciseId . "' />
  983. <input type='hidden' name='questionNum' value='" . $questionNum . "' />
  984. <input type='hidden' name='nbrQuestions' value='" . $nbrQuestions . "' />
  985. <input type='hidden' name='origin' value='" . $origin . "' />
  986. <input type='hidden' name='learnpath_id' value='" . $learnpath_id . "' />
  987. <input type='hidden' name='learnpath_item_id' value='" . $learnpath_item_id . "' />
  988. <table width='100%' border='0' cellpadding='1' cellspacing='0'>
  989. <tr>
  990. <td>
  991. <table width='100%' cellpadding='3' cellspacing='0' border='0'>";
  992. echo '<div id="highlight-plugin" class="glossary-content">';
  993. echo $s;
  994. $i = 1;
  995. foreach ($questionList as $questionId) {
  996. // for sequential exercises
  997. if ($exerciseType == 2) {
  998. // if it is not the right question, goes to the next loop iteration
  999. if ($questionNum != $i) {
  1000. $i++;
  1001. continue;
  1002. } else {
  1003. if ($exerciseFeedbackType != 1) {
  1004. // if the user has already answered this question
  1005. if (isset ($exerciseResult[$questionId])) {
  1006. // construction of the Question object
  1007. $objQuestionTmp = Question :: read($questionId);
  1008. $questionName = $objQuestionTmp->selectTitle();
  1009. // destruction of the Question object
  1010. unset ($objQuestionTmp);
  1011. Display :: display_normal_message(get_lang('AlreadyAnswered'));
  1012. $i++;
  1013. //echo '<tr><td>'.get_lang('AlreadyAnswered').' &quot;'.$questionName.'&quot;</td></tr>';
  1014. break;
  1015. }
  1016. }
  1017. }
  1018. }
  1019. // shows the question and its answers
  1020. showQuestion($questionId, false, $origin, $i, $nbrQuestions);
  1021. $i++;
  1022. // for sequential exercises
  1023. if ($exerciseType == 2) {
  1024. // quits the loop
  1025. break;
  1026. }
  1027. }
  1028. // end foreach()
  1029. echo "<!-- <button type='submit' name='buttonCancel' class='cancel'>" . get_lang('Cancel') . "</button>
  1030. &nbsp;&nbsp; //--><br />";
  1031. echo '<div style="padding-left:10px; margin-top:-10px;">';
  1032. $submit_btn = "<button class='next' type='submit' name='submit' name='submit_save' id='submit_save'>";
  1033. // $submit_btn.=get_lang('ValidateAnswer');
  1034. if ($objExercise->selectFeedbackType() == 1 && $_SESSION['objExercise']->selectType() == 2) {
  1035. $submit_btn = '';
  1036. echo '<script src="' . api_get_path(WEB_LIBRARY_PATH) . 'javascript/thickbox.js" type="text/javascript"></script>';
  1037. echo '<style type="text/css" media="all">@import "' . api_get_path(WEB_LIBRARY_PATH) . 'javascript/thickbox.css";</style>';
  1038. $hotspot_get = $_POST['hotspot'];
  1039. // Show a hidden div
  1040. echo "<script>$(document).ready( function(){
  1041. $('.rounded').corners();
  1042. $('.rounded_inner').corners();
  1043. });</script>";
  1044. //echo '<br /><span class="rounded" style="width: 300px; margin-top: 10px; padding: 3px; background-color:#ccc;"><span style="width: 300px" class="rounded_inner" ><a href="exercise_submit_modal.php?hotspot='.$hotspot_get.'&nbrQuestions='.$nbrQuestions.'&questionnum='.$questionNum.'&exerciseType='.$exerciseType.'&exerciseId='.$exerciseId.'&placeValuesBeforeTB_=savedValues&TB_iframe=true&height=480&width=640&modal=true" title="" class="thickbox" id="validationButton">'.get_lang('ValidateAnswer').'</a></span></span><br /><br /><br />';
  1045. } else {
  1046. if (api_is_allowed_to_session_edit() ) {
  1047. if ($exerciseType == 1 || $nbrQuestions == $questionNum) {
  1048. $submit_btn .= get_lang('ValidateAnswer');
  1049. $name_btn = get_lang('ValidateAnswer');
  1050. } else {
  1051. $submit_btn .= get_lang('NextQuestion');
  1052. $name_btn = get_lang('NextQuestion');
  1053. }
  1054. $submit_btn .= "</button>";
  1055. if ($exercise_row['expired_time'] != 0) {
  1056. echo $submit_btn ="<input class='submit_next' type='submit' id='submit_save' value='".$name_btn."' name='submit_save'/>";
  1057. } else {
  1058. echo $submit_btn;
  1059. }
  1060. }
  1061. }
  1062. echo "</table>
  1063. </td>
  1064. </tr>
  1065. </table></form>";
  1066. $b = 2;
  1067. }
  1068. echo '</div>';
  1069. if ($_configuration['live_exercise_tracking'] == true && $exerciseFeedbackType != 1) {
  1070. //if($questionNum < 2){
  1071. if ($table_recorded_not_exist) { //$table_recorded_not_exist
  1072. if ($exercise_row['expired_time'] != 0) {
  1073. $sql_fields = "expired_time_control, ";
  1074. $sql_fields_values = "'"."$clock_expired_time"."',";
  1075. } else {
  1076. $sql_fields = "";
  1077. $sql_fields_values = "";
  1078. }
  1079. if ($exerciseType == 2) {
  1080. $sql = "INSERT INTO $stat_table($sql_fields exe_exo_id,exe_user_id,exe_cours_id,status,session_id,data_tracking,start_date,orig_lp_id,orig_lp_item_id)
  1081. VALUES($sql_fields_values '$exerciseId','" . api_get_user_id() . "','" . $_course['id'] . "','incomplete','" . api_get_session_id() . "','" . implode(',', $questionList) . "','" . date('Y-m-d H:i:s') . "',$safe_lp_id,$safe_lp_item_id)";
  1082. Database::query($sql, __FILE__, __LINE__);
  1083. } else {
  1084. $sql = "INSERT INTO $stat_table ($sql_fields exe_exo_id,exe_user_id,exe_cours_id,status,session_id,start_date,orig_lp_id,orig_lp_item_id)
  1085. VALUES($sql_fields_values '$exerciseId','" . api_get_user_id() . "','" . $_course['id'] . "','incomplete','" . api_get_session_id() . "','" . date('Y-m-d H:i:s') . "',$safe_lp_id,$safe_lp_item_id)";
  1086. Database::query($sql, __FILE__, __LINE__);
  1087. }
  1088. }
  1089. }
  1090. if ($origin != 'learnpath') {
  1091. //so we are not in learnpath tool
  1092. echo '</div>'; //End glossary div
  1093. Display :: display_footer();
  1094. } else {
  1095. echo '</body></html>';
  1096. }