Passed
Push — master ( 6b02b9...a180a6 )
by Nico
26:39 queued 18:43
created

ShowShip::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 18
c 0
b 0
f 0
nc 1
nop 17
dl 0
loc 37
ccs 0
cts 19
cp 0
crap 2
rs 9.6666

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\Ship\View\ShowShip;
6
7
use NavPanel;
8
use request;
9
use Stu\Component\Player\ColonizationCheckerInterface;
10
use Stu\Component\Ship\AstronomicalMappingEnum;
11
use Stu\Component\Ship\Crew\ShipCrewCalculatorInterface;
12
use Stu\Component\Ship\Nbs\NbsUtilityInterface;
13
use Stu\Component\Ship\ShipModuleTypeEnum;
14
use Stu\Component\Ship\ShipRumpEnum;
15
use Stu\Component\Station\StationUtilityInterface;
16
use Stu\Lib\ColonyStorageCommodityWrapper\ColonyStorageCommodityWrapper;
17
use Stu\Lib\SessionInterface;
18
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
19
use Stu\Module\Control\GameControllerInterface;
20
use Stu\Module\Control\ViewControllerInterface;
21
use Stu\Module\Database\View\Category\Tal\DatabaseCategoryTalFactoryInterface;
22
use Stu\Module\Logging\LoggerUtilFactoryInterface;
23
use Stu\Module\Logging\LoggerUtilInterface;
24
use Stu\Module\Ship\Lib\Battle\FightLibInterface;
25
use Stu\Module\Ship\Lib\ShipLoaderInterface;
26
use Stu\Module\Ship\Lib\ShipRumpSpecialAbilityEnum;
27
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
28
use Stu\Module\Ship\Lib\ShipWrapperInterface;
29
use Stu\Module\Ship\Lib\Ui\ShipUiFactoryInterface;
30
use Stu\Orm\Entity\ColonyInterface;
31
use Stu\Orm\Entity\ShipInterface;
32
use Stu\Orm\Entity\StationShipRepairInterface;
33
use Stu\Orm\Entity\UserInterface;
34
use Stu\Orm\Repository\AstroEntryRepositoryInterface;
35
use Stu\Orm\Repository\DatabaseUserRepositoryInterface;
36
use Stu\Orm\Repository\ShipyardShipQueueRepositoryInterface;
37
use Stu\Orm\Repository\StationShipRepairRepositoryInterface;
38
use Stu\Orm\Repository\UserLayerRepositoryInterface;
39
40
final class ShowShip implements ViewControllerInterface
41
{
42
    public const VIEW_IDENTIFIER = 'SHOW_SHIP';
43
44
    private SessionInterface $session;
45
46
    private LoggerUtilFactoryInterface $loggerUtilFactory;
47
48
    private LoggerUtilInterface $loggerUtil;
49
50
    private ShipLoaderInterface $shipLoader;
51
52
    private ColonizationCheckerInterface $colonizationChecker;
53
54
    private DatabaseCategoryTalFactoryInterface $databaseCategoryTalFactory;
55
56
    private AstroEntryRepositoryInterface $astroEntryRepository;
57
58
    private DatabaseUserRepositoryInterface $databaseUserRepository;
59
60
    private NbsUtilityInterface $nbsUtility;
61
62
    private StationShipRepairRepositoryInterface $stationShipRepairRepository;
63
64
    private ShipyardShipQueueRepositoryInterface $shipyardShipQueueRepository;
65
66
    private UserLayerRepositoryInterface $userLayerRepository;
67
68
    private StationUtilityInterface $stationUtility;
69
70
    private ShipWrapperFactoryInterface $shipWrapperFactory;
71
72
    private ColonyLibFactoryInterface $colonyLibFactory;
73
74
    private ShipUiFactoryInterface $shipUiFactory;
75
76
    private ShipCrewCalculatorInterface $shipCrewCalculator;
77
78
    private FightLibInterface $fightLib;
79
80
    public function __construct(
81
        SessionInterface $session,
82
        ShipLoaderInterface $shipLoader,
83
        ColonizationCheckerInterface $colonizationChecker,
84
        DatabaseCategoryTalFactoryInterface $databaseCategoryTalFactory,
85
        AstroEntryRepositoryInterface $astroEntryRepository,
86
        DatabaseUserRepositoryInterface $databaseUserRepository,
87
        NbsUtilityInterface $nbsUtility,
88
        StationShipRepairRepositoryInterface $stationShipRepairRepository,
89
        ShipyardShipQueueRepositoryInterface $shipyardShipQueueRepository,
90
        UserLayerRepositoryInterface $userLayerRepository,
91
        StationUtilityInterface $stationUtility,
92
        ShipWrapperFactoryInterface $shipWrapperFactory,
93
        ColonyLibFactoryInterface $colonyLibFactory,
94
        ShipUiFactoryInterface $shipUiFactory,
95
        ShipCrewCalculatorInterface $shipCrewCalculator,
96
        FightLibInterface $fightLib,
97
        LoggerUtilFactoryInterface $loggerUtilFactory
98
    ) {
99
        $this->session = $session;
100
        $this->shipLoader = $shipLoader;
101
        $this->colonizationChecker = $colonizationChecker;
102
        $this->databaseCategoryTalFactory = $databaseCategoryTalFactory;
103
        $this->astroEntryRepository = $astroEntryRepository;
104
        $this->databaseUserRepository = $databaseUserRepository;
105
        $this->nbsUtility = $nbsUtility;
106
        $this->stationShipRepairRepository = $stationShipRepairRepository;
107
        $this->shipyardShipQueueRepository = $shipyardShipQueueRepository;
108
        $this->userLayerRepository = $userLayerRepository;
109
        $this->stationUtility = $stationUtility;
110
        $this->shipWrapperFactory = $shipWrapperFactory;
111
        $this->loggerUtilFactory = $loggerUtilFactory;
112
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
113
        $this->colonyLibFactory = $colonyLibFactory;
114
        $this->shipUiFactory = $shipUiFactory;
115
        $this->shipCrewCalculator = $shipCrewCalculator;
116
        $this->fightLib = $fightLib;
117
    }
118
119
    public function handle(GameControllerInterface $game): void
120
    {
121
        $user = $game->getUser();
122
        $userId = $user->getId();
123
        $ownsCurrentColony = false;
124
125
        $wrapper = $this->shipLoader->getWrapperByIdAndUser(
126
            request::indInt('id'),
127
            $userId,
128
            true
129
        );
130
        $ship = $wrapper->get();
131
132
        $tachyonFresh = $game->getViewContext()['TACHYON_SCAN_JUST_HAPPENED'] ?? false;
133
        $tachyonActive = $tachyonFresh;
134
135
        // check if tachyon scan still active
136
        if (!$tachyonActive) {
137
            $tachyonActive = $this->nbsUtility->isTachyonActive($ship);
138
        }
139
140
        $rump = $ship->getRump();
141
142
        $colony = $this->getColony($ship);
143
        $canColonize = false;
144
        if ($colony !== null) {
145
            if ($rump->hasSpecialAbility(ShipRumpSpecialAbilityEnum::COLONIZE)) {
146
                $canColonize = $this->colonizationChecker->canColonize($user, $colony);
147
            }
148
            $ownsCurrentColony = $colony->getUser() === $user;
149
        }
150
151
        //Forschungseintrag erstellen, damit System-Link optional erstellt werden kann
152
        $starSystem = $ship->getSystem();
153
        if ($starSystem !== null && $starSystem->getDatabaseEntry() !== null) {
154
            $starSystemEntryTal = $this->databaseCategoryTalFactory->createDatabaseCategoryEntryTal($starSystem->getDatabaseEntry(), $user);
155
            $game->setTemplateVar('STARSYSTEM_ENTRY_TAL', $starSystemEntryTal);
156
        }
157
158
        $isBase = $ship->isBase();
159
        $game->appendNavigationPart(
160
            $isBase ? 'station.php' : 'ship.php',
161
            $isBase ? _('Stationen') : _('Schiffe')
162
        );
163
164
        $game->appendNavigationPart(
165
            sprintf('?%s=1&id=%d', static::VIEW_IDENTIFIER, $ship->getId()),
166
            $ship->getName()
167
        );
168
        $game->setPagetitle($ship->getName());
169
170
        $game->setTemplateFile('html/ship.twig', true);
171
172
        $game->setTemplateVar('WRAPPER', $wrapper);
173
174
        if ($ship->getLss()) {
175
176
            $this->createUserLayerIfNecessary($user, $ship);
177
178
            $game->setTemplateVar('VISUAL_NAV_PANEL', $this->shipUiFactory->createVisualNavPanel(
179
                $ship,
180
                $game->getUser(),
181
                $this->loggerUtilFactory->getLoggerUtil(),
182
                $ship->getTachyonState(),
183
                $tachyonFresh
184
            ));
185
        }
186
        $game->setTemplateVar('NAV_PANEL', new NavPanel($ship));
187
188
        $this->doConstructionStuff($ship, $game);
189
        $this->doStationStuff($ship, $game);
190
191
        $this->nbsUtility->setNbsTemplateVars($ship, $game, $this->session, $tachyonActive);
192
193
        $game->setTemplateVar('ASTRO_STATE', $this->getAstroState($ship, $game));
194
        $game->setTemplateVar('TACHYON_ACTIVE', $tachyonActive);
195
        $game->setTemplateVar('CAN_COLONIZE', $canColonize);
196
        $game->setTemplateVar('OWNS_CURRENT_COLONY', $ownsCurrentColony);
197
        $game->setTemplateVar('CURRENT_COLONY', $colony);
198
        $game->setTemplateVar('FIGHT_LIB', $this->fightLib);
199
200
        $userLayers = $user->getUserLayers();
201
        if ($ship->hasTranswarp()) {
202
            $game->setTemplateVar('USER_LAYERS', $userLayers);
203
        }
204
205
        $layer = $ship->getLayer();
206
        if ($layer !== null && $userLayers->containsKey($layer->getId())) {
207
            $game->setTemplateVar('IS_MAP_BUTTON_VISIBLE', true);
208
        }
209
210
        $crewObj = $this->shipCrewCalculator->getCrewObj($rump);
211
212
        $game->setTemplateVar(
213
            'MAX_CREW_COUNT',
214
            $crewObj === null
215
                ? null
216
                : $this->shipCrewCalculator->getMaxCrewCountByShip($ship)
217
        );
218
219
        $this->addWarpcoreSplitJavascript($wrapper, $game);
220
221
        $this->loggerUtil->log(sprintf('ShowShip.handle-end, timestamp: %F', microtime(true)));
222
    }
223
224
    private function createUserLayerIfNecessary(UserInterface $user, ShipInterface $ship): void
225
    {
226
        $layer = $ship->getLayer();
227
        if ($layer === null) {
228
            return;
229
        }
230
231
        if ($ship->getMap() === null) {
232
            return;
233
        }
234
235
        $hasSeenLayer = $user->hasSeen($layer->getId());
236
        if ($hasSeenLayer) {
237
            return;
238
        }
239
240
        $userLayer = $this->userLayerRepository->prototype();
241
        $userLayer->setLayer($layer);
242
        $userLayer->setUser($user);
243
        $this->userLayerRepository->save($userLayer);
244
245
        $user->getUserLayers()->set($layer->getId(), $userLayer);
246
    }
247
248
    private function addWarpcoreSplitJavascript(ShipWrapperInterface $wrapper, GameControllerInterface $game): void
249
    {
250
        $warpCoreSystem = $wrapper->getWarpCoreSystemData();
251
        $warpDriveSystem = $wrapper->getWarpDriveSystemData();
252
        $epsSystem = $wrapper->getEpsSystemData();
253
254
        if ($warpCoreSystem !== null && $warpDriveSystem !== null && $epsSystem !== null) {
255
            $ship = $wrapper->get();
256
257
            $game->addExecuteJS(sprintf(
258
                'updateEPSSplitValue(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);',
259
                $warpCoreSystem->getWarpCoreSplit(),
260
                $ship->getReactorOutput(),
261
                $wrapper->getEpsUsage(),
262
                $ship->getRump()->getFlightEcost(),
263
                $wrapper->getEffectiveEpsProduction(),
264
                $epsSystem->getEps(),
265
                $epsSystem->getMaxEps(),
266
                $warpDriveSystem->getWarpDrive(),
267
                $warpDriveSystem->getMaxWarpDrive(),
268
                $ship->getReactorLoad()
269
            ), true);
270
        }
271
    }
272
273
    private function getColony(ShipInterface $ship): ?ColonyInterface
274
    {
275
        if ($ship->getStarsystemMap() === null) {
276
            return null;
277
        }
278
279
        return $ship->getStarsystemMap()->getColony();
280
    }
281
282
    private function getAstroState(ShipInterface $ship, GameControllerInterface $game): AstroStateWrapper
283
    {
284
        $system = $ship->getSystem() ?? $ship->isOverSystem();
285
286
        $astroEntry = null;
287
        if ($system === null || $system->getDatabaseEntry() === null) {
288
            $state = AstronomicalMappingEnum::NONE;
289
        } elseif ($this->databaseUserRepository->exists($game->getUser()->getId(), $system->getDatabaseEntry()->getId())) {
290
            $state = AstronomicalMappingEnum::DONE;
291
        } else {
292
            $astroEntry = $this->astroEntryRepository->getByUserAndSystem(
293
                $ship->getUser()->getId(),
294
                $system->getId()
295
            );
296
297
            $state = $astroEntry === null ? AstronomicalMappingEnum::PLANNABLE : $astroEntry->getState();
298
        }
299
        $turnsLeft = null;
300
        if ($state === AstronomicalMappingEnum::FINISHING && $astroEntry !== null) {
301
            $turnsLeft = AstronomicalMappingEnum::TURNS_TO_FINISH - ($game->getCurrentRound()->getTurn() - $astroEntry->getAstroStartTurn());
302
        }
303
        return new AstroStateWrapper($state, $turnsLeft);
304
    }
305
306
    private function doConstructionStuff(ShipInterface $ship, GameControllerInterface $game): void
307
    {
308
        if (!$ship->isConstruction() && !$ship->isBase()) {
309
            return;
310
        }
311
312
        $progress =  $this->stationUtility->getConstructionProgress($ship);
313
        if ($progress === null || $progress->getRemainingTicks() === 0) {
314
            $game->setTemplateVar('CONSTRUCTION_PROGRESS_WRAPPER', null);
315
        } else {
316
            $dockedWorkbees = $this->stationUtility->getDockedWorkbeeCount($ship);
317
            $neededWorkbees = $this->stationUtility->getNeededWorkbeeCount($ship, $ship->getRump());
318
319
            $game->setTemplateVar('CONSTRUCTION_PROGRESS_WRAPPER', new ConstructionProgressWrapper(
320
                $progress,
321
                $ship,
322
                $dockedWorkbees,
323
                $neededWorkbees
324
            ));
325
        }
326
327
        if ($progress === null) {
328
            $plans = $this->stationUtility->getStationBuildplansByUser($game->getUser()->getId());
329
            $game->setTemplateVar('POSSIBLE_STATIONS', $plans);
330
331
            $moduleSelectors = [];
332
            foreach ($plans as $plan) {
333
                $ms = $this->colonyLibFactory->createModuleSelectorSpecial(
334
                    ShipModuleTypeEnum::MODULE_TYPE_SPECIAL,
335
                    null,
336
                    $ship,
337
                    $plan->getRump(),
338
                    $game->getUser()->getId()
339
                );
340
341
                $ms->setDummyId($plan->getId());
342
                $moduleSelectors[] = $ms;
343
            }
344
345
            $game->setTemplateVar('MODULE_SELECTORS', $moduleSelectors);
346
            $game->setTemplateVar('HAS_STORAGE', new ColonyStorageCommodityWrapper($ship->getStorage()));
347
        }
348
    }
349
350
    private function doStationStuff(ShipInterface $ship, GameControllerInterface $game): void
351
    {
352
        if ($this->stationUtility->canManageShips($ship)) {
353
            $game->setTemplateVar('CAN_MANAGE', true);
354
        }
355
356
        if ($this->stationUtility->canRepairShips($ship)) {
357
            $game->setTemplateVar('CAN_REPAIR', true);
358
359
            $shipRepairProgress = array_map(
360
                fn (StationShipRepairInterface $repair): ShipWrapperInterface => $this->shipWrapperFactory->wrapShip($repair->getShip()),
361
                $this->stationShipRepairRepository->getByStation(
362
                    $ship->getId()
363
                )
364
            );
365
366
            $game->setTemplateVar('SHIP_REPAIR_PROGRESS', $shipRepairProgress);
367
        }
368
369
        if ($ship->getRump()->getRoleId() === ShipRumpEnum::SHIP_ROLE_SHIPYARD) {
370
            $game->setTemplateVar('SHIP_BUILD_PROGRESS', $this->shipyardShipQueueRepository->getByShipyard($ship->getId()));
371
        }
372
373
        $firstOrbitShip = null;
374
375
        /**
376
         * @var ShipInterface[] $shipList
377
         */
378
        $shipList = $ship->getDockedShips()->toArray();
379
        if ($shipList !== []) {
380
            // if selected, return the current target
381
            $target = request::postInt('target');
382
383
            if ($target !== 0) {
384
                foreach ($shipList as $ship) {
385
                    if ($ship->getId() === $target) {
386
                        $firstOrbitShip = $ship;
387
                    }
388
                }
389
            }
390
            if ($firstOrbitShip === null) {
391
                $firstOrbitShip = current($shipList);
392
            }
393
        }
394
395
        $game->setTemplateVar('FIRST_MANAGE_SHIP', $firstOrbitShip !== null ? $this->shipWrapperFactory->wrapShip($firstOrbitShip) : null);
396
        $game->setTemplateVar('CAN_UNDOCK', true);
397
398
        if ($ship->getRump()->isShipyard()) {
399
            $game->setTemplateVar('AVAILABLE_BUILDPLANS', $this->stationUtility->getShipyardBuildplansByUser($game->getUser()->getId()));
400
        }
401
    }
402
}
403