Passed
Pull Request — master (#2331)
by Janko
11:37 queued 06:03
created

TholianWebUtil::updateWebFinishTime()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 50
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 19.4658

Importance

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

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

259
        /** @scrutinizer ignore-call */ 
260
        $web = $source->getHoldingWeb();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
260 6
        if ($web === null || !$web->isFinished()) {
261 4
            return false;
262
        }
263
264 2
        return !$target instanceof Spacecraft || $target->getHoldingWeb() !== $web;
265
    }
266
267 2
    #[\Override]
268
    public function isTargetInsideFinishedTholianWeb(EntityWithInteractionCheckInterface $source, EntityWithInteractionCheckInterface $target): bool
269
    {
270 2
        if (!$target instanceof Spacecraft) {
271
            return false;
272
        }
273
274 2
        $web = $target->getHoldingWeb();
275 2
        if ($web === null || !$web->isFinished()) {
276 2
            return false;
277
        }
278
279
        return !$source instanceof Spacecraft || $source->getHoldingWeb() !== $web;
280
    }
281
}
282