testGetOrderedByLowestCount()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 24
rs 9.7998
cc 3
nc 4
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArpTest\DominoGame\Value;
6
7
use Arp\DominoGame\Exception\DominoGameException;
8
use Arp\DominoGame\Value\CollectionInterface;
9
use Arp\DominoGame\Value\Domino;
10
use Arp\DominoGame\Value\Player;
11
use Arp\DominoGame\Value\PlayerCollection;
12
use PHPUnit\Framework\MockObject\MockObject;
13
use PHPUnit\Framework\TestCase;
14
15
/**
16
 * @author  Alex Patterson <[email protected]>
17
 * @package ArpTest\Value\PlayerTest
18
 */
19
final class PlayerCollectionTest extends TestCase
20
{
21
    /**
22
     * Assert that the collection implements CollectionInterface.
23
     *
24
     * @covers \Arp\DominoGame\Value\PlayerCollection::__construct
25
     */
26
    public function testImplementsCollectionInterface(): void
27
    {
28
        $collection = new PlayerCollection([]);
29
30
        $this->assertInstanceOf(CollectionInterface::class, $collection);
31
    }
32
33
    /**
34
     * Assert that calls to getOrderedByLowestCount() will return a new collection of players that is ordered
35
     * by the number of cards they have in ascending order.
36
     *
37
     * @covers \Arp\DominoGame\Value\PlayerCollection::getOrderedByLowestCount
38
     *
39
     * @throws \Exception
40
     */
41
    public function testGetOrderedByLowestCount(): void
42
    {
43
        /** @var Player[]|MockObject[] $players */
44
        $players = [
45
            $this->createMock(Player::class),
46
            $this->createMock(Player::class),
47
            $this->createMock(Player::class),
48
        ];
49
50
        $randomHandCounts = [];
51
        foreach ($players as $player) {
52
            $randomHandCount = random_int(1, 28);
53
            $player->method('getHandCount')->willReturn($randomHandCount);
54
            $randomHandCounts[] = $randomHandCount;
55
        }
56
57
        $expectedOrders = $randomHandCounts;
58
        sort($expectedOrders, SORT_NUMERIC);
59
60
        $collection = (new PlayerCollection($players))->getOrderedByLowestCount();
61
62
        /** @var Player $player */
63
        foreach ($collection->getElements() as $index => $player) {
64
            $this->assertSame($expectedOrders[$index], $player->getHandCount());
65
        }
66
    }
67
68
    /**
69
     * Assert that getOrderedByHighestDouble() will return a new collection with the elements sorted by players who
70
     * have hands with the highest double.
71
     *
72
     * @param array $data
73
     *
74
     * @dataProvider getGetOrderedByHighestDoubleWillReturnANewOrderedCollectionData
75
     *
76
     * @covers       \Arp\DominoGame\Value\PlayerCollection::getOrderedByHighestDouble
77
     */
78
    public function testGetOrderedByHighestDoubleWillReturnANewOrderedCollection(array $data): void
79
    {
80
        $players = [];
81
        $highestValue = 0;
82
83
        foreach ($data as $index => $values) {
84
            /**
85
             * @var Player|MockObject $player
86
             * @var Domino|MockObject $domino
87
             */
88
            $player = $this->createMock(Player::class);
89
            $domino = $this->createMock(Domino::class);
90
91
            $value = array_sum($values);
92
            $expected[$value] = $player;
93
            if ($value >= $highestValue) {
94
                $highestValue = $value;
95
            }
96
97
            $player->method('getHighestDouble')->willReturn($domino);
98
            $domino->method('getValue')->willReturn($value);
99
            $domino->method('isDouble')->willReturn($values[0] === $values[1]);
100
101
            $players[] = $player;
102
        }
103
        krsort($expected);
104
        $expected = array_values($expected);
105
106
        $collection = new PlayerCollection($players);
107
108
        $orderedCollection = $collection->getOrderedByHighestDouble();
109
110
        $this->assertSame($collection->count(), $orderedCollection->count());
111
112
        foreach ($orderedCollection as $index => $player) {
113
            $this->assertSame($expected[$index], $player);
114
        }
115
    }
116
117
    /**
118
     * @return array
119
     */
120
    public function getGetOrderedByHighestDoubleWillReturnANewOrderedCollectionData(): array
121
    {
122
        return [
123
            [
124
                [
125
                    [1, 2],
126
                    [5, 6],
127
                    [6, 3],
128
                ],
129
            ],
130
        ];
131
    }
132
133
    /**
134
     * Assert that a call to getWithLowestHandValue() on an empty player collection will throw a DominoGameException.
135
     *
136
     * @covers \Arp\DominoGame\Value\PlayerCollection::getWithLowestHandValue
137
     *
138
     * @throws DominoGameException
139
     */
140
    public function testGetWithLowestHandValueWillThrowADominoGameExceptionIfCalledOnAnEmptyCollection(): void
141
    {
142
        $collection = new PlayerCollection([]);
143
144
        $this->expectException(DominoGameException::class);
145
        $this->expectExceptionMessage('Unable to find player with lowest value with an empty player collection');
146
147
        $collection->getWithLowestHandValue();
148
    }
149
150
    /**
151
     * Assert that when calling getWithLowestGHandValue() we return the single player instance that has the
152
     * highest total value hand within the collection.
153
     *
154
     * @param array $data
155
     *
156
     * @covers       \Arp\DominoGame\Value\PlayerCollection::getWithLowestHandValue
157
     *
158
     * @dataProvider getGetWithLowestHandValueWillReturnOrderedPlayerCollectionData
159
     *
160
     * @throws DominoGameException
161
     */
162
    public function testGetWithLowestHandValueWillReturnOrderedPlayerCollection(array $data): void
163
    {
164
        /** @var Player[]|MockObject[] $players */
165
        $lowestHandValue = PHP_INT_MAX;
166
        $expected = null;
167
        $players = [];
168
169
        foreach ($data as $value) {
170
            $player = $this->createMock(Player::class);
171
172
            $player->method('getHandValue')->willReturn($value);
173
174
            $players[] = $player;
175
            if ($value <= $lowestHandValue) {
176
                $expected = $player;
177
                $lowestHandValue = $value;
178
            }
179
        }
180
181
        $collection = new PlayerCollection($players);
182
        $result = $collection->getWithLowestHandValue();
183
184
        $this->assertSame($expected, $result);
185
        $this->assertSame($lowestHandValue, $result->getHandValue());
186
    }
187
188
    /**
189
     * @return array
190
     */
191
    public function getGetWithLowestHandValueWillReturnOrderedPlayerCollectionData(): array
192
    {
193
        return [
194
            // Two players
195
            [
196
                [7, 8],
197
            ],
198
            [
199
                [10, 7],
200
            ],
201
            [
202
                [1, 9],
203
            ],
204
205
            // Three Players
206
            [
207
                [1, 5, 8],
208
            ],
209
            [
210
                [10, 12, 1],
211
            ],
212
            [
213
                [1, 3, 5],
214
            ],
215
            [
216
                [1, 0, 12],
217
            ],
218
219
            // Four players
220
            [
221
                [2, 6, 8, 10],
222
            ],
223
            [
224
                [12, 11, 1, 6],
225
            ],
226
            [
227
                [3, 9, 7, 10],
228
            ],
229
        ];
230
    }
231
}
232