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

GameLogic::newGame()   B

Complexity

Conditions 8
Paths 24

Size

Total Lines 44
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 21
c 1
b 0
f 0
nc 24
nop 1
dl 0
loc 44
ccs 22
cts 22
cp 1
crap 8
rs 8.4444
1
<?php
2
3
namespace App\Game\BlackJack;
4
5
use App\Game\BlackJack;
6
7
class GameLogic
8
{
9
    private BlackJack $blackjack;
10
    private bool $isDealersTurn;
11
12 20
    public function __construct(BlackJack $blackjack)
13
    {
14 20
        $this->blackjack = $blackjack;
15 20
        $this->isDealersTurn = false;
16
    }
17
18
    /**
19
     * calculateWinner.
20
     */
21 12
    private function calculateWinner(int $index): void
22
    {
23
        // Get variables
24 12
        $player = $this->blackjack->getPlayers()[$index];
25 12
        $credits = $player->getCredits();
26 12
        $bet = $player->getBet();
27 12
        $gameState = $player->getGameState();
28 12
        $dealer = $this->blackjack->getDealer();
29
30
        // The winner is already decided or player broke
31 12
        if (Player::DEALER_WIN === $gameState or true === $player->isBroke()) {
32 3
            return;
33
        }
34
35
        // If player is busted dealer wins
36 10
        if (true === $player->isBust()) {
37 1
            $player->setGameState(Player::DEALER_WIN);
38 1
            $player->resetBet();
39 1
            $this->blackjack->setPlayer($index, $player);
40
41 1
            return;
42
        }
43
44
        // If dealer is bust: player wins
45 9
        if (true === $dealer->isBust()) {
46 3
            $player->setGameState(Player::PLAYER_WIN);
47 3
            $player->setCredits($credits + ($bet * 2));
48 3
            $player->resetBet();
49 3
            $this->blackjack->setPlayer($index, $player);
50
51 3
            return;
52
        }
53
54
        // Both are not busts, compare their hand values
55 6
        $playerHandValue = $player->getHandValue();
56 6
        $dealerHandValue = $dealer->getHandValue();
57
58 6
        if ($playerHandValue > $dealerHandValue) {
59 3
            $player->setGameState(Player::PLAYER_WIN);
60 3
            $player->setCredits($credits + ($bet * 2));
61 3
            $player->resetBet();
62 3
            $this->blackjack->setPlayer($index, $player);
63
64 3
            return;
65
        }
66
67 4
        if ($playerHandValue < $dealerHandValue) {
68 3
            $player->setGameState(Player::DEALER_WIN);
69 3
            $player->resetBet();
70 3
            $this->blackjack->setPlayer($index, $player);
71
72 3
            return;
73
        }
74
75 1
        $player->setGameState(Player::TIE);
76 1
        $player->setCredits($credits + $bet);
77 1
        $player->resetBet();
78 1
        $this->blackjack->setPlayer($index, $player);
79
    }
80
81
    /**
82
     * calculateAllWinners.
83
     */
84 12
    private function calculateAllWinners(): void
85
    {
86 12
        $numOfPlayers = $this->blackjack->getNumOfPlayers();
87 12
        for ($i = 0; $i < $numOfPlayers; ++$i) {
88 12
            $this->calculateWinner($i);
89
        }
90
    }
91
92
    /**
93
     * playDealer.
94
     *
95
     * The logic for the dealer to play
96
     */
97 12
    private function playDealer(): void
98
    {
99
        // Get variables
100 12
        $dealer = $this->blackjack->getDealer();
101 12
        $deck = $this->blackjack->getDeck();
102
103 12
        while (true === $dealer->play()) {
104 6
            $dealer->addCard($deck->drawCard());
105
        }
106
107
        // Set variables
108 12
        $this->blackjack->setDealer($dealer);
109 12
        $this->blackjack->setDeck($deck);
110
111
        // Calculate all winners
112 12
        $this->calculateAllWinners();
113
    }
114
115
    /**
116
     * newGame.
117
     *
118
     * Sets up a new game
119
     *
120
     * @param array<int, int> $bets
121
     */
122 13
    public function newGame(array $bets = []): void
123
    {
124
        // Get variables
125 13
        $players = $this->blackjack->getPlayers();
126 13
        $dealer = $this->blackjack->getDealer();
127 13
        $deck = $this->blackjack->getDeck();
128 13
        $numOfPlayers = $this->blackjack->getNumOfPlayers();
129
130
        // Reset game
131 13
        $dealer->dropHand();
132 13
        $deck->reshuffleDeck();
133
134
        // Set bets
135 13
        for ($i = 0; $i < $numOfPlayers; ++$i) {
136
            // Reset the player
137 13
            $players[$i]->resetBet();
138 13
            $players[$i]->dropHand();
139
140
            // If the player is broke skip
141 13
            if (true === $players[$i]->isBroke()) {
142 1
                continue;
143
            }
144
145
            // If there is a bet and it is lager then minimum
146 13
            (true === array_key_exists($i, $bets) and BlackJack::MINIMUM_BET < $bets[$i]) ? $players[$i]->increaseBet($bets[$i]) : $players[$i]->increaseBet(BlackJack::MINIMUM_BET);
147
        }
148
149
        // For 2 rounds of dealing a card
150 13
        for ($round = 0; $round < 2; ++$round) {
151 13
            for ($i = 0; $i < $numOfPlayers; ++$i) {
152
                // If the player is broke skip
153 13
                if (true === $players[$i]->isBroke()) {
154 1
                    continue;
155
                }
156
157 13
                $players[$i]->addCard($deck->drawCard());
158
            }
159 13
            $dealer->addCard($deck->drawCard());
160
        }
161
162
        // Set variables
163 13
        $this->blackjack->setPlayers($players);
164 13
        $this->blackjack->setDealer($dealer);
165 13
        $this->blackjack->setDeck($deck);
166
    }
167
168
    /**
169
     * stateOfGame.
170
     *
171
     * Returns the current game state.
172
     *
173
     * @return array
174
     *               Descriptive list of array contents:
175
     *               - numOfPlayers (int)
176
     *               - playersNames (array<string>)
177
     *               - playersCards (array<int, array<string>>)
178
     *               - playersHandValue (array<string>)
179
     *               - playersCredits (array<string>)
180
     *               - playersBets (array<string>)
181
     *               - dealerCards (array<string>)
182
     *               - dealerHandValue (string)
183
     *               - gameStates (array<string>)
184
     *
185
     * @phpstan-return array{
186
     *   numOfPlayers: int,
187
     *   playersNames: array<string>,
188
     *   playersCards: array<int, array<string>>,
189
     *   playersHandValue: array<string>,
190
     *   playersCredits: array<string>,
191
     *   playersBets: array<string>,
192
     *   dealerCards: array<string>,
193
     *   dealerHandValue: string,
194
     *   gameStates: array<string>
195
     * }
196
     */
197 11
    public function stateOfGame(): array
198
    {
199
        // Get variables
200 11
        $players = $this->blackjack->getPlayers();
201 11
        $dealer = $this->blackjack->getDealer();
202 11
        $numOfPlayers = $this->blackjack->getNumOfPlayers();
203
204 11
        $data = [
205 11
            'numOfPlayers' => $numOfPlayers,
206 11
            'playersNames' => [],
207 11
            'playersCards' => [],
208 11
            'playersHandValue' => [],
209 11
            'playersCredits' => [],
210 11
            'playersBets' => [],
211 11
            'dealerCards' => $dealer->getString(),
212 11
            'dealerHandValue' => strval($dealer->getHandValue()),
213 11
            'gameStates' => [],
214 11
        ];
215
216 11
        for ($i = 0; $i < $numOfPlayers; ++$i) {
217 11
            $data['playersNames'][$i] = $players[$i]->getName();
218 11
            $data['playersCards'][$i] = $players[$i]->getString();
219 11
            $data['playersHandValue'][$i] = strval($players[$i]->getHandValue());
220 11
            $data['playersCredits'][$i] = strval($players[$i]->getCredits());
221 11
            $data['playersBets'][$i] = strval($players[$i]->getBet());
222
223 11
            $roundState = $players[$i]->getGameState();
224
            switch ($roundState) {
225
                case Player::UNDECIDED:
226 5
                    $data['gameStates'][$i] = 'Undecided';
227 5
                    break;
228
                case Player::TIE:
229 1
                    $data['gameStates'][$i] = 'Tie';
230 1
                    break;
231
                case Player::PLAYER_WIN:
232 4
                    $data['gameStates'][$i] = 'Player';
233 4
                    break;
234
                case Player::DEALER_WIN:
235 2
                    $data['gameStates'][$i] = 'Dealer';
236 2
                    break;
237
            }
238
        }
239
240
        // If all players are not done
241 11
        if (false === $this->isDealersTurn) {
242 5
            $dealerCards = $dealer->getString();
243 5
            if (0 !== count($dealerCards)) {
244 4
                $data['dealerCards'] = [$dealerCards[0], '🂠'];
245 4
                $data['dealerHandValue'] = '0';
246
            }
247
        }
248
249 11
        return $data;
250
    }
251
252
    /**
253
     * checkIfDealersTurn.
254
     */
255 12
    public function checkIfDealersTurn(): void
256
    {
257
        // Get variables
258 12
        $players = $this->blackjack->getPlayers();
259 12
        $numOfPlayers = $this->blackjack->getNumOfPlayers();
260
261
        // Check if all players are done
262 12
        $allPlayersDone = true;
263
264 12
        for ($i = 0; $i < $numOfPlayers; ++$i) {
265 12
            $roundState = $players[$i]->getGameState();
266 12
            if (Player::UNDECIDED === $roundState) {
267 2
                $allPlayersDone = false;
268 2
                break;
269
            }
270
        }
271
272 12
        if (true === $allPlayersDone) {
273 12
            $this->isDealersTurn = true;
274 12
            $this->playDealer();
275
        }
276
    }
277
}
278