Passed
Push — dev ( 80c162...225d4f )
by Janko
09:12
created

TholianWebUtil::releaseSpacecraftFromWeb()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 1
dl 0
loc 20
ccs 0
cts 12
cp 0
crap 12
rs 9.8666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib;
6
7
use Doctrine\ORM\EntityManagerInterface;
8
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...
9
use RuntimeException;
10
use Stu\Component\Game\TimeConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Game\TimeConstants 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\Spacecraft\SpacecraftStateEnum;
12
use Stu\Component\Spacecraft\System\Data\WebEmitterSystemData;
13
use Stu\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
14
use Stu\Module\Control\StuTime;
15
use Stu\Module\Logging\LoggerUtilFactoryInterface;
16
use Stu\Module\Logging\LoggerUtilInterface;
17
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
18
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
19
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...
20
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperFactoryInterface;
21
use Stu\Module\Ship\Lib\ShipWrapperInterface;
22
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface;
23
use Stu\Orm\Entity\SpacecraftInterface;
24
use Stu\Orm\Entity\SpacecraftSystemInterface;
25
use Stu\Orm\Entity\TholianWebInterface;
26
use Stu\Orm\Repository\ShipRepositoryInterface;
27
use Stu\Orm\Repository\SpacecraftRepositoryInterface;
28
use Stu\Orm\Repository\SpacecraftSystemRepositoryInterface;
29
use Stu\Orm\Repository\TholianWebRepositoryInterface;
30
31
final class TholianWebUtil implements TholianWebUtilInterface
32
{
33
    private LoggerUtilInterface $loggerUtil;
34
35 2
    public function __construct(
36
        private SpacecraftRepositoryInterface $spacecraftRepository,
37
        private ShipRepositoryInterface $shipRepository,
38
        private TholianWebRepositoryInterface $tholianWebRepository,
39
        private SpacecraftSystemRepositoryInterface $shipSystemRepository,
40
        private StuTime $stuTime,
41
        private PrivateMessageSenderInterface $privateMessageSender,
42
        LoggerUtilFactoryInterface $loggerUtilFactory,
43
        private EntityManagerInterface $entityManager
44
    ) {
45 2
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
46
    }
47
48
    #[Override]
49
    public function releaseSpacecraftFromWeb(SpacecraftWrapperInterface $wrapper): void
50
    {
51
        $this->loggerUtil->log(sprintf('releaseSpacecraftFromWeb, shipId: %d', $wrapper->get()->getId()));
52
53
        $spacecraft = $wrapper->get();
54
        $web = $spacecraft->getHoldingWeb();
55
        if ($web === null) {
56
            return;
57
        }
58
59
        $web->getCapturedSpacecrafts()->removeElement($spacecraft);
60
61
        if ($web->getCapturedSpacecrafts()->isEmpty()) {
62
            $this->resetWebHelpers($web, $wrapper->getSpacecraftWrapperFactory());
63
            $this->removeWeb($web);
64
        }
65
66
        $spacecraft->setHoldingWeb(null);
67
        $this->spacecraftRepository->save($spacecraft);
68
    }
69
70
    #[Override]
71
    public function releaseAllShips(TholianWebInterface $web, SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory): void
72
    {
73
        foreach ($web->getCapturedSpacecrafts() as $target) {
74
            $this->releaseSpacecraftFromWeb($spacecraftWrapperFactory->wrapSpacecraft($target));
75
76
            //notify target owner
77
            $this->privateMessageSender->send(
78
                $web->getUser()->getId(),
79
                $target->getUser()->getId(),
80
                sprintf(
81
                    'Das Energienetz um die %s in Sektor %s wurde aufgelöst',
82
                    $target->getName(),
83
                    $target->getSectorString()
84
                ),
85
                $target->getType()->getMessageFolderType()
86
            );
87
        }
88
    }
89
90
    #[Override]
91
    public function removeWeb(TholianWebInterface $web): void
92
    {
93
        $this->loggerUtil->log(sprintf('removeWeb, webId: %d', $web->getId()));
94
95
        $this->tholianWebRepository->delete($web);
96
    }
97
98
    #[Override]
99
    public function releaseWebHelper(ShipWrapperInterface $wrapper): void
100
    {
101
        $this->loggerUtil->log(sprintf('releaseWebHelper, shipId: %d', $wrapper->get()->getId()));
102
103
        $emitter = $this->getMandatoryEmitter($wrapper);
104
        $web = $this->getMandatoryWebUnderConstruction($emitter);
105
106
        $finishedTime = $this->releaseWebHelperIntern($wrapper);
107
        if ($finishedTime === null) {
108
            throw new RuntimeException('this should not happen');
109
        }
110
111
        $currentSpinnerSystems = $this->shipSystemRepository->getWebConstructingShipSystems($web->getId());
112
113
        //remove web if lost
114
        if ($currentSpinnerSystems === []) {
115
            $this->releaseAllShips($web, $wrapper->getSpacecraftWrapperFactory());
116
            $this->removeWeb($web);
117
        } else {
118
            $ship = $wrapper->get();
119
120
            //notify other web spinners
121
            foreach ($currentSpinnerSystems as $shipSystem) {
122
                $this->privateMessageSender->send(
123
                    $ship->getUser()->getId(),
124
                    $shipSystem->getSpacecraft()->getUser()->getId(),
125
                    sprintf(
126
                        'Die %s hat den Netzaufbau in Sektor %s verlassen, Fertigstellung: %s',
127
                        $ship->getName(),
128
                        $ship->getSectorString(),
129
                        $this->stuTime->transformToStuDateTime($finishedTime)
130
                    ),
131
                    PrivateMessageFolderTypeEnum::SPECIAL_SHIP
132
                );
133
            }
134
        }
135
    }
136
137
    #[Override]
138
    public function resetWebHelpers(
139
        TholianWebInterface $web,
140
        SpacecraftWrapperFactoryInterface $spacecraftWrapperFactory,
141
        bool $isFinished = false
142
    ): void {
143
        $this->loggerUtil->log(sprintf('resetWebHelpers, webId: %d', $web->getId()));
144
145
        $systems = $this->shipSystemRepository->getWebConstructingShipSystems($web->getId());
146
        foreach ($systems as $system) {
147
            /** @var ShipWrapperInterface */
148
            $wrapper = $spacecraftWrapperFactory->wrapSpacecraft($system->getSpacecraft());
149
            $this->releaseWebHelperIntern($wrapper);
150
151
            //notify helpers when finished
152
            if ($isFinished) {
153
                $ship = $system->getSpacecraft();
154
155
                $this->privateMessageSender->send(
156
                    UserEnum::USER_NOONE,
157
                    $ship->getUser()->getId(),
158
                    sprintf(
159
                        'Das Energienetz in Sektor %s wurde fertiggestellt',
160
                        $ship->getSectorString()
161
                    ),
162
                    PrivateMessageFolderTypeEnum::SPECIAL_SHIP
163
                );
164
            }
165
        }
166
    }
167
168
    private function releaseWebHelperIntern(ShipWrapperInterface $wrapper): ?int
169
    {
170
        $emitter = $this->getMandatoryEmitter($wrapper);
171
        $web = $this->getMandatoryWebUnderConstruction($emitter);
172
173
        if ($emitter->ownedWebId === $emitter->webUnderConstructionId && !$web->isFinished()) {
174
            $emitter->setOwnedWebId(null);
175
        }
176
        $emitter->setWebUnderConstructionId(null)->update();
177
        $wrapper->getSpacecraftSystemManager()->deactivate($wrapper, SpacecraftSystemTypeEnum::THOLIAN_WEB, true);
178
179
        $ship = $wrapper->get();
180
        $ship->setState(SpacecraftStateEnum::SHIP_STATE_NONE);
181
        $this->shipRepository->save($ship);
182
183
        //update finish time last
184
        return $this->updateWebFinishTime($web, -1);
185
    }
186
187
    #[Override]
188
    public function updateWebFinishTime(TholianWebInterface $web, ?int $helperModifier = null): ?int
189
    {
190
        $this->loggerUtil->log(sprintf('updateWebFinishTime, webId: %d', $web->getId()));
191
192
        //flush to read persistent webIds from system data
193
        $this->entityManager->flush();
194
195
        if ($web->isFinished()) {
196
            return null;
197
        }
198
199
        $currentSpinnerSystems = $this->shipSystemRepository->getWebConstructingShipSystems($web->getId());
200
        $time = $this->stuTime->time();
201
202
        //adjust by modified web spinner count
203
        if ($helperModifier !== null) {
204
            $secondsLeft = $web->getFinishedTime() - $time;
205
            $currentSpinnerCount = count($currentSpinnerSystems);
206
            $oldSpinnerCount =  $currentSpinnerCount - $helperModifier;
207
208
            if ($currentSpinnerCount !== 0) {
209
                $web->setFinishedTime($time + (int)ceil($secondsLeft * $oldSpinnerCount / $currentSpinnerCount));
210
            }
211
            $this->tholianWebRepository->save($web);
212
213
            return $web->getFinishedTime();
214
        }
215
216
        //initialize by weight of targets and spinners
217
        $targetWeightSum = array_reduce(
218
            $web->getCapturedSpacecrafts()->toArray(),
219
            fn(int $sum, SpacecraftInterface $spacecraft): int => $sum + $spacecraft->getRump()->getTractorMass(),
220
            0
221
        );
222
        $webSpinnerWeightSum = array_reduce(
223
            $this->shipSystemRepository->getWebConstructingShipSystems($web->getId()),
224
            fn(int $sum, SpacecraftSystemInterface $shipSystem): int => $sum + $shipSystem->getSpacecraft()->getRump()->getTractorMass(),
225
            0
226
        );
227
228
        $this->loggerUtil->log(sprintf('targetWeightSum: %d, webSpinnerWeightSum: %d', $targetWeightSum, $webSpinnerWeightSum));
229
230
        //only update if web spinners left
231
        if ($webSpinnerWeightSum !== 0) {
232
            $web->setFinishedTime($time + ((int)ceil($targetWeightSum / $webSpinnerWeightSum)) * TimeConstants::ONE_HOUR_IN_SECONDS);
233
            $this->tholianWebRepository->save($web);
234
        }
235
236
        return $web->getFinishedTime();
237
    }
238
239
    private function getMandatoryEmitter(ShipWrapperInterface $wrapper): WebEmitterSystemData
240
    {
241
        $emitter = $wrapper->getWebEmitterSystemData();
242
        if ($emitter === null) {
243
            throw new RuntimeException('no emitter');
244
        }
245
246
        return $emitter;
247
    }
248
    private function getMandatoryWebUnderConstruction(WebEmitterSystemData $emitter): TholianWebInterface
249
    {
250
        $web = $emitter->getWebUnderConstruction();
251
        if ($web === null) {
252
            throw new RuntimeException('no web under construction');
253
        }
254
255
        return $web;
256
    }
257
}
258