diff --git a/app/Http/Controllers/QuizController.php b/app/Http/Controllers/QuizController.php index 59763962..9e6be790 100755 --- a/app/Http/Controllers/QuizController.php +++ b/app/Http/Controllers/QuizController.php @@ -14,105 +14,86 @@ class QuizController extends Controller */ public QuizState $quiz; - public Question $currentQuestion; + /** + * Display the welcome page. + * + * @throws \Exception + */ + public function index() + { + return view('quiz.index'); + } /** - * @param \Illuminate\Http\Request $request + * Set collection of questions and start the quiz. + * + * @throws \Exception + * + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response */ - public function startQuiz(Request $request) + public function start() { - $this->quiz = new QuizState(); - $this->quiz->countQuestions = $this->questions()->count(); - $this->quiz->start = true; - $this->quiz->lastQuestion--; + $this->quiz = new QuizState($this->questions()); - return $this->next($request); + return $this->show(); } + /** + * Move to the next question. + * + * @param \Illuminate\Http\Request $request + * + * @throws \Exception + * + * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response + */ public function next(Request $request) { $this->quiz ??= unserialize($request->session()->get('quiz')); - $this->quiz->isIncorrect = false; - $this->quiz->currentAnswers = []; - $this->quiz->displayInfo = false; - $this->quiz->userAnswer = ''; - $this->quiz->lastQuestion++; - $this->quiz->stepProgressBar = $this->quiz->lastQuestion; - - if (! $this->questions()->has($this->quiz->lastQuestion)) { - $this->quiz->finish = true; - $this->currentQuestion = Question::recovery($this->quiz->currentQuestion); - - return turbo_stream_view($this->show($request)); - } + $this->quiz->next(); - $this->currentQuestion = $this->questions()->get($this->quiz->lastQuestion); - $this->quiz->currentQuestion = $this->currentQuestion->toArray(); - - return turbo_stream_view($this->show($request)); + return $this->show(); } /** + * Process user's answer. + * * @param Request $request * * @throws \Exception * * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|void */ - public function setAnswer(Request $request) + public function answer(Request $request) { $userAnswer = $request->get('answer'); $this->quiz = unserialize($request->session()->get('quiz')); - $this->quiz->countAttempts++; - $this->quiz->userAnswer = $userAnswer; - $this->currentQuestion = Question::recovery($this->quiz->currentQuestion); + $this->quiz->applyAnswer($userAnswer); - if (! $this->currentQuestion->isCorrect($userAnswer)) { - $this->quiz->countIncorrect++; - $this->quiz->currentAnswers[] = $userAnswer; - $this->quiz->live--; - $this->quiz->isIncorrect = true; - - if ($this->quiz->live < 1) { - $this->quiz->gameOver = true; - } - - return turbo_stream_view($this->show($request)); - } - $this->quiz->isIncorrect = false; - $this->quiz->displayInfo = true; - $this->quiz->countCorrects++; - $this->quiz->stepProgressBar++; - - return turbo_stream_view($this->show($request)); + return $this->show(); } /** + * Display the quiz page. + * * @throws \Exception */ - public function show(Request $request) + protected function show() { - $request->session()->put('quiz', serialize($this->quiz)); + session()->put('quiz', serialize($this->quiz)); - return view('quiz.quiz', [ + return turbo_stream_view(view('quiz.quiz', [ 'quiz' => $this->quiz, - 'currentQuestion' => $this->currentQuestion ?? $this->questions()->get($this->quiz->lastQuestion), - 'currentStepPercent' => $this->currentStepPercent($this->quiz->stepProgressBar), - ]); + 'currentQuestion' => $this->quiz->question(), + ])); } /** - * @throws \Exception - */ - public function index(Request $request) - { - return view('quiz.index'); - } - - /** - * Для каждой эмоции у нас есть две ситуации, cчайным образом выбираем одну + * Generate questions for the quiz. + * + * Randomly choose one situation for each emotion. * * @throws \Exception * @@ -121,9 +102,16 @@ public function index(Request $request) public function questions(): Collection { return collect([ - Question::make(['Какова основная цель фреймворка Laravel?', 'Какой фреймворк акцентирует внимание на элегантном синтаксисе и призван делать процесс разработки приятным?']) - ->answers(['Symfony', 'Django', 'Rails', 'Express', 'Laravel']) - ->setCorrectAnswer('Laravel'), + Question::make(['### MVC Overview + +- **Model**: Represents the data and the business rules concerning the data. This includes data persistence, validation, business logic, and authentication. + +- **View**: Presents data to the user in a specific format. The view receives data from the model and user interactions from the controller. + +- **Controller**: Acts as an intermediary between models and views. It processes user input, interacts with the model, and selects the view to display. +']) + ->answers(['**Controller**: Acts as an intermediary between models and views. It processes user input, interacts with the model, and selects the view to display.', 'Django', 'Rails', 'Express', 'Laravel']) + ->setCorrectAnswer('**Controller**: Acts as an intermediary between models and views. It processes user input, interacts with the model, and selects the view to display.'), Question::make(['Какой компонент Laravel позволяет управлять операциями с базой данных упрощенным способом?', 'Какая функция в Laravel упрощает взаимодействие с базой данных?']) ->answers(['Eloquent ORM', 'Lumen', 'Blade', 'Artisan', 'Eloquent']) @@ -142,15 +130,4 @@ public function questions(): Collection ->setCorrectAnswer('Middleware'), ]); } - - public function currentStepPercent($stepProgressBar) - { - $currentStep = $stepProgressBar; - - if ($currentStep === 0) { - return 0; - } - - return $currentStep / $this->questions()->count() * 100; - } } diff --git a/app/Quiz/Question.php b/app/Quiz/Question.php index 84edbd10..12e5c2e3 100755 --- a/app/Quiz/Question.php +++ b/app/Quiz/Question.php @@ -4,6 +4,8 @@ namespace App\Quiz; +use Illuminate\Support\Str; + class Question { /** @@ -97,7 +99,7 @@ public function isCorrect(string $ansver): bool public function getTitle() { - return $this->title; + return Str::of($this->title)->markdown(); } public function getAnswers() diff --git a/app/Quiz/QuizState.php b/app/Quiz/QuizState.php index eec169cd..af87c527 100755 --- a/app/Quiz/QuizState.php +++ b/app/Quiz/QuizState.php @@ -2,25 +2,54 @@ namespace App\Quiz; +use Illuminate\Support\Collection; + class QuizState implements \JsonSerializable { - public string $title = ''; + /** + * Number of lives/attempts. + */ + public const LIVE = 3; + + /** + * Current step of the quiz. + * + * @var int + */ + public int $step = 0; + + /** + * User's answer to the previous question. + * + * @var string + */ public string $userAnswer = ''; - public int $lastQuestion = 0; - public int $stepProgressBar = 0; - public array $currentQuestion = []; - public array $currentAnswers = []; - public bool $start = false; - public int $countAttempts = 0; - public int $countCorrects = 0; - public int $countIncorrect = 0; - public int $countQuestions = 0; - public int $live = 3; - public bool $finish = false; + + /** + * Current incorrect answers given by the user for the current question + * (to avoid re-answering the same question). + * + * @var array + */ + public array $incorrectAnswers = []; + + /** + * Number of lives/attempts. + * + * @var int + */ + public int $live = self::LIVE; + public bool $displayInfo = false; - public bool $gameOver = false; public bool $isIncorrect = false; + /** + * Collection of questions for the quiz. + * + * @var \Illuminate\Support\Collection|null + */ + public ?Collection $questions; + /** * Convert the object into a JSON serializable array. * @@ -32,9 +61,10 @@ public function jsonSerialize(): array } /** - * Create a new QuizState object from JSON string. + * Create a new QuizState object from a JSON string. * * @param string $json The JSON string to deserialize. + * * @return QuizState The deserialized QuizState object. */ public static function fromJson(string $json): QuizState @@ -53,4 +83,110 @@ public static function fromJson(string $json): QuizState return $quizState; } + /** + * Move to the next question. + * + * @return $this + */ + public function next(): static + { + $this->isIncorrect = false; + $this->incorrectAnswers = []; + $this->displayInfo = false; + $this->userAnswer = ''; + $this->step++; + + return $this; + } + + /** + * Get the current question. + * + * @return \App\Quiz\Question|null + */ + public function question(): ?Question + { + return $this->questions->get($this->step); + } + + /** + * Initialize the QuizState object with questions. + * + * @param \Illuminate\Support\Collection|null $questions + */ + public function __construct(?Collection $questions = null) + { + $this->questions = $questions; + } + + /** + * Calculate the current step's percentage. + * + * @return float|int + */ + public function currentStepPercent(): float|int + { + $currentStep = $this->step + 1; + + if ($currentStep === 0) { + return 0; + } + + return $currentStep / $this->questions->count() * 100; + } + + /** + * Check if all questions have been asked. + * + * @return bool + */ + public function isFinish(): bool + { + return !$this->questions->has($this->step); + } + + /** + * Apply user's answer. + * + * @param mixed $answer The user's answer to the current question. + * + * @return $this + */ + public function applyAnswer($answer): static + { + $this->userAnswer = $answer; + + if (!$this->question()->isCorrect($answer)) { + $this->incorrectAnswers[] = $answer; + $this->live--; + $this->isIncorrect = true; + } else { + $this->isIncorrect = false; + $this->displayInfo = true; + } + + return $this; + } + + /** + * Check if the user has run out of lives/attempts. + * + * @return bool + */ + public function isDead(): bool + { + return $this->live < 1; + } + + /** + * Check if the given answer is in the list of incorrect answers. + * + * @param string $answer The answer to check. + * @return bool True if the answer is incorrect, false otherwise. + */ + public function hasIncorrectAnswer(string $answer): bool + { + return in_array($answer, $this->incorrectAnswers, true); + } + } diff --git a/resources/views/quiz/index.blade.php b/resources/views/quiz/index.blade.php index cbdf9eeb..ef639435 100644 --- a/resources/views/quiz/index.blade.php +++ b/resources/views/quiz/index.blade.php @@ -37,68 +37,6 @@ class="btn btn-primary m-auto d-flex align-items-center justify-content-center w Вернуться на главную - -
- - diff --git a/resources/views/quiz/quiz.blade.php b/resources/views/quiz/quiz.blade.php index a4cb2b5e..37041738 100644 --- a/resources/views/quiz/quiz.blade.php +++ b/resources/views/quiz/quiz.blade.php @@ -1,4 +1,4 @@ -@if ($quiz->finish) +@if ($quiz->isFinish())+ Пожалуйста, примите это сообщение как возможность для улучшения. Мы рекомендуем вам ознакомиться + с материалами на нашем сайте, чтобы подготовиться к повторному тестированию. +
Неверно, попробуйте еще раз. @@ -69,20 +74,19 @@ class="ms-auto btn btn-close px-2" @endif @foreach($currentQuestion->getAnswers() as $answer) - isCorrect($quiz->userAnswer) && $answer === $quiz->userAnswer ? 'btn-success' : '' }} - {{ in_array($answer, $quiz->currentAnswers, true) ? 'btn-danger' : '' }}" - {{ in_array($answer, $quiz->currentAnswers, true) ? "disabled" : '' }} + {{ $quiz->hasIncorrectAnswer($answer) ? 'btn-danger disabled' : '' }}" > - {{ __($answer) }} + {!! \Illuminate\Support\Str::of($answer)->inlineMarkdown() !!} @endforeach