Passed
Push — master ( 55cfd1...cb4d54 )
by Nico
22:41
created

ShipCreator::__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\Ship\Lib;
6
7
use RuntimeException;
8
use Stu\Component\Ship\ShipModuleTypeEnum;
9
use Stu\Component\Ship\ShipRumpEnum;
10
use Stu\Component\Ship\ShipStateEnum;
11
use Stu\Component\Ship\SpacecraftTypeEnum;
12
use Stu\Component\Ship\System\ShipSystemModeEnum;
13
use Stu\Component\Ship\System\ShipSystemTypeEnum;
14
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperComputer;
15
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperEnergyWeapon;
16
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperEps;
17
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperHull;
18
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperImpulseDrive;
19
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperInterface;
20
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperProjectileWeapon;
21
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperReactor;
22
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperShield;
23
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperSpecial;
24
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperWarpDrive;
25
use Stu\Lib\ModuleRumpWrapper\ModuleRumpWrapperSensor;
26
use Stu\Module\Logging\LoggerUtilFactoryInterface;
27
use Stu\Module\Logging\LoggerUtilInterface;
28
use Stu\Module\ShipModule\ModuleSpecialAbilityEnum;
29
use Stu\Orm\Entity\BuildplanModuleInterface;
30
use Stu\Orm\Entity\ColonyInterface;
31
use Stu\Orm\Entity\ConstructionProgressInterface;
32
use Stu\Orm\Entity\ModuleInterface;
33
use Stu\Orm\Entity\ShipBuildplanInterface;
34
use Stu\Orm\Entity\ShipInterface;
35
use Stu\Orm\Repository\BuildplanModuleRepositoryInterface;
36
use Stu\Orm\Repository\ModuleSpecialRepositoryInterface;
37
use Stu\Orm\Repository\ShipBuildplanRepositoryInterface;
38
use Stu\Orm\Repository\ShipRepositoryInterface;
39
use Stu\Orm\Repository\ShipRumpRepositoryInterface;
40
use Stu\Orm\Repository\ShipSystemRepositoryInterface;
41
use Stu\Orm\Repository\StarSystemMapRepositoryInterface;
42
use Stu\Orm\Repository\UserRepositoryInterface;
43
44
final class ShipCreator implements ShipCreatorInterface
45
{
46
    private BuildplanModuleRepositoryInterface $buildplanModuleRepository;
47
48
    private ShipSystemRepositoryInterface $shipSystemRepository;
49
50
    private ShipRepositoryInterface $shipRepository;
51
52
    private UserRepositoryInterface $userRepository;
53
54
    private ShipRumpRepositoryInterface $shipRumpRepository;
55
56
    private ShipBuildplanRepositoryInterface $shipBuildplanRepository;
57
58
    private ModuleSpecialRepositoryInterface $moduleSpecialRepository;
59
60
    private StarSystemMapRepositoryInterface $starSystemMapRepository;
61
62
    private ShipWrapperFactoryInterface $shipWrapperFactory;
63
64
    private LoggerUtilInterface $loggerUtil;
65
66
    public function __construct(
67
        BuildplanModuleRepositoryInterface $buildplanModuleRepository,
68
        ShipSystemRepositoryInterface $shipSystemRepository,
69
        ShipRepositoryInterface $shipRepository,
70
        UserRepositoryInterface $userRepository,
71
        ShipRumpRepositoryInterface $shipRumpRepository,
72
        ShipBuildplanRepositoryInterface $shipBuildplanRepository,
73
        ModuleSpecialRepositoryInterface $moduleSpecialRepository,
74
        StarSystemMapRepositoryInterface $starSystemMapRepository,
75
        ShipWrapperFactoryInterface $shipWrapperFactory,
76
        LoggerUtilFactoryInterface $loggerUtilFactory
77
    ) {
78
        $this->buildplanModuleRepository = $buildplanModuleRepository;
79
        $this->shipSystemRepository = $shipSystemRepository;
80
        $this->shipRepository = $shipRepository;
81
        $this->userRepository = $userRepository;
82
        $this->shipRumpRepository = $shipRumpRepository;
83
        $this->shipBuildplanRepository = $shipBuildplanRepository;
84
        $this->moduleSpecialRepository = $moduleSpecialRepository;
85
        $this->starSystemMapRepository = $starSystemMapRepository;
86
        $this->shipWrapperFactory = $shipWrapperFactory;
87
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
88
    }
89
90
    public function createBy(
91
        int $userId,
92
        int $shipRumpId,
93
        int $shipBuildplanId,
94
        ?ColonyInterface $colony = null,
95
        ?ConstructionProgressInterface $progress = null
96
    ): ShipWrapperInterface {
97
        $user = $this->userRepository->find($userId);
98
        if ($user === null) {
99
            throw new RuntimeException('user not existent');
100
        }
101
102
        $rump = $this->shipRumpRepository->find($shipRumpId);
103
        if ($rump === null) {
104
            throw new RuntimeException('rump not existent');
105
        }
106
107
        $buildplan = $this->shipBuildplanRepository->find($shipBuildplanId);
108
        if ($buildplan === null) {
109
            throw new RuntimeException('buildplan not existent');
110
        }
111
112
        $ship = $progress !== null ? $progress->getShip() : $this->shipRepository->prototype();
113
        $ship->setUser($user);
114
        $ship->setBuildplan($buildplan);
115
        $ship->setRump($rump);
116
        $ship->setState(ShipStateEnum::SHIP_STATE_NONE);
117
118
        if ($ship->getRump()->getCategoryId() === ShipRumpEnum::SHIP_CATEGORY_STATION) {
119
            $ship->setSpacecraftType(SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION);
120
        }
121
122
        //create ship systems
123
        $this->createShipSystemsByModuleList(
124
            $ship,
125
            $this->buildplanModuleRepository->getByBuildplan(
126
                $buildplan->getId()
127
            ),
128
            $progress
129
        );
130
131
        $moduleTypeList = [
132
            ShipModuleTypeEnum::MODULE_TYPE_HULL => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperHull($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_HULL)),
133
            ShipModuleTypeEnum::MODULE_TYPE_SHIELDS => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperShield($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_SHIELDS)),
134
            ShipModuleTypeEnum::MODULE_TYPE_EPS => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperEps($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_EPS)),
135
            ShipModuleTypeEnum::MODULE_TYPE_IMPULSEDRIVE => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperImpulseDrive($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_IMPULSEDRIVE)),
136
            ShipModuleTypeEnum::MODULE_TYPE_REACTOR => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperReactor($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_REACTOR)),
137
            ShipModuleTypeEnum::MODULE_TYPE_COMPUTER => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperComputer($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_COMPUTER)),
138
            ShipModuleTypeEnum::MODULE_TYPE_PHASER => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperEnergyWeapon($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_PHASER)),
139
            ShipModuleTypeEnum::MODULE_TYPE_TORPEDO => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperProjectileWeapon($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_TORPEDO)),
140
            ShipModuleTypeEnum::MODULE_TYPE_SENSOR => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperSensor($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_SENSOR)),
141
            ShipModuleTypeEnum::MODULE_TYPE_WARPDRIVE => fn (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface => new ModuleRumpWrapperWarpDrive($wrapper, $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_WARPDRIVE)),
142
            ShipModuleTypeEnum::MODULE_TYPE_SPECIAL => function (ShipBuildplanInterface $buildplan, ShipWrapperInterface $wrapper): ModuleRumpWrapperInterface {
143
                $specialMods = $buildplan->getModulesByType(ShipModuleTypeEnum::MODULE_TYPE_SPECIAL);
144
                return new ModuleRumpWrapperSpecial($wrapper, $specialMods);
145
            },
146
        ];
147
148
        $wrapper = $this->shipWrapperFactory->wrapShip($ship);
149
150
        foreach ($moduleTypeList as $moduleTypeId => $wrapperCallable) {
151
            if ($this->loggerUtil->doLog()) {
152
                $this->loggerUtil->log(sprintf("moduleTypeId: %d", $moduleTypeId));
153
            }
154
            $buildplanModules = $buildplan->getModulesByType($moduleTypeId);
155
            if ($buildplanModules !== []) {
156
                if ($this->loggerUtil->doLog()) {
157
                    $this->loggerUtil->log("wrapperCallable!");
158
                }
159
                $moduleRumpWrapper = $wrapperCallable($buildplan, $wrapper);
160
                $moduleRumpWrapper->apply($ship);
161
            }
162
        }
163
164
        if ($ship->getName() == '' || $ship->getName() === sprintf('%s in Bau', $ship->getRump()->getName())) {
165
            $ship->setName($ship->getRump()->getName());
166
        }
167
168
        $ship->setAlertStateGreen();
169
170
        $this->shipRepository->save($ship);
171
        if ($colony !== null) {
172
            $starsystemMap = $this->starSystemMapRepository->getByCoordinates($colony->getSystem()->getId(), $colony->getSx(), $colony->getSy());
173
174
            $ship->setCx($colony->getSystem()->getCx());
175
            $ship->setCy($colony->getSystem()->getCy());
176
            $ship->setStarsystemMap($starsystemMap);
177
            $this->shipRepository->save($ship);
178
        }
179
180
        return $wrapper;
181
    }
182
183
    /**
184
     * @param array<BuildplanModuleInterface> $modules
185
     */
186
    private function createShipSystemsByModuleList(
187
        ShipInterface $ship,
188
        array $modules,
189
        ?ConstructionProgressInterface $progress
190
    ): void {
191
        $systems = [];
192
193
        //default systems, that almost every ship should have
194
        if ($ship->getRump()->getCategoryId() !== ShipRumpEnum::SHIP_CATEGORY_SHUTTLE) {
195
            $systems[ShipSystemTypeEnum::SYSTEM_DEFLECTOR->value] = 0;
196
            $systems[ShipSystemTypeEnum::SYSTEM_TRACTOR_BEAM->value] = 0;
197
        }
198
        $systems[ShipSystemTypeEnum::SYSTEM_LIFE_SUPPORT->value] = 0;
199
        //TODO transporter
200
201
        if ($ship->getRump()->getCategoryId() === ShipRumpEnum::SHIP_CATEGORY_STATION) {
202
            $systems[ShipSystemTypeEnum::SYSTEM_BEAM_BLOCKER->value] = 0;
203
        }
204
205
        if ($ship->getRump()->isShipyard()) {
206
            $systems[ShipSystemTypeEnum::SYSTEM_CONSTRUCTION_HUB->value] = 0;
207
        }
208
209
        if ($ship->getRump()->getRoleId() === ShipRumpEnum::SHIP_ROLE_SENSOR) {
210
            $systems[ShipSystemTypeEnum::SYSTEM_UPLINK->value] = 0;
211
        }
212
213
        foreach ($modules as $buildplanmodule) {
214
            $module = $buildplanmodule->getModule();
215
216
            $systemType = $module->getSystemType();
217
            if (
218
                $systemType === null
219
                && array_key_exists($module->getType(), ShipModuleTypeEnum::MODULE_TYPE_TO_SYSTEM_TYPE)
220
            ) {
221
                $systemType = ShipModuleTypeEnum::MODULE_TYPE_TO_SYSTEM_TYPE[$module->getType()];
222
            }
223
224
            if ($systemType !== null) {
225
                $systems[$systemType->value] = $module;
226
            }
227
228
            switch ($module->getType()) {
229
                case ShipModuleTypeEnum::MODULE_TYPE_SENSOR:
230
                    $systems[ShipSystemTypeEnum::SYSTEM_NBS->value] = 0;
231
                    break;
232
                case ShipModuleTypeEnum::MODULE_TYPE_SPECIAL:
233
                    $this->addSpecialSystems($module, $systems);
234
                    break;
235
            }
236
        }
237
        if ($progress !== null) {
238
            foreach ($progress->getSpecialModules() as $mod) {
239
                $this->addSpecialSystems($mod->getModule(), $systems);
240
            }
241
        }
242
        foreach ($systems as $systemType => $module) {
243
            $obj = $this->shipSystemRepository->prototype();
244
            $obj->setShip($ship);
245
            $ship->getSystems()->set($systemType, $obj);
246
            $obj->setSystemType(ShipSystemTypeEnum::from($systemType));
247
            if ($module !== 0) {
248
                $obj->setModule($module);
249
            }
250
            $obj->setStatus(100);
251
            $obj->setMode(ShipSystemModeEnum::MODE_OFF);
252
253
            $this->shipSystemRepository->save($obj);
254
        }
255
    }
256
257
    /**
258
     * @param array<int, ModuleInterface> $systems
259
     */
260
    private function addSpecialSystems(ModuleInterface $module, &$systems): void
261
    {
262
        $moduleSpecials = $this->moduleSpecialRepository->getByModule($module->getId());
263
264
        foreach ($moduleSpecials as $special) {
265
            switch ($special->getSpecialId()) {
266
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_CLOAK:
267
                    $systems[ShipSystemTypeEnum::SYSTEM_CLOAK->value] = $module;
268
                    break;
269
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TACHYON_SCANNER:
270
                    $systems[ShipSystemTypeEnum::SYSTEM_TACHYON_SCANNER->value] = $module;
271
                    break;
272
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TROOP_QUARTERS:
273
                    $systems[ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS->value] = $module;
274
                    break;
275
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_ASTRO_LABORATORY:
276
                    $systems[ShipSystemTypeEnum::SYSTEM_ASTRO_LABORATORY->value] = $module;
277
                    break;
278
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_SUBSPACE_FIELD_SENSOR:
279
                    $systems[ShipSystemTypeEnum::SYSTEM_SUBSPACE_SCANNER->value] = $module;
280
                    break;
281
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_MATRIX_SENSOR:
282
                    $systems[ShipSystemTypeEnum::SYSTEM_MATRIX_SCANNER->value] = $module;
283
                    break;
284
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TORPEDO_STORAGE:
285
                    $systems[ShipSystemTypeEnum::SYSTEM_TORPEDO_STORAGE->value] = $module;
286
                    break;
287
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_SHUTTLE_RAMP:
288
                    $systems[ShipSystemTypeEnum::SYSTEM_SHUTTLE_RAMP->value] = $module;
289
                    break;
290
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TRANSWARP_COIL:
291
                    $systems[ShipSystemTypeEnum::SYSTEM_TRANSWARP_COIL->value] = $module;
292
                    break;
293
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_HIROGEN_TRACKER:
294
                    $systems[ShipSystemTypeEnum::SYSTEM_TRACKER->value] = $module;
295
                    break;
296
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_THOLIAN_WEB:
297
                    $systems[ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB->value] = $module;
298
                    break;
299
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_RPG:
300
                    $systems[ShipSystemTypeEnum::SYSTEM_RPG_MODULE->value] = 0;
301
                    break;
302
            }
303
        }
304
    }
305
}
306