lp_stats.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. <?php
  2. //$id:$
  3. /**
  4. * This script displays statistics on the current learning path (scorm)
  5. *
  6. * This script must be included by lp_controller.php to get basic initialisation
  7. * @package dokeos.learnpath
  8. * @author Yannick Warnier <ywarnier@beeznest.org>
  9. */
  10. /**
  11. * Script
  12. */
  13. require_once('learnpath.class.php');
  14. //require_once('scorm.class.php');
  15. require_once ('resourcelinker.inc.php');
  16. if(empty($_SESSION['_course']['id']) && isset($_GET['course']))
  17. {
  18. $course_code = Database :: escape_string($_GET['course']);
  19. }
  20. else
  21. {
  22. $course_code = $_SESSION['_course']['id'];
  23. }
  24. //The two following variables have to be declared by the includer script
  25. //$lp_id = $_SESSION['oLP']->get_id();
  26. //$list = $_SESSION['oLP']->get_flat_ordered_items_list($lp_id);
  27. //$user_id = $_user['user_id'];
  28. //$stats_charset = $_SESSION['oLP']->encoding
  29. if(!isset($origin))
  30. $origin = '';
  31. if($origin != 'tracking')
  32. {
  33. if (!empty ($stats_charset)) {
  34. $charset_lang = $stats_charset;
  35. } else {
  36. $charset_lang = api_get_setting('platform_charset');
  37. }
  38. $dokeos_charset = api_get_setting('platform_charset');
  39. $charset = $charset_lang;
  40. $w = $tablewidth -20;
  41. $htmlHeadXtra[] = ''.'<style type="text/css" media="screen, projection">
  42. /*<![CDATA[*/
  43. @import "../css/default/scorm.css";
  44. /*]]>*/
  45. </style>';
  46. include_once ('../inc/reduced_header.inc.php');
  47. echo '<body>';
  48. }
  49. //if display in fullscreen required
  50. if (strcmp($_GET["fs"], "true") == 0) {
  51. $output .= "<table align='center'>";
  52. } else {
  53. $output .= "<table class='margin_table'>";
  54. }
  55. //check if the user asked for the "extend all" option
  56. $extend_all_link = '';
  57. $extend_all = 0;
  58. if($origin == 'tracking')
  59. {
  60. $url_suffix = '&course='.$_GET['course'].'&student_id='.$_GET['student_id'].'&lp_id='.$_GET['lp_id'].'&origin='.$_GET['origin'];
  61. }
  62. else
  63. {
  64. $url_suffix = '';
  65. }
  66. if (!empty ($_GET['extend_all'])) {
  67. $extend_all_link = '<a href="'.api_get_self().'?action=stats'.$url_suffix.'"><img src="../img/view_less_stats.gif" alt="fold_view" border="0"></a>';
  68. $extend_all = 1;
  69. } else {
  70. $extend_all_link = '<a href="'.api_get_self().'?action=stats&extend_all=1'.$url_suffix.'"><img src="../img/view_more_stats.gif" alt="extend_view" border="0"></a>';
  71. }
  72. if($origin != 'tracking')
  73. {
  74. $output .= "<tr><td><div class='title'>".htmlentities(get_lang('ScormMystatus'), ENT_QUOTES, $dokeos_charset)."</div></td></tr>";
  75. }
  76. $output .= "<tr><td>&nbsp;</td></tr>"."<tr><td>"."<table border='0' class='data_table'><tr>\n".'<td width="16">'.$extend_all_link.'</td>'.'<td colspan="4" class="title"><div class="mystatusfirstrow">'.htmlentities(get_lang('ScormLessonTitle'), ENT_QUOTES, $dokeos_charset)."</div></td>\n".'<td colspan="2" class="title"><div class="mystatusfirstrow">'.htmlentities(get_lang('ScormStatus'), ENT_QUOTES, $dokeos_charset)."</div></td>\n".'<td colspan="2" class="title"><div class="mystatusfirstrow">'.htmlentities(get_lang('ScormScore'), ENT_QUOTES, $dokeos_charset)."</div></td>\n".'<td colspan="2" class="title"><div class="mystatusfirstrow">'.htmlentities(get_lang('ScormTime'), ENT_QUOTES, $dokeos_charset)."</div></td><td class='title'><div class='mystatusfirstrow'>".get_lang('Actions')."</div></td></tr>\n";
  77. //going through the items using the $items[] array instead of the database order ensures
  78. // we get them in the same order as in the imsmanifest file, which is rather random when using
  79. // the database table
  80. $TBL_LP_ITEM = Database :: get_course_table('lp_item');
  81. $TBL_LP_ITEM_VIEW = Database :: get_course_table('lp_item_view');
  82. $TBL_LP_VIEW = Database :: get_course_table('lp_view');
  83. $tbl_stats_exercices = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
  84. $sql = "SELECT max(view_count) FROM $TBL_LP_VIEW " .
  85. "WHERE lp_id = $lp_id AND user_id = '".$user_id."'";
  86. $res = api_sql_query($sql, __FILE__, __LINE__);
  87. $view = '';
  88. if (Database :: num_rows($res) > 0) {
  89. $myrow = Database :: fetch_array($res);
  90. $view = $myrow[0];
  91. }
  92. $counter = 0;
  93. //error_log('New LP - Querying views for latest attempt: '.$sql,0);
  94. $total_score = 0;
  95. $total_max_score = 0;
  96. $total_time = 0;
  97. $h = get_lang('h');
  98. if($export_csv)
  99. {
  100. $csv_content[] = array (
  101. get_lang('ScormLessonTitle'),
  102. get_lang('ScormStatus'),
  103. get_lang('ScormScore'),
  104. get_lang('ScormTime')
  105. );
  106. }
  107. foreach ($list as $my_item_id) {
  108. $extend_this = 0;
  109. $qry_order = 'DESC';
  110. if ((!empty ($_GET['extend_id']) and $_GET['extend_id'] == $my_item_id) OR $extend_all) {
  111. $extend_this = 1;
  112. $qry_order = 'ASC';
  113. }
  114. if (!empty ($view)) {
  115. $sql = "SELECT iv.status as mystatus, v.view_count as mycount, " .
  116. "iv.score as myscore, iv.total_time as mytime, i.id as myid, " .
  117. "i.title as mytitle, i.max_score as mymaxscore, " .
  118. "iv.max_score as myviewmaxscore, " .
  119. "i.item_type as item_type, iv.view_count as iv_view_count, " .
  120. "iv.id as iv_id, path as path ".
  121. " FROM $TBL_LP_ITEM as i, $TBL_LP_ITEM_VIEW as iv, $TBL_LP_VIEW as v ".
  122. " WHERE i.id = iv.lp_item_id ".
  123. " AND i.id = $my_item_id ".
  124. " AND iv.lp_view_id = v.id ".
  125. " AND i.lp_id = $lp_id ".
  126. " AND v.user_id = ".$user_id." ".
  127. " AND v.view_count = $view ".
  128. " ORDER BY iv.view_count $qry_order ";
  129. } else {
  130. $sql = "SELECT iv.status as mystatus, v.view_count as mycount, " .
  131. "iv.score as myscore, iv.total_time as mytime, i.id as myid, " .
  132. "i.title as mytitle, i.max_score as mymaxscore, " .
  133. "iv.max_score as myviewmaxscore, " .
  134. "i.item_type as item_type, iv.view_count as iv_view_count, " .
  135. "iv.id as iv_id, path as path ".
  136. " FROM $TBL_LP_ITEM as i, $TBL_LP_ITEM_VIEW as iv, $TBL_LP_VIEW as v ".
  137. " WHERE i.id = iv.lp_item_id ".
  138. " AND i.id = $my_item_id ".
  139. " AND iv.lp_view_id = v.id ".
  140. " AND i.lp_id = $lp_id ".
  141. " AND v.user_id = ".$user_id." ".
  142. " ORDER BY iv.view_count $qry_order ";
  143. }
  144. $result = api_sql_query($sql, __FILE__, __LINE__);
  145. $num = Database :: num_rows($result);
  146. $time_for_total = 'NaN';
  147. if (($extend_this OR $extend_all) && $num > 0) {
  148. $row = Database :: fetch_array($result);
  149. //if there are several attempts, and the link to extend has been clicked...
  150. if (($counter % 2) == 0) {
  151. $oddclass = "row_odd";
  152. } else {
  153. $oddclass = "row_even";
  154. }
  155. if ($inter_num)
  156. $extend_link = '<a href="'.api_get_self().'?action=stats&fold_id='.$my_item_id.$url_suffix.'"><img src="../img/visible.gif" alt="fold_view" border="0"></a>'."\n";
  157. $title = $row['mytitle'];
  158. $title = stripslashes($title);
  159. if (empty ($title)) {
  160. $title = rl_get_resource_name(api_get_course_id(), $lp_id, $row['myid']);
  161. }
  162. if ($row['item_type'] != 'dokeos_chapter') {
  163. if($row['item_type'] == 'quiz'){
  164. if($origin != 'tracking'){
  165. $sql_last_attempt='SELECT exe_id FROM '.$tbl_stats_exercices.' WHERE exe_exo_id="'.$row['path'].'" AND exe_user_id="'.api_get_user_id().'" AND exe_cours_id="'.$course_code.'" ORDER BY exe_date DESC LIMIT 1';
  166. }
  167. else{
  168. $sql_last_attempt='SELECT exe_id FROM '.$tbl_stats_exercices.' WHERE exe_exo_id="'.$row['path'].'" AND exe_user_id="'.$_GET['student_id'].'" AND exe_cours_id="'.$course_code.'" ORDER BY exe_date DESC LIMIT 1';
  169. }
  170. $resultLastAttempt = api_sql_query($sql_last_attempt);
  171. $id_last_attempt=mysql_result($resultLastAttempt,0,0);
  172. if($origin != 'tracking'){
  173. $correct_test_link = '<a href="../exercice/exercise_show.php?origin=student_progress&id='.$id_last_attempt.'&cidReq='.$course_code.'" target="_parent"><img src="'.api_get_path(WEB_IMG_PATH).'quiz.gif"></a>';
  174. }
  175. else{
  176. $correct_test_link = '<a href="../exercice/exercise_show.php?origin=tracking_course&id='.$id_last_attempt.'&cidReq='.$course_code.'&student='.$_GET['student_id'].'" target="_parent"><img src="'.api_get_path(WEB_IMG_PATH).'quiz.gif"></a>';
  177. }
  178. }
  179. else{
  180. $correct_test_link='-';
  181. }
  182. $output .= "<tr class='$oddclass'>\n"."<td>$extend_link</td>\n".'<td colspan="4" class="content"><div class="mystatus">'.htmlentities($title)."</div></td>\n".'<td colspan="2" class="content"></td>'."\n".'<td colspan="2" class="content"></td>'."\n".'<td colspan="2" class="content"></td><td class="content">'.$correct_test_link.'</td>'."\n"."</tr>\n";
  183. }
  184. $counter ++;
  185. do {
  186. //check if there are interactions below
  187. $extend_attempt_link = '';
  188. $extend_this_attempt = 0;
  189. if ((learnpath :: get_interactions_count_from_db($row['iv_id']) > 0 || learnpath :: get_objectives_count_from_db($row['iv_id']) > 0 ) && !$extend_all) {
  190. if (!empty ($_GET['extend_attempt_id']) && $_GET['extend_attempt_id'] == $row['iv_id']) {
  191. //the extend button for this attempt has been clicked
  192. $extend_this_attempt = 1;
  193. $extend_attempt_link = '<a href="'.api_get_self().'?action=stats&extend_id='.$my_item_id.'&fold_attempt_id='.$row['iv_id'].$url_suffix.'"><img src="../img/visible.gif" alt="fold_attempt_view" border="0"></a>'."\n";
  194. } else { //same case if fold_attempt_id is set, so not implemented explicitly
  195. //the extend button for this attempt has not been clicked
  196. $extend_attempt_link = '<a href="'.api_get_self().'?action=stats&extend_id='.$my_item_id.'&extend_attempt_id='.$row['iv_id'].$url_suffix.'"><img src="../img/invisible.gif" alt="extend_attempt_view" border="0"></a>'."\n";
  197. }
  198. }
  199. if (($counter % 2) == 0) {
  200. $oddclass = "row_odd";
  201. } else {
  202. $oddclass = "row_even";
  203. }
  204. $lesson_status = $row['mystatus'];
  205. $score = $row['myscore'];
  206. $time_for_total = $row['mytime'];
  207. $time = learnpathItem :: get_scorm_time('js', $row['mytime']);
  208. $type;
  209. $scoIdentifier = $row['myid'];
  210. if ($score == 0) {
  211. $maxscore = 0;
  212. } else {
  213. if($row['item_type'] == 'sco')
  214. {
  215. if(!empty($row['myviewmaxscore']) and $row['myviewmaxscore']>0)
  216. {
  217. $maxscore=$row['myviewmaxscore'];
  218. }
  219. elseif($row['myviewmaxscore'] === '')
  220. {
  221. $maxscore = 0;
  222. }
  223. else
  224. {
  225. $maxscore = $row['mymaxscore'];
  226. }
  227. }
  228. else
  229. {
  230. $maxscore = $row['mymaxscore'];
  231. }
  232. }
  233. //Remove "NaN" if any (@todo: locate the source of these NaN)
  234. $time = str_replace('NaN', '00'.$h.'00\'00"', $time);
  235. if (($lesson_status == 'completed') or ($lesson_status == 'passed')) {
  236. $color = 'green';
  237. } else {
  238. $color = 'black';
  239. }
  240. $mylanglist = array ('completed' => 'ScormCompstatus', 'incomplete' => 'ScormIncomplete', 'failed' => 'ScormFailed', 'passed' => 'ScormPassed', 'browsed' => 'ScormBrowsed', 'not attempted' => 'ScormNotAttempted',);
  241. $my_lesson_status = htmlentities(get_lang($mylanglist[$lesson_status]), ENT_QUOTES, $dokeos_charset);
  242. //$my_lesson_status = get_lang($mylanglist[$lesson_status]);
  243. if ($row['item_type'] != 'dokeos_chapter') {
  244. $output .= "<tr class='$oddclass'>\n"."<td></td>\n"."<td>$extend_attempt_link</td>\n".'<td colspan="3">'.htmlentities(get_lang('Attempt'), ENT_QUOTES, $dokeos_charset).' '.$row['iv_view_count']."</td>\n"
  245. //."<td><font color='$color'><div class='mystatus'>".htmlentities($array_status[$lesson_status],ENT_QUOTES,$charset_lang)."</div></font></td>\n"
  246. .'<td colspan="2"><font color="'.$color.'"><div class="mystatus">'.$my_lesson_status."</div></font></td>\n".'<td colspan="2"><div class="mystatus" align="center">'. ($score == 0 ? '-' : ($maxscore==0?$score:$score.'/'.$maxscore))."</div></td>\n".'<td colspan="2"><div class="mystatus">'.$time."</div></td><td></td>\n"."</tr>\n";
  247. }
  248. $counter ++;
  249. if ($extend_this_attempt OR $extend_all) {
  250. $list1 = learnpath :: get_iv_interactions_array($row['iv_id']);
  251. foreach ($list1 as $id => $interaction) {
  252. if (($counter % 2) == 0) {
  253. $oddclass = "row_odd";
  254. } else {
  255. $oddclass = "row_even";
  256. }
  257. $output .= "<tr class='$oddclass'>\n".'<td></td>'."\n".'<td></td>'."\n".'<td>&nbsp;</td>'."\n".'<td>'.$interaction['order_id'].'</td>'."\n".'<td>'.$interaction['id'].'</td>'."\n"
  258. //."<td><font color='$color'><div class='mystatus'>".htmlentities($array_status[$lesson_status],ENT_QUOTES,$charset_lang)."</div></font></td>\n"
  259. .'<td colspan="2">'.$interaction['type']."</td>\n"
  260. //.'<td>'.$interaction['correct_responses']."</td>\n"
  261. .'<td>'.urldecode($interaction['student_response'])."</td>\n".'<td>'.$interaction['result']."</td>\n".'<td>'.$interaction['latency']."</td>\n".'<td>'.$interaction['time']."</td>\n<td></td>\n</tr>\n";
  262. $counter ++;
  263. }
  264. $list2 = learnpath :: get_iv_objectives_array($row['iv_id']);
  265. foreach ($list2 as $id => $interaction) {
  266. if (($counter % 2) == 0) {
  267. $oddclass = "row_odd";
  268. } else {
  269. $oddclass = "row_even";
  270. }
  271. $output .= "<tr class='$oddclass'>\n".'<td></td>'."\n".'<td></td>'."\n".'<td>&nbsp;</td>'."\n".'<td>'.$interaction['order_id'].'</td>'."\n".'<td colspan="2">'.$interaction['objective_id'].'</td>'."\n"
  272. .'<td colspan="2">'.$interaction['status']."</td>\n"
  273. .'<td>'.$interaction['score_raw']."</td>\n".'<td>'.$interaction['score_max']."</td>\n".'<td>'.$interaction['score_min']."</td>\n<td></td>\n</tr>\n";
  274. $counter ++;
  275. }
  276. }
  277. } while ($row = Database :: fetch_array($result));
  278. } elseif($num>0) {
  279. $row = Database :: fetch_array($result);
  280. //check if there are interactions below
  281. $extend_attempt_link = '';
  282. $extend_this_attempt = 0;
  283. $inter_num = learnpath :: get_interactions_count_from_db($row['iv_id']);
  284. $objec_num = learnpath :: get_objectives_count_from_db($row['iv_id']);
  285. if (($inter_num > 0 || $objec_num > 0) && !$extend_all) {
  286. if (!empty ($_GET['extend_attempt_id']) && $_GET['extend_attempt_id'] == $row['iv_id']) {
  287. //the extend button for this attempt has been clicked
  288. $extend_this_attempt = 1;
  289. $extend_attempt_link = '<a href="'.api_get_self().'?action=stats&extend_id='.$my_item_id.'&fold_attempt_id='.$row['iv_id'].$url_suffix.'"><img src="../img/visible.gif" alt="fold_attempt_view" border="0"></a>'."\n";
  290. } else { //same case if fold_attempt_id is set, so not implemented explicitly
  291. //the extend button for this attempt has not been clicked
  292. $extend_attempt_link = '<a href="'.api_get_self().'?action=stats&extend_id='.$my_item_id.'&extend_attempt_id='.$row['iv_id'].$url_suffix.'"><img src="../img/invisible.gif" alt="extend_attempt_view" border="0"></a>'."\n";
  293. }
  294. }
  295. if (($counter % 2) == 0) {
  296. $oddclass = "row_odd";
  297. } else {
  298. $oddclass = "row_even";
  299. }
  300. //$extend_link = '<img src="../img/invisible.gif" alt="extend_disabled">';
  301. $extend_link = '';
  302. if ($inter_num > 1) {
  303. $extend_link = '<a href="'.api_get_self().'?action=stats&extend_id='.$my_item_id.'&extend_attempt_id='.$row['iv_id'].$url_suffix.'"><img src="../img/invisible.gif" alt="extend_view" border="0"></a>';
  304. }
  305. if (($counter % 2) == 0) {
  306. $oddclass = "row_odd";
  307. } else {
  308. $oddclass = "row_even";
  309. }
  310. $lesson_status = $row['mystatus'];
  311. $score = $row['myscore'];
  312. $subtotal_time = $row['mytime'];
  313. //if($row['mytime']==0){
  314. while ($tmp_row = Database :: fetch_array($result)) {
  315. $subtotal_time += $tmp_row['mytime'];
  316. }
  317. //}
  318. $time_for_total = $subtotal_time;
  319. $time = learnpathItem :: get_scorm_time('js', $subtotal_time);
  320. $scoIdentifier = $row['myid'];
  321. $title = $row['mytitle'];
  322. $title = stripslashes($title);
  323. if ($score == 0) {
  324. $maxscore = 0;
  325. } else {
  326. if($row['item_type'] == 'sco')
  327. {
  328. if(!empty($row['myviewmaxscore']) and $row['myviewmaxscore']>0)
  329. {
  330. $maxscore=$row['myviewmaxscore'];
  331. }
  332. elseif($row['myviewmaxscore'] === '')
  333. {
  334. $maxscore = 0;
  335. }
  336. else
  337. {
  338. $maxscore = $row['mymaxscore'];
  339. }
  340. }
  341. else
  342. {
  343. $maxscore = $row['mymaxscore'];
  344. }
  345. }
  346. if (empty ($title)) {
  347. $title = rl_get_resource_name(api_get_course_id(), $lp_id, $row['myid']);
  348. }
  349. //Remove "NaN" if any (@todo: locate the source of these NaN)
  350. //$time = str_replace('NaN', '00'.$h.'00\'00"', $time);
  351. if (($lesson_status == 'completed') or ($lesson_status == 'passed')) {
  352. $color = 'green';
  353. } else {
  354. $color = 'black';
  355. }
  356. $mylanglist = array ('completed' => 'ScormCompstatus', 'incomplete' => 'ScormIncomplete', 'failed' => 'ScormFailed', 'passed' => 'ScormPassed', 'browsed' => 'ScormBrowsed', 'not attempted' => 'ScormNotAttempted',);
  357. $my_lesson_status = htmlentities(get_lang($mylanglist[$lesson_status]), ENT_QUOTES, $dokeos_charset);
  358. if ($row['item_type'] != 'dokeos_chapter') {
  359. if($row['item_type'] == 'quiz'){
  360. $correct_test_link = '';
  361. if($origin != 'tracking' && $origin != 'tracking_course'){
  362. $sql_last_attempt='SELECT exe_id FROM '.$tbl_stats_exercices.' WHERE exe_exo_id="'.$row['path'].'" AND exe_user_id="'.api_get_user_id().'" AND exe_cours_id="'.$course_code.'" ORDER BY exe_date ASC';
  363. }
  364. else{
  365. $sql_last_attempt='SELECT exe_id FROM '.$tbl_stats_exercices.' WHERE exe_exo_id="'.$row['path'].'" AND exe_user_id="'.Database::escape_string($_GET['student_id']).'" AND exe_cours_id="'.Database::escape_string($_GET['course']).'" ORDER BY exe_date';
  366. }
  367. $resultLastAttempt = api_sql_query($sql_last_attempt);
  368. $num = Database::num_rows($resultLastAttempt);
  369. if($num>0)
  370. {
  371. if($num>1)
  372. {
  373. $i = 1;
  374. while($rowLA = Database::fetch_array($resultLastAttempt))
  375. {
  376. $laid = $rowLA['exe_id'];
  377. if($origin != 'tracking'){
  378. $correct_test_link .= '<a href="../exercice/exercise_show.php?origin=student_progress&id='.$laid.'&cidReq='.$course_code.'" target="_parent" title="'.get_lang('Attempt').' '.$i.'"><img src="'.api_get_path(WEB_IMG_PATH).'quiz.gif"></a> ';
  379. }
  380. else
  381. {
  382. $correct_test_link .= '<a href="../exercice/exercise_show.php?origin=tracking_course&id='.$laid.'&cidReq='.Security::remove_XSS(Database::escape_string($_GET['course'])).'&student='.$_GET['student_id'].'" target="_parent" title="'.get_lang('Attempt').' '.$i.'"><img src="'.api_get_path(WEB_IMG_PATH).'quiz.gif"></a> ';
  383. }
  384. $i++;
  385. }
  386. $correct_test_link = substr($correct_test_link,0,-1);
  387. }
  388. else
  389. {
  390. $id_last_attempt=mysql_result($resultLastAttempt,0,0);
  391. if($origin != 'tracking'){
  392. $correct_test_link = '<a href="../exercice/exercise_show.php?origin=student_progress&id='.$id_last_attempt.'&cidReq='.$course_code.'" target="_parent"><img src="'.api_get_path(WEB_IMG_PATH).'quiz.gif"></a>';
  393. }
  394. else{
  395. $correct_test_link = '<a href="../exercice/exercise_show.php?origin=tracking_course&id='.$id_last_attempt.'&cidReq='.Security::remove_XSS(Database::escape_string($_GET['course'])).'&student='.$_GET['student_id'].'" target="_parent"><img src="'.api_get_path(WEB_IMG_PATH).'quiz.gif"></a>';
  396. }
  397. }
  398. }
  399. else
  400. {
  401. $correct_test_link='-';
  402. }
  403. }
  404. else{
  405. $correct_test_link='-';
  406. }
  407. $output .= "<tr class='$oddclass'>\n"."<td>$extend_link</td>\n".'<td colspan="4"><div class="mystatus">'.htmlentities($title).'</div></td>'."\n"
  408. //."<td><font color='$color'><div class='mystatus'>".htmlentities($array_status[$lesson_status],ENT_QUOTES,$charset_lang)."</div></font></td>\n"
  409. .'<td colspan="2"><font color="'.$color.'"><div class="mystatus">'.$my_lesson_status."</div></font></td>\n".'<td colspan="2"><div class="mystatus" align="center">'. ($score == 0 ? '-' : ($maxscore==0?$score:$score.'/'.$maxscore))."</div></td>\n".'<td colspan="2"><div class="mystatus">'.$time."</div></td><td>$correct_test_link</td>\n"."</tr>\n";
  410. if($export_csv)
  411. {
  412. $temp = array();
  413. $temp[] = $title;
  414. $temp[] = html_entity_decode($my_lesson_status);
  415. $temp[] = ($score == 0 ? '-' : ($maxscore==0?$score:$score.'/'.$maxscore));
  416. $temp[] = $time;
  417. $csv_content[] = $temp;
  418. }
  419. }
  420. $counter ++;
  421. if ($extend_this_attempt OR $extend_all) {
  422. $list1 = learnpath :: get_iv_interactions_array($row['iv_id']);
  423. foreach ($list1 as $id => $interaction) {
  424. if (($counter % 2) == 0) {
  425. $oddclass = "row_odd";
  426. } else {
  427. $oddclass = "row_even";
  428. }
  429. $output .= "<tr class='$oddclass'>\n".'<td></td>'."\n".'<td></td>'."\n".'<td>&nbsp;</td>'."\n".'<td>'.$interaction['order_id'].'</td>'."\n".'<td>'.$interaction['id'].'</td>'."\n"
  430. //."<td><font color='$color'><div class='mystatus'>".htmlentities($array_status[$lesson_status],ENT_QUOTES,$charset_lang)."</div></font></td>\n"
  431. .'<td colspan="2">'.$interaction['type']."</td>\n"
  432. //.'<td>'.$interaction['correct_responses']."</td>\n"
  433. .'<td>'.urldecode($interaction['student_response'])."</td>\n".'<td>'.$interaction['result']."</td>\n".'<td>'.$interaction['latency']."</td>\n".'<td>'.$interaction['time']."</td>\n<td></td>\n</tr>\n";
  434. $counter ++;
  435. }
  436. $list2 = learnpath :: get_iv_objectives_array($row['iv_id']);
  437. foreach ($list2 as $id => $interaction) {
  438. if (($counter % 2) == 0) {
  439. $oddclass = "row_odd";
  440. } else {
  441. $oddclass = "row_even";
  442. }
  443. $output .= "<tr class='$oddclass'>\n".'<td></td>'."\n".'<td></td>'."\n".'<td>&nbsp;</td>'."\n".'<td>'.$interaction['order_id'].'</td>'."\n".'<td colspan="2">'.$interaction['objective_id'].'</td>'."\n"
  444. .'<td colspan="2">'.$interaction['status']."</td>\n"
  445. .'<td>'.$interaction['score_raw']."</td>\n".'<td>'.$interaction['score_max']."</td>\n".'<td>'.$interaction['score_min']."</td>\n<td></td>\n</tr>\n";
  446. $counter ++;
  447. }
  448. }
  449. }
  450. //only sum up the latest attempt each time
  451. $total_max_score += $maxscore;
  452. $total_score += $score;
  453. $total_time += $time_for_total;
  454. }
  455. $total_time = learnpathItem :: get_scorm_time('js', $total_time);
  456. //$total_time = str_replace('NaN','00:00:00',$total_time);
  457. $total_time = str_replace('NaN', '00'.$h.'00\'00"', $total_time);
  458. $lp_type = learnpath::get_type_static($lp_id);
  459. $total_percent = 0;
  460. $final_score = '0%';
  461. if($lp_type == 2) //if scorm
  462. {
  463. if($total_max_score == 0)
  464. {
  465. $total_percent = number_format((float) $total_score, 1, '.', '');
  466. $final_score = ($total_score == 0 ? '-' : $total_percent);
  467. }
  468. else
  469. {
  470. $total_percent = number_format((((float) $total_score / (float) $total_max_score) * 100), 1, '.', '');
  471. $final_score = ($total_score == 0 ? '-' : $total_percent.'%');
  472. }
  473. }
  474. else
  475. {
  476. if ($total_max_score == 0) {
  477. $total_max_score = 1;
  478. }
  479. $total_percent = number_format((((float) $total_score / (float) $total_max_score) * 100), 1, '.', '');
  480. $final_score = ($total_score == 0 ? '-' : $total_percent.'%');
  481. }
  482. if (($counter % 2) == 0) {
  483. $oddclass = "row_odd";
  484. } else {
  485. $oddclass = "row_even";
  486. }
  487. $output .= "<tr class='$oddclass'>\n"."<td></td>\n".'<td colspan="4"><div class="mystatus"><i>'.htmlentities(get_lang('AccomplishedStepsTotal'), ENT_QUOTES, $dokeos_charset)."</i></div></td>\n"
  488. //."<td><font color='$color'><div class='mystatus'>".htmlentities($array_status[$lesson_status],ENT_QUOTES,$charset_lang)."</div></font></td>\n"
  489. .'<td colspan="2"></td>'."\n".'<td colspan="2"><div class="mystatus" align="center">'. $final_score."</div></td>\n".'<td colspan="2"><div class="mystatus">'.$total_time.'</div></td><td></td>'."\n"."</tr>\n";
  490. $output .= "</table></td></tr></table>";
  491. if($export_csv)
  492. {
  493. $temp = array('','','','');
  494. $csv_content[] = $temp;
  495. $temp = array(get_lang('AccomplishedStepsTotal'),'',$final_score,$total_time);
  496. $csv_content[] = $temp;
  497. ob_end_clean();
  498. Export :: export_table_csv($csv_content, 'reporting_learning_path_details');
  499. }
  500. if($origin != 'tracking')
  501. {
  502. $output .= "</body></html>";
  503. }
  504. echo $output;
  505. ?>