Passed
Push — master ( f4068b...77f637 )
by Nico
40:27 queued 14:09
created

TholianWebUtil::resetWebHelpers()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 14
nc 3
nop 3
dl 0
loc 24
ccs 0
cts 16
cp 0
crap 12
rs 9.7998
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 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\Ship\ShipStateEnum;
11
use Stu\Component\Ship\System\ShipSystemTypeEnum;
12
use Stu\Module\Control\StuTime;
13
use Stu\Module\Logging\LoggerUtilFactoryInterface;
14
use Stu\Module\Logging\LoggerUtilInterface;
15
use Stu\Module\Message\Lib\PrivateMessageFolderSpecialEnum;
16
use Stu\Module\Message\Lib\PrivateMessageSenderInterface;
17
use Stu\Module\PlayerSetting\Lib\UserEnum;
18
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
19
use Stu\Module\Ship\Lib\ShipWrapperInterface;
20
use Stu\Orm\Entity\ShipInterface;
21
use Stu\Orm\Entity\ShipSystemInterface;
22
use Stu\Orm\Entity\TholianWebInterface;
23
use Stu\Orm\Repository\ShipRepositoryInterface;
24
use Stu\Orm\Repository\ShipSystemRepositoryInterface;
25
use Stu\Orm\Repository\TholianWebRepositoryInterface;
26
27
final class TholianWebUtil implements TholianWebUtilInterface
28
{
29
    private ShipRepositoryInterface $shipRepository;
30
31
    private TholianWebRepositoryInterface $tholianWebRepository;
32
33
    private ShipSystemRepositoryInterface $shipSystemRepository;
34
35
    private StuTime $stuTime;
36
37
    private PrivateMessageSenderInterface $privateMessageSender;
38
39
    private LoggerUtilInterface $loggerUtil;
40
41
    private EntityManagerInterface $entityManager;
42
43 4
    public function __construct(
44
        ShipRepositoryInterface $shipRepository,
45
        TholianWebRepositoryInterface $tholianWebRepository,
46
        ShipSystemRepositoryInterface $shipSystemRepository,
47
        StuTime $stuTime,
48
        PrivateMessageSenderInterface $privateMessageSender,
49
        LoggerUtilFactoryInterface $loggerUtilFactory,
50
        EntityManagerInterface $entityManager
51
    ) {
52 4
        $this->shipRepository = $shipRepository;
53 4
        $this->tholianWebRepository = $tholianWebRepository;
54 4
        $this->shipSystemRepository = $shipSystemRepository;
55 4
        $this->stuTime = $stuTime;
56 4
        $this->privateMessageSender = $privateMessageSender;
57 4
        $this->entityManager = $entityManager;
58 4
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
59
    }
60
61
    public function releaseShipFromWeb(ShipWrapperInterface $wrapper): void
62
    {
63
        $this->loggerUtil->log(sprintf('releaseShipFromWeb, shipId: %d', $wrapper->get()->getId()));
64
65
        $ship = $wrapper->get();
66
        $web = $ship->getHoldingWeb();
67
        if ($web === null) {
68
            return;
69
        }
70
71
        $web->getCapturedShips()->removeElement($ship);
72
73
        if ($web->getCapturedShips()->isEmpty()) {
74
            $this->resetWebHelpers($web, $wrapper->getShipWrapperFactory());
75
            $this->removeWeb($web);
76
        }
77
78
        $ship->setHoldingWeb(null);
79
        $this->shipRepository->save($ship);
80
    }
81
82
    public function releaseAllShips(TholianWebInterface $web, ShipWrapperFactoryInterface $shipWrapperFactory): void
83
    {
84
        foreach ($web->getCapturedShips() as $target) {
85
            $this->releaseShipFromWeb($shipWrapperFactory->wrapShip($target));
86
87
            //notify target owner
88
            $this->privateMessageSender->send(
89
                $web->getWebShip()->getUser()->getId(),
90
                $target->getUser()->getId(),
91
                sprintf(
92
                    'Das Energienetz um die %s in Sektor %s wurde aufgelöst',
93
                    $target->getName(),
94
                    $target->getSectorString()
95
                ),
96
                $target->isBase() ? PrivateMessageFolderSpecialEnum::PM_SPECIAL_STATION : PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP
97
            );
98
        }
99
    }
100
101
    public function removeWeb(TholianWebInterface $web): void
102
    {
103
        $this->loggerUtil->log(sprintf('removeWeb, webId: %d', $web->getId()));
104
105
        $this->tholianWebRepository->delete($web);
106
        $this->shipRepository->delete($web->getWebShip());
107
    }
108
109
    public function releaseWebHelper(ShipWrapperInterface $wrapper): void
110
    {
111
        $this->loggerUtil->log(sprintf('releaseWebHelper, shipId: %d', $wrapper->get()->getId()));
112
113
        $emitter = $wrapper->getWebEmitterSystemData();
114
        $web = $emitter->getWebUnderConstruction();
115
        if ($web === null) {
116
            throw new RuntimeException('no web under construction');
117
        }
118
119
        $this->releaseWebHelperIntern($wrapper);
120
121
        $currentSpinnerSystems = $this->shipSystemRepository->getWebConstructingShipSystems($web->getId());
122
123
        //remove web if lost
124
        if (empty($currentSpinnerSystems)) {
125
            $this->releaseAllShips($web, $wrapper->getShipWrapperFactory());
126
            $this->removeWeb($web);
127
        } else {
128
            $ship = $wrapper->get();
129
130
            //notify other web spinners
131
            foreach ($currentSpinnerSystems as $shipSystem) {
132
                $this->privateMessageSender->send(
133
                    $ship->getUser()->getId(),
134
                    $shipSystem->getShip()->getUser()->getId(),
135
                    sprintf(
136
                        'Die %s hat den Netzaufbau in Sektor %s verlassen, Fertigstellung: %s',
137
                        $ship->getName(),
138
                        $ship->getSectorString(),
139
                        $this->stuTime->transformToStuDate($web->getFinishedTime())
0 ignored issues
show
Bug introduced by
It seems like $web->getFinishedTime() can also be of type null; however, parameter $unixTimestamp of Stu\Module\Control\StuTime::transformToStuDate() does only seem to accept integer, 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

139
                        $this->stuTime->transformToStuDate(/** @scrutinizer ignore-type */ $web->getFinishedTime())
Loading history...
140
                    ),
141
                    PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP
142
                );
143
            }
144
        }
145
    }
146
147
    public function resetWebHelpers(
148
        TholianWebInterface $web,
149
        ShipWrapperFactoryInterface $shipWrapperFactory,
150
        bool $isFinished = false
151
    ): void {
152
        $this->loggerUtil->log(sprintf('resetWebHelpers, webId: %d', $web->getId()));
153
154
        $systems = $this->shipSystemRepository->getWebConstructingShipSystems($web->getId());
155
        foreach ($systems as $system) {
156
            $wrapper = $shipWrapperFactory->wrapShip($system->getShip());
157
            $this->releaseWebHelperIntern($wrapper);
158
159
            //notify helpers when finished
160
            if ($isFinished) {
161
                $ship = $system->getShip();
162
163
                $this->privateMessageSender->send(
164
                    UserEnum::USER_NOONE,
165
                    $ship->getUser()->getId(),
166
                    sprintf(
167
                        'Das Energienetz in Sektor %s wurde fertiggestellt',
168
                        $ship->getSectorString()
169
                    ),
170
                    PrivateMessageFolderSpecialEnum::PM_SPECIAL_SHIP
171
                );
172
            }
173
        }
174
    }
175
176
    private function releaseWebHelperIntern(ShipWrapperInterface $wrapper): void
177
    {
178
        $emitter = $wrapper->getWebEmitterSystemData();
179
        $web = $emitter->getWebUnderConstruction();
180
181
        if ($emitter->ownedWebId === $emitter->webUnderConstructionId && !$web->isFinished()) {
182
            $emitter->setOwnedWebId(null);
183
        }
184
        $emitter->setWebUnderConstructionId(null)->update();
185
        $wrapper->getShipSystemManager()->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_THOLIAN_WEB, true);
186
187
        $ship = $wrapper->get();
188
        $ship->setState(ShipStateEnum::SHIP_STATE_NONE);
189
        $this->shipRepository->save($ship);
190
191
        //update finish time last
192
        $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

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