Passed
Push — main ( 101f2d...06b8a6 )
by Emil
25:10
created

BlackJack::stateOfGame()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 1
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace App\Game;
4
5
use App\Cards\DeckOfCards;
6
use App\Game\BlackJack\Dealer;
7
use App\Game\BlackJack\GameLogic;
8
use App\Game\BlackJack\Player;
9
10
/**
11
 * BlackJack.
12
 */
13
class BlackJack
14
{
15
    public const MAX_PLAYERS = 7;
16
    public const MINIMUM_BET = 50;
17
18
    private GameLogic $gameLogic;
19
    private int $numOfPlayers;
20
    /**
21
     * @var array<Player> Is an array that contains BlackJackPlayer objects
22
     */
23
    private array $players;
24
    private Dealer $dealer;
25
    private DeckOfCards $deck;
26
27
    /**
28
     * __construct.
29
     *
30
     * Constructor of the class
31
     *
32
     * @return void
33
     */
34 22
    public function __construct(int $numOfPlayers = 1)
35
    {
36 22
        if ($numOfPlayers < 1) {
37 1
            throw new \RuntimeException("Can't have less then one player in Black Jack");
38
        }
39
40 21
        if ($numOfPlayers > self::MAX_PLAYERS) {
41 1
            throw new \RuntimeException('Maximum of '.self::MAX_PLAYERS.' players in Black Jack');
42
        }
43
44 20
        $this->numOfPlayers = $numOfPlayers;
45 20
        $this->deck = new DeckOfCards();
46 20
        $this->dealer = new Dealer();
47 20
        for ($i = 0; $i < $this->numOfPlayers; ++$i) {
48 20
            $this->players[$i] = new Player();
49
        }
50
51
        // Needs to be last or can create error if accessing any BlackJack properties before set
52 20
        $this->gameLogic = new GameLogic($this);
53
    }
54
55
    /**
56
     * drawUpdate.
57
     */
58 4
    private function drawUpdate(int $index): void
59
    {
60 4
        if ($this->players[$index]->isBust()) {
61 2
            $this->players[$index]->setGameState(Player::DEALER_WIN);
62 2
            $this->players[$index]->resetBet();
63 2
            $this->gameLogic->checkIfDealersTurn();
64
        }
65
66 4
        if (Player::DOUBLE_DOWN === $this->players[$index]->getGameState()) {
67 2
            $this->gameLogic->checkIfDealersTurn();
68
        }
69
    }
70
71
    /**
72
     * getNumOfPlayers.
73
     */
74 19
    public function getNumOfPlayers(): int
75
    {
76 19
        return $this->numOfPlayers;
77
    }
78
79
    /**
80
     * getPlayers.
81
     *
82
     * @return array<Player>
83
     */
84 19
    public function getPlayers(): array
85
    {
86 19
        return $this->players;
87
    }
88
89
    /**
90
     * getDealer.
91
     */
92 19
    public function getDealer(): Dealer
93
    {
94 19
        return $this->dealer;
95
    }
96
97
    /**
98
     * getDeck.
99
     */
100 19
    public function getDeck(): DeckOfCards
101
    {
102 19
        return $this->deck;
103
    }
104
105
    /**
106
     * setPlayers.
107
     *
108
     * @param array<Player> $players
109
     */
110 19
    public function setPlayers(array $players): void
111
    {
112
        // If not to many players
113 19
        if (self::MAX_PLAYERS >= count($players)) {
114 19
            $this->players = $players;
115 19
            $this->numOfPlayers = count($players);
116
        }
117
    }
118
119
    /**
120
     * setPlayer.
121
     */
122 11
    public function setPlayer(int $index, Player $player): void
123
    {
124
        // If index is out of bounds
125 11
        if ($index < 0 or $index >= $this->numOfPlayers) {
126 1
            return;
127
        }
128
129 11
        $this->players[$index] = $player;
130
    }
131
132
    /**
133
     * setDealer.
134
     */
135 19
    public function setDealer(Dealer $dealer): void
136
    {
137 19
        $this->dealer = $dealer;
138
    }
139
140
    /**
141
     * setDeck.
142
     */
143 19
    public function setDeck(DeckOfCards $deck): void
144
    {
145 19
        $this->deck = $deck;
146
    }
147
148
    /**
149
     * isPlayerBust.
150
     *
151
     * Returns if the player's hand value is over 21
152
     */
153 5
    public function isPlayerBust(int $index = 0): bool
154
    {
155 5
        return $this->players[$index]->isBust();
156
    }
157
158
    /**
159
     * isDealerBust.
160
     *
161
     * Returns if the dealer's hand value is over 21
162
     */
163 2
    public function isDealerBust(): bool
164
    {
165 2
        return $this->dealer->isBust();
166
    }
167
168
    /**
169
     * newGame.
170
     *
171
     * Sets up a new game
172
     *
173
     * @param array<int, int> $bets
174
     */
175 11
    public function newGame(array $bets = []): void
176
    {
177 11
        $this->gameLogic->newGame($bets);
178
    }
179
180
    /**
181
     * stateOfGame.
182
     *
183
     * Returns the current game state.
184
     *
185
     * @return array
186
     *               Descriptive list of array contents:
187
     *               - numOfPlayers (int)
188
     *               - playersNames (array<string>)
189
     *               - playersCards (array<int, array<string>>)
190
     *               - playersHandValue (array<string>)
191
     *               - playersCredits (array<string>)
192
     *               - playersBets (array<string>)
193
     *               - dealerCards (array<string>)
194
     *               - dealerHandValue (string)
195
     *               - gameStates (array<string>)
196
     *
197
     * @phpstan-return array{
198
     *   numOfPlayers: int,
199
     *   playersNames: array<string>,
200
     *   playersCards: array<int, array<string>>,
201
     *   playersHandValue: array<string>,
202
     *   playersCredits: array<string>,
203
     *   playersBets: array<string>,
204
     *   dealerCards: array<string>,
205
     *   dealerHandValue: string,
206
     *   gameStates: array<string>
207
     * }
208
     */
209 5
    public function stateOfGame(): array
210
    {
211 5
        return $this->gameLogic->stateOfGame();
212
    }
213
214
    /**
215
     * stayPlayer.
216
     */
217 3
    public function stayPlayer(int $index = 0): void
218
    {
219
        // If index is out of bounds
220 3
        if ($index < 0 or $index >= $this->numOfPlayers) {
221 1
            return;
222
        }
223
224
        // If game not over
225 3
        if (Player::UNDECIDED === $this->players[$index]->getGameState()) {
226 3
            $this->players[$index]->setGameState(Player::STAYED);
227 3
            $this->gameLogic->checkIfDealersTurn();
228
        }
229
    }
230
231
    /**
232
     * hitPlayer.
233
     */
234 3
    public function hitPlayer(int $index = 0): void
235
    {
236
        // If index is out of bounds
237 3
        if ($index < 0 or $index >= $this->numOfPlayers) {
238 1
            return;
239
        }
240
241
        // Stops drawing new cards if game is over
242 3
        if (Player::UNDECIDED === $this->players[$index]->getGameState()) {
243 3
            $this->players[$index]->addCard($this->deck->drawCard());
244
245 3
            $this->drawUpdate($index);
246
        }
247
    }
248
249 2
    public function doubleDownPlayer(int $index = 0): void
250
    {
251
        // If index is out of bounds
252 2
        if ($index < 0 or $index >= $this->numOfPlayers) {
253 1
            return;
254
        }
255
256
        // Can't double down if game is over
257 2
        if (Player::UNDECIDED === $this->players[$index]->getGameState() and 2 === count($this->players[$index]->getString())) {
258
            // Double bet
259 2
            $currentBet = $this->players[$index]->getBet();
260 2
            $this->players[$index]->increaseBet($currentBet);
261
262 2
            $this->players[$index]->addCard($this->deck->drawCard());
263
264 2
            $this->players[$index]->setGameState(Player::DOUBLE_DOWN);
265
266 2
            $this->drawUpdate($index);
267
        }
268
    }
269
}
270