<?php

error_reporting(E_ALL);

abstract class AbstractQuestion
{
    public $text; // Текст вопроса
    public $points; // Количество баллов
    public $correctAnswer; // Правильный ответ

    /* Функция выводящая вопросы с ответами */  
    abstract function printQuestions($questions);
    /* Функция проверяющая ответы */
    abstract function checkAnswers($questions, $answers);
}

class MultipleChoiceQuestion extends AbstractQuestion
{
    public $points = 5; // По умолчанию 5 баллов
    public $answers; // Варианты ответов
    public $hint; // Подсказка

    public function printQuestions($questions) {
        $number = 1; // номер вопроса

        echo "\nВопросы с выбором варианта ответа:\n";

        foreach ($questions as $question) {

            echo "\n{$number}. {$question->text}\n\n";
            echo "Варианты ответов:\n";

            foreach ($question->answers as $letter => $answer) {
                echo " {$letter}. {$answer}\n";
            }
            $number++;

        }
    }
    public function checkAnswers($questions, $answers) {

        if (count($questions) != count($answers)) {
            die("Число ответов и вопросов не совпадает\n");
        }

        $pointsTotal = 0;
        $pointsMax = 0;
        $correctAnswers = 0; 
        $totalQuestions = count($questions);

        for ($i = 0; $i < count($questions); $i++) {
            $question = $questions[$i];
            $answer = $answers[$i];

            $pointsMax += $question->points;

            if ($answer == $question->correctAnswer) {
                $correctAnswers ++;
                $pointsTotal += $question->points;
            } else {
                $number = $i + 1;
                echo "\nНеправильный ответ на вопрос №{$number} ({$question->text})\n";
                echo "Подсказка: {$question->hint}\n";
            }
        }

        echo "Правильных ответов: {$correctAnswers} из {$totalQuestions}, баллов набрано: $pointsTotal из $pointsMax\n";
    }
}

class NumericalQuestion extends AbstractQuestion
{
    public $points = 10;
    public $deviation; // допустимая погрешность

    public function printQuestions($questions) {
        $number = 1;

        echo "\nВопросы с числовым ответом:\n";

        foreach ($questions as $question) {
                echo "\n{$number}. {$question->text}\n";
                $number++;
        }
    }
    public function checkAnswers($questions, $answers) {

        if (count($questions) != count($answers)) {
            die("Число ответов и вопросов не совпадает\n");
        }

        $pointsTotal = 0;
        $pointsMax = 0;
        $correctAnswers = 0; 
        $totalQuestions = count($questions);

        for ($i = 0; $i < count($questions); $i++) {
            $question = $questions[$i];
            $answer = $answers[$i];

            $pointsMax += $question->points;

            if ($answer == $question->correctAnswer) {
                $correctAnswers ++;
                $pointsTotal += $question->points;
            } else {
                $number = $i + 1;
                echo "\nНеправильный ответ на вопрос №{$number} ({$question->text})\n";
            }
        }

        echo "Правильных ответов: {$correctAnswers} из {$totalQuestions}, баллов набрано: $pointsTotal из $pointsMax\n";
    }
}

/* Создает пустой массив, наполяемый вопросами с множественным выбором */
function createMultipleChoiceQuestions() {

    $questions = [];

    $q = new MultipleChoiceQuestion;
    $q->text = "Какая планета располагается четвертой по счету от Солнца?";
    $q->points = 10;
    $q->answers = array('a' => 'Венера', 'b' => 'Марс', 'c' => 'Юпитер', 'd' => 'Меркурий');
    $q->correctAnswer = 'b';
    $q->hint = "Одноименное название носит шоколадный батончик.";

    $questions[] = $q;

    $q = new MultipleChoiceQuestion;
    $q->text = "Какой город является столицей Великобритании?";
    $q->answers = array('a' => 'Париж', 'b' => 'Москва', 'c' => 'Нью-Йорк', 'd' => 'Лондон');
    $q->correctAnswer = 'd';
    $q->hint = "%Городнейм% из кэпитал оф грейт британ.";

    $questions[] = $q;

    $q = new MultipleChoiceQuestion;
    $q->text = "Кто придумал теорию относительности?";
    $q->points = 30;
    $q->answers = array('a' => 'Джон Леннон', 'b' => 'Джим Моррисон', 'c' => 'Альберт Эйнштейн', 'd' => 'Исаак Ньютон');
    $q->correctAnswer = 'c';
    $q->hint = "Этим парнем был...";

    $questions[] = $q;

    return $questions;
}

/* Создает пустой массив, наполяемый вопросами с числовым ответами */
function createNumericalQuestions() {

    $questions = [];

    $q = new NumericalQuestion;
    $q->text = "Чему равна скорость света в км/с?";
    $q->correctAnswer = 300000;

    $questions[] = $q;

    $q = new NumericalQuestion;
    $q->text = "Чему равно число Пи?";
    $q->correctAnswer = 3.14;

    $questions[] = $q;

    $q = new NumericalQuestion;
    $q->text = "В каком году закончилась вторая мировая война?";
    $q->correctAnswer = 1945;

    $questions[] = $q;

    return $questions;
}

$multipleChoiceQuestions = createMultipleChoiceQuestions();
$numericalQuestions = createNumericalQuestions();

// Обработка вопросов с множественным выбором ответов
$answers = array('b', 'd', 'a');

$print = new MultipleChoiceQuestion;
$print->printQuestions($multipleChoiceQuestions);
$print->checkAnswers($multipleChoiceQuestions, $answers);

// Обработка вопросов с числовым ответом
$answers = array('300000', '3.14', '1944');

$print = new NumericalQuestion;
$print->printQuestions($numericalQuestions);
$print->checkAnswers($numericalQuestions, $answers);