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

ShipCreator::addSpecialSystems()   C

Complexity

Conditions 14
Paths 14

Size

Total Lines 42
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 210

Importance

Changes 0
Metric Value
cc 14
eloc 39
c 0
b 0
f 0
nc 14
nop 2
dl 0
loc 42
ccs 0
cts 40
cp 0
crap 210
rs 6.2666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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