<?php

abstract class AbstractQuestion {
	public $text;			//текст вопроса
	public $correctAnswer;	//правильный ответ
	public $points;			//баллы за правильный ответ
	
	public function __construct($text, $correctAnswer, $points = 5) {
		$this->text= $text;
		$this->correctAnswer= $correctAnswer;
		$this->points= $points;
	}
	abstract function showQuestion();
	abstract function checkAnswer($answer);
}

class ChoiceQuestion extends AbstractQuestion {
	public $options;		// варианты ответов
	public function showQuestion() {
		echo "\n{$this->text}\n";
    	foreach($this->options as $key => $option) {
    		echo "  {$key}. {$option}\n";
    	}
	}
	
	public function checkAnswer($answer) {
	    if($this->correctAnswer == $answer) {
	    	return true;
	    } else {
	    	return false;
	    }
	}
}

class NumericQuestion extends AbstractQuestion {
	public $deviation;	// допустимая погрешность
	
	public function showQuestion() {
		echo "\n{$this->text}\n";
	}
	
	public function checkAnswer($answer) {
	    $plusDeviation = $this->correctAnswer + $this->deviation;
	    $minusDeviation = $this->correctAnswer - $this->deviation;
	
	    /*проверяем совпадает или ответ с правильным или входит ли он в диапазон погрешности*/
		if (($this->correctAnswer == $answer) || (($answer <= $plusDeviation) && ($answer >= $minusDeviation))) {
			return true;
	    } else {
	    	return false;
	    }
	}
}

function createQuestions() {
	$questions = array();
			
	$q1 = new ChoiceQuestion("Какая планета располагается четвертой по счету от Солнца?", 'b');
	$q1->options = array('a' => 'Венера', 'b' => 'Марс', 'c' => 'Юпитер', 'd' => 'Меркурий');
	
	$questions[] = $q1;
	
	$q2 = new NumericQuestion("Чему равна скорость света в км/с?", 300000, 20);
	$q2->deviation = 20000;
	
	$questions[] = $q2;
	
	return $questions;
}

function showQuestions($questions) {
  foreach ($questions as $question) {
    $question->showQuestion();
  } 
}

function checkAnswers($questions, $answers) {
	

	$pointsTotal = 0;		// баллов набрано
	$pointsMax = 0; 		// сколько вообще можно набрать
	$correctAnswers = 0;	// сколько отвечено верно
	$totalQuestions = count($questions); //всего вопросов

	for($i = 0; $i < count($questions); $i++) {
		$currentQuestion = $questions[$i];
		$currentAnswer = $answers[$i];
	
		$pointsMax += $currentQuestion->points;
	
		if ($currentQuestion->checkAnswer($currentAnswer)) {
			$correctAnswers++;
			$pointsTotal += $currentQuestion->points;
		} else {
			$number = $i + 1;
			echo "\nНеправильный ответ на вопрос №{$number}: {$currentQuestion->text}\n";
		}
	}
	echo "Правильных ответов {$correctAnswers} из {$totalQuestions}, баллов набрано: {$pointsTotal} из {$pointsMax}";
}

$questions = createQuestions();  
showQuestions($questions); 

$answers = array('b', 320001);

checkAnswers($questions, $answers);