Доброго времени суток всем. Это моя первая запись про веб-программирование, в ней я расскажу о том, как реализовывал тестирование на знание английского языка для сайта языкового клуба в Челябинске. Писал на небезызвестном языке программирования, а именно 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 кода.
На этом все, спасибо за внимание!