Test Setup Failed
Push — master ( a63fa0...36623d )
by Jesse
04:59
created

Cards::offsetOf()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\CardGame\Match;
4
5
use function array_filter;
6
use function array_reduce;
7
use function array_search;
8
use Closure;
9
use function assert;
10
use function count;
11
use Stratadox\ImmutableCollection\ImmutableCollection;
12
13
final class Cards extends ImmutableCollection
14
{
15
    public function __construct(Card ...$cards)
16
    {
17
        parent::__construct(...$cards);
18
    }
19
20
    public function current(): Card
21
    {
22
        return parent::current();
23
    }
24
25
    public function inHand(): Cards
26
    {
27
        return $this->filterBy(static function (Card $card): bool {
28
            return $card->isInHand();
29
        });
30
    }
31
32
    public function inPlay(): Cards
33
    {
34
        return $this->filterBy(static function (Card $card): bool {
35
            return $card->isInPlay();
36
        });
37
    }
38
39
    public function thatAttack(): Cards
40
    {
41
        return $this->filterBy(static function (Card $card): bool {
42
            return $card->isAttacking();
43
        });
44
    }
45
46
    public function thatDefend(): Cards
47
    {
48
        return $this->filterBy(static function (Card $card): bool {
49
            return $card->isDefending();
50
        });
51
    }
52
53
    public function drawFromTopOfDeck(MatchId $match, int $player): void
54
    {
55
        $this->draw($this->topMostCardInDeck(), $match, $player);
56
    }
57
58
    public function theOneThatAttacksTheAmbushOf(Card $defender): Card
59
    {
60
        return $this->filterBy(static function (Card $card) use ($defender): bool {
61
            return $card->isAttackingThe($defender);
62
        })[0];
63
    }
64
65
    private function topMostCardInDeck(): Card
66
    {
67
        $card = array_reduce(
68
            array_filter($this->items(), static function (Card $card): bool {
69
                return $card->isInDeck();
70
            }),
71
            static function (?Card $topmost, Card $card): ?Card {
72
                if ($topmost === null || $card->hasHigherPositionThan($topmost)) {
73
                    return $card;
74
                }
75
                return $topmost;
76
            }
77
        );
78
        assert($card !== null);
79
        return $card;
80
    }
81
82
    private function draw(Card $card, MatchId $match, int $player): void
83
    {
84
        $card->draw(
85
            $match,
86
            count($this->inHand()),
87
            $player
88
        );
89
    }
90
91
    private function filterBy(Closure $function): Cards
92
    {
93
        return new self(...array_filter($this->items(), $function));
94
    }
95
}
96