Completed
Branch v1.x-dev (59bcf7)
by Benjamin
05:08
created

createInducementAsPlayer()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 13
c 0
b 0
f 0
dl 0
loc 17
ccs 0
cts 14
cp 0
rs 9.8333
cc 3
nc 3
nop 2
crap 12
1
<?php
2
3
namespace Obblm\Core\Helper\Rule\Traits;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\Common\Collections\Criteria;
7
use Doctrine\Common\Collections\Expr\CompositeExpression;
8
use Doctrine\Common\Collections\Expr\Expression;
9
use Obblm\Core\Contracts\InducementInterface;
10
use Obblm\Core\Entity\Player;
11
use Obblm\Core\Entity\PlayerVersion;
12
use Obblm\Core\Entity\Team;
13
use Obblm\Core\Exception\InvalidArgumentException;
14
use Obblm\Core\Exception\NotFoundKeyException;
15
use Obblm\Core\Helper\CoreTranslation;
16
use Obblm\Core\Helper\Rule\Inducement\Inducement;
17
use Obblm\Core\Helper\Rule\Inducement\StarPlayer;
18
19
/*********************
20
 * INDUCEMENT METHODS
21
 ********************/
22
trait AbstractInducementRuleTrait
23
{
24
    abstract public function getInducementTable():ArrayCollection;
25
26 2
    private function getInducementExpression($options):CompositeExpression
27
    {
28 2
        $expressions = [];
29 2
        if (isset($options['type'])) {
30
            // Criteria by inducement type
31 2
            $expressions['type'] = $this->getTypeExpression($options);
32
        }
33 2
        if (isset($options['cost_limit'])) {
34
            // Criteria by cost limit
35
            $expressions['cost'] = $this->getBudgetExpression($options);
36
        }
37 2
        if (isset($options['roster'])) {
38
            // Criteria by roster
39
            $expressions['roster'] = $this->getRosterExpression($options);
40
        }
41 2
        return new CompositeExpression(CompositeExpression::TYPE_AND, $expressions);
42
    }
43
44 2
    private function getTypeExpression($options):Expression
45
    {
46 2
        if (isset($options['type'])) {
47
            // Criteria by inducement type
48 2
            if (is_array($options['type'])) {
49
                $types = [];
50
                foreach ($options['type'] as $type) {
51
                    if (is_string($type)) {
52
                        $inducementType = $this->getInducementType($type);
0 ignored issues
show
Bug introduced by
The method getInducementType() does not exist on Obblm\Core\Helper\Rule\T...ractInducementRuleTrait. Did you maybe mean getInducementTable()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

52
                        /** @scrutinizer ignore-call */ 
53
                        $inducementType = $this->getInducementType($type);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
53
                        $types[] = Criteria::expr()->eq('type', $inducementType);
54
                    }
55
                }
56
                return new CompositeExpression(CompositeExpression::TYPE_OR, $types);
57 2
            } elseif (is_string($options['type'])) {
58 2
                $inducementType = $this->getInducementType($options['type']);
59 2
                return Criteria::expr()->eq('type', $inducementType);
60
            }
61
            throw new InvalidArgumentException('"type" option is not an array or a string');
62
        }
63
        throw new InvalidArgumentException('"type" option must be defined');
64
    }
65
66
    private function getRosterExpression($options):Expression
67
    {
68
        if (isset($options['roster']) && is_string($options['roster'])) {
69
            // Criteria by roster
70
            return Criteria::expr()->orX(
71
                Criteria::expr()->memberOf('rosters', $options['roster']),
72
                Criteria::expr()->eq('rosters', [])
73
            );
74
        }
75
        throw new InvalidArgumentException('"roster" option must be defined');
76
    }
77
78
    private function getBudgetExpression($options):Expression
79
    {
80
        if (isset($options['cost_limit']) && is_int($options['cost_limit'])) {
81
            // Criteria by cost limit
82
            return Criteria::expr()->lte('value', $options['cost_limit']);
83
        }
84
        throw new InvalidArgumentException('"cost_limit" option must be defined');
85
    }
86
87 2
    public function getInducements():ArrayCollection
88
    {
89 2
        $criteria = Criteria::create()
90 2
            ->where($this->getInducementExpression(['type' => 'inducements']));
91 2
        return $this->getInducementTable()->matching($criteria);
92
    }
93
94 2
    public function getStarPlayers():ArrayCollection
95
    {
96 2
        $criteria = Criteria::create()
97 2
            ->where($this->getInducementExpression(['type' => 'star_players']));
98 2
        return $this->getInducementTable()->matching($criteria);
99
    }
100
101
    public function getInducementsFor(Team $team, ?int $budget = null):ArrayCollection
102
    {
103
        $criteria = Criteria::create();
104
        $expr = [
105
            'type' => [
106
                'inducements',
107
                'star_players'
108
            ],
109
            'roster' => $team->getRoster()
110
        ];
111
        if ($budget !== null) {
112
            $expr['cost_limit'] = $budget;
113
        }
114
        $criteria->where(Criteria::expr()->andX(
115
            $this->getInducementExpression($expr)
116
        ));
117
        $availableInducements = $this->getInducementTable()->matching($criteria);
118
        return $availableInducements->toArray();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $availableInducements->toArray() returns the type array which is incompatible with the type-hinted return Doctrine\Common\Collections\ArrayCollection.
Loading history...
119
    }
120
121
    public function getInducementsByTeamOptions(array $options):array
122
    {
123
        $inducements = [];
124
        $ruleKey = $this->getAttachedRule()->getRuleKey();
0 ignored issues
show
Bug introduced by
It seems like getAttachedRule() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
        $ruleKey = $this->/** @scrutinizer ignore-call */ getAttachedRule()->getRuleKey();
Loading history...
125
        $availableInducements = $this->rule['inducements'];
126
127
        foreach ($availableInducements as $key => $value) {
128
            if ($key !== 'star_players') {
129
                if ($options[$key]) {
130
                    $inducement = [
131
                        'type' => $this->getInducementType('inducements'),
132
                        'key' => join(CoreTranslation::TRANSLATION_GLUE, [$ruleKey, 'inducements', $key]),
133
                        'translation_domain' => $this->getAttachedRule()->getRuleKey(),
134
                        'translation_key' => CoreTranslation::getInducementName($ruleKey, $key),
135
                        'max' => $value['max'] ?? 0,
136
                        'value' => ($options[$key] === 'discount') ? $value['discounted_cost'] : $value['cost'],
137
                    ];
138
                    $inducements[] = new Inducement($inducement);
139
                }
140
            }
141
        }
142
        return $inducements;
143
    }
144
145
    public function getMaxStarPlayers():int
146
    {
147
        return $this->rule['inducements']['star_players']['max'];
148
    }
149
150
    public function getStarPlayer(string $key):InducementInterface
151
    {
152
        if (!$this->getStarPlayers()->containsKey($key)) {
153
            throw new NotFoundKeyException($key, 'starPlayers', self::class);
154
        }
155
        return $this->getStarPlayers()->get($key);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getStarPlayers()->get($key) could return the type null which is incompatible with the type-hinted return Obblm\Core\Contracts\InducementInterface. Consider adding an additional type-check to rule them out.
Loading history...
156
    }
157
158
    public function getAvailableStarPlayers(Team $team):array
159
    {
160
        $criteria = Criteria::create();
161
        $criteria->where(Criteria::expr()->andX(
162
            $this->getInducementExpression([
163
                'type' => 'star_players',
164
                'roster' => $team->getRoster()
165
            ])
166
        ));
167
        return $this->getInducementTable()->matching($criteria)->toArray();
168
    }
169
170
    public function createInducementAsPlayer(InducementInterface $inducement, $number = 0):?Player
171
    {
172
        if (!$inducement instanceof StarPlayer) {
173
            return null;
174
        }
175
        $version = (new PlayerVersion())
176
            ->setCharacteristics($inducement->getCharacteristics())
177
            ->setValue($inducement->getValue());
178
        if ($inducement->getSkills()) {
179
            $version->setSkills($inducement->getSkills());
180
        }
181
        $player = (new Player())
182
            ->setNumber($number)
183
            ->setPosition($inducement->getType()->getName())
184
            ->setName($inducement->getName())
185
            ->addVersion($version);
186
        return $player;
187
    }
188
189
    public function createStarPlayerAsPlayer(string $key, int $number):Player
190
    {
191
        $ruleKey = $this->getAttachedRule()->getRuleKey();
192
193
        $starPlayer = $this->getStarPlayer($key);
194
        if (isset($starPlayer['multi_parts']) && $starPlayer['multi_parts']) {
195
            throw new \Exception('You cannot create a player with a multiple parts InducementInterface');
196
        }
197
        $version = (new PlayerVersion())
198
            ->setCharacteristics($starPlayer['characteristics'])
199
            ->setValue($starPlayer['cost']);
200
        if ($starPlayer['skills']) {
201
            $version->setSkills($starPlayer['skills']);
202
        }
203
        $player = (new Player())
204
            ->setNumber($number)
205
            ->setPosition(CoreTranslation::getStarPlayerTitle($ruleKey))
206
            ->setName(CoreTranslation::getStarPlayerName($ruleKey, $key))
207
            ->addVersion($version);
208
        return $player;
209
    }
210
211
    public function getTransformedInducementsFor(string $roster)
212
    {
213
        $table = $this->getInducementTable();
214
        foreach ($table as $inducement) {
215
            if ($roster == 'halfling') {
216
                $inducement->setValue(10000);
217
            }
218
        }
219
220
        return $table;
221
    }
222
}
223