Passed
Push — master ( f544cb...b3a3d9 )
by Nico
36:43 queued 09:10
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
        $game->addExecuteJS('refreshHost();');
80
81
        $user = $game->getUser();
82
        $userId = $user->getId();
83
84
        $field = $this->planetFieldHostProvider->loadFieldViaRequestParameter($game->getUser());
85
        $host = $field->getHost();
86
87
        if ($field->getTerraformingId() > 0) {
88
            return;
89
        }
90
        $building = $this->buildingRepository->find(request::indInt('bid'));
91
        if ($building === null) {
92
            return;
93
        }
94
95
        $buildingId = $building->getId();
96
        $researchId = $building->getResearchId();
97
98
        if ($building->getBuildableFields()->containsKey($field->getFieldType()) === false) {
99
            return;
100
        }
101
102
        if ($userId !== UserEnum::USER_NOONE) {
103
            if ($researchId > 0 && $this->researchedRepository->hasUserFinishedResearch($user, [$researchId]) === false) {
104
                return;
105
            }
106
107
            $researchId = $building->getBuildableFields()->get($field->getFieldType())->getResearchId();
108
            if ($researchId != null && $this->researchedRepository->hasUserFinishedResearch($user, [$researchId]) === false) {
109
                return;
110
            }
111
        }
112
113
        if (
114
            $building->hasLimitColony() &&
115
            $this->planetFieldRepository->getCountByHostAndBuilding($host, $buildingId) >= $building->getLimitColony()
116
        ) {
117
            $game->addInformationf(
118
                _('Dieses Gebäude kann auf dieser Kolonie nur %d mal gebaut werden'),
119
                $building->getLimitColony()
120
            );
121
            return;
122
        }
123
        if ($building->hasLimit() && $this->planetFieldRepository->getCountByBuildingAndUser($buildingId, $userId) >= $building->getLimit()) {
124
            $game->addInformationf(
125
                _('Dieses Gebäude kann insgesamt nur %d mal gebaut werden'),
126
                $building->getLimit()
127
            );
128
            return;
129
        }
130
131
        // Check for alternative building
132
        $alt_building = $this->buildingFieldAlternativeRepository->getByBuildingAndFieldType(
133
            $buildingId,
134
            $field->getFieldType()
135
        );
136
        if ($alt_building !== null) {
137
            $building = $alt_building->getAlternativeBuilding();
138
        }
139
140
        if ($host instanceof ColonyInterface) {
141
            if (!$this->doColonyChecksAndConsume($field, $building, $host, $game)) {
142
                return;
143
            }
144
        }
145
146
        $field->setBuilding($building);
147
        $field->setActivateAfterBuild(true);
148
149
        if ($host instanceof ColonySandboxInterface) {
150
            $this->buildingManager->finish($field);
151
152
            $game->addInformationf(
153
                _('%s wurde gebaut'),
154
                $building->getName()
155
            );
156
        } else {
157
            $this->planetFieldRepository->save($field);
158
159
            $game->addInformationf(
160
                _('%s wird gebaut - Fertigstellung: %s'),
161
                $building->getName(),
162
                date('d.m.Y H:i', $field->getActive())
163
            );
164
        }
165
    }
166
167
    private function doColonyChecksAndConsume(
168
        PlanetFieldInterface $field,
169
        BuildingInterface $building,
170
        ColonyInterface $colony,
171
        GameControllerInterface $game
172
    ): bool {
173
        if (
174
            $this->planetFieldTypeRetriever->isOrbitField($field)
175
            && $colony->isBlocked()
176
        ) {
177
            $game->addInformation(_('Der Orbit kann nicht bebaut werden während die Kolonie blockiert wird'));
178
            return false;
179
        }
180
181
        //check for sufficient commodities
182
        if (!$this->checkBuildingCosts($colony, $building, $field, $game)) {
183
            return false;
184
        }
185
186
        if ($colony->getEps() < $building->getEpsCost()) {
187
            $game->addInformationf(
188
                _('Zum Bau wird %d Energie benötigt - Vorhanden ist nur %d'),
189
                $building->getEpsCost(),
190
                $colony->getEps()
191
            );
192
            return false;
193
        }
194
195
        if ($field->hasBuilding()) {
196
            if ($colony->getEps() > $colony->getMaxEps() - $field->getBuilding()->getEpsStorage() && $colony->getMaxEps() - $field->getBuilding()->getEpsStorage() < $building->getEpsCost()) {
197
                $game->addInformation(_('Nach der Demontage steht nicht mehr genügend Energie zum Bau zur Verfügung'));
198
                return false;
199
            }
200
            $this->buildingAction->remove($field, $game);
201
        }
202
203
        foreach ($building->getCosts() as $cost) {
204
            $this->colonyStorageManager->lowerStorage($colony, $cost->getCommodity(), $cost->getAmount());
205
        }
206
207
        $colony->lowerEps($building->getEpsCost());
208
        $field->setActive(time() + $building->getBuildtime());
209
210
        $this->colonyRepository->save($colony);
211
212
        return true;
213
    }
214
215
    private function checkBuildingCosts(
216
        ColonyInterface $colony,
217
        BuildingInterface $building,
218
        PlanetFieldInterface $field,
219
        GameControllerInterface $game
220
    ): bool {
221
        $isEnoughAvailable = true;
222
        $storage = $colony->getStorage();
223
224
        foreach ($building->getCosts() as $cost) {
225
            $commodityId = $cost->getCommodityId();
226
227
            $currentBuildingCost = [];
228
229
            if ($field->hasBuilding()) {
230
                $currentBuildingCost = $field->getBuilding()->getCosts()->toArray();
231
                $result = array_filter(
232
                    $currentBuildingCost,
233
                    fn (BuildingCostInterface $buildingCost): bool => $commodityId === $buildingCost->getCommodityId()
234
                );
235
                if (
236
                    !$storage->containsKey($commodityId) &&
237
                    $result === []
238
                ) {
239
                    $game->addInformationf(
240
                        _('Es werden %d %s benötigt - Es ist jedoch keines vorhanden'),
241
                        $cost->getAmount(),
242
                        $cost->getCommodity()->getName()
243
                    );
244
                    $isEnoughAvailable = false;
245
                    continue;
246
                }
247
            } elseif (!$storage->containsKey($commodityId)) {
248
                $game->addInformationf(
249
                    _('Es werden %s %s benötigt - Es ist jedoch keines vorhanden'),
250
                    $cost->getAmount(),
251
                    $cost->getCommodity()->getName()
252
                );
253
                $isEnoughAvailable = false;
254
                continue;
255
            }
256
            $amount = $storage->containsKey($commodityId) ? $storage[$commodityId]->getAmount() : 0;
257
            if ($field->hasBuilding()) {
258
                $result = array_filter(
259
                    $currentBuildingCost,
260
                    fn (BuildingCostInterface $buildingCost): bool => $commodityId === $buildingCost->getCommodityId()
261
                );
262
                if ($result !== []) {
263
                    $amount += current($result)->getHalfAmount();
264
                }
265
            }
266
            if ($cost->getAmount() > $amount) {
267
                $game->addInformationf(
268
                    _('Es werden %d %s benötigt - Vorhanden sind nur %d'),
269
                    $cost->getAmount(),
270
                    $cost->getCommodity()->getName(),
271
                    $amount
272
                );
273
                $isEnoughAvailable = false;
274
                continue;
275
            }
276
        }
277
278
        return $isEnoughAvailable;
279
    }
280
281
    public function performSessionCheck(): bool
282
    {
283
        return true;
284
    }
285
}
286