Passed
Pull Request — master (#1849)
by Nico
55:37 queued 21:01
created

ShipCreator::getDefaultSystems()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 12
nc 16
nop 1
dl 0
loc 25
ccs 0
cts 13
cp 0
crap 30
rs 9.5555
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib;
6
7
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use RuntimeException;
9
use Stu\Component\Ship\ShipModuleTypeEnum;
10
use Stu\Component\Ship\ShipRumpEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\ShipRumpEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use Stu\Component\Ship\ShipStateEnum;
12
use Stu\Component\Ship\SpacecraftTypeEnum;
13
use Stu\Component\Ship\System\ShipSystemModeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\System\ShipSystemModeEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

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