Passed
Push — dev ( 262e9d...837c0e )
by Nico
30:19
created

ShipRetrofit::addSpecialSystems()   C

Complexity

Conditions 16
Paths 16

Size

Total Lines 48
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 272

Importance

Changes 0
Metric Value
cc 16
eloc 45
nc 16
nop 2
dl 0
loc 48
ccs 0
cts 46
cp 0
crap 272
rs 5.5666
c 0
b 0
f 0

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 Stu\Component\Ship\ShipModuleTypeEnum;
8
use Stu\Component\Ship\System\ShipSystemTypeEnum;
9
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...
10
use Stu\Module\ShipModule\ModuleSpecialAbilityEnum;
11
use Stu\Orm\Entity\ShipInterface;
12
use Stu\Orm\Entity\ShipBuildplanInterface;
13
use Stu\Orm\Entity\ModuleInterface;
14
use Stu\Orm\Repository\ShipSystemRepositoryInterface;
15
use Stu\Orm\Repository\BuildplanModuleRepositoryInterface;
16
use Stu\Orm\Repository\ModuleSpecialRepositoryInterface;
17
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
18
use Stu\Orm\Entity\BuildplanModuleInterface;
19
20
21
final class ShipRetrofit implements ShipRetrofitInterface
22
{
23
    private ShipSystemRepositoryInterface $shipSystemRepository;
24
    private BuildplanModuleRepositoryInterface $buildplanModuleRepository;
25
    private ModuleSpecialRepositoryInterface $moduleSpecialRepository;
26
    private ShipWrapperFactoryInterface $shipWrapperFactory;
27
28
    public function __construct(
29
        ShipSystemRepositoryInterface $shipSystemRepository,
30
        BuildplanModuleRepositoryInterface $buildplanModuleRepository,
31
        ModuleSpecialRepositoryInterface $moduleSpecialRepository,
32
        ShipWrapperFactoryInterface $shipWrapperFactory
33
    ) {
34
        $this->shipSystemRepository = $shipSystemRepository;
35
        $this->buildplanModuleRepository = $buildplanModuleRepository;
36
        $this->moduleSpecialRepository = $moduleSpecialRepository;
37
        $this->shipWrapperFactory = $shipWrapperFactory;
38
    }
39
40
    public function updateBy(ShipInterface $ship, ShipBuildplanInterface $newBuildplan): void
41
    {
42
        $oldBuildplan = $ship->getBuildplan();
43
        $wrapper = $this->shipWrapperFactory->wrapShip($ship);
44
45
        if ($oldBuildplan === null) {
46
            return;
47
        }
48
49
50
        foreach (ShipModuleTypeEnum::cases() as $moduleType) {
51
            $oldModules = $this->buildplanModuleRepository->getByBuildplanAndModuleType($oldBuildplan->getId(), $moduleType->value);
52
            $newModules = $this->buildplanModuleRepository->getByBuildplanAndModuleType($newBuildplan->getId(), $moduleType->value);
53
54
            $addingModules = array_udiff($newModules, $oldModules, function ($a, $b) {
55
                return $a->getModule()->getId() - $b->getModule()->getId();
56
            });
57
58
            if (!empty($addingModules)) {
59
                $systems = [];
60
                $this->addModuleSystems($addingModules, $systems);
61
                foreach ($systems as $systemType => $module) {
62
                    $this->createShipSystem($systemType, $ship, $module);
63
                    $moduleRumpWrapper = $moduleType->getModuleRumpWrapperCallable()($ship->getRump(), $newBuildplan);
64
                    $moduleRumpWrapper->apply($wrapper);
65
                }
66
            }
67
68
            $deletingModules = array_udiff($oldModules, $newModules, function ($a, $b) {
69
                return $a->getModule()->getId() - $b->getModule()->getId();
70
            });
71
72
            foreach ($deletingModules as $oldModule) {
73
                $system = $this->shipSystemRepository->getByShipAndModule($ship->getId(), $oldModule->getModule()->getId());
74
                if ($system !== null) {
75
                    $this->shipSystemRepository->delete($system);
76
                }
77
            }
78
        }
79
80
81
82
        $ship->setBuildplan($newBuildplan);
83
    }
84
85
    /**
86
     * @param array<BuildplanModuleInterface> $modules
87
     * @param array<int, ModuleInterface|null> $systems
88
     */
89
    private function addModuleSystems(array $modules, array &$systems): void
90
    {
91
        foreach ($modules as $buildplanmodule) {
92
            $module = $buildplanmodule->getModule();
93
94
            $systemType = $module->getSystemType();
95
            if (
96
                $systemType === null
97
                && $module->getType()->hasCorrespondingSystemType()
98
            ) {
99
                $systemType = $module->getType()->getSystemType();
100
            }
101
102
            if ($systemType !== null) {
103
                $systems[$systemType->value] = $module;
104
            }
105
106
            switch ($module->getType()) {
107
                case ShipModuleTypeEnum::SPECIAL:
108
                    $this->addSpecialSystems($module, $systems);
109
                    break;
110
            }
111
        }
112
    }
113
114
    /**
115
     * @param array<int, null|ModuleInterface> $systems
116
     */
117
    private function addSpecialSystems(ModuleInterface $module, array &$systems): void
118
    {
119
        $moduleSpecials = $this->moduleSpecialRepository->getByModule($module->getId());
120
121
        foreach ($moduleSpecials as $special) {
122
            switch ($special->getSpecialId()) {
123
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_CLOAK:
124
                    $systems[ShipSystemTypeEnum::SYSTEM_CLOAK->value] = $module;
125
                    break;
126
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TACHYON_SCANNER:
127
                    $systems[ShipSystemTypeEnum::SYSTEM_TACHYON_SCANNER->value] = $module;
128
                    break;
129
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TROOP_QUARTERS:
130
                    $systems[ShipSystemTypeEnum::SYSTEM_TROOP_QUARTERS->value] = $module;
131
                    break;
132
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_ASTRO_LABORATORY:
133
                    $systems[ShipSystemTypeEnum::SYSTEM_ASTRO_LABORATORY->value] = $module;
134
                    break;
135
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_SUBSPACE_FIELD_SENSOR:
136
                    $systems[ShipSystemTypeEnum::SYSTEM_SUBSPACE_SCANNER->value] = $module;
137
                    break;
138
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_MATRIX_SENSOR:
139
                    $systems[ShipSystemTypeEnum::SYSTEM_MATRIX_SCANNER->value] = $module;
140
                    break;
141
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TORPEDO_STORAGE:
142
                    $systems[ShipSystemTypeEnum::SYSTEM_TORPEDO_STORAGE->value] = $module;
143
                    break;
144
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_SHUTTLE_RAMP:
145
                    $systems[ShipSystemTypeEnum::SYSTEM_SHUTTLE_RAMP->value] = $module;
146
                    break;
147
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_TRANSWARP_COIL:
148
                    $systems[ShipSystemTypeEnum::SYSTEM_TRANSWARP_COIL->value] = $module;
149
                    break;
150
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_HIROGEN_TRACKER:
151
                    $systems[ShipSystemTypeEnum::SYSTEM_TRACKER->value] = $module;
152
                    break;
153
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_THOLIAN_WEB:
154
                    $systems[ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB->value] = $module;
155
                    break;
156
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_BUSSARD_COLLECTOR:
157
                    $systems[ShipSystemTypeEnum::SYSTEM_BUSSARD_COLLECTOR->value] = $module;
158
                    break;
159
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_RPG:
160
                    $systems[ShipSystemTypeEnum::SYSTEM_RPG_MODULE->value] = null;
161
                    break;
162
                case ModuleSpecialAbilityEnum::MODULE_SPECIAL_AGGREGATION_SYSTEM:
163
                    $systems[ShipSystemTypeEnum::SYSTEM_AGGREGATION_SYSTEM->value] = $module;
164
                    break;
165
            }
166
        }
167
    }
168
169
170
    private function createShipSystem(int $systemType, ShipInterface $ship, ?ModuleInterface $module): void
171
    {
172
        $shipSystem = $this->shipSystemRepository->prototype();
173
        $shipSystem->setShip($ship);
174
        $ship->getSystems()->set($systemType, $shipSystem);
175
        $shipSystem->setSystemType(ShipSystemTypeEnum::from($systemType));
176
        if ($module !== null) {
177
            $shipSystem->setModule($module);
178
        }
179
        $shipSystem->setStatus(100);
180
        $shipSystem->setMode(ShipSystemModeEnum::MODE_OFF);
181
182
        $this->shipSystemRepository->save($shipSystem);
183
    }
184
}