Passed
Push — main ( 22e7dc...c4a240 )
by Karl
05:37
created

DeckOfCards::dealCards()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
c 3
b 0
f 0
nc 3
nop 2
dl 0
loc 14
rs 9.9666
ccs 7
cts 7
cp 1
crap 3
1
<?php
2
3
namespace App\Model;
4
5
use SplSubject;
6
use SplObjectStorage;
7
use SplObserver;
8
use Exception;
9
10
abstract class DeckOfCards implements SplSubject
11
{
12
    /**
13
     * @var array<string> The suits of the cards in a deck.
14
     */
15
    public static $suitsOfCards = ['Spade', 'Diamond', 'Heart', 'Club'];
16
17
    public static $namesOfCards = [
18
        'Ace' => [1, 14],
19
        '2' => [2],
20
        '3' => [3],
21
        '4' => [4],
22
        '5' => [5],
23
        '6' => [6],
24
        '7' => [7],
25
        '8' => [8],
26
        '9' => [9],
27
        '10' => [10],
28
        'Jack' => [11],
29
        'Queen' => [12],
30
        'King' => [13],
31
    ];
32
    /**
33
     * @var array<Card> The array of cards in the deck.
34
     **/
35
    public array $cards = [];
36
37
    protected SplObjectStorage $observers;
38
39
    protected bool $isShuffled = false;
40
41
    /**
42
     * Constructor for the DeckOfCards class.
43
     *
44
     * @param array $observers An optional array of observer objects to attach to the deck.
45
     */
46
    public function __construct(array $observers = [])
47
    {
48
        $this->observers = new SplObjectStorage();
49
        foreach ($observers as $observer) {
50 17
            $this->attach($observer);
51
        }
52 17
    }
53 17
54 17
    public function getObservers(): SplObjectStorage
55 1
    {
56
        return $this->observers;
57
    }
58
59 1
    public function attach(SplObserver $observer): void
60
    {
61 1
        $this->observers->attach($observer);
62
    }
63
    public function detach(SplObserver $observer): void
64 2
    {
65
        $this->observers->detach($observer);
66 2
    }
67
    public function notify(): void
68 1
    {
69
        foreach ($this->observers as $observer) {
70 1
            $observer->update($this->getDeck());
71
        }
72 16
    }
73
74 16
    abstract public static function create(array $observers = []): DeckOfCards;
75
76
    abstract public function sort(): void;
77
78
    public function addCard(Card $card): void
79
    {
80
        $this->cards[] = $card;
81
        $this->notify();
82
    }
83
84
    /**
85
     * Get the deck of cards.
86
     *
87
     * @return array<Card> The array representing the deck of cards.
88
     */
89
    public function getDeck(): array
90
    {
91
        return $this->cards;
92
    }
93
94
    public function setDeck(array $cards): void
95
    {
96
        $this->cards = $cards;
97
        $this->notify();
98
    }
99
100
    public function hasCards(): bool
101
    {
102
        return count($this->cards) > 0;
103
    }
104
105 16
    public function getNumberOfCards(): int
106
    {
107 16
        return count($this->cards);
108 16
    }
109
110
    /**
111 3
     * Draws a specified number of cards from the deck.
112
     *
113
     * @param int $numberOfCards The number of cards to draw.
114 3
     * @return array<Card> An array of drawn cards.
115 3
     */
116 3
    public function drawCards(int $numberOfCards): array
117
    {
118
        $cards = [];
119
        for ($i = 0; $i < $numberOfCards; $i++) {
120
            if (!$this->hasCards()) {
121
                throw new Exception('No cards left in the deck');
122
            }
123
            $cards[] = array_pop($this->cards);
124 3
            $this->notify();
125
        }
126 3
        return $cards;
127
    }
128
129 3
    /**
130
     * Deals a specified number of cards to a specified number of players.
131 3
     *
132
     * @param int $numberOfPlayers The number of players to deal cards to.
133
     * @param int $numberOfCards The number of cards to deal to each player.
134 1
     * @return array<CardHand> An array of CardHand objects representing the hands of each player.
135
     */
136 1
    public function dealCards(int $numberOfPlayers, int $numberOfCards): array
137
    {
138
        $hands = [];
139
        for ($i = 0; $i < $numberOfPlayers; $i++) {
140
            $hand = new CardHand();
141 3
            for ($j = 0; $j < $numberOfCards; $j++) {
142
                $card = $this->drawCards(1)[0];
143 3
                $hand->addCard($card);
144 1
            }
145
            $hands[] = $hand;
146 3
        }
147 3
148 3
        $this->notify();
149
        return $hands;
150
    }
151
}
152