Turn::isNotOf()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\CardGame\Match;
4
5
use function array_merge;
6
use function assert;
7
use DateTimeInterface;
8
use Stratadox\CardGame\Match\Event\MatchStarted;
9
use Stratadox\CardGame\Match\Event\NextTurnStarted;
10
11
final class Turn
12
{
13
    /** @var int */
14
    private $currentPlayer;
15
    /** @var TurnPhase */
16
    private $phase;
17
    /** @var MatchEvent[] */
18
    private $events;
19
20
    private function __construct(
21
        int $currentPlayer,
22
        TurnPhase $phase,
23
        MatchEvent ...$events
24
    ) {
25
        $this->currentPlayer = $currentPlayer;
26
        $this->phase = $phase;
27
        $this->events = $events;
28
    }
29
30
    public static function first(
31
        int $player,
32
        DateTimeInterface $since,
33
        MatchId $match
34
    ): Turn {
35
        return new Turn(
36
            $player,
37
            TurnPhase::play($since, $match),
38
            new MatchStarted($match, $player)
39
        );
40
    }
41
42
    /** @throws NotYourTurn */
43
    public function mustAllowCardPlaying(
44
        int $player,
45
        DateTimeInterface $now
46
    ): void {
47
        if ($this->isNotOf($player) || $this->phase->prohibitsPlaying($now)) {
48
            throw NotYourTurn::cannotPlayCards();
49
        }
50
    }
51
52
    /** @throws NotYourTurn */
53
    public function mustAllowAttacking(
54
        int $player,
55
        DateTimeInterface $now
56
    ): void {
57
        if ($this->isNotOf($player) || $this->phase->prohibitsAttacking($now)) {
58
            throw NotYourTurn::cannotAttack();
59
        }
60
    }
61
62
    /** @throws NotYourTurn */
63
    public function mustAllowDefending(
64
        int $player,
65
        DateTimeInterface $now
66
    ): void {
67
        if ($this->isNotOf($player) || $this->phase->prohibitsDefending($now)) {
68
            throw NotYourTurn::cannotDefend();
69
        }
70
    }
71
72
    /** @throws NotYourTurn */
73
    public function mustAllowStartingCombat(int $player): void
74
    {
75
        if ($this->isNotOf($player) || $this->phase->prohibitsCombat()) {
76
            throw NotYourTurn::cannotStartCombat();
77
        }
78
    }
79
80
    public function events(): array
81
    {
82
        return array_merge($this->events, $this->phase->events());
83
    }
84
85
    public function hasNotHadCombatYet(): bool
86
    {
87
        return !$this->phase->isAfterCombat();
88
    }
89
90
    public function hasExpired(DateTimeInterface $now): bool
91
    {
92
        return $this->phase->hasExpired($now);
93
    }
94
95
    public function currentPlayer(): int
96
    {
97
        return $this->currentPlayer;
98
    }
99
100
    /** @throws NotYourTurn */
101
    public function endCardPlayingPhaseFor(
102
        int $player,
103
        DateTimeInterface $now,
104
        MatchId $match
105
    ): Turn {
106
        if ($this->isNotOf($player)) {
107
            throw NotYourTurn::cannotEndCardPlayingPhase();
108
        }
109
        return new Turn($this->currentPlayer, $this->phase->startAttack($now, $match));
110
    }
111
112
    public function startPlayPhase(DateTimeInterface $now, MatchId $match): Turn
113
    {
114
        return new Turn($this->currentPlayer, $this->phase->startPlay($now, $match));
115
    }
116
117
    /** @throws NotYourTurn */
118
    public function beginTheTurnOf(
119
        int $player,
120
        DateTimeInterface $now,
121
        int $previousPlayer,
122
        bool $shouldDefendFirst,
123
        MatchId $match
124
    ): Turn {
125
        if ($this->isNotOf($previousPlayer)) {
126
            throw NotYourTurn::cannotEndTurn();
127
        }
128
        return new Turn(
129
            $player,
130
            TurnPhase::defendOrPlay($shouldDefendFirst, $now, $match),
131
            new NextTurnStarted($match, $player)
132
        );
133
    }
134
135
    /** @throws NoNextPhase|NeedCombatFirst */
136
    public function endExpiredPhase(DateTimeInterface $now, MatchId $match): Turn
137
    {
138
        assert($this->hasExpired($now));
139
140
        return new self($this->currentPlayer, $this->phase->next($now, $match));
141
    }
142
143
    private function isNotOf(int $player): bool
144
    {
145
        return $this->currentPlayer !== $player;
146
    }
147
}
148