Доброго времени суток всем. Это моя первая запись про веб-программирование, в ней я расскажу о том, как реализовывал тестирование на знание английского языка для сайта языкового клуба в Челябинске. Писал на небезызвестном языке программирования, а именно PHP. Его я начал изучать незадолго до того, как создал этот самый блог, который часто использую в качестве «песочницы» для тестирования. Но ведь кроме песочницы, мой блог это еще и копилка знаний, поэтому сразу к делу!
Задача
Дать возможность посетителям сайта оценить свой уровень английского языка в режиме онлайн. Необходимо, чтобы ответ был получен сразу же, не привлекая к проверке живого человека. Признаюсь, первое и самое забавное решение, которое пришло мне в голову это отправлять заполненный тест преподавателю по почте(слава богу не голубиной), но это, конечно же, шутка. И самое главное желание, уже мое личное — не использовать плагины, написать все самому. Они создают лишнюю нагрузку, а мы хотим, чтобы даже на IE6 можно было пройти наш тест. А еще в них может быть вшит какой угодно вредоносный код и вообще я же программист, верно?
В тесте 40 вопросов, которые разбиты на 4 логические секции. К сожалению, они разной длины, это чуть усложнило исходный код. Каждая секция оценивается отдельно, в итоге пользователю сообщается о его уровне в каждой секции. У вопроса 4 варианта ответа, один верный.
Кроме того, нужно продумать, как убирать тест со страницы после отправки ответов. Чтобы крупным планом был результат и не было возможности исправить ответ, а только начать проходить тест заново.
Реализация
Приступим к реализации. Писать я твердо решил на PHP, не привлекая JavaScript и прочие радости. Все вопросы было решено поместить в форму и прилепить к ним кнопку «отправить результаты». Варианты ответа в виде радиокнопок, чтобы хитрецы не выбирали все подряд. Списки вопросов, вариантов ответа и правильные ответы были мной заботливо переписаны в массивы. Из файла читать я не захотел, хотя это было бы разумнее и красивее. Все мое внимание было сосредоточено на функции проверки результатов. Вот, как выглядит вывод вопросов на страницу. Определение массивов я стер, оставил только объявление.
Исходный код на php
$questions = array(
/* Один вопрос - один элемент массива */
);
$answers = array(
/* Один вариант ответа - один элемент массива */
);
//Value радиокнопок с правильными ответами
$keys = array("q0b", "q1b", "q2c", "q3d", "q4d", "q5c", "q6c", "q7a", "q8b", "q9d", "q10b", "q11b", "q12a", "q13a", "q14c", "q15b", "q16a", "q17d", "q18b", "q19a", "q20c", "q21c", "q22a", "q23a", "q24c", "q25b", "q26b", "q27c", "q28a", "q29b", "q30a", "q31c", "q32d", "q33a", "q34a", "q35c", "q36b", "q37c", "q38a", "q39b");
//Приветствие, либо результаты
if($showResults == False) {
echo "<p>Здравствуйте, ниже вам будет предложено ответить на 40 вопросов с вариантом выбора ответа. В каждом вопросе только один правильный вариант ответа, время на прохождение теста не ограничено. По результатам вам будет присвоен предварительный уровень подготовки по английскому языку. Удачи!</p>
<h2>Choose the best word or phrase (a, b, c or d) to fill each blank.<br></h2>";
}
else {
echo "<p>Ваши результаты:</p>";
}
//Отображение теста
if($showResults == False) {
echo "<form method='post'>";
for($i = 0; $i < count($questions); $i++) {
if($i == 0) {
echo "<h2>Section 1</h2>";
}
else if($i == 12) {
echo "<h2>Section 2</h2>";
}
else if($i == 20) {
echo "<h2>Section 3</h2>";
}
else if ($i == 32) {
echo "<h2>Section 4</h2>";
}
echo "<p>", $questions[$i], "</p>";
for($j = $i * 4; $j < $i * 4 + 4; $j++) {
echo '<input type="radio" name="q'.$i.'" value="q'.$i.$answers[$j][0].'" />'.$answers[$j];
}
}
echo '<br>';
echo "<input type='submit' value='Посмотреть результат'>";
echo "</form>";
}
Тест заполняется, пользователь нажимает на кнопку и в бой вступает алгоритм подсчета правильных ответов. Сравниваем ответ, полученный от формы с правильным и инкрементируем нужный счетчик. Вот сам алгоритм:
//Считаем правильные ответы
$numberOfRightAns = array(0, 0, 0, 0); //Количество правильных ответов в каждой из 4 секций
for($num = 0; $num < count($questions); $num++) {
if(isset($_POST['q'.$num])) {
if($_POST['q'.$num] == $keys[$num]) {
if($num < 12) { /* Section 1 */
$numberOfRightAns[0]++;
}
else if($num < 20) { /* Section 2 */
$numberOfRightAns[1]++;
}
else if($num < 32) { /* Section 3 */
$numberOfRightAns[2]++;
}
else { /* Section 4 */
$numberOfRightAns[3]++;
}
}
}
}
//Делаем вывод о результатах теста
$langLevel = array('', '', '', '');
for($i = 0; $i < count($numberOfRightAns); $i++) {
switch ($i) {
case 0:
if($numberOfRightAns[$i] < 6) {
$langLevel[$i] = 'Starter';
}
else if($numberOfRightAns[$i] < 9) {
$langLevel[$i] = 'Elementary';
}
else if($numberOfRightAns[$i] < 10) {
$langLevel[$i] = 'Pre-intermediate';
}
else {
$langLevel[$i] = 'Intermediate';
}
break;
case 1:
if($numberOfRightAns[$i] < 3) {
$langLevel[$i] = 'Starter';
}
else if($numberOfRightAns[$i] < 5) {
$langLevel[$i] = 'Elementary';
}
else if($numberOfRightAns[$i] < 6) {
$langLevel[$i] = 'Pre-intermediate';
}
else {
$langLevel[$i] = 'Intermediate';
}
break;
case 2:
if($numberOfRightAns[$i] < 3) {
$langLevel[$i] = 'Starter';
}
else if($numberOfRightAns[$i] < 5) {
$langLevel[$i] = 'Elementary';
}
else if($numberOfRightAns[$i] < 8) {
$langLevel[$i] = 'Pre-intermediate';
}
else {
$langLevel[$i] = 'Intermediate';
}
break;
case 3:
if($numberOfRightAns[$i] < 3) {
$langLevel[$i] = 'Starter';
}
else if($numberOfRightAns[$i] < 4) {
$langLevel[$i] = 'Elementary';
}
else if($numberOfRightAns[$i] < 7) {
$langLevel[$i] = 'Pre-intermediate';
}
else {
$langLevel[$i] = 'Intermediate';
}
break;
}
}
//Сообщаем результаты и предлагаем пройти тест еще раз
if($showResults == True) {
for($i = 0; $i < count($langLevel); $i++) {
echo "<p>In section ", $i + 1, ": ", $langLevel[$i], "</p>";
}
echo "<form method='post'>";
echo "<input type='submit' value='Пройти тест еще раз'>";
echo "</form>";
}
Как вы могли заметить, самая интересная особенно, а именно сокрытие теста после отправки результатов, была реализована самым обыкновенным флагом $showResults. Люблю использовать флаги, ничего не могу с собой поделать. Если при отправке в форме был хоть один ответ, мы считаем и показываем результаты.
//Флаг, что показывать в данный момент, тест или результаты
$showResults;
//Пробежать по всем радиокнопкам и посмотреть есть ли хоть один ответ, если есть, то показать результаты теста
for($i = 0; $i < count($keys); $i++) {
if(isset($_POST['q'.$i])) {
$showResults = True;
break;
}
else {
$showResults = False;
}
}
Заключение
Задача выполнена, посетитель может оценить свои знания и тем самым повысить в себе уверенность и записаться в группу, в теории. На практике, конечно, уверенность может и упасть из-за плохих результатов, но это уже не наша с вами забота. Кроме того, появился дополнительный повод задержаться на сайте, кроме просмотра контактов и карты.
Слабое место моей реализации это массивы с вопросами, ответами и ключами. Если структура теста внезапно поменяется, будет не так уж и просто перебить все данные в массивах. Решение я тут вижу одно: поместить вопросы и ответы в отдельный файл и регламентировать его формат, дабы все изменения в структуре были совсем незаметны для нашего php кода.
На этом все, спасибо за внимание!