Skip to content

Commit

Permalink
Rework
Browse files Browse the repository at this point in the history
  • Loading branch information
tabuna committed May 1, 2024
1 parent ba821f5 commit 0902255
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 194 deletions.
129 changes: 53 additions & 76 deletions app/Http/Controllers/QuizController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -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'])
Expand All @@ -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;
}
}
4 changes: 3 additions & 1 deletion app/Quiz/Question.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace App\Quiz;

use Illuminate\Support\Str;

class Question
{
/**
Expand Down Expand Up @@ -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()
Expand Down
164 changes: 150 additions & 14 deletions app/Quiz/QuizState.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand All @@ -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
Expand All @@ -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);
}

}
Loading

0 comments on commit 0902255

Please sign in to comment.