Passed
Push — dev ( c4f015...eeaa0f )
by Janko
27:51
created

RepairActions::repairShipOnStation()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 4
nop 1
dl 0
loc 13
ccs 0
cts 9
cp 0
crap 20
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Tick\Ship\ManagerComponent;
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 Stu\Component\Building\BuildingEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Building\BuildingEnum 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...
9
use Stu\Component\Colony\ColonyFunctionManagerInterface;
10
use Stu\Component\Colony\Storage\ColonyStorageManagerInterface;
11
use Stu\Component\Ship\Repair\RepairUtilInterface;
12
use Stu\Component\Ship\ShipStateEnum;
13
use Stu\Component\Ship\System\ShipSystemManagerInterface;
14
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
15
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
16
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...
17
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
18
use Stu\Module\Ship\Lib\ShipWrapperInterface;
19
use Stu\Orm\Entity\ColonyInterface;
20
use Stu\Orm\Entity\ShipInterface;
21
use Stu\Orm\Repository\ColonyShipRepairRepositoryInterface;
22
use Stu\Orm\Repository\ModuleQueueRepositoryInterface;
23
use Stu\Orm\Repository\PlanetFieldRepositoryInterface;
24
use Stu\Orm\Repository\ShipRepositoryInterface;
25
use Stu\Orm\Repository\StationShipRepairRepositoryInterface;
26
27
final class RepairActions implements ManagerComponentInterface
28
{
29
    public function __construct(private ShipRepositoryInterface $shipRepository, private PrivateMessageSenderInterface $privateMessageSender, private ShipSystemManagerInterface $shipSystemManager, private ColonyShipRepairRepositoryInterface $colonyShipRepairRepository, private StationShipRepairRepositoryInterface $stationShipRepairRepository, private ColonyStorageManagerInterface $colonyStorageManager, private ModuleQueueRepositoryInterface $moduleQueueRepository, private RepairUtilInterface $repairUtil, private ShipWrapperFactoryInterface $shipWrapperFactory, private PlanetFieldRepositoryInterface $planetFieldRepository, private ColonyFunctionManagerInterface $colonyFunctionManager)
30
    {
31
    }
32
33
    #[Override]
34
    public function work(): void
35
    {
36
        //spare parts and system components are generated by ship tick, to avoid dead locks
37
        $this->proceedSpareParts();
38
        $this->repairShipsOnColonies(1);
39
        $this->repairShipsOnStations();
40
    }
41
42
    private function proceedSpareParts(): void
43
    {
44
        foreach ($this->moduleQueueRepository->findAll() as $queue) {
45
            $buildingFunction = $queue->getBuildingFunction();
46
47
            if (
48
                $buildingFunction === BuildingEnum::BUILDING_FUNCTION_FABRICATION_HALL ||
49
                $buildingFunction === BuildingEnum::BUILDING_FUNCTION_TECH_CENTER
50
            ) {
51
                $colony = $queue->getColony();
52
53
                if ($this->colonyFunctionManager->hasActiveFunction($colony, $buildingFunction)) {
54
                    $this->colonyStorageManager->upperStorage(
55
                        $colony,
56
                        $queue->getModule()->getCommodity(),
57
                        $queue->getAmount()
58
                    );
59
60
                    $this->privateMessageSender->send(
61
                        UserEnum::USER_NOONE,
62
                        $colony->getUser()->getId(),
63
                        sprintf(
64
                            _('Es wurden %d %s hergestellt'),
65
                            $queue->getAmount(),
66
                            $queue->getModule()->getName()
67
                        ),
68
                        PrivateMessageFolderTypeEnum::SPECIAL_COLONY
69
                    );
70
71
                    $this->moduleQueueRepository->delete($queue);
72
                }
73
            }
74
        }
75
    }
76
77
    private function repairShipsOnColonies(int $tickId): void
78
    {
79
        $usedShipyards = [];
80
81
        foreach ($this->colonyShipRepairRepository->getMostRecentJobs($tickId) as $obj) {
82
            $ship = $obj->getShip();
83
            $colony = $obj->getColony();
84
85
            if ($colony->isBlocked()) {
86
                continue;
87
            }
88
89
            $field = $this->planetFieldRepository->getByColonyAndFieldIndex(
90
                $obj->getColonyId(),
91
                $obj->getFieldId()
92
            );
93
94
            if ($field === null) {
95
                continue;
96
            }
97
98
            if (!$field->isActive()) {
99
                continue;
100
            }
101
102
            if (!array_key_exists($colony->getId(), $usedShipyards)) {
103
                $usedShipyards[$colony->getId()] = [];
104
            }
105
106
            $isRepairStationBonus = $this->colonyFunctionManager->hasActiveFunction($colony, BuildingEnum::BUILDING_FUNCTION_REPAIR_SHIPYARD);
107
108
            //already repaired a ship on this colony field, max is one without repair station
109
            if (
110
                !$isRepairStationBonus
111
                && array_key_exists($field->getFieldId(), $usedShipyards[$colony->getId()])
112
            ) {
113
                continue;
114
            }
115
116
            $usedShipyards[$colony->getId()][$field->getFieldId()] = [$field->getFieldId()];
117
118
            if ($this->repairShipOnEntity($ship, $colony, $isRepairStationBonus)) {
119
                $this->colonyShipRepairRepository->delete($obj);
120
                $this->shipRepository->save($ship);
121
            }
122
        }
123
    }
124
125
    private function repairShipsOnStations(): void
126
    {
127
        foreach ($this->stationShipRepairRepository->getMostRecentJobs() as $obj) {
128
            $ship = $obj->getShip();
129
            $station = $obj->getStation();
130
131
            if (!$station->hasEnoughCrew()) {
132
                continue;
133
            }
134
135
            if ($this->repairShipOnEntity($ship, $station, false)) {
136
                $this->stationShipRepairRepository->delete($obj);
137
                $this->shipRepository->save($ship);
138
            }
139
        }
140
    }
141
142
    private function repairShipOnEntity(ShipInterface $ship, ColonyInterface|ShipInterface $entity, bool $isRepairStationBonus): bool
143
    {
144
        // check for U-Mode
145
        if ($entity->getUser()->isVacationRequestOldEnough()) {
146
            return false;
147
        }
148
149
        $wrapper = $this->shipWrapperFactory->wrapShip($ship);
150
        $neededParts = $this->repairUtil->determineSpareParts($wrapper, true);
151
152
        // parts stored?
153
        if (!$this->repairUtil->enoughSparePartsOnEntity($neededParts, $entity, $ship)) {
154
            return false;
155
        }
156
157
        $repairFinished = false;
158
159
        $this->repairHull($ship, $isRepairStationBonus);
160
        $this->repairShipSystems($wrapper, $isRepairStationBonus);
161
162
        // consume spare parts
163
        $this->repairUtil->consumeSpareParts($neededParts, $entity);
164
165
        if (!$wrapper->canBeRepaired()) {
166
            $repairFinished = true;
167
168
            $ship->setHuell($ship->getMaxHull());
169
            $ship->setState(ShipStateEnum::SHIP_STATE_NONE);
170
171
            $this->sendPrivateMessages($ship, $entity);
172
        }
173
        $this->shipRepository->save($ship);
174
175
        return $repairFinished;
176
    }
177
178
    private function repairHull(ShipInterface $ship, bool $isRepairStationBonus): void
179
    {
180
        $hullRepairRate = $isRepairStationBonus ? $ship->getRepairRate() * 2 : $ship->getRepairRate();
181
        $ship->setHuell($ship->getHull() + $hullRepairRate);
182
        if ($ship->getHull() > $ship->getMaxHull()) {
183
            $ship->setHuell($ship->getMaxHull());
184
        }
185
    }
186
187
    private function repairShipSystems(ShipWrapperInterface $wrapper, bool $isRepairStationBonus): void
188
    {
189
        $ship = $wrapper->get();
190
191
        $damagedSystems = $wrapper->getDamagedSystems();
192
        if ($damagedSystems !== []) {
193
            $firstSystem = $damagedSystems[0];
194
            $firstSystem->setStatus(100);
195
196
            if ($ship->getCrewCount() > 0) {
197
                $firstSystem->setMode($this->shipSystemManager->lookupSystem($firstSystem->getSystemType())->getDefaultMode());
198
            }
199
200
            // maximum of two systems get repaired
201
            if (count($damagedSystems) > 1) {
202
                $secondSystem = $damagedSystems[1];
203
                $secondSystem->setStatus(100);
204
205
                if ($ship->getCrewCount() > 0) {
206
                    $secondSystem->setMode($this->shipSystemManager->lookupSystem($secondSystem->getSystemType())->getDefaultMode());
207
                }
208
            }
209
210
            // maximum of two additional systems get repaired
211
            if ($isRepairStationBonus) {
212
                if (count($damagedSystems) > 2) {
213
                    $thirdSystem = $damagedSystems[2];
214
                    $thirdSystem->setStatus(100);
215
216
                    if ($ship->getCrewCount() > 0) {
217
                        $thirdSystem->setMode($this->shipSystemManager->lookupSystem($thirdSystem->getSystemType())->getDefaultMode());
218
                    }
219
                }
220
                if (count($damagedSystems) > 3) {
221
                    $fourthSystem = $damagedSystems[3];
222
                    $fourthSystem->setStatus(100);
223
224
                    if ($ship->getCrewCount() > 0) {
225
                        $fourthSystem->setMode($this->shipSystemManager->lookupSystem($fourthSystem->getSystemType())->getDefaultMode());
226
                    }
227
                }
228
            }
229
        }
230
    }
231
232
    private function sendPrivateMessages(ShipInterface $ship, ColonyInterface|ShipInterface $entity): void
233
    {
234
        $shipOwnerMessage = $entity instanceof ColonyInterface ? sprintf(
235
            "Die Reparatur der %s wurde in Sektor %s bei der Kolonie %s des Spielers %s fertiggestellt",
236
            $ship->getName(),
237
            $ship->getSectorString(),
238
            $entity->getName(),
239
            $entity->getUser()->getName()
240
        ) : sprintf(
241
            "Die Reparatur der %s wurde in Sektor %s von der %s %s des Spielers %s fertiggestellt",
242
            $ship->getName(),
243
            $ship->getSectorString(),
244
            $entity->getRump()->getName(),
245
            $entity->getName(),
246
            $entity->getUser()->getName()
247
        );
248
249
        $this->privateMessageSender->send(
250
            $entity->getUser()->getId(),
251
            $ship->getUser()->getId(),
252
            $shipOwnerMessage,
253
            PrivateMessageFolderTypeEnum::SPECIAL_SHIP
254
        );
255
256
        $entityOwnerMessage = $entity instanceof ColonyInterface ? sprintf(
257
            "Die Reparatur der %s von Siedler %s wurde in Sektor %s bei der Kolonie %s fertiggestellt",
258
            $ship->getName(),
259
            $ship->getUser()->getName(),
260
            $ship->getSectorString(),
261
            $entity->getName()
262
        ) : sprintf(
263
            "Die Reparatur der %s von Siedler %s wurde in Sektor %s von der %s %s fertiggestellt",
264
            $ship->getName(),
265
            $ship->getUser()->getName(),
266
            $ship->getSectorString(),
267
            $entity->getRump()->getName(),
268
            $entity->getName()
269
        );
270
271
        $this->privateMessageSender->send(
272
            UserEnum::USER_NOONE,
273
            $entity->getUser()->getId(),
274
            $entityOwnerMessage,
275
            $entity instanceof ColonyInterface ? PrivateMessageFolderTypeEnum::SPECIAL_COLONY :
276
                PrivateMessageFolderTypeEnum::SPECIAL_STATION
277
        );
278
    }
279
}
280