preloading articles

Реалізація тесту "English Word"

Навчальний матеріал: Розглядається зв'язок "AJAX запит до Бази Даних"

листопад 2015

ЗАВДАННЯ: Сконструювати веб-сторінку тесту "English Word", застосовуючи jQuery, PHP, MySQLi.

Час проведення тесту 30 секунд.

Вихідні дані: таблиця БД "English_Word" пар слів:



id_wordwhat_wordcorrect_word
1ConcludeВисновок
2ConsiderPозглядати
3CompriseBключати
.........
.........
nHandleOбробляти

Зміст


1. Демо-тест.
2. Алгоритм роботи скрипту.
3. Графіка таймеру.
4. Відправлення AJAX-запитів до PHP-обробника.
5. Серверна частина. PHP-обробник..
6. Коди веб-сторінки тесту.
Заключення :)



1. Демо "English Word. Verb."

Спробуйте вказати максимальну кількість коректних відповідей перекладу пари слів за 30 секунд...

Наприклад,
правильна відповідність пари слів:
"explore - досліджувати"
неправильна відповідність:
"explore - турбувати"

              

можна використовувати клавіші "вліво", "вправо"

   Показати пари слів

   
    1 Conclude Висновок
    2 Explore Досліджувати
    3 Retrieve Витягувати
    4 Consider Pозглядати
    5 Comprise Bключати
    6 Establish Bстановити
    7 Recieve Отримувати
    8 Explain Пояснювати
    9 Customize Hалаштувати
    10 Decide Вирішувати
    11 Scratch Шкрябати
    12 Handle Oбробляти
    13 Violation Порушення
    14 Compare Порівнювати
    15 Suit Пасувати
    16 Offer Пропонувати
    17 Stuck Застрягати
    18 Afford Надавати
    19 Skip Пропускати
    20 Avoid Уникати
    21 Stick Приліпати
    22 Instruct Вчити
    23 Survey Огляд
    24 Persist Наполягати
    25 Remark Помічати
    26 Refuse Відмовляти
    27 Retreat Відступати
    28 Vanish Зникати
    29 Pour Наливати
    30 Encourage Заохочувати
    31 Capture Захоплення
    32 Occur Траплятися
    33 Alter Змінювати
    34 Approval Схвалення
    35 Enchant Зачаровувати
    36 Obstruct Перешкоджати
    37 Annoy Дратувати
    38 Attempt Пробувати


2. Алгоритм роботи тесту "English Word"

алгоритм роботи тесту

Рис.1. Структура взаємозвязку основних блоків тесту

Коротко про роботу основних блоків, що необхідні для реалізації тесту.

Блок 1 - початкова веб-сторінка, саме за станом подій веб-сторінки відслідковує скрипт блоку 2. Блок 2 контролює чи користувач активував кнопки HTML-сторінки такі як: "Розпочати тест", "Правильно", "Неправильно" чи клавіші "Вліво", "Вправо". Якщо користував активував кнопку, відбувається AJAX-запит до серверу на опрацювання даних. Блок 3 - серверна частина, виконана логіка аналізу отриманих даних, та логіка обміну даних із таблицею Бази Даних.

Блок 4 представлений таблицею "English_word" Бази Даних:

id_wordwhat_wordcorrect_word
1ConcludeВисновок
2ConsiderPозглядати
3CompriseBключати
.........
.........
nHandleOбробляти

Коди всіх блоків, що необхідні для реалізації тесту, представлені в кінці статті.

3. Графічна частина таймеру

Графічна частина таймеру реалізована засобами jQuery та засобами HTML5 CANVAS.

Детальніше стаття Реалізація годинникового таймеру із застосуванням бібліотеки jQuery та елементу HTML5 CANVAS

4. Відправлення AJAX запитів тесту

Коротко суть: В поле тесту потрібно генерувати HTML сторінку відповідно до алгоритму PHP обробника, згенерувати можемо застосовуючи ajax метод:


 $(selector).load(URL,data,callback);
Відправлення AJAX запитів тесту

Рис.2. AJAX запити до PHP-обробника

Реалізувати Ajax запити тесту можна за слідуючою схемою:
- Якщо юзер активує кнопку "Розпочати тест", то формуємо ajax запит лиш з одним даним quiz='start'
частина коду може мати вигляд:


// AJAX запит початку тесту
var quiz = 'start';
$( '.example_test' ).load( 'english_quiz.php',{quiz});

- коли відповідає на пари слів, може бути варіант правильна відповідність слів, то формуємо ajax запит даним quiz='correct'
- коли відповідає на пари слів, може бути варіант неправильна відповідність слів, ajax запит з одним даним quiz='incorrect'
- та коли час вийшов, маємо можливість відправити запит із диними quiz='finish'

PHP-обробник отримавши відповідний $_POST['quiz'] формує відповідну HTML сторінку
частина коду може мати виглд:


<?php

Some function...
...
// отримуємо дані AJAX запиту
$quiz=$_POST['quiz'];

//формуємо першу пару слів

if ($quiz=="start") {

  // початкові дані тесту
  ...  
  // комірка для індикатора веб-сторінки
  // правильної відповіді юзера
  $_SESSION["user_number_correct_word"] = 0;
  
  // початковий рівень знань
  echo '<div class="show_your_result">
          <div class="one_right_item"></div>
          <div class="clear"></div>
          </div>';
  
  // вибір слова
  Choose_Word ();
  
  //виводимо пару слів
  Show_Word($what_word,$quiz_word);  
};

//блок що виконується, якщо юзер правильно відповів
if ( $quiz == "correct" ) {
   Check_Word(1);
   Choose_Word ();   
   Show_Word($what_word,$quiz_word);
};

//блок що формується, якщо юзер непраильно відповів
if ( $quiz == "incorrect" ) {
  Check_Word(0);
  Choose_Word ();  
  Show_Word($what_word,$quiz_word);
};

?>

Вибір слів тесту. Скрипт jQuery.

Реалізація деяких елементів тесту веб-сторінки вимагає застосування можливостей бібліотеки jQuery. Так, наприклад, щоб реалізувати для зручності вибір відповіді "Правильно/неправильно" тесту застосовуються клавіші "Вліво", "Вправо" клавіатури. Активуючи відповідні клавіші відправляємо AJAX-запити до PHP-обробника.
Ця частина скрипту, має вигляд:


$( document ).keydown(function( event ) {
  if ( event.which == 37 ) {  
    $( '#right_word' ).css("box-shadow","1px 5px 14px #2e9c03");
    $( '#wrong_word' ).css("box-shadow","1px 5px 14px #6ed147");
    quiz='correct';              	  
    $( '.example_test' ).load( 'english_quiz.php',{quiz});
  };

  if ( event.which == 39 ) {   
    $( '#wrong_word' ).css("box-shadow","1px 5px 14px #2e9c03");
    $( '#right_word' ).css("box-shadow","1px 5px 14px #6ed147");
    quiz='incorrect';              	  
    $( '.example_test' ).load( 'english_quiz.php',{quiz});
  };
  
}); 

Активація/деактивація кнопок тесту та зміна CSS стилю. Скрипт jQuery.

Кнопки тесту "Розпочати тест", "Правильно", "Неправильно" активні чи навпаки не активні в залежності від стану тесту. Зрозуміло, що якщо тест не активований, то нема на що і відповідати чи наприклад під час тесту недоречно запускати додатково ще один тест. Тобто необхідно виключити можливість активації "нелогічних" кнопок.

Дане питання можна вирішити застосовуючи можливості jQuery, якщо наприклад необхідно деактивувати кнопки:


// деактивуємо кнопки відповіді до початку тесту
$('#right_word').prop('disabled', true);
$('#wrong_word').prop('disabled', true);

// змінюємо колір кнопок
$('#right_word').addClass('disable_test');
$('#wrong_word').addClass('disable_test');

Чи навпаки активувати кнопки:


// деактивуємо кнопку старт до слідуючого тесту
$('#start_test').prop('disabled', true);
$('#start_test' ).addClass('disable_test');
      
// активуємо кнопки відповіді 
$('#right_word').prop('disabled', false);
$('#wrong_word').prop('disabled', false);

// повертаємо попередній вигляд кнопок (активні)      
$('#right_word' ).removeClass('disable_test');
$('#wrong_word' ).removeClass('disable_test');

5. Серверна частина. PHP-обробник.

PHP-обробник. Функція Choose_Word()

Php-обробник повинен формувати випадковим чином пари слів із таблиці "English_word" Бази Даних, що як на мене досить легко реалізувати. Вищепредставлений тест працює за слідуючим алгоритмом:
1. Беремо випадкове число від 0 до 100.
2. Імовірність вибору скриптом коректної пари слів перекладу візьмем 30%.
    Тобто, якщо випадкове число менше 30% - коректний переклад слів.
3. Якщо випадкове число більше 30% - скрипт виводить на сторінку невідповідну пару слів таблиці.

Варто сказати, що для збереження статистичних даних використаємо можливості PHP Sessions.

Приклад виконання функції php-скрипту:


// функція вибору слова
function Choose_Word (){

  // зєднуємось із сервером БД
  $mysqli = new mysqli( дані доступу до БД);
  mysqli_set_charset($mysqli, "utf8");
        
  // визначаємо слова для тесту	  
  // правильна відповідність слів за умови, якщо випадкове число менше 30%   
   $random_word=rand(1,100);    

  //вибираємо слово, що будемо відгадувати - what_word
  $res = $mysqli->query("SELECT * FROM `english_word`
			ORDER BY RAND()
			LIMIT 1;");
  $row = $res->fetch_assoc();

  // формуємо слова тесту random менше 30%
  if ($random_word<30){
           
    $GLOBALS['what_word'] = $row['what_word']; // англійське слово, що задаємо
    $GLOBALS['quiz_word'] = $row['correct_word']; // варіант перекладу
    
    //зберігаємо мітку слова в сесії для подальшої перевірки відповіді юзера
    $_SESSION["correct_translate"] = 1;
    
    // рахуємо кількість пар слів для статистики
    $_SESSION["count_all_word"]++;
              
    // формуємо неправильну відповідність слів (випадкове число більше 30%)  
  } else {
     $result = $mysqli->query("SELECT * FROM `english_word`
	 		ORDER BY RAND()
			LIMIT 1;");
     $row_other_word = $result->fetch_assoc();
   
     // формуємо слова тесту random більше 30%
     $GLOBALS['what_word'] = $row['what_word']; // англійське слово, що задаємо
     $GLOBALS['quiz_word'] = $row_other_word['correct_word']; // варіант перекладу
     
     //зберігаємо мітку слова в сесії для подальшої перевірки відповіді юзера
     $_SESSION["correct_translate"] = 0;
    
     // раптом інше випадкове слово всеж попаде на правильний переклад
     // тоді вкажемо що переклад коректний
     
     if ($row['id_word'] == $row_other_word['id_word']){
       // мітка слова в сесії для подальшої перевірки відповіді юзера
       $_SESSION["correct_translate"] = 1;
     };    
    
    // рахуємо кількість пар слів для статистики
    $_SESSION["count_all_word"]++;
    
  };
   
  // закриваємо зєднання з БД      
  $mysqli->close();      
        
};

PHP-обробник. Функція Check_Word()

Щодо перевірки правильної відповіді юзера, реалізована функція Check_Word.
Працює функція за простим алгоритмом: Ідея перевірки відповіді юзера полягає в слідуючому: 1. Під час створення пари слів випадковим числом, записуємо правильну пару як $_SESSION["correct_translate"] = 1, а неправильну пару слів як $_SESSION["correct_translate"] = 0. В поле функції Check_Word() передаємо відповідь юзера $answer, що приймає значення 1, якщо юзер на веб-сторінці активував кнопку "правильно" та $answer має значення 0, якщо активовано "Неправильно".

Задля більшого інтересу користувача функція Check_Word() також формує індикатор кількості безперервно правильних відповідей користувача, знову ж використовуючи PHP Sessions.


// функція перевірки відповіді
function Check_Word($answer){
  // перевіряємо чи була задана правильна відповідність пари слів юзеру 
  // та отримана правильна відповідь
  
  if ($_SESSION["correct_translate"] == $answer){
    // рахуємо слова для індикатора 
    $_SESSION["user_number_correct_word"]++;
    // рахуємо всі правильні слова
    $_SESSION["user_number_all_correct_word"]++;
  }else{
  // обнуляємо індикатор
  $_SESSION["user_number_correct_word"] = 0;
  };
  
  // формуємо індикатор правильних відповідей
  echo '<div class="show_your_result">';
  for ($i = 1; $i <= $_SESSION["user_number_correct_word"]; $i++){
      echo '<div class="one_right_item"></div>';
  };
  echo '<div class="clear"></div></div>';
};

Що ж здається основні блоки тесту переглянув, та висвітив своє бачення в реалізації тесту "English Word". Все інші можливі моменти роботи скриптів вважаю досить легко розуміються.

6. Теги, коди веб сторінки тесту "English Word".

HTML

   

	
// область для виведення тесту
<div class="result_test">
	
<div id="for_time"></div>
	   
<canvas id="canvas_area" width="200px" height="150px"></canvas>
	   
<div class="example_test">
  <p>Вкажіть коректну відповідь пар слів за 30 секунд...</p>
  <p>Наприклад,
  правильна відповідність пари слів:
  "explore - досліджувати"
  неправильна відповідність:
  "explore - турбувати"
</div>
	   
<div id="quiz_button">			
  <button id="right_word">Правильно</button>
  <button id="wrong_word">Неправильно</button>	  				  			
</div>
	         
<div class="for_button">
  <button onclick="Start_Timer()">Розпочати тест</button>
</div>  
	    
</div>
	

jQuery він же javascript

   

частина скрипту розміщена в голові HTML-документу
<script>
$( document ).ready(function() {
      
  $('#right_word').click(function() {	  
    var quiz='correct';              	  
    $(".example_test").load("exe_english_quiz_forum_community.php",{quiz}); 	 
  });
       
  $('#wrong_word').click(function() {	  
    var quiz='incorrect';            	  
    $(".example_test").load("exe_english_quiz_forum_community.php",{quiz}); 	 
   });
</script>

скрипт розміщений після блоку div id=result_test	
<script>
var canvas = document.getElementById("canvas_area");
var ctx = canvas.getContext("2d");
    
// деактивуємо кнопки відповіді до початку тесту
  $('#right_word').prop('disabled', true);
  $('#wrong_word').prop('disabled', true);
  $('#right_word' ).addClass( 'disable_test' );
  $('#wrong_word' ).addClass( 'disable_test' );
    
  ctx.beginPath();
// повертаємо контейнер на -90°
  ctx.rotate(-90*Math.PI/180);
//та дещо зміщуємо всторону контейнер;
  ctx.translate(-150, 0);
  ctx.lineWidth = 20;
  ctx.strokeStyle = "#CDCDCD";
  ctx.shadowBlur=20;
  ctx.shadowColor="#CDCDCD";
  ctx.arc(75,75,50,0,2*Math.PI);
  ctx.stroke();
  ctx.beginPath();
    
  var timer;
  var Estimated_Time;
  var Timer_Element;
  var Clock_Estimated_Time;
    
//ініціалізуємо
  function init(){
    Estimated_Time = 10;
    Timer_Element = 2 / Estimated_Time;
    Clock_Estimated_Time = 0;
  };
    
  init();   
        
  //позиціонуємо цифри
  $( "#for_time" ).text( Estimated_Time);
   
// запускаємо та малюємо графіку таймеру		
  function Msg_Timer(){
   Estimated_Time--;
   if (Estimated_Time == 0){  	
      Stop_Test();      	
   };
   $( "#for_time" ).text(Estimated_Time);
   Clock_Estimated_Time = Clock_Estimated_Time + Timer_Element;   
   ctx.beginPath();
   ctx.clearRect(0,0,200,150);   
   ctx.lineWidth = 20;
   ctx.strokeStyle = "#CDCDCD";
   ctx.shadowBlur=20;
   ctx.shadowColor="#CDCDCD";
   ctx.arc(75,75,50,0,2*Math.PI);
   ctx.stroke();
   ctx.beginPath();
   ctx.strokeStyle = "#2ade2a"; 
   ctx.lineWidth = 15; 
   ctx.shadowBlur = 18;
   ctx.shadowColor="#079907"; 
   ctx.arc(75,75,50,0,Clock_Estimated_Time*Math.PI);
   ctx.stroke();	
 };	
  
  
// функція активації тесту
  function Start_Test() {  
  init(); 
     
// деактивуємо кнопку старт до слідуючого тесту
   $('#start_test').prop('disabled', true);
   $('#start_test' ).addClass('disable_test');
      
// активуємо кнопки відповіді 
   $('#right_word').prop('disabled', false);
   $('#wrong_word').prop('disabled', false);
   $('#right_word' ).removeClass('disable_test');
   $('#wrong_word' ).removeClass('disable_test');
    
   timer = setInterval(Msg_Timer, 1000);      
     
// AJAX запит початку тесту
   var quiz = 'start';
   $(".example_test").load("exe_english_quiz_forum_community.php",{quiz});      
  };   
   
// функція закінчення тесту 
   function Stop_Test() {
    clearInterval(timer);
    
   //активуємо кнопку старт для слідуючого тесту
   $('#start_test').prop('disabled', false);
   $('#start_test' ).removeClass('disable_test'); 
    
   // деактивуємо кнопки відповіді до початку тесту
   $('#right_word').prop('disabled', true);
   $('#wrong_word').prop('disabled', true);
   $('#right_word').addClass('disable_test');
   $('#wrong_word').addClass('disable_test');  
     
   // AJAX запит закінчення тесту
   var quiz = 'finish';
   $(".example_test").load("exe_english_quiz_forum_community.php",{quiz});
    
  };
	
</script>	

PHP обробник

   

<?php
 
// Start the session
session_start();

// функція вибору слова
function Choose_Word (){
  $mysqli = new mysqli( дані доступу до БД);
  mysqli_set_charset($mysqli, "utf8");
        
  // визначаємо слова для тесту	  
  // правильна відповідність слів за умови, якщо випадкове число менше 30%   
   $random_word=rand(1,100);    

  //вибираємо слово, що будемо відгадувати - what_word
  $res = $mysqli->query("SELECT * FROM `english_word`
			ORDER BY RAND()
			LIMIT 1;");
  $row = $res->fetch_assoc();

  // формуємо слова тесту random менше 30%
  if ($random_word<30){
           
    $GLOBALS['what_word'] = $row['what_word']; // англійське слово, що задаємо
    $GLOBALS['quiz_word'] = $row['correct_word']; // варіант перекладу
    
    //зберігаємо мітку слова в сесії для подальшої перевірки відповіді юзера
    $_SESSION["correct_translate"] = 1;
    
    // рахуємо слова
    $_SESSION["count_all_word"]++;
              
    // формуємо неправильну відповідність слів (випадкове число більше 30%)  
  } else {
     $result = $mysqli->query("SELECT * FROM `english_word`
	 		ORDER BY RAND()
			LIMIT 1;");
     $row_other_word = $result->fetch_assoc();
   
     // формуємо слова тесту random більше 30%
     $GLOBALS['what_word'] = $row['what_word']; // англійське слово, що задаємо
     $GLOBALS['quiz_word'] = $row_other_word['correct_word']; // варіант перекладу
     
     //зберігаємо мітку слова в сесії для подальшої перевірки відповіді юзера
     $_SESSION["correct_translate"] = 0;
    
     // раптом інше випадкове слово всеж попаде на правильний переклад
     // тоді вкажемо що переклад коректний
     
     if ($row['id_word'] == $row_other_word['id_word']){
       $_SESSION["correct_translate"] = 1;
     };    
    
    // рахуємо слова
    $_SESSION["count_all_word"]++;
    
  };
        
  $mysqli->close();      
        
};

// функція перевірки відповіді
function Check_Word($answer){
  // перевіряємо чи була задана правильна відповідність пари слів юзеру 
  // та отримана правильна відповідь
  
  if ($_SESSION["correct_translate"] == $answer){
    // рахуємо слова для індикатора 
    $_SESSION["user_number_correct_word"]++;
    // рахуємо всі правильні слова
    $_SESSION["user_number_all_correct_word"]++;
  }else{
  // обнуляємо індикатор
  $_SESSION["user_number_correct_word"] = 0;
  };
  
  // формуємо індикатор правильних відповідей
  echo '<div class="show_your_result">';
  for ($i = 1; $i <= $_SESSION["user_number_correct_word"]; $i++){
      echo '<div class="one_right_item"></div>';
  };
  echo '</div>';
};

// функція виведення пар слів юзеру
function Show_Word($show_what,$show_quiz){
  echo  '<div class="what_word">
	    <p>English word:</p>
	    <h2>'.$show_what.'</h2>
	 </div>
	 <div class="quiz_word">
	    <p>Quiz word:</p>
	    <h2>'.$show_quiz.'</h2>
	</div#62;	
       ';
};

// отримуємо дані AJAX запиту
$quiz=$_POST['quiz'];

//формуємо першу пару слів
if ($quiz=="start") {

  // початкові дані тесту
  // мітка коректного перекладу пар слів
  // що задається випадковим числом даного тесту
  $_SESSION["correct_translate"] = 0;  
  
  // комірка для підрахунку кількості всіх слів
  $_SESSION["count_all_word"] = 0;
  
  // комірка для підрахунку кількості правильних
  // пар слів за час тесту
  $_SESSION["user_number_all_correct_word"] = 0;
  
  // комірка для індикатора веб-сторінки
  // правильної відповіді юзера
  $_SESSION["user_number_correct_word"] = 0;
  
  // початковий рівень знань
  echo '<div class="show_your_result">
          <div class="one_right_item"></div>
          <div class="clear"></div>
          </div>
  ';
  
  // вибір слова
  Choose_Word ();
  
  //виводимо пару слів
  Show_Word($what_word,$quiz_word);  
};

//блок що виконується, якщо юзер правильно відповів
if ( $quiz == "correct" ) {
   Check_Word(1);
   Choose_Word ();   
   Show_Word($what_word,$quiz_word);
};

//блок що формується, якщо юзер непраильно відповів
if ( $quiz == "incorrect" ) {
  Check_Word(0);
  Choose_Word ();  
  Show_Word($what_word,$quiz_word);
};

//формуємо закінчення тесту
if ( $quiz == "finish" ) {
  $all_word = $_SESSION["count_all_word"] - 1;
  
  //індикатор знань
  //результат тестування
  echo '<div class="show_your_result"><div class="one_right_item"></div>';
  for ($i = 1; $i <= $_SESSION["user_number_correct_word"]; $i++){
      echo '<div class="one_right_item"></div>';
  };
  echo '<div class="clear"></div></div>';
  
  echo '<h3>- Тест закінчено!<br>  
  Всього слів: '.$all_word.'<br>
  Правильних слів: '.$_SESSION["user_number_all_correct_word"].'</h3>';  
};   
	     
?>	


Заключення

Реалізація тесту "English Word" є досить миленьким практичним завданням, щоб розібратись яким ж чином можна реалізувати інтерактивну вебсторінку із Базою Даних.

Дещо повторю думку даного практичного завдання:
Скрипт jQuery відслідковує події веб-сторінки, і в залежності від того, що активував на сторінці користувач, відправляється ассинхронний запит до PHP-обробника на сервер. Обробник на сервері, з'єднується із Базою Даних формує результуючі дані та знову в залежності від отриманих даних ajax-запиту обробляє всі дані та формує область HTML-сторінки.

Більше того, в даному завданні також реалізований графічний таймер, що, вважаю, також дуже корисно :)

В цілому все досить легко.


Удачі в програмуванні! Анатолій...