testcategory.class.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /** @author hubert.borderiou **/
  4. if (!class_exists('Testcategory')):
  5. class Testcategory {
  6. public $id;
  7. public $name;
  8. public $description;
  9. /**
  10. * Constructor of the class Category
  11. * @author - Hubert Borderiou
  12. If you give an in_id and no in_name, you get info concerning the category of id=in_id
  13. otherwise, you've got an category objet avec your in_id, in_name, in_descr
  14. */
  15. function Testcategory($in_id=0, $in_name = '', $in_description="") {
  16. if ($in_id != 0 && $in_name == "") {
  17. $tmpobj = new Testcategory();
  18. $tmpobj->getCategory($in_id);
  19. $this->id = $tmpobj->id;
  20. $this->name = $tmpobj->name;
  21. $this->description = $tmpobj->description;
  22. }
  23. else {
  24. $this->id = $in_id;
  25. $this->name = $in_name;
  26. $this->description = $in_description;
  27. }
  28. }
  29. /** return the Testcategory object with id=in_id
  30. */
  31. function getCategory($in_id) {
  32. $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  33. $in_id = Database::escape_string($in_id);
  34. $sql = "SELECT * FROM $t_cattable WHERE id=$in_id AND c_id=".api_get_course_int_id();
  35. $res = Database::query($sql);
  36. $numrows = Database::num_rows($res);
  37. if ($numrows > 0) {
  38. $row = Database::fetch_array($res);
  39. $this->id = $row['id'];
  40. $this->name = $row['title'];
  41. $this->description = $row['description'];
  42. }
  43. }
  44. /** add Testcategory in the database if name doesn't already exists
  45. */
  46. function addCategoryInBDD() {
  47. $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  48. $v_name = $this->name;
  49. $v_name = Database::escape_string($v_name);
  50. $v_description = $this->description;
  51. $v_description = Database::escape_string($v_description);
  52. // check if name already exists
  53. $sql_verif = "SELECT count(*) AS nb FROM $t_cattable WHERE title = '$v_name' AND c_id=".api_get_course_int_id();
  54. $result_verif = Database::query($sql_verif);
  55. $data_verif = Database::fetch_array($result_verif);
  56. // lets add in BDD if not the same name
  57. if ($data_verif['nb'] <= 0) {
  58. $c_id = api_get_course_int_id();
  59. $sql = "INSERT INTO $t_cattable VALUES ('$c_id', '', '$v_name', '$v_description')";
  60. $res = Database::query($sql);
  61. return true;
  62. }
  63. else {
  64. return false;
  65. }
  66. }
  67. /**
  68. * Removes the category with id=in_id from the database if no question use this category
  69. * @todo I'm removing the $in_id parameter because it seems that you're using $this->id instead of $in_id after confirmation delete this
  70. * jmontoya
  71. */
  72. //function removeCategory($in_id) {
  73. function removeCategory() {
  74. $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  75. $v_id = Database::escape_string($this->id);
  76. $sql = "DELETE FROM $t_cattable WHERE id=$v_id AND c_id=".api_get_course_int_id();
  77. $res = Database::query($sql);
  78. if (Database::affected_rows() <= 0) {
  79. return false;
  80. } else {
  81. return true;
  82. }
  83. }
  84. /** modify category name or description of category with id=in_id
  85. */
  86. //function modifyCategory($in_id, $in_name, $in_description) {
  87. function modifyCategory() {
  88. $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  89. $v_id = Database::escape_string($this->id);
  90. $v_name = Database::escape_string($this->name);
  91. $v_description = Database::escape_string($this->description);
  92. $sql = "UPDATE $t_cattable SET title='$v_name', description='$v_description' WHERE id='$v_id' AND c_id=".api_get_course_int_id();
  93. $res = Database::query($sql);
  94. if (Database::affected_rows() <= 0) {
  95. return false;
  96. }
  97. else {
  98. return true;
  99. }
  100. }
  101. /**
  102. * Gets the number of question of category id=in_id
  103. * @todo I'm removing the $in_id parameter because it seems that you're using $this->id instead of $in_id after confirmation delete this
  104. * jmontoya
  105. */
  106. //function getCategoryQuestionsNumber($in_id) {
  107. function getCategoryQuestionsNumber() {
  108. $t_reltable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  109. $in_id = Database::escape_string($this->id);
  110. $sql = "SELECT count(*) AS nb FROM $t_reltable WHERE category_id=$in_id AND c_id=".api_get_course_int_id();
  111. $res = Database::query($sql);
  112. $row = Database::fetch_array($res);
  113. return $row['nb'];
  114. }
  115. function display($in_color="#E0EBF5") {
  116. echo "<textarea style='background-color:$in_color; width:60%; height:100px;'>";
  117. print_r($this);
  118. echo "</textarea>";
  119. }
  120. /** return an array of all Category objects in the database
  121. If in_field=="" Return an array of all category objects in the database
  122. Otherwise, return an array of all in_field value in the database (in_field = id or name or description)
  123. */
  124. public static function getCategoryListInfo($in_field="", $in_courseid="") {
  125. if (empty($in_courseid) || $in_courseid=="") {
  126. $in_courseid = api_get_course_int_id();
  127. }
  128. $t_cattable = Database :: get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  129. $in_field = Database::escape_string($in_field);
  130. $tabres = array();
  131. if ($in_field=="") {
  132. $sql = "SELECT * FROM $t_cattable WHERE c_id=$in_courseid ORDER BY title ASC";
  133. $res = Database::query($sql);
  134. while ($row = Database::fetch_array($res)) {
  135. $tmpcat = new Testcategory($row['id'], $row['title'], $row['description']);
  136. $tabres[] = $tmpcat;
  137. }
  138. }
  139. else {
  140. $sql = "SELECT $in_field FROM $t_cattable WHERE c_id=$in_courseid ORDER BY $in_field ASC";
  141. $res = Database::query($sql);
  142. while ($row = Database::fetch_array($res)) {
  143. $tabres[] = $row[$in_field];
  144. }
  145. }
  146. return $tabres;
  147. }
  148. /**
  149. Return the testcategory id for question with question_id = $in_questionid
  150. In this version, a question has only 1 testcategory.
  151. Return the testcategory id, 0 if none
  152. */
  153. public static function getCategoryForQuestion($in_questionid, $in_courseid = null) {
  154. $result = array(); // result
  155. if (empty($in_courseid) || $in_courseid=="") {
  156. $in_courseid = api_get_course_int_id();
  157. }
  158. $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  159. $question_id = Database::escape_string($in_questionid);
  160. $sql = "SELECT category_id FROM $t_cattable WHERE question_id = '$question_id' AND c_id = $in_courseid";
  161. $res = Database::query($sql);
  162. if (Database::num_rows($res) > 0) {
  163. while ($row = Database::fetch_array($res)) {
  164. $result[] = $row['category_id'];
  165. }
  166. }
  167. return $result;
  168. }
  169. public static function getCategoryNamesForQuestion($in_questionid, $in_courseid = null, $display_into_labels = true) {
  170. $result = array(); // result
  171. if (empty($in_courseid) || $in_courseid=="") {
  172. $in_courseid = api_get_course_int_id();
  173. }
  174. $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  175. $table_category = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  176. $question_id = Database::escape_string($in_questionid);
  177. $sql = "SELECT c.title FROM $t_cattable qc INNER JOIN $table_category c
  178. ON (qc.category_id = c.id AND qc.c_id = $in_courseid AND c.c_id = $in_courseid)
  179. WHERE question_id = '$question_id' ";
  180. $res = Database::query($sql);
  181. if (Database::num_rows($res) > 0) {
  182. while ($row = Database::fetch_array($res)) {
  183. $result[] = $row['title'];
  184. }
  185. }
  186. if ($display_into_labels) {
  187. $html = self::draw_category_label($result, 'header');
  188. return $html;
  189. }
  190. return $result;
  191. }
  192. /**
  193. * true if question id has a category
  194. */
  195. public static function isQuestionHasCategory($in_questionid) {
  196. $category_list = Testcategory::getCategoryForQuestion($in_questionid);
  197. if (!empty($category_list)) {
  198. return true;
  199. }
  200. return false;
  201. }
  202. /**
  203. * @todo fix this
  204. Return the category name for question with question_id = $in_questionid
  205. In this version, a question has only 1 category.
  206. Return the category id, "" if none
  207. */
  208. public static function getCategoryNameForQuestion($question_id, $course_id = null) {
  209. if (empty($course_id) || $course_id == "") {
  210. $course_id = api_get_course_int_id();
  211. }
  212. $course_id = intval($course_id);
  213. $category_list = Testcategory::getCategoryForQuestion($question_id, $course_id);
  214. $result = array(); // result
  215. $t_cattable = Database::get_course_table(TABLE_QUIZ_QUESTION_CATEGORY);
  216. $catid = Database::escape_string($catid);
  217. $sql = "SELECT title FROM $t_cattable WHERE id='$catid' AND c_id = $course_id";
  218. $res = Database::query($sql);
  219. $data = Database::fetch_array($res);
  220. if (Database::num_rows($res) > 0) {
  221. $result = $data['title'];
  222. }
  223. return $result;
  224. }
  225. /**
  226. * return the list of differents categories ID for a test
  227. * input : test_id
  228. * return : array of category id (integer)
  229. * @author hubert.borderiou 07-04-2011, Julio Montoya
  230. */
  231. public static function getListOfCategoriesIDForTest($exercise_id) {
  232. // parcourir les questions d'un test, recup les categories uniques dans un tableau
  233. $categories_in_exercise = array();
  234. $quiz = new Exercise();
  235. $quiz->read($exercise_id);
  236. $question_list = $quiz->selectQuestionList();
  237. // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ???
  238. for ($i=1; $i <= count($question_list); $i++) {
  239. $category_list = Testcategory::getCategoryForQuestion($question_list[$i]);
  240. if (!empty($category_list)) {
  241. $categories_in_exercise = array_merge($categories_in_exercise, $category_list);
  242. }
  243. }
  244. if (!empty($categories_in_exercise)) {
  245. $categories_in_exercise = array_unique(array_filter($categories_in_exercise));
  246. }
  247. return $categories_in_exercise;
  248. }
  249. /**
  250. * return the list of differents categories NAME for a test
  251. * input : test_id
  252. * return : array of string
  253. * hubert.borderiou 07-04-2011
  254. * @author function rewrote by jmontoya
  255. */
  256. public static function getListOfCategoriesNameForTest($in_testid) {
  257. $tabcatName = array();
  258. $tabcatID = self::getListOfCategoriesIDForTest($in_testid);
  259. for ($i=0; $i < count($tabcatID); $i++) {
  260. $cat = new Testcategory($tabcatID[$i]);
  261. $tabcatName[$cat->id] = $cat->name;
  262. }
  263. return $tabcatName;
  264. }
  265. /**
  266. * return the number of differents categories for a test
  267. * input : test_id
  268. * return : integer
  269. * hubert.borderiou 07-04-2011
  270. */
  271. public static function getNumberOfCategoriesForTest($in_testid) {
  272. return count(Testcategory::getListOfCategoriesIDForTest($in_testid));
  273. }
  274. /**
  275. * return the number of question of a category id in a test
  276. * input : test_id, category_id
  277. * return : integer
  278. * hubert.borderiou 07-04-2011
  279. */
  280. public static function getNumberOfQuestionsInCategoryForTest($exercise_id, $category_id) {
  281. $number_questions_in_category = 0;
  282. $exercise = new Exercise();
  283. $exercise->read($exercise_id);
  284. $question_list = $exercise->selectQuestionList();
  285. // the array given by selectQuestionList start at indice 1 and not at indice 0 !!! ? ? ?
  286. for ($i=1; $i <= count($question_list); $i++) {
  287. $category_in_question = Testcategory::getCategoryForQuestion($question_list[$i]);
  288. if (in_array($category_id, $category_in_question)) {
  289. $number_questions_in_category++;
  290. }
  291. }
  292. return $number_questions_in_category;
  293. }
  294. /**
  295. * return the number of question for a test using random by category
  296. * input : test_id, number of random question (min 1)
  297. * hubert.borderiou 07-04-2011
  298. * question witout categories are not counted
  299. */
  300. public static function getNumberOfQuestionRandomByCategory($exercise_id, $in_nbrandom) {
  301. $nbquestionresult = 0;
  302. $list_categories = Testcategory::getListOfCategoriesIDForTest($exercise_id);
  303. if (!empty($list_categories)) {
  304. for ($i=0; $i < count($list_categories); $i++) {
  305. if ($list_categories[$i] > 0) { // 0 = no category for this question
  306. $nbQuestionInThisCat = Testcategory::getNumberOfQuestionsInCategoryForTest($exercise_id, $list_categories[$i]);
  307. if ($nbQuestionInThisCat > $in_nbrandom) {
  308. $nbquestionresult += $in_nbrandom;
  309. } else {
  310. $nbquestionresult += $nbQuestionInThisCat;
  311. }
  312. }
  313. }
  314. }
  315. return $nbquestionresult;
  316. }
  317. /**
  318. * Return an array (id=>name)
  319. * tabresult[0] = get_lang('NoCategory');
  320. *
  321. */
  322. static function getCategoriesIdAndName($in_courseid = "") {
  323. if (empty($in_courseid) || $in_courseid=="") {
  324. $in_courseid = api_get_course_int_id();
  325. }
  326. $tabcatobject = Testcategory::getCategoryListInfo("", $in_courseid);
  327. $tabresult = array("0"=>get_lang('NoCategorySelected'));
  328. for ($i=0; $i < count($tabcatobject); $i++) {
  329. $tabresult[$tabcatobject[$i]->id] = $tabcatobject[$i]->name;
  330. }
  331. return $tabresult;
  332. }
  333. /**
  334. * return an array of question_id for each category
  335. * tabres[0] = array of question id with category id = 0 (i.e. no category)
  336. * tabres[24] = array of question id with category id = 24
  337. * In this version, a question has 0 or 1 category
  338. */
  339. static function getQuestionsByCat($in_exerciceId) {
  340. $tabres = array();
  341. $TBL_EXERCICE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
  342. $TBL_QUESTION_REL_CATEGORY = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  343. $in_exerciceId = intval($in_exerciceId);
  344. $sql = "SELECT qrc.question_id, qrc.category_id FROM $TBL_QUESTION_REL_CATEGORY qrc, $TBL_EXERCICE_QUESTION eq
  345. WHERE exercice_id=$in_exerciceId AND eq.question_id=qrc.question_id AND eq.c_id=".api_get_course_int_id()." AND eq.c_id=qrc.c_id ORDER BY category_id, question_id";
  346. $res = Database::query($sql);
  347. while ($data = Database::fetch_array($res)) {
  348. if (!is_array($tabres[$data['category_id']])) {
  349. $tabres[$data['category_id']] = array();
  350. }
  351. $tabres[$data['category_id']][] = $data['question_id'];
  352. }
  353. return $tabres;
  354. }
  355. /**
  356. * return a tab of $in_number random elements of $in_tab
  357. */
  358. static function getNElementsFromArray($in_tab, $in_number) {
  359. $tabres = $in_tab;
  360. shuffle($tabres);
  361. if ($in_number < count($tabres)) {
  362. $tabres = array_slice($tabres, 0, $in_number);
  363. }
  364. return $tabres;
  365. }
  366. /**
  367. * Display signs [+] and/or (>0) after question title if question has options
  368. * scoreAlwaysPositive and/or uncheckedMayScore
  369. */
  370. function displayQuestionOption($in_objQuestion) {
  371. if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->scoreAlwaysPositive) {
  372. echo "<span style='font-size:75%'> (>0)</span>";
  373. }
  374. if ($in_objQuestion->type == MULTIPLE_ANSWER && $in_objQuestion->uncheckedMayScore) {
  375. echo "<span style='font-size:75%'> [+]</span>";
  376. }
  377. }
  378. /**
  379. * sortTabByBracketLabel ($tabCategoryQuestions)
  380. * key of $tabCategoryQuestions are the categopy id (0 for not in a category)
  381. * value is the array of question id of this category
  382. * Sort question by Category
  383. */
  384. static function sortTabByBracketLabel($in_tab) {
  385. $tabResult = array();
  386. $tabCatName = array(); // tab of category name
  387. while (list($cat_id, $tabquestion) = each($in_tab)) {
  388. $catTitle = new Testcategory($cat_id);
  389. $tabCatName[$cat_id] = $catTitle->name;
  390. }
  391. reset($in_tab);
  392. // sort table by value, keeping keys as they are
  393. asort($tabCatName);
  394. // keys of $tabCatName are keys order for $in_tab
  395. while (list($key, $val) = each($tabCatName)) {
  396. $tabResult[$key] = $in_tab[$key];
  397. }
  398. return $tabResult;
  399. }
  400. /**
  401. * return total score for test exe_id for all question in the category $in_cat_id for user
  402. * If no question for this category, return ""
  403. */
  404. public static function getCatScoreForExeidForUserid($in_cat_id, $in_exe_id, $in_user_id) {
  405. $tbl_track_attempt = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
  406. $tbl_question_rel_category = Database::get_course_table(TABLE_QUIZ_QUESTION_REL_CATEGORY);
  407. $in_cat_id = intval($in_cat_id);
  408. $in_exe_id = intval($in_exe_id);
  409. $in_user_id = intval($in_user_id);
  410. $query = "SELECT DISTINCT marks, exe_id, user_id, ta.question_id, category_id FROM $tbl_track_attempt ta , $tbl_question_rel_category qrc
  411. WHERE ta.question_id=qrc.question_id AND qrc.category_id=$in_cat_id AND exe_id=$in_exe_id AND user_id=$in_user_id";
  412. $res = Database::query($query);
  413. $totalcatscore = "";
  414. while ($data = Database::fetch_array($res)) {
  415. $totalcatscore += $data['marks'];
  416. }
  417. return $totalcatscore;
  418. }
  419. /**
  420. * return the number max of question in a category
  421. * count the number of questions in all categories, and return the max
  422. * @author - hubert borderiou
  423. */
  424. public static function getNumberMaxQuestionByCat($in_testid) {
  425. $res_num_max = 0;
  426. // foreach question
  427. $tabcatid = Testcategory::getListOfCategoriesIDForTest($in_testid);
  428. for ($i=0; $i < count($tabcatid); $i++) {
  429. if ($tabcatid[$i] > 0) { // 0 = no category for this question
  430. $nbQuestionInThisCat = Testcategory::getNumberOfQuestionsInCategoryForTest($in_testid, $tabcatid[$i]);
  431. if ($nbQuestionInThisCat > $res_num_max) {
  432. $res_num_max = $nbQuestionInThisCat;
  433. }
  434. }
  435. }
  436. return $res_num_max;
  437. }
  438. public static function getCategoryListName($course_id = null) {
  439. $category_list = self::getCategoryListInfo(null, $course_id);
  440. $category_name_list = array();
  441. if (!empty($category_list)) {
  442. foreach($category_list as $category) {
  443. $category_name_list[$category->id] = $category->name;
  444. }
  445. }
  446. return $category_name_list;
  447. }
  448. public static function return_category_labels($category_list, $all_categories) {
  449. $category_list_to_render = array();
  450. foreach ($category_list as $category_id) {
  451. $category_name = null;
  452. if (!isset($all_categories[$category_id])) {
  453. $category_name = get_lang('Untitled');
  454. } else {
  455. $category_name = Text::cut($all_categories[$category_id], 15);
  456. }
  457. $category_list_to_render[] = $category_name;
  458. }
  459. $html = self::draw_category_label($category_list_to_render, 'label');
  460. return $html;
  461. }
  462. static function draw_category_label($category_list, $type = 'label') {
  463. $new_category_list = array();
  464. foreach ($category_list as $category_name) {
  465. switch ($type) {
  466. case 'label':
  467. $new_category_list[] = Display::label($category_name, 'info');
  468. break;
  469. case 'header':
  470. $new_category_list[] = $category_name;
  471. break;
  472. }
  473. }
  474. $html = null;
  475. if (!empty($new_category_list)) {
  476. switch ($type) {
  477. case 'label':
  478. $html = implode(' ', $new_category_list);
  479. break;
  480. case 'header':
  481. $html = Display::page_subheader3(get_lang('Category').': '.implode(', ', $new_category_list));
  482. }
  483. }
  484. return $html;
  485. }
  486. /**
  487. * Returns a category summary report
  488. * @params int exercise id
  489. * @params array prefilled array with the category_id, score, and weight example: array(1 => array('score' => '10', 'total' => 20));
  490. */
  491. public static function get_stats_table_by_attempt($exercise_id, $category_list = array()) {
  492. if (empty($category_list)) {
  493. return null;
  494. }
  495. $category_name_list = Testcategory::getListOfCategoriesNameForTest($exercise_id);
  496. $table = new HTML_Table(array('class' => 'data_table'));
  497. $table->setHeaderContents(0, 0, get_lang('Categories'));
  498. $table->setHeaderContents(0, 1, get_lang('AbsoluteScore'));
  499. $table->setHeaderContents(0, 2, get_lang('RelativeScore'));
  500. $row = 1;
  501. $none_category = array();
  502. if (isset($category_list['none'])) {
  503. $none_category = $category_list['none'];
  504. unset($category_list['none']);
  505. }
  506. $total = array();
  507. if (isset($category_list['total'])) {
  508. $total = $category_list['total'];
  509. unset($category_list['total']);
  510. }
  511. if (count($category_list) > 1) {
  512. foreach ($category_list as $category_id => $category_item) {
  513. $table->setCellContents($row, 0, $category_name_list[$category_id]);
  514. $table->setCellContents($row, 1, show_score($category_item['score'], $category_item['total'], false));
  515. $table->setCellContents($row, 2, show_score($category_item['score'], $category_item['total'], true, false, true));
  516. $row++;
  517. }
  518. if (!empty($none_category)) {
  519. $table->setCellContents($row, 0, get_lang('None'));
  520. $table->setCellContents($row, 1, show_score($none_category['score'], $none_category['total'], false));
  521. $table->setCellContents($row, 2, show_score($none_category['score'], $none_category['total'], true, false, true));
  522. $row++;
  523. }
  524. if (!empty($total)) {
  525. $table->setCellContents($row, 0, get_lang('Total'));
  526. $table->setCellContents($row, 1, show_score($total['score'], $total['total'], false));
  527. $table->setCellContents($row, 2, show_score($total['score'], $total['total'], true, false, true));
  528. }
  529. return $table->toHtml();
  530. }
  531. return null;
  532. }
  533. }
  534. endif;