Test Failed
Push — master ( dec5f4...b3761e )
by Nico
31:29 queued 20:45
created

BuildOnField::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 10
dl 0
loc 22
ccs 0
cts 11
cp 0
crap 2
rs 9.9332
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Colony\Action\BuildOnField;
6
7
use request;
8
use Stu\Component\Building\BuildingManagerInterface;
9
use Stu\Component\Colony\Storage\ColonyStorageManagerInterface;
10
use Stu\Lib\Colony\PlanetFieldHostProviderInterface;
11
use Stu\Module\Colony\Lib\BuildingActionInterface;
12
use Stu\Module\Colony\Lib\PlanetFieldTypeRetrieverInterface;
13
use Stu\Module\Colony\View\ShowInformation\ShowInformation;
14
use Stu\Module\Control\ActionControllerInterface;
15
use Stu\Module\Control\GameControllerInterface;
16
use Stu\Module\PlayerSetting\Lib\UserEnum;
17
use Stu\Orm\Entity\BuildingCostInterface;
18
use Stu\Orm\Entity\BuildingInterface;
19
use Stu\Orm\Entity\ColonyInterface;
20
use Stu\Orm\Entity\ColonySandboxInterface;
21
use Stu\Orm\Entity\PlanetFieldInterface;
22
use Stu\Orm\Repository\BuildingFieldAlternativeRepositoryInterface;
23
use Stu\Orm\Repository\BuildingRepositoryInterface;
24
use Stu\Orm\Repository\ColonyRepositoryInterface;
25
use Stu\Orm\Repository\PlanetFieldRepositoryInterface;
26
use Stu\Orm\Repository\ResearchedRepositoryInterface;
27
28
final class BuildOnField implements ActionControllerInterface
29
{
30
    public const ACTION_IDENTIFIER = 'B_BUILD';
31
32
    private PlanetFieldHostProviderInterface $planetFieldHostProvider;
33
34
    private BuildingFieldAlternativeRepositoryInterface $buildingFieldAlternativeRepository;
35
36
    private ResearchedRepositoryInterface $researchedRepository;
37
38
    private BuildingRepositoryInterface $buildingRepository;
39
40
    private PlanetFieldRepositoryInterface $planetFieldRepository;
41
42
    private ColonyStorageManagerInterface $colonyStorageManager;
43
44
    private ColonyRepositoryInterface $colonyRepository;
45
46
    private BuildingActionInterface $buildingAction;
47
48
    private PlanetFieldTypeRetrieverInterface $planetFieldTypeRetriever;
49
50
    private BuildingManagerInterface $buildingManager;
51
52
    public function __construct(
53
        PlanetFieldHostProviderInterface $planetFieldHostProvider,
54
        BuildingFieldAlternativeRepositoryInterface $buildingFieldAlternativeRepository,
55
        ResearchedRepositoryInterface $researchedRepository,
56
        BuildingRepositoryInterface $buildingRepository,
57
        PlanetFieldRepositoryInterface $planetFieldRepository,
58
        ColonyStorageManagerInterface $colonyStorageManager,
59
        ColonyRepositoryInterface $colonyRepository,
60
        BuildingActionInterface $buildingAction,
61
        PlanetFieldTypeRetrieverInterface $planetFieldTypeRetriever,
62
        BuildingManagerInterface $buildingManager
63
    ) {
64
        $this->planetFieldHostProvider = $planetFieldHostProvider;
65
        $this->buildingFieldAlternativeRepository = $buildingFieldAlternativeRepository;
66
        $this->researchedRepository = $researchedRepository;
67
        $this->buildingRepository = $buildingRepository;
68
        $this->planetFieldRepository = $planetFieldRepository;
69
        $this->colonyStorageManager = $colonyStorageManager;
70
        $this->colonyRepository = $colonyRepository;
71
        $this->buildingAction = $buildingAction;
72
        $this->planetFieldTypeRetriever = $planetFieldTypeRetriever;
73
        $this->buildingManager = $buildingManager;
74
    }
75
76
    public function handle(GameControllerInterface $game): void
77
    {
78
        $game->setView(ShowInformation::VIEW_IDENTIFIER);
79
80
        $user = $game->getUser();
81
        $userId = $user->getId();
82
83
        $field = $this->planetFieldHostProvider->loadFieldViaRequestParameter($game->getUser());
84
        $host = $field->getHost();
85
86
        if ($field->getTerraformingId() > 0) {
87
            return;
88
        }
89
        $building = $this->buildingRepository->find(request::indInt('bid'));
90
        if ($building === null) {
91
            return;
92
        }
93
94
        $buildingId = $building->getId();
95
        $researchId = $building->getResearchId();
96
97
        if ($building->getBuildableFields()->containsKey($field->getFieldType()) === false) {
98
            return;
99
        }
100
101
        if ($userId !== UserEnum::USER_NOONE) {
102
            if ($researchId > 0 && $this->researchedRepository->hasUserFinishedResearch($user, [$researchId]) === false) {
103
                return;
104
            }
105
106
            $researchId = $building->getBuildableFields()->get($field->getFieldType())->getResearchId();
107
            if ($researchId != null && $this->researchedRepository->hasUserFinishedResearch($user, [$researchId]) === false) {
108
                return;
109
            }
110
        }
111
112
        if (
113
            $building->hasLimitColony() &&
114
            $this->planetFieldRepository->getCountByHostAndBuilding($host, $buildingId) >= $building->getLimitColony()
115
        ) {
116
            $game->addInformationf(
117
                _('Dieses Gebäude kann auf dieser Kolonie nur %d mal gebaut werden'),
118
                $building->getLimitColony()
119
            );
120
            return;
121
        }
122
        if (
123
            $host instanceof ColonyInterface
124
            && $building->hasLimit()
125
            && $this->planetFieldRepository->getCountByBuildingAndUser($buildingId, $userId) >= $building->getLimit()
126
        ) {
127
            $game->addInformationf(
128
                _('Dieses Gebäude kann insgesamt nur %d mal gebaut werden'),
129
                $building->getLimit()
130
            );
131
            return;
132
        }
133
134
        // Check for alternative building
135
        $alt_building = $this->buildingFieldAlternativeRepository->getByBuildingAndFieldType(
136
            $buildingId,
137
            $field->getFieldType()
138
        );
139
        if ($alt_building !== null) {
140
            $building = $alt_building->getAlternativeBuilding();
141
        }
142
143
        if ($field->hasBuilding()) {
144
            if ($host instanceof ColonyInterface) {
145
                if (!$this->checkBuildingCosts($host, $building, $field, $game)) {
146
                    return;
147
                } elseif ($host->getEps() < $building->getEpsCost()) {
148
                    $game->addInformationf(
149
                        _('Zum Bau wird %d Energie benötigt - Vorhanden ist nur %d'),
150
                        $building->getEpsCost(),
151
                        $host->getEps()
152
                    );
153
                    return;
154
                } elseif ($host->getEps() > $host->getMaxEps() - $field->getBuilding()->getEpsStorage() && $host->getMaxEps() - $field->getBuilding()->getEpsStorage() < $building->getEpsCost()) {
155
                    $game->addInformation(_('Nach der Demontage steht nicht mehr genügend Energie zum Bau zur Verfügung'));
156
                    return;
157
                } else {
158
                    $this->buildingAction->remove($field, $game);
159
                }
160
            }
161
        }
162
163
        if ($host instanceof ColonyInterface) {
164
            if (!$this->doColonyChecksAndConsume($field, $building, $host, $game)) {
165
                return;
166
            }
167
        }
168
169
        $field->setBuilding($building);
170
        $field->setActivateAfterBuild(true);
171
172
        $game->addExecuteJS('refreshHost();');
173
174
        if ($host instanceof ColonySandboxInterface) {
175
            $this->buildingManager->finish($field);
176
177
            $game->addInformationf(
178
                _('%s wurde gebaut'),
179
                $building->getName()
180
            );
181
        } else {
182
            $this->planetFieldRepository->save($field);
183
184
            $game->addInformationf(
185
                _('%s wird gebaut - Fertigstellung: %s'),
186
                $building->getName(),
187
                date('d.m.Y H:i', $field->getActive())
188
            );
189
        }
190
    }
191
192
    private function doColonyChecksAndConsume(
193
        PlanetFieldInterface $field,
194
        BuildingInterface $building,
195
        ColonyInterface $colony,
196
        GameControllerInterface $game
197
    ): bool {
198
        if (
199
            $this->planetFieldTypeRetriever->isOrbitField($field)
200
            && $colony->isBlocked()
201
        ) {
202
            $game->addInformation(_('Der Orbit kann nicht bebaut werden während die Kolonie blockiert wird'));
203
            return false;
204
        }
205
206
        //check for sufficient commodities
207
        if (!$this->checkBuildingCosts($colony, $building, $field, $game)) {
208
            return false;
209
        }
210
211
        if ($colony->getEps() < $building->getEpsCost()) {
212
            $game->addInformationf(
213
                _('Zum Bau wird %d Energie benötigt - Vorhanden ist nur %d'),
214
                $building->getEpsCost(),
215
                $colony->getEps()
216
            );
217
            return false;
218
        }
219
220
        foreach ($building->getCosts() as $cost) {
221
            $this->colonyStorageManager->lowerStorage($colony, $cost->getCommodity(), $cost->getAmount());
222
        }
223
224
        $colony->lowerEps($building->getEpsCost());
225
        $field->setActive(time() + $building->getBuildtime());
226
227
        $this->colonyRepository->save($colony);
228
229
        return true;
230
    }
231
232
    private function checkBuildingCosts(
233
        ColonyInterface $colony,
234
        BuildingInterface $building,
235
        PlanetFieldInterface $field,
236
        GameControllerInterface $game
237
    ): bool {
238
        $isEnoughAvailable = true;
239
        $storage = $colony->getStorage();
240
241
        foreach ($building->getCosts() as $cost) {
242
            $commodityId = $cost->getCommodityId();
243
244
            $currentBuildingCost = [];
245
246
            if ($field->hasBuilding()) {
247
                $currentBuildingCost = $field->getBuilding()->getCosts()->toArray();
248
                $result = array_filter(
249
                    $currentBuildingCost,
250
                    fn (BuildingCostInterface $buildingCost): bool => $commodityId === $buildingCost->getCommodityId()
251
                );
252
                if (
253
                    !$storage->containsKey($commodityId) &&
254
                    $result === []
255
                ) {
256
                    $game->addInformationf(
257
                        _('Es werden %d %s benötigt - Es ist jedoch keines vorhanden'),
258
                        $cost->getAmount(),
259
                        $cost->getCommodity()->getName()
260
                    );
261
                    $isEnoughAvailable = false;
262
                    continue;
263
                }
264
            } elseif (!$storage->containsKey($commodityId)) {
265
                $game->addInformationf(
266
                    _('Es werden %s %s benötigt - Es ist jedoch keines vorhanden'),
267
                    $cost->getAmount(),
268
                    $cost->getCommodity()->getName()
269
                );
270
                $isEnoughAvailable = false;
271
                continue;
272
            }
273
            $amount = $storage->containsKey($commodityId) ? $storage[$commodityId]->getAmount() : 0;
274
            if ($field->hasBuilding()) {
275
                $result = array_filter(
276
                    $currentBuildingCost,
277
                    fn (BuildingCostInterface $buildingCost): bool => $commodityId === $buildingCost->getCommodityId()
278
                );
279
                if ($result !== []) {
280
                    $amount += current($result)->getHalfAmount();
281
                }
282
            }
283
            if ($cost->getAmount() > $amount) {
284
                $game->addInformationf(
285
                    _('Es werden %d %s benötigt - Vorhanden sind nur %d'),
286
                    $cost->getAmount(),
287
                    $cost->getCommodity()->getName(),
288
                    $amount
289
                );
290
                $isEnoughAvailable = false;
291
                continue;
292
            }
293
        }
294
295
        return $isEnoughAvailable;
296
    }
297
298
    public function performSessionCheck(): bool
299
    {
300
        return true;
301
    }
302
}
303