Битрикс: вывод списка лучших результатов тестов

В битриксе есть очень полезный модуль – обучение. Благодаря ему можно легко обучать новичков и контролировать уровень знаний опытных сотрудников. По результатам обучения сотрудники проходят тесты и получают баллы.

Задача

В целях повышения мотивации к безошибочному прохождению теста создать страницу, на которой будет выводиться список лучших результатов теста.

Поиск решения

Т.к. ничего похожего в стандартном модуле нет, кастомизирование шаблонов сразу отпадает.

Сначала я решил, что всё просто. И сделать нужную выборку можно простой настройкой фильтра метода CTestAttempt::GetList(), но не тут то было.

Оказывается, в битриксе нет понятия номера попытки прохождения теста. Если просто отсортировать попытки по полученным баллам, то в выборке будут участвовать как самые худшие, так и самые лучшие попытки.

В итоге те? кто сдал тест с первого раза плохо будут в списке лузеров, и они же могут быть в списке лучших, т.к. пройти тест второй раз никто не мешает.

Найденное решение

Сначала я всё-таки сделал общий топ по всем попыткам. Но пользователи очень сильно возбубнили и пришлось делать два отдельных топа – по первой попытке и по лучшей попытке от каждого пользователя.

В итоге получился вот такой вот код для первых попыток:

  1. <?$testList = CTest::GetList(
  2.         Array("SORT"=>"ASC"),
  3.         Array("ACTIVE" => "Y", "MIN_PERMISSION" => "R")
  4. );//получаем список тестов
  5.        
  6. while ($arTest = $testList->GetNext()){?>
  7.         <div id="testList">
  8.                 <h2><?=$arTest[‘NAME’]?></h2>
  9.                 <table class="testList-table">
  10.                         <tr>
  11.                                 <td class="testList-best-top"><span>Лучшие результаты</span></td>
  12.                                 <td class="testList-bad-top"><span>Худшие результаты</span></td>
  13.                         </tr>
  14.                        
  15.                         <tr class="testList-result">
  16.                                 <td class="testList-result-best">
  17.                                         <table class="testList-result-table">
  18.                                                 <thead>
  19.                                                         <td class="testList-position">Место
  20.                                                         </td>
  21.                                                        
  22.                                                         <td class="testList-user-name">Имя
  23.                                                         </td>
  24.                                                        
  25.                                                         <td class="testList-score">Балл
  26.                                                         </td>
  27.                                                 </thead>
  28.                                                
  29.                                                 <tbody>
  30.                                                         <?$attemptListByDate = CTestAttempt::GetList(
  31.                                                                 Array("DATE_START" => "ASC"),
  32.                                                                 Array("TEST_ID" => $arTest[‘ID’],"STATUS" => "F")
  33.                                                         );//получаем список попыток по дате
  34.                                                        
  35.                                                         while ($arAttemptByDate = $attemptListByDate->GetNext()){
  36.                                                                 if(!in_array($arAttemptByDate[‘USER_NAME’],$arUsers)){//проверяем уникальность попытки
  37.                                                                         if(($arAttemptByDate[‘SCORE’] != "") && ($arAttemptByDate[‘SCORE’] != "0")){
  38.                                                                                 $arUsers[] = $arAttemptByDate[‘USER_NAME’];
  39.                                                                                 $arAttemptScore[] = $arAttemptByDate[‘SCORE’];
  40.                                                                         }
  41.                                                                 }
  42.                                                         }//создаём массив первых попыток
  43.                                                        
  44.                                                         arsort($arAttemptScore);//сортируем очки по убыванию
  45.                                                        
  46.                                                         $attemptCount = 0;
  47.                                                        
  48.                                                         while (($element = current($arAttemptScore)) && ($attemptCount != 5)){//проходим по 5ти первым элементам массива
  49.                                                                 $key = key($arAttemptScore);//номер попытки
  50.                                                                 $f_USER_NAME = explode(")", $arUsers[$key]);//извлекаем имя пользователя?>
  51.                                                                 <tr>
  52.                                                                         <td class="testList-position"><?echo (1 + $attemptCount);?>
  53.                                                                         </td>
  54.                                                                                
  55.                                                                         <td class="testList-user-name"><?=$f_USER_NAME[1]?>
  56.                                                                         </td>
  57.                                                                                
  58.                                                                         <td class="testList-user-score"><?=$arAttemptScore[$key]?>
  59.                                                                         </td>
  60.                                                                 </tr>
  61.                                                                
  62.                                                                 <?$attemptCount++;
  63.                                                                 next($arAttemptScore);//переводим фокус
  64.                                                         }?>
  65.                                                        
  66.                                                 </tbody>
  67.                                         </table>
  68.                                 <td class="testList-result-bad">
  69.                                         <table class="testList-result-table">
  70.                                                 <thead>
  71.                                                         <td class="testList-score">Балл
  72.                                                         </td>
  73.                                                        
  74.                                                         <td class="testList-user-name">Имя
  75.                                                         </td>
  76.                                                        
  77.                                                         <td class="testList-position">Место
  78.                                                         </td>
  79.                                                 </thead>
  80.                                                
  81.                                                 <tbody>
  82.                                                         <?asort($arAttemptScore);//сортируем очки по возрастанию
  83.                                                        
  84.                                                         $attemptCount = 0;?>
  85.                                                        
  86.                                                         <?while (($element = current($arAttemptScore)) && ($attemptCount != 5)){//проходим по 5ти первым элементам массива
  87.                                                                 $key = key($arAttemptScore);//номер попытки
  88.                                                                 $f_USER_NAME = explode(")", $arUsers[$key]);//извлекаем имя пользователя?>
  89.                                                                 <tr>
  90.                                                                         <td class="testList-user-score"><?=$arAttemptScore[$key]?>
  91.                                                                         </td>
  92.                                                                                
  93.                                                                         <td class="testList-user-name"><?=$f_USER_NAME[1]?>
  94.                                                                         </td>
  95.                                                                        
  96.                                                                         <td class="testList-position"><?echo (1 + $attemptCount);?>
  97.                                                                         </td>
  98.                                                                 </tr>
  99.                                                                
  100.                                                                 <?$attemptCount++;
  101.                                                                 next($arAttemptScore);//переводим фокус
  102.                                                         }?>
  103.                                                 </tbody>
  104.                                         </table>
  105.                                 </td>
  106.                         </tr>
  107.                        
  108.                         <tr>
  109.                                 <td class="testList-bottom-best">&nbsp;</span></td>
  110.                                 <td class="testList-bottom-bad">&nbsp;</td>
  111.                         </tr>
  112.                 </table>
  113.         </div>
  114.        
  115.         <?unset($arUsers,$arAttemptByDate,$arAttemptScore);//очищаем переменные?>
  116.        
  117. <?}//конец вывода тестов?>Syhi-подсветка кода

И для лучших попыток:

  1. <?if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?>
  2.  
  3. <?$testList = CTest::GetList(
  4.         Array("SORT"=>"ASC"),
  5.         Array("ACTIVE" => "Y", "MIN_PERMISSION" => "R")
  6. );//получаем список тестов
  7.        
  8. while ($arTest = $testList->GetNext()){?>
  9.         <div id="testList">
  10.                 <h2><?=$arTest[‘NAME’]?></h2>
  11.                 <table class="testList-table">
  12.                         <tr>
  13.                                 <td class="testList-best-top"><span>Лучшие результаты</span></td>
  14.                                 <td class="testList-bad-top"><span>Худшие результаты</span></td>
  15.                         </tr>
  16.                        
  17.                         <tr class="testList-result">
  18.                                 <td class="testList-result-best">
  19.                                         <table class="testList-result-table">
  20.                                                 <thead>
  21.                                                         <td class="testList-position">Место
  22.                                                         </td>
  23.                                                        
  24.                                                         <td class="testList-user-name">Имя
  25.                                                         </td>
  26.                                                        
  27.                                                         <td class="testList-score">Балл
  28.                                                         </td>
  29.                                                 </thead>
  30.                                                
  31.                                                 <tbody>
  32.                                                         <?$attemptListByDate = CTestAttempt::GetList(
  33.                                                                 Array("SCORE" => "DESC","DATE_START" => "ASC"),
  34.                                                                 Array("TEST_ID" => $arTest[‘ID’],"STATUS" => "F")
  35.                                                         );//получаем список попыток по дате
  36.                                                        
  37.                                                         while ($arAttemptByDate = $attemptListByDate->GetNext()){
  38.                                                                 if(!in_array($arAttemptByDate[‘USER_NAME’],$arUsers)){//проверяем уникальность попытки
  39.                                                                         if(($arAttemptByDate[‘SCORE’] != "") && ($arAttemptByDate[‘SCORE’] != "0")){
  40.                                                                                 $arUsers[] = $arAttemptByDate[‘USER_NAME’];
  41.                                                                                 $arAttemptScore[] = $arAttemptByDate[‘SCORE’];
  42.                                                                         }
  43.                                                                 }
  44.                                                         }//создаём массив попыток
  45.                                                        
  46.                                                         arsort($arAttemptScore);//сортируем очки по убыванию
  47.                                                        
  48.                                                         $attemptCount = 0;
  49.                                                        
  50.                                                         while (($element = current($arAttemptScore)) && ($attemptCount != 5)){//проходим по 5ти первым элементам массива
  51.                                                                 $key = key($arAttemptScore);//номер попытки
  52.                                                                 $f_USER_NAME = explode(")", $arUsers[$key]);//извлекаем имя пользователя?>
  53.                                                                 <tr>
  54.                                                                         <td class="testList-position"><?echo (1 + $attemptCount);?>
  55.                                                                         </td>
  56.                                                                                
  57.                                                                         <td class="testList-user-name"><?=$f_USER_NAME[1]?>
  58.                                                                         </td>
  59.                                                                                
  60.                                                                         <td class="testList-user-score"><?=$arAttemptScore[$key]?>
  61.                                                                         </td>
  62.                                                                 </tr>
  63.                                                                
  64.                                                                 <?$attemptCount++;
  65.                                                                 next($arAttemptScore);//переводим фокус
  66.                                                         }?>
  67.                                                        
  68.                                                 </tbody>
  69.                                         </table>
  70.                                 <td class="testList-result-bad">
  71.                                         <table class="testList-result-table">
  72.                                                 <thead>
  73.                                                         <td class="testList-score">Балл
  74.                                                         </td>
  75.                                                        
  76.                                                         <td class="testList-user-name">Имя
  77.                                                         </td>
  78.                                                        
  79.                                                         <td class="testList-position">Место
  80.                                                         </td>
  81.                                                 </thead>
  82.                                                
  83.                                                 <tbody>
  84.                                                         <?asort($arAttemptScore);//сортируем очки по возрастанию
  85.                                                        
  86.                                                         $attemptCount = 0;?>
  87.                                                        
  88.                                                         <?while (($element = current($arAttemptScore)) && ($attemptCount != 5)){//проходим по 5ти первым элементам массива
  89.                                                                 $key = key($arAttemptScore);//номер попытки
  90.                                                                 $f_USER_NAME = explode(")", $arUsers[$key]);//извлекаем имя пользователя?>
  91.                                                                 <tr>
  92.                                                                         <td class="testList-user-score"><?=$arAttemptScore[$key]?>
  93.                                                                         </td>
  94.                                                                                
  95.                                                                         <td class="testList-user-name"><?=$f_USER_NAME[1]?>
  96.                                                                         </td>
  97.                                                                        
  98.                                                                         <td class="testList-position"><?echo (1 + $attemptCount);?>
  99.                                                                         </td>
  100.                                                                 </tr>
  101.                                                                
  102.                                                                 <?$attemptCount++;
  103.                                                                 next($arAttemptScore);//переводим фокус
  104.                                                         }?>
  105.                                                 </tbody>
  106.                                         </table>
  107.                                 </td>
  108.                         </tr>
  109.                        
  110.                         <tr>
  111.                                 <td class="testList-bottom-best">&nbsp;</span></td>
  112.                                 <td class="testList-bottom-bad">&nbsp;</td>
  113.                         </tr>
  114.                 </table>
  115.         </div>
  116.        
  117.         <?unset($arUsers,$arAttemptByDate,$arAttemptScore);//очищаем переменные?>
  118.        
  119. <?}//конец вывода тестов?>Syhi-подсветка кода

Внешне это выглядит вот так (все фамилии вымышлены совпадения случайны)

Bitrix - лучшие и худшие результаты тестов

Bitrix - лучшие и худшие результаты тестов

Такая табличка выводится на каждый тест, к которому имеет доступ пользователь.

Итог

В результате получилась классная пузомерка, хорошо мотивирующая сотрудников искать правильные ответы на тесты.

3 комментария

Вячеслав

Максим, подскажите как отобразить общий топ по всем попыткам? Задача была поставлена по кастомизации компонента профайла, таким образом чтобы к профайлу каждого сотрудника привязать результат прохождения тестов таким образом, чтобы этот результат был доступен каждому сотруднику. Заранее благодарен.

Ответить

murzix

За попытки отвечает класс CTestAttempt у которого есть метод GetList.

Ему нужно передать идентификатор студента, который можно получить воспользовавшись методом GetList класса CStudent. USER_ID текущего пользователя у вас в профиле есть.

Если вы не продумаете как скрыть эту информацию, то она будет доступна всем =)

P.S. не смотрите на код, который написан выше, так писать не стоит =)

Ответить

Сергей

И еще подскажите пожалуйста. У меня порядка 6-8 вопросов в тесте и у каждого по 10 предположительных ответов заполнено. Как можно выводить например по 5 рандомно ?

Ответить

Ваш отзыв

logo