Skip to content

Commit 0902255

Browse files
committed
Rework
1 parent ba821f5 commit 0902255

File tree

6 files changed

+263
-194
lines changed

6 files changed

+263
-194
lines changed

app/Http/Controllers/QuizController.php

Lines changed: 53 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -14,105 +14,86 @@ class QuizController extends Controller
1414
*/
1515
public QuizState $quiz;
1616

17-
public Question $currentQuestion;
17+
/**
18+
* Display the welcome page.
19+
*
20+
* @throws \Exception
21+
*/
22+
public function index()
23+
{
24+
return view('quiz.index');
25+
}
1826

1927
/**
20-
* @param \Illuminate\Http\Request $request
28+
* Set collection of questions and start the quiz.
29+
*
30+
* @throws \Exception
31+
*
32+
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
2133
*/
22-
public function startQuiz(Request $request)
34+
public function start()
2335
{
24-
$this->quiz = new QuizState();
25-
$this->quiz->countQuestions = $this->questions()->count();
26-
$this->quiz->start = true;
27-
$this->quiz->lastQuestion--;
36+
$this->quiz = new QuizState($this->questions());
2837

29-
return $this->next($request);
38+
return $this->show();
3039
}
3140

41+
/**
42+
* Move to the next question.
43+
*
44+
* @param \Illuminate\Http\Request $request
45+
*
46+
* @throws \Exception
47+
*
48+
* @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
49+
*/
3250
public function next(Request $request)
3351
{
3452
$this->quiz ??= unserialize($request->session()->get('quiz'));
3553

36-
$this->quiz->isIncorrect = false;
37-
$this->quiz->currentAnswers = [];
38-
$this->quiz->displayInfo = false;
39-
$this->quiz->userAnswer = '';
40-
$this->quiz->lastQuestion++;
41-
$this->quiz->stepProgressBar = $this->quiz->lastQuestion;
42-
43-
if (! $this->questions()->has($this->quiz->lastQuestion)) {
44-
$this->quiz->finish = true;
45-
$this->currentQuestion = Question::recovery($this->quiz->currentQuestion);
46-
47-
return turbo_stream_view($this->show($request));
48-
}
54+
$this->quiz->next();
4955

50-
$this->currentQuestion = $this->questions()->get($this->quiz->lastQuestion);
51-
$this->quiz->currentQuestion = $this->currentQuestion->toArray();
52-
53-
return turbo_stream_view($this->show($request));
56+
return $this->show();
5457
}
5558

5659
/**
60+
* Process user's answer.
61+
*
5762
* @param Request $request
5863
*
5964
* @throws \Exception
6065
*
6166
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|void
6267
*/
63-
public function setAnswer(Request $request)
68+
public function answer(Request $request)
6469
{
6570
$userAnswer = $request->get('answer');
6671
$this->quiz = unserialize($request->session()->get('quiz'));
6772

68-
$this->quiz->countAttempts++;
69-
$this->quiz->userAnswer = $userAnswer;
70-
$this->currentQuestion = Question::recovery($this->quiz->currentQuestion);
73+
$this->quiz->applyAnswer($userAnswer);
7174

72-
if (! $this->currentQuestion->isCorrect($userAnswer)) {
73-
$this->quiz->countIncorrect++;
74-
$this->quiz->currentAnswers[] = $userAnswer;
75-
$this->quiz->live--;
76-
$this->quiz->isIncorrect = true;
77-
78-
if ($this->quiz->live < 1) {
79-
$this->quiz->gameOver = true;
80-
}
81-
82-
return turbo_stream_view($this->show($request));
83-
}
84-
$this->quiz->isIncorrect = false;
85-
$this->quiz->displayInfo = true;
86-
$this->quiz->countCorrects++;
87-
$this->quiz->stepProgressBar++;
88-
89-
return turbo_stream_view($this->show($request));
75+
return $this->show();
9076
}
9177

9278
/**
79+
* Display the quiz page.
80+
*
9381
* @throws \Exception
9482
*/
95-
public function show(Request $request)
83+
protected function show()
9684
{
97-
$request->session()->put('quiz', serialize($this->quiz));
85+
session()->put('quiz', serialize($this->quiz));
9886

99-
return view('quiz.quiz', [
87+
return turbo_stream_view(view('quiz.quiz', [
10088
'quiz' => $this->quiz,
101-
'currentQuestion' => $this->currentQuestion ?? $this->questions()->get($this->quiz->lastQuestion),
102-
'currentStepPercent' => $this->currentStepPercent($this->quiz->stepProgressBar),
103-
]);
89+
'currentQuestion' => $this->quiz->question(),
90+
]));
10491
}
10592

10693
/**
107-
* @throws \Exception
108-
*/
109-
public function index(Request $request)
110-
{
111-
return view('quiz.index');
112-
}
113-
114-
/**
115-
* Для каждой эмоции у нас есть две ситуации, cчайным образом выбираем одну
94+
* Generate questions for the quiz.
95+
*
96+
* Randomly choose one situation for each emotion.
11697
*
11798
* @throws \Exception
11899
*
@@ -121,9 +102,16 @@ public function index(Request $request)
121102
public function questions(): Collection
122103
{
123104
return collect([
124-
Question::make(['Какова основная цель фреймворка Laravel?', 'Какой фреймворк акцентирует внимание на элегантном синтаксисе и призван делать процесс разработки приятным?'])
125-
->answers(['Symfony', 'Django', 'Rails', 'Express', 'Laravel'])
126-
->setCorrectAnswer('Laravel'),
105+
Question::make(['### MVC Overview
106+
107+
- **Model**: Represents the data and the business rules concerning the data. This includes data persistence, validation, business logic, and authentication.
108+
109+
- **View**: Presents data to the user in a specific format. The view receives data from the model and user interactions from the controller.
110+
111+
- **Controller**: Acts as an intermediary between models and views. It processes user input, interacts with the model, and selects the view to display.
112+
'])
113+
->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'])
114+
->setCorrectAnswer('**Controller**: Acts as an intermediary between models and views. It processes user input, interacts with the model, and selects the view to display.'),
127115

128116
Question::make(['Какой компонент Laravel позволяет управлять операциями с базой данных упрощенным способом?', 'Какая функция в Laravel упрощает взаимодействие с базой данных?'])
129117
->answers(['Eloquent ORM', 'Lumen', 'Blade', 'Artisan', 'Eloquent'])
@@ -142,15 +130,4 @@ public function questions(): Collection
142130
->setCorrectAnswer('Middleware'),
143131
]);
144132
}
145-
146-
public function currentStepPercent($stepProgressBar)
147-
{
148-
$currentStep = $stepProgressBar;
149-
150-
if ($currentStep === 0) {
151-
return 0;
152-
}
153-
154-
return $currentStep / $this->questions()->count() * 100;
155-
}
156133
}

app/Quiz/Question.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace App\Quiz;
66

7+
use Illuminate\Support\Str;
8+
79
class Question
810
{
911
/**
@@ -97,7 +99,7 @@ public function isCorrect(string $ansver): bool
9799

98100
public function getTitle()
99101
{
100-
return $this->title;
102+
return Str::of($this->title)->markdown();
101103
}
102104

103105
public function getAnswers()

app/Quiz/QuizState.php

Lines changed: 150 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,54 @@
22

33
namespace App\Quiz;
44

5+
use Illuminate\Support\Collection;
6+
57
class QuizState implements \JsonSerializable
68
{
7-
public string $title = '';
9+
/**
10+
* Number of lives/attempts.
11+
*/
12+
public const LIVE = 3;
13+
14+
/**
15+
* Current step of the quiz.
16+
*
17+
* @var int
18+
*/
19+
public int $step = 0;
20+
21+
/**
22+
* User's answer to the previous question.
23+
*
24+
* @var string
25+
*/
826
public string $userAnswer = '';
9-
public int $lastQuestion = 0;
10-
public int $stepProgressBar = 0;
11-
public array $currentQuestion = [];
12-
public array $currentAnswers = [];
13-
public bool $start = false;
14-
public int $countAttempts = 0;
15-
public int $countCorrects = 0;
16-
public int $countIncorrect = 0;
17-
public int $countQuestions = 0;
18-
public int $live = 3;
19-
public bool $finish = false;
27+
28+
/**
29+
* Current incorrect answers given by the user for the current question
30+
* (to avoid re-answering the same question).
31+
*
32+
* @var array
33+
*/
34+
public array $incorrectAnswers = [];
35+
36+
/**
37+
* Number of lives/attempts.
38+
*
39+
* @var int
40+
*/
41+
public int $live = self::LIVE;
42+
2043
public bool $displayInfo = false;
21-
public bool $gameOver = false;
2244
public bool $isIncorrect = false;
2345

46+
/**
47+
* Collection of questions for the quiz.
48+
*
49+
* @var \Illuminate\Support\Collection|null
50+
*/
51+
public ?Collection $questions;
52+
2453
/**
2554
* Convert the object into a JSON serializable array.
2655
*
@@ -32,9 +61,10 @@ public function jsonSerialize(): array
3261
}
3362

3463
/**
35-
* Create a new QuizState object from JSON string.
64+
* Create a new QuizState object from a JSON string.
3665
*
3766
* @param string $json The JSON string to deserialize.
67+
*
3868
* @return QuizState The deserialized QuizState object.
3969
*/
4070
public static function fromJson(string $json): QuizState
@@ -53,4 +83,110 @@ public static function fromJson(string $json): QuizState
5383
return $quizState;
5484
}
5585

86+
/**
87+
* Move to the next question.
88+
*
89+
* @return $this
90+
*/
91+
public function next(): static
92+
{
93+
$this->isIncorrect = false;
94+
$this->incorrectAnswers = [];
95+
$this->displayInfo = false;
96+
$this->userAnswer = '';
97+
$this->step++;
98+
99+
return $this;
100+
}
101+
102+
/**
103+
* Get the current question.
104+
*
105+
* @return \App\Quiz\Question|null
106+
*/
107+
public function question(): ?Question
108+
{
109+
return $this->questions->get($this->step);
110+
}
111+
112+
/**
113+
* Initialize the QuizState object with questions.
114+
*
115+
* @param \Illuminate\Support\Collection|null $questions
116+
*/
117+
public function __construct(?Collection $questions = null)
118+
{
119+
$this->questions = $questions;
120+
}
121+
122+
/**
123+
* Calculate the current step's percentage.
124+
*
125+
* @return float|int
126+
*/
127+
public function currentStepPercent(): float|int
128+
{
129+
$currentStep = $this->step + 1;
130+
131+
if ($currentStep === 0) {
132+
return 0;
133+
}
134+
135+
return $currentStep / $this->questions->count() * 100;
136+
}
137+
138+
/**
139+
* Check if all questions have been asked.
140+
*
141+
* @return bool
142+
*/
143+
public function isFinish(): bool
144+
{
145+
return !$this->questions->has($this->step);
146+
}
147+
148+
/**
149+
* Apply user's answer.
150+
*
151+
* @param mixed $answer The user's answer to the current question.
152+
*
153+
* @return $this
154+
*/
155+
public function applyAnswer($answer): static
156+
{
157+
$this->userAnswer = $answer;
158+
159+
if (!$this->question()->isCorrect($answer)) {
160+
$this->incorrectAnswers[] = $answer;
161+
$this->live--;
162+
$this->isIncorrect = true;
163+
} else {
164+
$this->isIncorrect = false;
165+
$this->displayInfo = true;
166+
}
167+
168+
return $this;
169+
}
170+
171+
/**
172+
* Check if the user has run out of lives/attempts.
173+
*
174+
* @return bool
175+
*/
176+
public function isDead(): bool
177+
{
178+
return $this->live < 1;
179+
}
180+
181+
/**
182+
* Check if the given answer is in the list of incorrect answers.
183+
*
184+
* @param string $answer The answer to check.
185+
* @return bool True if the answer is incorrect, false otherwise.
186+
*/
187+
public function hasIncorrectAnswer(string $answer): bool
188+
{
189+
return in_array($answer, $this->incorrectAnswers, true);
190+
}
191+
56192
}

0 commit comments

Comments
 (0)