Passed
Pull Request — master (#1894)
by Janko
54:56 queued 28:47
created

TholianWebUtil::resetWebHelpers()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 15
nc 3
nop 3
dl 0
loc 25
ccs 0
cts 16
cp 0
crap 12
rs 9.7666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Interaction;
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\Ship\ShipStateEnum;
12
use Stu\Component\Ship\System\ShipSystemTypeEnum;
13
use Stu\Module\Control\StuTime;
14
use Stu\Module\Logging\LoggerUtilFactoryInterface;
15
use Stu\Module\Logging\LoggerUtilInterface;
16
use Stu\Module\Message\Lib\PrivateMessageFolderTypeEnum;
17
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
18
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...
19
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
20
use Stu\Module\Ship\Lib\ShipWrapperInterface;
21
use Stu\Orm\Entity\ShipInterface;
22
use Stu\Orm\Entity\ShipSystemInterface;
23
use Stu\Orm\Entity\TholianWebInterface;
24
use Stu\Orm\Repository\ShipRepositoryInterface;
25
use Stu\Orm\Repository\ShipSystemRepositoryInterface;
26
use Stu\Orm\Repository\TholianWebRepositoryInterface;
27
28
final class TholianWebUtil implements TholianWebUtilInterface
29
{
30
    private LoggerUtilInterface $loggerUtil;
31
32 4
    public function __construct(
33
        private ShipRepositoryInterface $shipRepository,
34
        private TholianWebRepositoryInterface $tholianWebRepository,
35
        private ShipSystemRepositoryInterface $shipSystemRepository,
36
        private StuTime $stuTime,
37
        private PrivateMessageSenderInterface $privateMessageSender,
38
        LoggerUtilFactoryInterface $loggerUtilFactory,
39
        private EntityManagerInterface $entityManager
40
    ) {
41 4
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
42
    }
43
44
    #[Override]
45
    public function releaseShipFromWeb(ShipWrapperInterface $wrapper): void
46
    {
47
        $this->loggerUtil->log(sprintf('releaseShipFromWeb, shipId: %d', $wrapper->get()->getId()));
48
49
        $ship = $wrapper->get();
50
        $web = $ship->getHoldingWeb();
51
        if ($web === null) {
52
            return;
53
        }
54
55
        $web->getCapturedShips()->removeElement($ship);
56
57
        if ($web->getCapturedShips()->isEmpty()) {
58
            $this->resetWebHelpers($web, $wrapper->getShipWrapperFactory());
59
            $this->removeWeb($web);
60
        }
61
62
        $ship->setHoldingWeb(null);
63
        $this->shipRepository->save($ship);
64
    }
65
66
    #[Override]
67
    public function releaseAllShips(TholianWebInterface $web, ShipWrapperFactoryInterface $shipWrapperFactory): void
68
    {
69
        foreach ($web->getCapturedShips() as $target) {
70
            $this->releaseShipFromWeb($shipWrapperFactory->wrapShip($target));
71
72
            //notify target owner
73
            $this->privateMessageSender->send(
74
                $web->getWebShip()->getUser()->getId(),
75
                $target->getUser()->getId(),
76
                sprintf(
77
                    'Das Energienetz um die %s in Sektor %s wurde aufgelöst',
78
                    $target->getName(),
79
                    $target->getSectorString()
80
                ),
81
                $target->isBase() ? PrivateMessageFolderTypeEnum::SPECIAL_STATION : PrivateMessageFolderTypeEnum::SPECIAL_SHIP
82
            );
83
        }
84
    }
85
86
    #[Override]
87
    public function removeWeb(TholianWebInterface $web): void
88
    {
89
        $this->loggerUtil->log(sprintf('removeWeb, webId: %d', $web->getId()));
90
91
        $this->tholianWebRepository->delete($web);
92
        $this->shipRepository->delete($web->getWebShip());
93
    }
94
95
    #[Override]
96
    public function releaseWebHelper(ShipWrapperInterface $wrapper): void
97
    {
98
        $this->loggerUtil->log(sprintf('releaseWebHelper, shipId: %d', $wrapper->get()->getId()));
99
100
        $emitter = $wrapper->getWebEmitterSystemData();
101
        $web = $emitter->getWebUnderConstruction();
102
        if ($web === null) {
103
            throw new RuntimeException('no web under construction');
104
        }
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->getShipWrapperFactory());
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->getShip()->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
        ShipWrapperFactoryInterface $shipWrapperFactory,
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
            $wrapper = $shipWrapperFactory->wrapShip($system->getShip());
148
            $this->releaseWebHelperIntern($wrapper);
149
150
            //notify helpers when finished
151
            if ($isFinished) {
152
                $ship = $system->getShip();
153
154
                $this->privateMessageSender->send(
155
                    UserEnum::USER_NOONE,
156
                    $ship->getUser()->getId(),
157
                    sprintf(
158
                        'Das Energienetz in Sektor %s wurde fertiggestellt',
159
                        $ship->getSectorString()
160
                    ),
161
                    PrivateMessageFolderTypeEnum::SPECIAL_SHIP
162
                );
163
            }
164
        }
165
    }
166
167
    private function releaseWebHelperIntern(ShipWrapperInterface $wrapper): ?int
168
    {
169
        $emitter = $wrapper->getWebEmitterSystemData();
170
        $web = $emitter->getWebUnderConstruction();
171
172
        if ($emitter->ownedWebId === $emitter->webUnderConstructionId && !$web->isFinished()) {
173
            $emitter->setOwnedWebId(null);
174
        }
175
        $emitter->setWebUnderConstructionId(null)->update();
176
        $wrapper->getShipSystemManager()->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB, true);
177
178
        $ship = $wrapper->get();
179
        $ship->setState(ShipStateEnum::SHIP_STATE_NONE);
180
        $this->shipRepository->save($ship);
181
182
        //update finish time last
183
        return $this->updateWebFinishTime($web, -1);
0 ignored issues
show
Bug introduced by
It seems like $web can also be of type null; however, parameter $web of Stu\Module\Ship\Lib\Inte...::updateWebFinishTime() does only seem to accept Stu\Orm\Entity\TholianWebInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

183
        return $this->updateWebFinishTime(/** @scrutinizer ignore-type */ $web, -1);
Loading history...
184
    }
185
186
    #[Override]
187
    public function updateWebFinishTime(TholianWebInterface $web, ?int $helperModifier = null): ?int
188
    {
189
        $this->loggerUtil->log(sprintf('updateWebFinishTime, webId: %d', $web->getId()));
190
191
        //flush to read persistent webIds from system data
192
        $this->entityManager->flush();
193
194
        if ($web->isFinished()) {
195
            return null;
196
        }
197
198
        $currentSpinnerSystems = $this->shipSystemRepository->getWebConstructingShipSystems($web->getId());
199
        $time = $this->stuTime->time();
200
201
        //adjust by modified web spinner count
202
        if ($helperModifier !== null) {
203
            $secondsLeft = $web->getFinishedTime() - $time;
204
            $currentSpinnerCount = count($currentSpinnerSystems);
205
            $oldSpinnerCount =  $currentSpinnerCount - $helperModifier;
206
207
            if ($currentSpinnerCount !== 0) {
208
                $web->setFinishedTime($time + (int)ceil($secondsLeft * $oldSpinnerCount / $currentSpinnerCount));
209
            }
210
            $this->tholianWebRepository->save($web);
211
212
            return $web->getFinishedTime();
213
        }
214
215
        //initialize by weight of targets and spinners
216
        $targetWeightSum = array_reduce(
217
            $web->getCapturedShips()->toArray(),
218
            fn(int $sum, ShipInterface $ship): int => $sum + $ship->getRump()->getTractorMass(),
219
            0
220
        );
221
        $webSpinnerWeightSum = array_reduce(
222
            $this->shipSystemRepository->getWebConstructingShipSystems($web->getId()),
223
            fn(int $sum, ShipSystemInterface $shipSystem): int => $sum + $shipSystem->getShip()->getRump()->getTractorMass(),
224
            0
225
        );
226
227
        $this->loggerUtil->log(sprintf('targetWeightSum: %d, webSpinnerWeightSum: %d', $targetWeightSum, $webSpinnerWeightSum));
228
229
        //only update if web spinners left
230
        if ($webSpinnerWeightSum !== 0) {
231
            $web->setFinishedTime($time + ((int)ceil($targetWeightSum / $webSpinnerWeightSum)) * TimeConstants::ONE_HOUR_IN_SECONDS);
232
            $this->tholianWebRepository->save($web);
233
        }
234
235
        return $web->getFinishedTime();
236
    }
237
}
238