Completed
Push — master ( ab8332...e88ec9 )
by Rémi
03:04
created

Hangman::playerWins()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 13
ccs 8
cts 8
cp 1
rs 9.2
cc 4
eloc 7
nc 3
nop 1
crap 4
1
<?php
2
3
namespace Hangman\Entity;
4
5
use Broadway\EventSourcing\EventSourcedAggregateRoot;
6
use Hangman\Event\HangmanGameCreatedEvent;
7
use Hangman\Event\HangmanGameFailedStartingEvent;
8
use Hangman\Event\HangmanGameLostEvent;
9
use Hangman\Event\HangmanGameStartedEvent;
10
use Hangman\Event\HangmanPlayerCreatedEvent;
11
use Hangman\Event\HangmanPlayerFailedCreatingEvent;
12
use Hangman\Event\HangmanPlayerLostEvent;
13
use Hangman\Event\HangmanPlayerProposedInvalidAnswerEvent;
14
use Hangman\Event\HangmanPlayerTriedPlayingDuringAnotherPlayerTurnEvent;
15
use Hangman\Event\HangmanPlayerTriedPlayingInactiveGameEvent;
16
use Hangman\Event\HangmanPlayerTurnEvent;
17
use Hangman\Exception\HangmanException;
18
use Hangman\Exception\HangmanPlayerOptionsException;
19
use Hangman\Move\Answer;
20
use Hangman\Move\Proposition;
21
use Hangman\Options\HangmanPlayerOptions;
22
use Hangman\Result\HangmanBadProposition;
23
use Hangman\Result\HangmanGoodProposition;
24
use Hangman\Result\HangmanLost;
25
use Hangman\Result\HangmanWon;
26
use Hangman\Word;
27
use MiniGame\Entity\MiniGame;
28
use MiniGame\Entity\MiniGameId;
29
use MiniGame\Entity\Player;
30
use MiniGame\Entity\PlayerId;
31
use MiniGame\Entity\PlayTrait;
32
use MiniGame\GameResult;
33
use MiniGame\PlayerOptions;
34
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 Word
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 87
    public function getId()
112
    {
113 87
        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)
190
    {
191 36
        return $this->currentPlayer && $this->currentPlayer->getId()->equals($playerId);
192
    }
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)
208
    {
209 51
        if ($this->state !== self::STATE_READY) {
210 3
            $event = new HangmanGameFailedStartingEvent(
211 3
                $this->id,
212 2
                $playerId,
213 1
                HangmanGameFailedStartingEvent::BAD_STATE
214 2
            );
215 3
            $this->apply($event);
216 3
            return $event;
217
        }
218
219 51
        if (count($this->players) === 0) {
220 3
            $event = new HangmanGameFailedStartingEvent(
221 3
                $this->id,
222 2
                $playerId,
223 1
                HangmanGameFailedStartingEvent::NO_PLAYER
224 2
            );
225 3
            $this->apply($event);
226 3
            return $event;
227
        }
228
229 48
        $event = new HangmanGameStartedEvent($this->id, $playerId);
230 48
        $this->apply($event);
231
232 48
        $this->setNextPlayer($playerId);
233
234 48
        return $event;
235
    }
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 66
    public function addPlayerToGame(PlayerOptions $playerOptions)
248
    {
249 66
        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 63
        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 63
        $event = new HangmanPlayerCreatedEvent(
268 63
            $this->id,
269 63
            $playerOptions->getPlayerId(),
270 63
            $playerOptions->getName(),
271 63
            $playerOptions->getLives(),
272 63
            $playerOptions->getExternalReference()
273 42
        );
274 63
        $this->apply($event);
275 63
        return $event;
276
    }
277
278
    /**
279
     * A player leaves the game
280
     *
281
     * @param PlayerId $playerId
282
     *
283
     * @return GameResult
284
     */
285 19
    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 18
        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->word->contains($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->word->equals($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
        $event = $player->win($this->word);
484
485 6
        foreach ($this->players as $otherPlayer) {
486 6
            if ($otherPlayer->equals($player) || $otherPlayer->hasLost()) {
487 6
                continue;
488
            }
489 6
            $otherPlayer->lose($this->word);
490 4
        }
491
492 6
        return $event;
493
    }
494
495
    /**
496
     * Function to call when game is lost by a player
497
     *
498
     * @param HangmanPlayer $player
499
     *
500
     * @return hangmanLost | HangmanGameLostEvent
501
     */
502 15
    private function playerLoses(HangmanPlayer $player)
503
    {
504 15
        $event = $player->lose($this->word);
505
506 15
        if ($this->thereIsAnInGamePlayer() &&
507 15
            $this->currentPlayer &&
508 13
            $player->equals($this->currentPlayer)
509 10
        ) {
510 12
            $this->setNextPlayer($this->getNextPlayerId());
511 12
            return $event;
512
        }
513
514 3
        $event = new HangmanGameLostEvent(
515 3
            $this->id,
516 3
            $player->getId(),
517 3
            (string) $this->word
518 2
        );
519 3
        $this->apply($event);
520
521 3
        return $event;
522
    }
523
524
    /**
525
     * Sets the next player
526
     *
527
     * @param PlayerId $id
528
     */
529 48
    private function setNextPlayer(PlayerId $id = null)
530
    {
531 48
        if ($id === null || ($this->currentPlayer && $this->currentPlayer->getId()->equals($id))) {
532
            return;
533
        }
534
535 48
        $this->apply(
536 48
            new HangmanPlayerTurnEvent($this->getId(), $id)
537 32
        );
538 48
    }
539
540
    /**
541
     * Returns the next player in line
542
     *
543
     * @return PlayerId
544
     */
545 18
    private function getNextPlayerId()
546
    {
547 18
        $nbPlayers = count($this->gameOrder);
548 18
        $currentPlayerId = (string)$this->currentPlayer->getId();
549 18
        $nextPlayerPosition = (array_search($currentPlayerId, $this->gameOrder) + 1) % $nbPlayers;
550
551 18
        $pos = $nextPlayerPosition;
552
        do {
553 18
            $id = PlayerId::create($this->gameOrder[$pos]);
554 18
            $player = $this->getPlayer($id);
555
556 18
            if ($player->getState() === HangmanPlayer::STATE_IN_GAME) {
557 18
                return $id;
558
            }
559
560
            $pos = ($pos + 1) % $nbPlayers;
561
        } while ($pos !== $nextPlayerPosition);
562
563
        return null;
564
    }
565
566
    /**
567
     * Build the word from played letters
568
     *
569
     * @param string[] $playedLetters
570
     *
571
     * @return string
572
     */
573 42
    public function buildWord($playedLetters)
574
    {
575 42
        return $this->word->buildWord($playedLetters);
576
    }
577
578
    /**
579
     * Checks if all letters for the word have been found
580
     *
581
     * @param HangmanPlayer $player
582
     *
583
     * @return bool
584
     */
585 6
    private function isAllLettersFoundForPlayer(HangmanPlayer $player)
586
    {
587 6
        $wordLetters = $this->word->getLetters();
588 6
        $playerLetters = $player->getPlayedLetters();
589 6
        return count(array_intersect($wordLetters, $playerLetters)) == count($wordLetters);
590
    }
591
592
    /**
593
     * Checks if the answer is valid
594
     * If it's not, ends player turn and throws an HangmanException
595
     *
596
     * @param string $answer
597
     *
598
     * @throws HangmanException
599
     */
600 12
    private function checkAnswerIsValid($answer)
601
    {
602 12
        if (! $this->word->isValid($answer)) {
603 3
            throw new HangmanException(sprintf('"%s" is not a valid answer!', $answer));
604
        }
605 9
    }
606
607
    /**
608
     * @return bool
609
     */
610 15
    private function thereIsAnInGamePlayer()
611
    {
612 15
        foreach ($this->gameOrder as $gameOrder) {
613 15
            $player = $this->getPlayer(PlayerId::create($gameOrder));
614
615 15
            if ($player->getState() === HangmanPlayer::STATE_IN_GAME) {
616 13
                return true;
617
            }
618 10
        }
619
620 3
        return false;
621
    }
622
623
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
624
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
625
    ////////////////////////////////////////////   APPLY EVENTS   //////////////////////////////////////////////////
626
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
627
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
628
629
    /**
630
     * Apply the game created event
631
     *
632
     * @param HangmanGameCreatedEvent $event
633
     *
634
     * @return void
635
     */
636 111
    protected function applyHangmanGameCreatedEvent(HangmanGameCreatedEvent $event)
637
    {
638 111
        $this->id = $event->getGameId();
639 111
        $this->word = new Word($event->getWord());
640 111
        $this->players = [];
641 111
        $this->gameOrder = [];
642 111
        $this->state = self::STATE_READY;
643 111
    }
644
645
    /**
646
     * Apply the player created event
647
     *
648
     * @param HangmanPlayerCreatedEvent $event
649
     *
650
     * @return void
651
     */
652 63
    protected function applyHangmanPlayerCreatedEvent(HangmanPlayerCreatedEvent $event)
653
    {
654 63
        $player = new HangmanPlayer(
655 63
            $event->getPlayerId(),
656 63
            $event->getPlayerName(),
657 63
            $event->getLives(),
658 42
            $this,
659 63
            $event->getExternalReference()
660 42
        );
661
662 63
        $this->gameOrder[] = (string)$player->getId();
663 63
        $this->players[(string)$player->getId()] = $player;
664 63
    }
665
666
    /**
667
     * Apply the game created event
668
     */
669 48
    protected function applyHangmanGameStartedEvent()
670
    {
671 48
        $this->state = self::STATE_STARTED;
672 48
    }
673
674
    /**
675
     * Apply the player turn event
676
     *
677
     * @param HangmanPlayerTurnEvent $event
678
     */
679 48
    protected function applyHangmanPlayerTurnEvent(HangmanPlayerTurnEvent $event)
680
    {
681 48
        $this->currentPlayer = $this->getPlayer($event->getPlayerId());
682 48
    }
683
684
    /**
685
     * Apply the hangman player lost event
686
     *
687
     * @param HangmanPlayerLostEvent $event
688
     */
689 21
    protected function applyHangmanPlayerLostEvent(HangmanPlayerLostEvent $event)
0 ignored issues
show
Unused Code introduced by
The parameter $event is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
690
    {
691 21
        $this->state = self::STATE_OVER;
692 21
    }
693
694
    /**
695
     * Apply the hangman player win event
696
     *
697
     * @return void
698
     */
699 6
    protected function applyHangmanPlayerWinEvent()
700
    {
701 6
        $this->currentPlayer = null;
702 6
        $this->state = self::STATE_OVER;
703 6
    }
704
705
    /**
706
     * Apply the hangman lost by all event
707
     *
708
     * @return void
709
     */
710 3
    protected function applyHangmanGameLostEvent()
711
    {
712 3
        $this->currentPlayer = null;
713 3
        $this->state = self::STATE_OVER;
714 3
    }
715
716
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
717
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
718
    ////////////////////////////////////////////   EVENT SOURCED   /////////////////////////////////////////////////
719
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
720
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
721
722
    /**
723
     * @return Player[]
724
     */
725 111
    protected function getChildEntities()
726
    {
727 111
        return $this->getPlayers();
728
    }
729
730
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
731
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
732
    /////////////////////////////////////////   STATIC CONSTRUCTOR   ///////////////////////////////////////////////
733
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
734
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
735
736
    /**
737
     * Create a new instance
738
     *
739
     * @param MiniGameId $id
740
     * @param string     $word
741
     *
742
     * @return Hangman
743
     */
744 111
    public static function createGame(MiniGameId $id, $word)
745
    {
746 111
        $hangman = new self();
747 111
        $hangman->initialize($id, $word);
748
749 111
        return $hangman;
750
    }
751
752
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
753
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
754
    ///////////////////////////////////////////   RECONSTITUTION   /////////////////////////////////////////////////
755
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
756
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
757
758
    /**
759
     * Static construction method for reconstitution
760
     *
761
     * @return Hangman
762
     */
763 3
    public static function instantiateForReconstitution()
764
    {
765 3
        return new self();
766
    }
767
768
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
769
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
770
    /////////////////////////////////////////   APPLY RESTRICTIONS   ///////////////////////////////////////////////
771
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
772
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
773
774
    /**
775
     * @param mixed $event
776
     */
777 111
    public function apply($event)
778
    {
779 111
        if (! $this->isSupportedEvent($event)) {
780
            return;
781
        }
782
783 111
        parent::apply($event);
784 111
    }
785
786
    /**
787
     * @param mixed $event
788
     *
789
     * @return bool
790
     */
791 111
    private function isSupportedEvent($event)
792
    {
793
        return (
794 111
            $event instanceof GameResult &&
795 111
            ($this->id === null || $this->id == $event->getGameId())
796 74
        );
797
    }
798
}
799