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