Dealer::dealCardsToPlayers()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 0
cp 0
rs 9.0856
c 0
b 0
f 0
cc 2
eloc 13
nc 1
nop 1
crap 6
1
<?php
2
3
namespace Cysha\Casino\Holdem\Game;
4
5
use Cysha\Casino\Cards\Card;
6
use Cysha\Casino\Cards\CardCollection;
7
use Cysha\Casino\Cards\Contracts\CardEvaluator;
8
use Cysha\Casino\Cards\Deck;
9
use Cysha\Casino\Cards\Hand;
10
use Cysha\Casino\Cards\HandCollection;
11
use Cysha\Casino\Cards\ResultCollection;
12
use Cysha\Casino\Game\Contracts\Dealer as DealerContract;
13
use Cysha\Casino\Game\Contracts\Player as PlayerContract;
14
use Cysha\Casino\Game\Dealer as BaseDealer;
15
use Cysha\Casino\Game\PlayerCollection;
16
use Cysha\Casino\Holdem\Exceptions\RoundException;
17
18
class Dealer extends BaseDealer implements DealerContract
19
{
20
    /**
21
     * @var Deck
22
     */
23
    private $deck;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
24
25
    /**
26
     * @var CardEvaluator
27
     */
28
    private $cardEvaluationRules;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
29
30
    /**
31 78
     * @var CardCollection
32
     */
33 78
    private $communityCards;
34 78
35 78
    /**
36
     * @var CardCollection
37
     */
38
    private $burnCards;
39
40
    /**
41
     * @var HandCollection
42
     */
43 78
    private $hands;
44
45 78
    /**
46
     * Dealer constructor.
47
     *
48
     * @param Deck          $deck
49
     * @param CardEvaluator $cardEvaluationRules
50
     */
51 50
    private function __construct(Deck $deck, CardEvaluator $cardEvaluationRules)
0 ignored issues
show
Bug introduced by
Consider using a different method name as you override a private method of the parent class.

Overwriting private methods is generally fine as long as you also use private visibility. It might still be preferable for understandability to use a different method name.

Loading history...
52
    {
53 50
        $this->deck = $deck;
54
        $this->cardEvaluationRules = $cardEvaluationRules;
55
56
        $this->communityCards = CardCollection::make();
57
        $this->burnCards = CardCollection::make();
58
        $this->hands = HandCollection::make();
59 23
    }
60
61 23
    /**
62
     * @param Deck          $deck
63
     * @param CardEvaluator $cardEvaluationRules
64
     *
65
     * @return Dealer
66
     */
67 50
    public static function startWork(Deck $deck, CardEvaluator $cardEvaluationRules)
68
    {
69 50
        return new self($deck, $cardEvaluationRules);
70 50
    }
71
72
    /**
73
     * @return Deck
74
     */
75
    public function deck(): Deck
76
    {
77
        return $this->deck;
78 22
    }
79
80 22
    /**
81
     * @return CardCollection
82
     */
83
    public function communityCards(): CardCollection
84
    {
85
        return $this->communityCards;
86
    }
87
88
    /**
89
     * @return CardCollection
90
     */
91
    public function burnCards(): CardCollection
92
    {
93
        return $this->burnCards;
94
    }
95
96
    /**
97
     * @return Card
98
     */
99
    public function dealCard(): Card
100
    {
101
        return $this->deck()->draw();
102
    }
103
104
    /**
105
     * @return HandCollection
106
     */
107
    public function hands(): HandCollection
108
    {
109
        return $this->hands;
110
    }
111
112
    /**
113
     * Shuffles the deck.
114
     */
115
    public function shuffleDeck()
116
    {
117
        $this->deck()->shuffle();
118
    }
119
120
    /**
121
     * Adds a card to the BurnCards(), also Adds a card to the CommunityCards().
122
     *
123
     * @param int $cards
124
     */
125
    public function dealCommunityCards(int $cards = 1)
126
    {
127
        // burn one
128
        $this->burnCards()->push($this->dealCard());
129
130
        // deal
131
        for ($i = 0; $i < $cards; ++$i) {
132
            $this->communityCards()->push($this->dealCard());
133
        }
134
    }
135
136
    /**
137
     * Deals the remainder of the community cards, whilst taking burn cards into account.
138
     */
139
    public function checkCommunityCards()
140
    {
141
        if ($this->communityCards()->count() === 5) {
142
            return;
143
        }
144
145
        if ($this->communityCards()->count() === 0) {
146
            $this->dealCommunityCards(3);
147
        }
148
149
        if ($this->communityCards()->count() === 3) {
150
            $this->dealCommunityCards(1);
151
        }
152
153
        if ($this->communityCards()->count() === 4) {
154
            $this->dealCommunityCards(1);
155
        }
156
    }
157
158
    /**
159
     * Deal the hands to the players.
160
     */
161
    public function dealHands(PlayerCollection $players)
162
    {
163
        $this->hands = $this->dealCardsToPlayers($players);
164
    }
165
166
    /**
167
     * @param PlayerContract $player
168
     *
169
     * @return Hand
170
     */
171
    public function playerHand(PlayerContract $player): Hand
172
    {
173
        $hand = $this->hands()->findByPlayer($player);
174
175
        if ($hand === null) {
176
            throw RoundException::playerHasNoHand($player);
177
        }
178
179
        return $hand;
180
    }
181
182
    /**
183
     * @return HandCollection
184
     */
185
    public function dealCardsToPlayers(PlayerCollection $players): HandCollection
186
    {
187
        $hands = HandCollection::make();
188
189
        // deal to the player after the button first
190
        $players
191
            ->each(function (PlayerContract $player) use ($hands) {
192
                $hands->push(Hand::create(CardCollection::make([
193
                    $this->dealCard(),
194
                ]), $player));
195
            })
196
            ->each(function (PlayerContract $player) use ($hands) {
197
                $hands->map(function (Hand $hand) use ($player, $hands) {
198
                    if ($hand->player()->equals($player) === false) {
199
                        return false;
200
                    }
201
202
                    return $hand->addCard($this->dealCard());
203
                });
204
            });
205
206
        return $hands;
207
    }
208
209
    /**
210
     * @param CardCollection $board
211
     * @param HandCollection $playerHands
212
     *
213
     * @return ResultCollection
214
     */
215
    public function evaluateHands(CardCollection $board, HandCollection $playerHands): ResultCollection
216
    {
217
        return $this->cardEvaluationRules->evaluateHands($board, $playerHands);
218
    }
219
}
220