Complex classes like Hangman often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Hangman, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
35 | class Hangman extends EventSourcedAggregateRoot implements MiniGame |
||
36 | { |
||
37 | use PlayTrait; |
||
38 | |||
39 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
40 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
41 | ////////////////////////////////////////////// CONSTANTS /////////////////////////////////////////////////// |
||
42 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
43 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
44 | |||
45 | const STATE_UNINITIALIZED = 'uninitialized'; |
||
46 | const STATE_READY = 'ready'; |
||
47 | const STATE_STARTED = 'started'; |
||
48 | const STATE_OVER = 'over'; |
||
49 | |||
50 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
51 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
52 | ///////////////////////////////////////////// PROPERTIES /////////////////////////////////////////////////// |
||
53 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
54 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
55 | |||
56 | /** |
||
57 | * @var MiniGameId |
||
58 | */ |
||
59 | private $id; |
||
60 | |||
61 | /** |
||
62 | * @var string |
||
63 | */ |
||
64 | private $word; |
||
65 | |||
66 | /** |
||
67 | * @var HangmanPlayer[] |
||
68 | **/ |
||
69 | private $players; |
||
70 | |||
71 | /** |
||
72 | * @var array |
||
73 | */ |
||
74 | protected $gameOrder; |
||
75 | |||
76 | /** |
||
77 | * @var HangmanPlayer |
||
78 | **/ |
||
79 | private $currentPlayer; |
||
80 | |||
81 | /** |
||
82 | * @var string |
||
83 | */ |
||
84 | private $state; |
||
85 | |||
86 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
87 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
88 | ///////////////////////////////////////// PRIVATE CONSTRUCTOR ////////////////////////////////////////////// |
||
89 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
90 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
91 | |||
92 | /** |
||
93 | * Constructor |
||
94 | */ |
||
95 | 111 | private function __construct() |
|
96 | { |
||
97 | 111 | $this->state = self::STATE_UNINITIALIZED; |
|
98 | 111 | } |
|
99 | |||
100 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
101 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
102 | ////////////////////////////////////////////// ACCESSORS /////////////////////////////////////////////////// |
||
103 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
104 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
105 | |||
106 | /** |
||
107 | * Returns the id of the game |
||
108 | * |
||
109 | * @return MiniGameId |
||
110 | */ |
||
111 | 93 | public function getId() |
|
112 | { |
||
113 | 93 | return $this->id; |
|
114 | } |
||
115 | |||
116 | /** |
||
117 | * Returns the aggregate id |
||
118 | * |
||
119 | * @return MiniGameId |
||
120 | */ |
||
121 | 111 | public function getAggregateRootId() |
|
122 | { |
||
123 | 111 | return $this->id; |
|
124 | } |
||
125 | |||
126 | /** |
||
127 | * Returns the name of the mini-game |
||
128 | * |
||
129 | * @return string |
||
130 | */ |
||
131 | 3 | public static function getName() |
|
132 | { |
||
133 | 3 | return 'HANGMAN'; |
|
134 | } |
||
135 | |||
136 | /** |
||
137 | * Get the player identified by PlayerId |
||
138 | * |
||
139 | * @param PlayerId $playerId |
||
140 | * |
||
141 | * @return HangmanPlayer |
||
142 | */ |
||
143 | 57 | public function getPlayer(PlayerId $playerId = null) |
|
144 | { |
||
145 | 57 | if ($playerId === null) { |
|
146 | 3 | return null; |
|
147 | } |
||
148 | |||
149 | 54 | return isset($this->players[(string)$playerId]) ? $this->players[(string)$playerId] : null; |
|
150 | } |
||
151 | |||
152 | /** |
||
153 | * Returns the player who can play |
||
154 | * |
||
155 | * @return Player |
||
156 | */ |
||
157 | 3 | public function getCurrentPlayer() |
|
158 | { |
||
159 | 3 | return $this->currentPlayer; |
|
160 | } |
||
161 | |||
162 | /** |
||
163 | * Get the players |
||
164 | * |
||
165 | * @return Player[] |
||
166 | */ |
||
167 | 111 | public function getPlayers() |
|
168 | { |
||
169 | 111 | return array_values($this->players); |
|
170 | } |
||
171 | |||
172 | /** |
||
173 | * Is game started? |
||
174 | * |
||
175 | * @return bool |
||
176 | */ |
||
177 | 36 | public function isGameStarted() |
|
178 | { |
||
179 | 36 | return $this->state === self::STATE_STARTED; |
|
180 | } |
||
181 | |||
182 | /** |
||
183 | * Is it the player's turn? |
||
184 | * |
||
185 | * @param PlayerId $playerId |
||
186 | * |
||
187 | * @return bool |
||
188 | */ |
||
189 | 36 | public function canPlayerPlay(PlayerId $playerId) |
|
193 | |||
194 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
195 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
196 | /////////////////////////////////////////// DOMAIN METHODS ///////////////////////////////////////////////// |
||
197 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
198 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
199 | |||
200 | /** |
||
201 | * Starts the game |
||
202 | * |
||
203 | * @param PlayerId $playerId |
||
204 | * |
||
205 | * @return GameResult |
||
206 | */ |
||
207 | 51 | public function startGame(PlayerId $playerId) |
|
236 | |||
237 | /** |
||
238 | * Adds a player to the game |
||
239 | * |
||
240 | * @param PlayerOptions $playerOptions |
||
241 | * |
||
242 | * @throws HangmanPlayerOptionsException |
||
243 | * @throws HangmanException |
||
244 | * |
||
245 | * @return GameResult |
||
246 | */ |
||
247 | 75 | public function addPlayerToGame(PlayerOptions $playerOptions) |
|
248 | { |
||
249 | 75 | if (! $playerOptions instanceof HangmanPlayerOptions) { |
|
250 | 3 | throw new HangmanPlayerOptionsException( |
|
251 | 3 | $playerOptions->getPlayerId(), |
|
252 | 3 | $this->getId(), |
|
253 | 1 | 'Options are not recognized' |
|
254 | 2 | ); |
|
255 | } |
||
256 | |||
257 | 75 | if ($this->state !== self::STATE_READY) { |
|
258 | 3 | $event = new HangmanPlayerFailedCreatingEvent( |
|
259 | 3 | $this->id, |
|
260 | 3 | $playerOptions->getPlayerId(), |
|
261 | 3 | $playerOptions->getExternalReference() |
|
262 | 2 | ); |
|
263 | 3 | $this->apply($event); |
|
264 | 3 | return $event; |
|
265 | } |
||
266 | |||
267 | 75 | $event = new HangmanPlayerCreatedEvent( |
|
268 | 75 | $this->id, |
|
269 | 75 | $playerOptions->getPlayerId(), |
|
270 | 75 | $playerOptions->getName(), |
|
271 | 75 | $playerOptions->getLives(), |
|
272 | 75 | $playerOptions->getExternalReference() |
|
273 | 50 | ); |
|
274 | 75 | $this->apply($event); |
|
275 | 75 | return $event; |
|
276 | } |
||
277 | |||
278 | /** |
||
279 | * A player leaves the game |
||
280 | * |
||
281 | * @param PlayerId $playerId |
||
282 | * |
||
283 | * @return GameResult |
||
284 | */ |
||
285 | 9 | public function leaveGame(PlayerId $playerId) |
|
286 | { |
||
287 | 9 | switch ($this->state) { |
|
288 | 9 | case self::STATE_STARTED: |
|
289 | 3 | $player = $this->getPlayer($playerId); |
|
290 | 3 | return $player ? $this->playerLoses($player) : null; |
|
291 | 6 | case self::STATE_OVER: |
|
292 | 3 | break; |
|
293 | 2 | default: |
|
294 | 3 | if (isset($this->players[(string) $playerId])) { |
|
295 | 3 | unset($this->players[(string) $playerId]); |
|
296 | 2 | } |
|
297 | 3 | break; |
|
298 | 4 | } |
|
299 | 6 | return null; |
|
300 | } |
||
301 | |||
302 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
303 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
304 | ////////////////////////////////////////// PRIVATE METHODS ///////////////////////////////////////////////// |
||
305 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
306 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
307 | |||
308 | /** |
||
309 | * Initialize the game |
||
310 | * |
||
311 | * @param MiniGameId $id |
||
312 | * @param string $word |
||
313 | */ |
||
314 | 111 | private function initialize(MiniGameId $id, $word) |
|
315 | { |
||
316 | 111 | $this->apply(new HangmanGameCreatedEvent($id, $word)); |
|
317 | 111 | } |
|
318 | |||
319 | /** |
||
320 | * Player proposes a letter |
||
321 | * |
||
322 | * @param PlayerId $playerId |
||
323 | * @param Proposition $move |
||
324 | * |
||
325 | * @return GameResult |
||
326 | */ |
||
327 | 21 | private function playProposition(PlayerId $playerId, Proposition $move) |
|
328 | { |
||
329 | 21 | if ($errorEvent = $this->ensurePlayerCanPlay($playerId)) { |
|
330 | 6 | $this->apply($errorEvent); |
|
331 | 6 | return $errorEvent; |
|
332 | } |
||
333 | |||
334 | 15 | return $this->currentPlayerProposeLetter($move->getText()); |
|
335 | } |
||
336 | |||
337 | /** |
||
338 | * Player tries an answer |
||
339 | * |
||
340 | * @param PlayerId $playerId |
||
341 | * @param Answer $move |
||
342 | * |
||
343 | * @return GameResult |
||
344 | */ |
||
345 | 15 | private function playAnswer(PlayerId $playerId, Answer $move) |
|
346 | { |
||
347 | 15 | if ($errorEvent = $this->ensurePlayerCanPlay($playerId)) { |
|
348 | 3 | $this->apply($errorEvent); |
|
349 | 3 | return $errorEvent; |
|
350 | } |
||
351 | |||
352 | try { |
||
353 | 12 | return $this->currentPlayerProposeAnswer($move->getText()); |
|
354 | 3 | } catch (HangmanException $e) { |
|
355 | 3 | $event = new HangmanPlayerProposedInvalidAnswerEvent( |
|
356 | 3 | $this->getId(), |
|
357 | 2 | $playerId, |
|
358 | $move |
||
359 | 2 | ); |
|
360 | 3 | $this->apply($event); |
|
361 | 3 | return $event; |
|
362 | } |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Returns an error event if player cannot play |
||
367 | * |
||
368 | * @param PlayerId $playerId |
||
369 | * |
||
370 | * @return GameResult |
||
371 | */ |
||
372 | 36 | private function ensurePlayerCanPlay(PlayerId $playerId) |
|
373 | { |
||
374 | 36 | if (!$this->isGameStarted()) { |
|
375 | 3 | $event = new HangmanPlayerTriedPlayingInactiveGameEvent( |
|
376 | 3 | $this->getId(), |
|
377 | $playerId |
||
378 | 2 | ); |
|
379 | 3 | return $event; |
|
380 | } |
||
381 | |||
382 | 33 | if (!$this->canPlayerPlay($playerId)) { |
|
383 | 6 | $event = new HangmanPlayerTriedPlayingDuringAnotherPlayerTurnEvent( |
|
384 | 6 | $this->getId(), |
|
385 | $playerId |
||
386 | 4 | ); |
|
387 | 6 | return $event; |
|
388 | } |
||
389 | |||
390 | 27 | return null; |
|
391 | } |
||
392 | |||
393 | /** |
||
394 | * Propose a letter |
||
395 | * |
||
396 | * @param string $letter |
||
397 | * |
||
398 | * @return HangmanBadProposition | HangmanGoodProposition |
||
399 | */ |
||
400 | 15 | private function currentPlayerProposeLetter($letter) |
|
401 | { |
||
402 | 15 | $capLetter = strtoupper($letter); |
|
403 | 15 | $letterPresent = $this->wordContains($capLetter); |
|
404 | |||
405 | 15 | $result = (!$letterPresent) |
|
406 | 13 | ? $this->currentPlayerBadProposition($letter) // remove a life |
|
407 | 15 | : $this->currentPlayerGoodProposition($letter); // yay! |
|
408 | |||
409 | 15 | return $result; |
|
410 | } |
||
411 | |||
412 | /** |
||
413 | * Propose an answer |
||
414 | * |
||
415 | * @param string $answer |
||
416 | * |
||
417 | * @return HangmanLost | HangmanWon |
||
418 | */ |
||
419 | 12 | private function currentPlayerProposeAnswer($answer) |
|
420 | { |
||
421 | 12 | $this->checkAnswerIsValid($answer); |
|
422 | |||
423 | 9 | if ($this->isTheAnswer(strtoupper($answer))) { |
|
424 | 3 | return $this->playerWins($this->currentPlayer); // you win |
|
425 | } else { |
||
426 | 6 | return $this->playerLoses($this->currentPlayer); // you lose |
|
427 | } |
||
428 | } |
||
429 | |||
430 | /** |
||
431 | * Function to call when a bad proposition has been made |
||
432 | * |
||
433 | * @param string $letter |
||
434 | * |
||
435 | * @return HangmanBadProposition | HangmanLost |
||
436 | */ |
||
437 | 9 | private function currentPlayerBadProposition($letter) |
|
438 | { |
||
439 | 9 | $player = $this->currentPlayer; |
|
440 | |||
441 | 9 | $event = $player->playBadLetter($letter, 1); |
|
442 | |||
443 | 9 | if ($event->getRemainingLives() === 0) { |
|
444 | 6 | return $this->playerLoses($player); |
|
445 | } |
||
446 | |||
447 | 3 | $this->setNextPlayer($this->getNextPlayerId()); |
|
448 | |||
449 | 3 | return $event; |
|
450 | } |
||
451 | |||
452 | /** |
||
453 | * Function to call after a good proposition of letter has been made |
||
454 | * |
||
455 | * @param string $letter |
||
456 | * |
||
457 | * @return HangmanGoodProposition | HangmanWon |
||
458 | */ |
||
459 | 6 | private function currentPlayerGoodProposition($letter) |
|
460 | { |
||
461 | 6 | $player = $this->currentPlayer; |
|
462 | |||
463 | 6 | $event = $player->playGoodLetter($letter); |
|
464 | |||
465 | 6 | if ($this->isAllLettersFoundForPlayer($player)) { |
|
466 | 3 | return $this->playerWins($player); |
|
467 | } |
||
468 | |||
469 | 3 | $this->setNextPlayer($this->getNextPlayerId()); |
|
470 | |||
471 | 3 | return $event; |
|
472 | } |
||
473 | |||
474 | /** |
||
475 | * Function to call when game is won by a player |
||
476 | * |
||
477 | * @param HangmanPlayer $player |
||
478 | * |
||
479 | * @return HangmanWon |
||
480 | */ |
||
481 | 6 | private function playerWins(HangmanPlayer $player) |
|
482 | { |
||
483 | 6 | $playerId = $player->getId(); |
|
484 | |||
485 | 6 | $playedLetters = $this->getPlayedLettersForPlayer($playerId); |
|
486 | 6 | $remainingLives = $this->getRemainingLives($playerId); |
|
487 | |||
488 | 6 | $event = new HangmanPlayerWinEvent( |
|
489 | 6 | $this->id, |
|
490 | 4 | $playerId, |
|
491 | 4 | $playedLetters, |
|
492 | 4 | $remainingLives, |
|
493 | 6 | $this->word |
|
494 | 4 | ); |
|
495 | 6 | $this->apply($event); |
|
496 | |||
497 | 6 | foreach ($this->players as $otherPlayer) { |
|
498 | 6 | if ($otherPlayer->equals($player) || $otherPlayer->hasLost()) { |
|
499 | 6 | continue; |
|
500 | } |
||
501 | 6 | $otherPlayer->lose($this->word); |
|
502 | 4 | } |
|
503 | |||
504 | 6 | return $event; |
|
505 | } |
||
506 | |||
507 | /** |
||
508 | * Function to call when game is lost by a player |
||
509 | * |
||
510 | * @param HangmanPlayer $player |
||
511 | * |
||
512 | * @return hangmanLost | HangmanGameLostEvent |
||
513 | */ |
||
514 | 15 | private function playerLoses(HangmanPlayer $player) |
|
515 | { |
||
516 | 15 | $nextPlayerId = $this->getNextPlayerId(); |
|
517 | |||
518 | 15 | $event = $player->lose($this->word); |
|
519 | |||
520 | 15 | if (count($this->gameOrder) > 0 && |
|
521 | 15 | $this->currentPlayer && |
|
522 | 13 | $player->equals($this->currentPlayer) |
|
523 | 10 | ) { |
|
524 | 12 | $this->setNextPlayer($nextPlayerId); |
|
525 | 12 | return $event; |
|
526 | } |
||
527 | |||
528 | 3 | $event = new HangmanGameLostEvent( |
|
529 | 3 | $this->id, |
|
530 | 3 | $player->getId(), |
|
531 | 3 | $this->word |
|
532 | 2 | ); |
|
533 | 3 | $this->apply($event); |
|
534 | |||
535 | 3 | return $event; |
|
536 | } |
||
537 | |||
538 | /** |
||
539 | * Sets the next player |
||
540 | * |
||
541 | * @param PlayerId $id |
||
542 | */ |
||
543 | 48 | private function setNextPlayer(PlayerId $id = null) |
|
544 | { |
||
545 | 48 | if ($id === null || ($this->currentPlayer && $this->currentPlayer->getId()->equals($id))) { |
|
546 | return; |
||
547 | } |
||
548 | |||
549 | 48 | $this->apply( |
|
550 | 48 | new HangmanPlayerTurnEvent($this->getId(), $id) |
|
551 | 32 | ); |
|
552 | 48 | } |
|
553 | |||
554 | /** |
||
555 | * Returns the next player in line |
||
556 | * |
||
557 | * @return PlayerId |
||
558 | */ |
||
559 | 21 | private function getNextPlayerId() |
|
560 | { |
||
561 | 21 | if ($this->currentPlayer === null) { |
|
562 | return null; |
||
563 | } |
||
564 | |||
565 | 21 | $nbPlayers = count($this->gameOrder); |
|
566 | 21 | $currentPlayerId = (string)$this->currentPlayer->getId(); |
|
567 | 21 | $nextPlayerPosition = (array_search($currentPlayerId, $this->gameOrder) + 1) % $nbPlayers; |
|
568 | |||
569 | 21 | $pos = $nextPlayerPosition; |
|
570 | do { |
||
571 | 21 | $id = PlayerId::create($this->gameOrder[$pos]); |
|
572 | 21 | $player = $this->getPlayer($id); |
|
573 | |||
574 | 21 | if ($player->getState() === HangmanPlayer::STATE_IN_GAME) { |
|
575 | 21 | return $id; |
|
576 | } |
||
577 | |||
578 | $pos = ($pos + 1) % $nbPlayers; |
||
579 | } while ($pos !== $nextPlayerPosition); |
||
580 | |||
581 | return null; |
||
582 | } |
||
583 | |||
584 | /** |
||
585 | * Returns the list of played letters |
||
586 | * |
||
587 | * @param PlayerId $playerId |
||
588 | * |
||
589 | * @return array |
||
590 | */ |
||
591 | 6 | private function getPlayedLettersForPlayer(PlayerId $playerId) |
|
592 | { |
||
593 | 6 | return $this->getPlayer($playerId)->getPlayedLetters(); |
|
594 | } |
||
595 | |||
596 | /** |
||
597 | * Gets the remaining lives for the player |
||
598 | * |
||
599 | * @param PlayerId $playerId |
||
600 | * |
||
601 | * @return int |
||
602 | */ |
||
603 | 6 | private function getRemainingLives(PlayerId $playerId) |
|
604 | { |
||
605 | 6 | return $this->getPlayer($playerId)->getRemainingLives(); |
|
606 | } |
||
607 | |||
608 | /** |
||
609 | * Returns the indexes of the letter in the word |
||
610 | * |
||
611 | * @param string $letter |
||
612 | * |
||
613 | * @return boolean |
||
614 | */ |
||
615 | 15 | private function wordContains($letter) |
|
616 | { |
||
617 | 15 | return strpos(strtoupper($this->word), strtoupper($letter)) !== false; |
|
618 | } |
||
619 | |||
620 | /** |
||
621 | * Get the letters of the word |
||
622 | * |
||
623 | * @return string[] |
||
624 | */ |
||
625 | 42 | private function getLettersFromWord() |
|
626 | { |
||
627 | 42 | return array_unique(str_split(strtoupper($this->word))); |
|
628 | } |
||
629 | |||
630 | /** |
||
631 | * Build the word from played letters |
||
632 | * |
||
633 | * @param string[] $playedLetters |
||
634 | * |
||
635 | * @return string |
||
636 | */ |
||
637 | 42 | public function buildWord($playedLetters) |
|
638 | { |
||
639 | 42 | $wordLetters = $this->getLettersFromWord(); |
|
640 | |||
641 | 42 | $goodLetters = array_intersect($wordLetters, $playedLetters); |
|
642 | |||
643 | 42 | $splitWord = str_split(strtoupper($this->word)); |
|
644 | 42 | $word = ''; |
|
645 | 42 | foreach ($splitWord as $letter) { |
|
646 | 42 | $word .= (in_array($letter, $goodLetters) ? $letter : '_') . ' '; |
|
647 | 28 | } |
|
648 | |||
649 | 42 | return trim($word); |
|
650 | } |
||
651 | |||
652 | /** |
||
653 | * Checks if all letters for the word have been found |
||
654 | * |
||
655 | * @param HangmanPlayer $player |
||
656 | * |
||
657 | * @return bool |
||
658 | */ |
||
659 | 6 | private function isAllLettersFoundForPlayer(HangmanPlayer $player) |
|
660 | { |
||
661 | 6 | $wordLetters = $this->getLettersFromWord(); |
|
662 | 6 | $playerLetters = $player->getPlayedLetters(); |
|
663 | 6 | return count(array_intersect($wordLetters, $playerLetters)) == count($wordLetters); |
|
664 | } |
||
665 | |||
666 | /** |
||
667 | * Checks if the answer is valid |
||
668 | * If it's not, ends player turn and throws an HangmanException |
||
669 | * |
||
670 | * @param string $answer |
||
671 | * |
||
672 | * @throws HangmanException |
||
673 | */ |
||
674 | 12 | private function checkAnswerIsValid($answer) |
|
675 | { |
||
676 | 12 | if (strlen($answer) !== strlen($this->word)) { |
|
677 | 3 | throw new HangmanException(sprintf('"%s" is not a valid answer!', $answer)); |
|
678 | } |
||
679 | 9 | } |
|
680 | |||
681 | /** |
||
682 | * Checks if the word is the same as the solution |
||
683 | * |
||
684 | * @param string $word |
||
685 | * |
||
686 | * @return bool |
||
687 | */ |
||
688 | 9 | private function isTheAnswer($word) |
|
689 | { |
||
690 | 9 | return ($this->word === strtoupper($word)); |
|
691 | } |
||
692 | |||
693 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
694 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
695 | //////////////////////////////////////////// APPLY EVENTS ////////////////////////////////////////////////// |
||
696 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
697 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
698 | |||
699 | /** |
||
700 | * Apply the game created event |
||
701 | * |
||
702 | * @param HangmanGameCreatedEvent $event |
||
703 | * |
||
704 | * @return void |
||
705 | */ |
||
706 | 111 | protected function applyHangmanGameCreatedEvent(HangmanGameCreatedEvent $event) |
|
707 | { |
||
708 | 111 | $this->id = $event->getGameId(); |
|
709 | 111 | $this->word = strtoupper($event->getWord()); |
|
710 | 111 | $this->players = []; |
|
711 | 111 | $this->gameOrder = []; |
|
712 | 111 | $this->state = self::STATE_READY; |
|
713 | 111 | } |
|
714 | |||
715 | /** |
||
716 | * Apply the player created event |
||
717 | * |
||
718 | * @param HangmanPlayerCreatedEvent $event |
||
719 | * |
||
720 | * @return void |
||
721 | */ |
||
722 | 75 | protected function applyHangmanPlayerCreatedEvent(HangmanPlayerCreatedEvent $event) |
|
723 | { |
||
724 | 75 | $player = new HangmanPlayer( |
|
725 | 75 | $event->getPlayerId(), |
|
726 | 75 | $event->getPlayerName(), |
|
727 | 75 | $event->getLives(), |
|
728 | 50 | $this, |
|
729 | 75 | $event->getExternalReference() |
|
730 | 50 | ); |
|
731 | |||
732 | 75 | $this->gameOrder[] = (string)$player->getId(); |
|
733 | 75 | $this->players[(string)$player->getId()] = $player; |
|
734 | 75 | } |
|
735 | |||
736 | /** |
||
737 | * Apply the game created event |
||
738 | */ |
||
739 | 48 | protected function applyHangmanGameStartedEvent() |
|
740 | { |
||
741 | 48 | $this->state = self::STATE_STARTED; |
|
742 | 48 | } |
|
743 | |||
744 | /** |
||
745 | * Apply the player turn event |
||
746 | * |
||
747 | * @param HangmanPlayerTurnEvent $event |
||
748 | */ |
||
749 | 48 | protected function applyHangmanPlayerTurnEvent(HangmanPlayerTurnEvent $event) |
|
753 | |||
754 | /** |
||
755 | * Apply the hangman player lost event |
||
756 | * |
||
757 | * @param HangmanPlayerLostEvent $event |
||
758 | */ |
||
759 | 21 | protected function applyHangmanPlayerLostEvent(HangmanPlayerLostEvent $event) |
|
760 | { |
||
761 | 21 | $this->state = self::STATE_OVER; |
|
762 | 21 | unset($this->gameOrder[array_search((string) $event->getPlayerId(), $this->gameOrder)]); |
|
763 | 21 | } |
|
764 | |||
765 | /** |
||
766 | * Apply the hangman player win event |
||
767 | * |
||
768 | * @return void |
||
769 | */ |
||
770 | 6 | protected function applyHangmanPlayerWinEvent() |
|
775 | |||
776 | /** |
||
777 | * Apply the hangman lost by all event |
||
778 | * |
||
779 | * @return void |
||
780 | */ |
||
781 | 3 | protected function applyHangmanGameLostEvent() |
|
782 | { |
||
783 | 3 | $this->currentPlayer = null; |
|
784 | 3 | $this->state = self::STATE_OVER; |
|
785 | 3 | } |
|
786 | |||
787 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
788 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
789 | //////////////////////////////////////////// EVENT SOURCED ///////////////////////////////////////////////// |
||
790 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
791 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
792 | |||
793 | /** |
||
794 | * @return Player[] |
||
795 | */ |
||
796 | 111 | protected function getChildEntities() |
|
797 | { |
||
798 | 111 | return $this->getPlayers(); |
|
799 | } |
||
800 | |||
801 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
802 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
803 | ///////////////////////////////////////// STATIC CONSTRUCTOR /////////////////////////////////////////////// |
||
804 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
805 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
806 | |||
807 | /** |
||
808 | * Create a new instance |
||
809 | * |
||
810 | * @param MiniGameId $id |
||
811 | * @param string $word |
||
812 | * |
||
813 | * @return Hangman |
||
814 | */ |
||
815 | 111 | public static function createGame(MiniGameId $id, $word) |
|
822 | |||
823 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
824 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
825 | /////////////////////////////////////////// RECONSTITUTION ///////////////////////////////////////////////// |
||
826 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
827 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
828 | |||
829 | /** |
||
830 | * Static construction method for reconstitution |
||
831 | * |
||
832 | * @return Hangman |
||
833 | */ |
||
834 | 3 | public static function instantiateForReconstitution() |
|
838 | |||
839 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
840 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
841 | ///////////////////////////////////////// APPLY RESTRICTIONS /////////////////////////////////////////////// |
||
842 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
843 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
||
844 | |||
845 | |||
846 | /** |
||
847 | * @param mixed $event |
||
848 | */ |
||
849 | 111 | public function apply($event) |
|
857 | |||
858 | /** |
||
859 | * @param mixed $event |
||
860 | * |
||
861 | * @return bool |
||
862 | */ |
||
863 | 111 | private function isSupportedEvent($event) |
|
870 | } |
||
871 |