Passed
Push — dev ( 0f4afd...29c427 )
by Janko
25:18 queued 14:48
created

ShipRetrofit::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 0
nc 1
nop 5
dl 0
loc 7
ccs 2
cts 2
cp 1
crap 1
rs 10
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\Spacecraft\SpacecraftModuleTypeEnum;
10
use Stu\Lib\Transfer\Storage\StorageManagerInterface;
11
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
12
use Stu\Component\Spacecraft\System\SpacecraftSystemModeEnum;
13
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
14
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
15
use Stu\Module\PlayerSetting\Lib\UserEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\PlayerSetting\Lib\UserEnum 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...
16
use Stu\Orm\Entity\ColonyInterface;
17
use Stu\Orm\Entity\ShipInterface;
18
use Stu\Orm\Entity\SpacecraftBuildplanInterface;
19
use Stu\Orm\Entity\ModuleInterface;
20
use Stu\Orm\Repository\SpacecraftSystemRepositoryInterface;
21
use Stu\Orm\Repository\ModuleSpecialRepositoryInterface;
22
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperFactoryInterface;
23
use Stu\Orm\Entity\SpacecraftSystemInterface;
24
25
final class ShipRetrofit implements ShipRetrofitInterface
26
{
27 1
    public function __construct(
28
        private SpacecraftSystemRepositoryInterface $shipSystemRepository,
29
        private ModuleSpecialRepositoryInterface $moduleSpecialRepository,
30
        private SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory,
31
        private StorageManagerInterface $storageManager,
32
        private PrivateMessageSenderInterface $privateMessageSender
33 1
    ) {}
34
35
    #[Override]
36
    public function updateBy(ShipInterface $ship, SpacecraftBuildplanInterface $newBuildplan, ColonyInterface $colony): void
37
    {
38
        $oldBuildplan = $ship->getBuildplan();
39
        $wrapper = $this->spacecraftWrapperFactory->wrapShip($ship);
40
41
        if ($oldBuildplan === null) {
42
            return;
43
        }
44
45
        $returnedmodules = [];
46
47
        foreach (SpacecraftModuleTypeEnum::getModuleSelectorOrder() as $moduleType) {
48
49
            $oldModules = $oldBuildplan->getModulesByType($moduleType)->toArray();
50
            $newModules = $newBuildplan->getModulesByType($moduleType)->toArray();
51
52
            /** @var array<ModuleInterface> */
53
            $addingModules = array_udiff($newModules, $oldModules, function (ModuleInterface $a, ModuleInterface $b): int {
54
                return $a->getId() - $b->getId();
55
            });
56
57
            /** @var array<ModuleInterface> */
58
            $deletingModules = array_udiff($oldModules, $newModules, function (ModuleInterface $a, ModuleInterface $b): int {
59
                return $a->getId() - $b->getId();
60
            });
61
62
            foreach ($deletingModules as $oldModule) {
63
                $this->removeModule($ship, $oldModule, $returnedmodules);
64
            }
65
66
            if ($addingModules !== []) {
67
                $systems = [];
68
                $this->addModuleSystems($addingModules, $systems);
69
                foreach ($systems as $systemType => $module) {
70
                    $this->createShipSystem($systemType, $ship, $module);
71
                    $moduleRumpWrapper = $moduleType->getModuleRumpWrapperCallable()($ship->getRump(), $newBuildplan);
72
                    $moduleRumpWrapper->apply($wrapper);
73
                }
74
            }
75
        }
76
77
        if ($returnedmodules !== []) {
78
            $msg = "
79
            Die folgenden Module wurden durch den Umbau zurückgewonnen: ";
80
            foreach ($returnedmodules as $module) {
81
                if ($module != null) {
82
                    $this->storageManager->upperStorage($colony, $module->getCommodity(), 1);
83
                    $msg .= $module->getName() . ", ";
84
                }
85
            }
86
            $msg = rtrim($msg, ", ");
87
        } else {
88
            $msg = null;
89
        }
90
91
        $txt = _("Auf der Kolonie " . $colony->getName() . " wurde die " . $ship->getName() . " umgerüstet");
92
93
        if ($msg !== null) {
94
            $txt .= '. ' . $msg;
95
        }
96
97
        $this->privateMessageSender->send(
98
            UserEnum::USER_NOONE,
99
            $colony->getUserId(),
100
            $txt,
101
            PrivateMessageFolderTypeEnum::SPECIAL_COLONY
102
        );
103
104
        $ship->setBuildplan($newBuildplan);
105
    }
106
107
    /** @param array<ModuleInterface> $returnedmodules */
108
    private function removeModule(ShipInterface $ship, ModuleInterface $oldModule, array &$returnedmodules): void
109
    {
110
        $system = $this->getSystemByModule($oldModule, $ship);
111
        if ($system->getStatus() >= 100 && mt_rand(1, 100) <= 25) {
112
            $returnedmodules[] = $oldModule;
113
        }
114
        $this->shipSystemRepository->delete($system);
115
        $ship->getSystems()->removeElement($system);
116
    }
117
118
    private function getSystemByModule(ModuleInterface $module, ShipInterface $ship): SpacecraftSystemInterface
119
    {
120
        foreach ($ship->getSystems()  as $system) {
121
            if ($system->getModule() === $module) {
122
                return $system;
123
            }
124
        }
125
126
        throw new RuntimeException(sprintf('no system installed with moduleId: %d', $module->getId()));
127
    }
128
129
    /**
130
     * @param array<ModuleInterface> $modules
131
     * @param array<int, ModuleInterface|null> $systems
132
     */
133
    private function addModuleSystems(array $modules, array &$systems): void
134
    {
135
        foreach ($modules as $module) {
136
137
            $systemType = $module->getSystemType();
138
            if (
139
                $systemType === null
140
                && $module->getType()->hasCorrespondingSystemType()
141
            ) {
142
                $systemType = $module->getType()->getSystemType();
143
            }
144
145
            if ($systemType !== null) {
146
                $systems[$systemType->value] = $module;
147
            }
148
149
            if ($module->getType() === SpacecraftModuleTypeEnum::SPECIAL) {
150
                $this->addSpecialSystems($module, $systems);
151
            }
152
        }
153
    }
154
155
    /**
156
     * @param array<int, null|ModuleInterface> $systems
157
     */
158
    private function addSpecialSystems(ModuleInterface $module, array &$systems): void
159
    {
160
        $moduleSpecials = $this->moduleSpecialRepository->getByModule($module->getId());
161
162
        foreach ($moduleSpecials as $special) {
163
            $moduleSpecial = $special->getSpecialId();
164
            $systems[$moduleSpecial->getSystemType()->value] = $moduleSpecial->hasCorrespondingModule() ? $module : null;
165
        }
166
    }
167
168
169
    private function createShipSystem(int $systemType, ShipInterface $ship, ?ModuleInterface $module): void
170
    {
171
        $shipSystem = $this->shipSystemRepository
172
            ->prototype()
173
            ->setSpacecraft($ship)
174
            ->setSystemType(SpacecraftSystemTypeEnum::from($systemType))
175
            ->setStatus(100)
176
            ->setMode(SpacecraftSystemModeEnum::MODE_OFF);
177
178
        if ($module !== null) {
179
            $shipSystem->setModule($module);
180
        }
181
182
        $this->shipSystemRepository->save($shipSystem);
183
184
        $ship->getSystems()->set($systemType, $shipSystem);
185
    }
186
}
187