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

RuleConfigBuilder   A

Complexity

Total Complexity 41

Size/Duplication

Total Lines 260
Duplicated Lines 0 %

Test Coverage

Coverage 85.81%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 41
eloc 136
c 1
b 0
f 0
dl 0
loc 260
ccs 133
cts 155
cp 0.8581
rs 9.1199

22 Methods

Rating   Name   Duplication   Size   Complexity  
A getInjuries() 0 3 1
A prepareSkillsTable() 0 15 3
A setInducementTable() 0 4 1
A getSppLevels() 0 3 1
A prepareRosterTable() 0 14 2
A getSkills() 0 3 1
A getInducementType() 0 3 1
A prepareSppTable() 0 16 5
A prepareInducementTable() 0 25 6
A getRosters() 0 3 1
A prepareInducementTypes() 0 17 1
A prepareInjuriesTable() 0 17 4
A build() 0 10 1
A setSkills() 0 4 1
A createStarPlayerInducement() 0 27 5
A getInducementTable() 0 3 1
A setInjuries() 0 4 1
A setRosters() 0 4 1
A getInducementTypes() 0 3 1
A setInducementTypes() 0 4 1
A setSppLevels() 0 4 1
A getRoster() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like RuleConfigBuilder often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RuleConfigBuilder, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Obblm\Core\Helper\Rule;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Obblm\Core\Contracts\InducementInterface;
7
use Obblm\Core\Contracts\RosterInterface;
8
use Obblm\Core\Contracts\Rule\RuleBuilderInterface;
9
use Obblm\Core\Entity\Team;
10
use Obblm\Core\Helper\CoreTranslation;
11
use Obblm\Core\Helper\Rule\Config\ConfigResolver;
12
use Obblm\Core\Helper\Rule\Config\RuleConfigResolver;
13
use Obblm\Core\Helper\Rule\Inducement\Inducement;
14
use Obblm\Core\Helper\Rule\Inducement\InducementType;
15
use Obblm\Core\Helper\Rule\Inducement\MultipleStarPlayer;
16
use Obblm\Core\Helper\Rule\Inducement\StarPlayer;
17
use Obblm\Core\Helper\Rule\Roster\Roster;
18
use Obblm\Core\Helper\Rule\Skill\Skill;
19
20
class RuleConfigBuilder extends RuleConfigResolver implements RuleBuilderInterface
21
{
22
    /** @var ArrayCollection */
23
    private $injuries;
24
    /** @var ArrayCollection|Skill[] */
25
    private $skills;
26
    /** @var ArrayCollection|InducementType[] */
27
    private $inducementTypes;
28
    /** @var ArrayCollection */
29
    private $sppLevels;
30
    /** @var ArrayCollection|InducementInterface[] */
31
    private $inducements;
32
    /** @var ArrayCollection|RosterInterface[] */
33
    private $rosters;
34
35 1
    protected function build(string $ruleKey, array $rule)
36
    {
37 1
        $treeResolver = new ConfigResolver($this);
38 1
        $rule = $treeResolver->resolve($rule);
39 1
        $this->prepareInjuriesTable($ruleKey, $rule);
40 1
        $this->prepareSppTable($ruleKey, $rule);
41 1
        $this->prepareSkillsTable($ruleKey, $rule);
42 1
        $this->prepareInducementTypes($ruleKey);
43 1
        $this->prepareInducementTable($ruleKey, $rule);
44 1
        $this->prepareRosterTable($ruleKey, $rule);
45 1
    }
46
47
    public function getInjuries():ArrayCollection
48
    {
49
        return $this->injuries;
50
    }
51
52
    public function setInjuries(ArrayCollection $injuries):self
53
    {
54
        $this->injuries = $injuries;
55
        return $this;
56
    }
57
58 2
    public function getInducementTypes():ArrayCollection
59
    {
60 2
        return $this->inducementTypes;
61
    }
62
63
    public function setInducementTypes(ArrayCollection $inducementTypes):self
64
    {
65
        $this->inducementTypes = $inducementTypes;
66
        return $this;
67
    }
68
69 2
    public function getInducementType(string $type):InducementType
70
    {
71 2
        return $this->getInducementTypes()->get($type);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getInducementTypes()->get($type) could return the type null which is incompatible with the type-hinted return Obblm\Core\Helper\Rule\Inducement\InducementType. Consider adding an additional type-check to rule them out.
Loading history...
72
    }
73
74
    public function getSppLevels():ArrayCollection
75
    {
76
        return $this->sppLevels;
77
    }
78
79
    public function setSppLevels(ArrayCollection $sppLevels):self
80
    {
81
        $this->sppLevels = $sppLevels;
82
        return $this;
83
    }
84
85 2
    public function getInducementTable():ArrayCollection
86
    {
87 2
        return $this->inducements;
88
    }
89
90
    public function setInducementTable(ArrayCollection $inducements):self
91
    {
92
        $this->inducements = $inducements;
93
        return $this;
94
    }
95
96
    /** @return RosterInterface[]|ArrayCollection */
97 4
    public function getRosters():ArrayCollection
98
    {
99 4
        return $this->rosters;
100
    }
101
102 1
    public function getRoster(Team $team):RosterInterface
103
    {
104 1
        return $this->rosters->get($team->getRoster());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->rosters->get($team->getRoster()) could return the type null which is incompatible with the type-hinted return Obblm\Core\Contracts\RosterInterface. Consider adding an additional type-check to rule them out.
Loading history...
105
    }
106
107
    public function setRosters(ArrayCollection $rosters):self
108
    {
109
        $this->rosters = $rosters;
110
        return $this;
111
    }
112
113 2
    public function getSkills():ArrayCollection
114
    {
115 2
        return $this->skills;
116
    }
117
118
    public function setSkills(ArrayCollection $skills):self
119
    {
120
        $this->skills = $skills;
121
        return $this;
122
    }
123
124 1
    private function prepareInjuriesTable(string $ruleKey, array $rule)
125
    {
126 1
        $this->injuries = new ArrayCollection();
127 1
        foreach ($rule['injuries'] as $key => $injury) {
128 1
            $label = CoreTranslation::getInjuryKey($ruleKey, $key);
129 1
            $effectLabel = CoreTranslation::getInjuryEffect($ruleKey, $key);
130 1
            if (isset($injury['to'])) {
131 1
                for ($i = $injury['from']; $i <= $injury['to']; $i++) {
132 1
                    $this->injuries->set(
133 1
                        $i,
134 1
                        (object) ['value' => $i, 'label' => $label, 'effect_label' => $effectLabel, 'effects' => $injury['effects']]
135
                    );
136
                }
137
            } else {
138 1
                $this->injuries->set(
139 1
                    $injury['from'],
140 1
                    (object) ['value' => $injury['from'], 'label' => $label, 'effect_label' => $effectLabel, 'effects' => $injury['effects']]
141
                );
142
            }
143
        }
144 1
    }
145
146 1
    private function prepareInducementTypes(string $ruleKey)
147
    {
148 1
        $this->inducementTypes = new ArrayCollection();
149 1
        $this->inducementTypes->set('star_players', new InducementType([
150 1
            'key' => 'star_players',
151 1
            'name' => CoreTranslation::getStarPlayerTitle($ruleKey),
152 1
            'translation_domain' => $ruleKey,
153
        ]));
154 1
        $this->inducementTypes->set('inducements', new InducementType([
155 1
            'key' => 'inducements',
156 1
            'name' => CoreTranslation::getInducementTitle($ruleKey),
157 1
            'translation_domain' => $ruleKey,
158
        ]));
159 1
        $this->inducementTypes->set('mercenary', new InducementType([
160 1
            'key' => 'mercenary',
161 1
            'name' => CoreTranslation::getMercenaryTitle($ruleKey),
162 1
            'translation_domain' => $ruleKey,
163
        ]));
164 1
    }
165
166 1
    private function prepareSppTable(string $ruleKey, array $rule)
167
    {
168 1
        $spps = new ArrayCollection($rule['spp_levels']);
169 1
        foreach ($spps as $from => $level) {
170 1
            $to = $spps->next();
171 1
            if ($to) {
172 1
                for ($i = $from; $i < $spps->indexOf($to); $i++) {
173 1
                    if (!isset($spps[$i])) {
174 1
                        $spps[$i] = $level;
175
                    }
176
                }
177
            }
178
        }
179 1
        $spps = $spps->toArray();
180 1
        ksort($spps);
181 1
        $this->sppLevels = new ArrayCollection($spps);
182 1
    }
183
184 1
    private function prepareSkillsTable(string $ruleKey, array $rule)
185
    {
186 1
        $this->skills = new ArrayCollection();
187 1
        foreach ($rule['skills'] as $type => $skills) {
188 1
            foreach ($skills as $skill) {
189 1
                $key = join(CoreTranslation::TRANSLATION_GLUE, [$type, $skill]);
190 1
                $this->skills->set(
191 1
                    $key,
192 1
                    new Skill([
193 1
                        'key'         => $skill,
194 1
                        'type'        => $type,
195 1
                        'name'        => CoreTranslation::getSkillNameKey($ruleKey, $skill),
196 1
                        'description' => CoreTranslation::getSkillDescription($ruleKey, $skill),
197 1
                        'type_name'   => CoreTranslation::getSkillType($ruleKey, $type),
198 1
                        'translation_domain'      => $ruleKey,
199
                    ])
200
                );
201
            }
202
        }
203 1
    }
204
205 1
    private function prepareInducementTable(string $ruleKey, array $rule)
206
    {
207 1
        $this->inducements = new ArrayCollection();
208
209 1
        foreach ($rule['inducements'] as $key => $value) {
210 1
            if ($key !== 'star_players') {
211 1
                $inducement = new Inducement([
212 1
                    'type' => $this->inducementTypes['inducements'],
213 1
                    'key' => join(CoreTranslation::TRANSLATION_GLUE, [$ruleKey, 'inducements', $key]),
214 1
                    'translation_domain' => $ruleKey,
215 1
                    'name' => CoreTranslation::getInducementName($ruleKey, $key),
216 1
                    'max' => $value['max'] ?? 0,
217 1
                    'rosters' => $value['rosters'] ?? null,
218 1
                    'value' => $value['cost'],
219 1
                    'discount_value' => $value['discount_cost'] ?? null,
220
                ]);
221 1
                if (!$this->inducements->contains($inducement)) {
222 1
                    $this->inducements->add($inducement);
223
                }
224
            }
225
        }
226 1
        foreach ($rule['star_players'] as $key => $starPlayer) {
227 1
            $inducement = $this->createStarPlayerInducement($ruleKey, $key, $starPlayer);
228 1
            if (!$this->inducements->contains($inducement)) {
229 1
                $this->inducements->add($inducement);
230
            }
231
        }
232 1
    }
233
234 1
    private function prepareRosterTable(string $ruleKey, array $rule)
235
    {
236 1
        $this->rosters = new ArrayCollection();
237 1
        foreach ($rule['rosters'] as $key => $roster) {
238 1
            $this->rosters->set(
239 1
                $key,
240 1
                new Roster([
241 1
                    'key' => $key,
242 1
                    'name' => CoreTranslation::getRosterKey($ruleKey, $key),
243 1
                    'translation_domain' => $ruleKey,
244 1
                    'player_types' => $roster['players'],
245 1
                    'reroll_cost' => $roster['reroll_cost'] ?? 0,
246 1
                    'can_have_apothecary' => $roster['options']['can_have_apothecary'] ?? true,
247 1
                    'inducement_options' => $roster['options']['inducements'] ?? [],
248
                ])
249
            );
250
        }
251 1
    }
252
253 1
    private function createStarPlayerInducement(string $ruleKey, string $key, array $starPlayer):InducementInterface
254
    {
255
        $options = [
256 1
            'type' => $this->inducementTypes['star_players'],
257 1
            'key' => join(CoreTranslation::TRANSLATION_GLUE, [$ruleKey, 'star_players', $key]),
258 1
            'value' => $starPlayer['cost'],
259 1
            'discount_value' => $starPlayer['discount_cost'] ?? null,
260 1
            'translation_domain' => $ruleKey,
261 1
            'name' => CoreTranslation::getStarPlayerName($ruleKey, $key),
262 1
            'max' => $starPlayer['max'] ?? 1,
263 1
            'characteristics' => $starPlayer['characteristics'] ?? null,
264 1
            'skills' => $starPlayer['skills'] ?? null,
265 1
            'rosters' => $starPlayer['rosters'] ?? null,
266
        ];
267 1
        if (isset($starPlayer['multi_parts']) && $starPlayer['multi_parts']) {
268 1
            $options['parts'] = [];
269 1
            $first = true;
270 1
            foreach ($starPlayer['multi_parts'] as $key => $part) {
271 1
                $part['cost'] = $first ? $starPlayer['cost'] : 0;
272 1
                $options['parts'][] = $this->createStarPlayerInducement($ruleKey, $key, $part);
273 1
                $first = false;
274
            }
275 1
            $inducement = new MultipleStarPlayer($options);
276
        } else {
277 1
            $inducement = new StarPlayer($options);
278
        }
279 1
        return $inducement;
280
    }
281
}
282