Passed
Pull Request — master (#1686)
by Nico
31:24
created

DisassembleShip::retrieveSomeIntactModules()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 37
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 20
nc 12
nop 3
dl 0
loc 37
ccs 0
cts 22
cp 0
crap 56
rs 8.6666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Colony\Action\DisassembleShip;
6
7
use request;
8
use Stu\Component\Colony\Storage\ColonyStorageManagerInterface;
9
use Stu\Module\Colony\Lib\ColonyLibFactoryInterface;
10
use Stu\Module\Colony\Lib\ColonyLoaderInterface;
11
use Stu\Module\Colony\View\ShowShipDisassembly\ShowShipDisassembly;
12
use Stu\Module\Control\ActionControllerInterface;
13
use Stu\Module\Control\GameControllerInterface;
14
use Stu\Module\Ship\Lib\Crew\TroopTransferUtilityInterface;
15
use Stu\Module\Ship\Lib\ShipLoaderInterface;
16
use Stu\Module\Ship\Lib\ShipRemoverInterface;
17
use Stu\Module\Ship\Lib\ShipWrapperInterface;
18
use Stu\Module\Ship\Lib\Torpedo\ClearTorpedoInterface;
19
use Stu\Orm\Entity\ColonyInterface;
20
use Stu\Orm\Entity\ShipInterface;
21
use Stu\Orm\Repository\ColonyRepositoryInterface;
22
use Stu\Orm\Repository\CommodityRepositoryInterface;
23
24
final class DisassembleShip implements ActionControllerInterface
25
{
26
    public const ACTION_IDENTIFIER = 'B_DISASSEMBLE_SHIP';
27
28
    private ColonyLoaderInterface $colonyLoader;
29
30
    private ShipLoaderInterface $shipLoader;
31
32
    private ColonyRepositoryInterface $colonyRepository;
33
34
    private ShipRemoverInterface $shipRemover;
35
36
    private ColonyStorageManagerInterface $colonyStorageManager;
37
38
    private CommodityRepositoryInterface $commodityRepository;
39
40
    private ClearTorpedoInterface $clearTorpedo;
41
42
    private TroopTransferUtilityInterface $troopTransferUtility;
43
44
    private ColonyLibFactoryInterface $colonyLibFactory;
45
46
    public function __construct(
47
        ColonyLoaderInterface $colonyLoader,
48
        ShipLoaderInterface $shipLoader,
49
        ColonyRepositoryInterface $colonyRepository,
50
        ShipRemoverInterface $shipRemover,
51
        ColonyStorageManagerInterface $colonyStorageManager,
52
        CommodityRepositoryInterface $commodityRepository,
53
        ClearTorpedoInterface $clearTorpedo,
54
        ColonyLibFactoryInterface $colonyLibFactory,
55
        TroopTransferUtilityInterface $troopTransferUtility
56
    ) {
57
        $this->colonyLoader = $colonyLoader;
58
        $this->shipLoader = $shipLoader;
59
        $this->colonyRepository = $colonyRepository;
60
        $this->shipRemover = $shipRemover;
61
        $this->colonyStorageManager = $colonyStorageManager;
62
        $this->commodityRepository = $commodityRepository;
63
        $this->clearTorpedo = $clearTorpedo;
64
        $this->troopTransferUtility = $troopTransferUtility;
65
        $this->colonyLibFactory = $colonyLibFactory;
66
    }
67
68
    public function handle(GameControllerInterface $game): void
69
    {
70
        $game->setView(ShowShipDisassembly::VIEW_IDENTIFIER);
71
72
        $userId = $game->getUser()->getId();
73
74
        $colony = $this->colonyLoader->byIdAndUser(
75
            request::indInt('id'),
76
            $userId
77
        );
78
79
        if ($colony->getEps() < 20) {
80
            $game->addInformation(_('Zur Demontage des Schiffes wird 20 Energie benötigt'));
81
            return;
82
        }
83
84
        $freeAssignmentCount = $this->colonyLibFactory->createColonyPopulationCalculator(
85
            $colony
86
        )->getFreeAssignmentCount();
87
88
        $ship_id = request::getIntFatal('ship_id');
89
        $wrapper = $this->shipLoader->getWrapperByIdAndUser($ship_id, $userId);
90
        $ship = $wrapper->get();
91
        if ($ship->getCrewCount() > $freeAssignmentCount) {
92
            $game->addInformation(_('Nicht genügend Platz für die Crew auf der Kolonie'));
93
            return;
94
        }
95
96
        $colony->lowerEps(20);
97
98
        $this->colonyRepository->save($colony);
99
100
        $this->retrieveSomeIntactModules($ship, $colony, $game);
101
        $this->retrieveReactorLoad($wrapper, $colony, $game);
102
        $this->retrieveLoadedTorpedos($wrapper, $colony, $game);
103
104
        $this->transferCrewToColony($ship, $colony);
105
106
        $this->shipRemover->remove($ship);
107
108
        $game->addInformationf(_('Das Schiff wurde demontiert'));
109
    }
110
111
    private function transferCrewToColony(ShipInterface $ship, ColonyInterface $colony): void
112
    {
113
        foreach ($ship->getCrewAssignments() as $crewAssignment) {
114
            $this->troopTransferUtility->assignCrew($crewAssignment, $colony);
115
        }
116
    }
117
118
    private function retrieveSomeIntactModules(ShipInterface $ship, ColonyInterface $colony, GameControllerInterface $game): void
119
    {
120
        $intactModules = [];
121
122
        foreach ($ship->getSystems() as $system) {
123
            if (
124
                $system->getModule() !== null
125
                && $system->getStatus() == 100
126
            ) {
127
                $module = $system->getModule();
128
129
                if (!array_key_exists($module->getId(), $intactModules)) {
130
                    $intactModules[$module->getId()] = $module;
131
                }
132
            }
133
        }
134
135
        $maxStorage = $colony->getMaxStorage();
136
137
        //retrieve 50% of all intact modules
138
        $recycleCount = (int) ceil(count($intactModules) / 2);
139
        for ($i = 1; $i <= $recycleCount; $i++) {
140
            if ($colony->getStorageSum() >= $maxStorage) {
141
                $game->addInformationf(_('Kein Lagerraum frei um Module zu recyclen!'));
142
                break;
143
            }
144
145
            $module = $intactModules[array_rand($intactModules)];
146
            unset($intactModules[$module->getId()]);
147
148
            $this->colonyStorageManager->upperStorage(
149
                $colony,
150
                $module->getCommodity(),
151
                1
152
            );
153
154
            $game->addInformationf(sprintf(_('Folgendes Modul konnte recycelt werden: %s'), $module->getName()));
155
        }
156
    }
157
158
    private function retrieveReactorLoad(ShipWrapperInterface $wrapper, ColonyInterface $colony, GameControllerInterface $game): void
159
    {
160
        $reactorWrapper = $wrapper->getReactorWrapper();
161
        if ($reactorWrapper === null) {
162
            return;
163
        }
164
165
        $reactor = $reactorWrapper->get();
166
167
        $loads = (int) floor($reactorWrapper->getLoad() / $reactor->getLoadUnits());
168
        if ($loads < 1) {
169
            return;
170
        }
171
172
        $maxStorage = $colony->getMaxStorage();
173
174
        foreach ($reactor->getLoadCost() as $commodityId => $loadCost) {
175
            if ($colony->getStorageSum() >= $maxStorage) {
176
                $game->addInformationf(
177
                    _('Kein Lagerraum frei um %s-Mix zu sichern!'),
178
                    $reactor->getSystemType()->getDescription()
179
                );
180
                break;
181
            }
182
183
            $amount = $loads * $loadCost;
184
            if ($maxStorage - $colony->getStorageSum() < $amount) {
185
                $amount = $maxStorage - $colony->getStorageSum();
186
            }
187
188
            $commodity = $this->commodityRepository->find($commodityId);
189
            $this->colonyStorageManager->upperStorage(
190
                $colony,
191
                $commodity,
0 ignored issues
show
Bug introduced by
It seems like $commodity can also be of type null; however, parameter $commodity of Stu\Component\Colony\Sto...terface::upperStorage() does only seem to accept Stu\Orm\Entity\CommodityInterface, 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

191
                /** @scrutinizer ignore-type */ $commodity,
Loading history...
192
                $amount
193
            );
194
195
            $game->addInformationf(sprintf(_('%d Einheiten folgender Ware konnten recycelt werden: %s'), $amount, $commodity->getName()));
196
        }
197
    }
198
199
    private function retrieveLoadedTorpedos(ShipWrapperInterface $wrapper, ColonyInterface $colony, GameControllerInterface $game): void
200
    {
201
        $ship = $wrapper->get();
202
        $torpedoStorage = $ship->getTorpedoStorage();
203
204
        if ($torpedoStorage === null) {
205
            return;
206
        }
207
208
        $maxStorage = $colony->getMaxStorage();
209
210
        if ($colony->getStorageSum() >= $maxStorage) {
211
            $game->addInformationf(_('Kein Lagerraum frei um geladene Torpedos zu sichern!'));
212
            return;
213
        }
214
215
        $amount = $torpedoStorage->getStorage()->getAmount();
216
        if ($maxStorage - $colony->getStorageSum() < $amount) {
217
            $amount = $maxStorage - $colony->getStorageSum();
218
        }
219
220
        $commodity = $torpedoStorage->getStorage()->getCommodity();
221
        $this->colonyStorageManager->upperStorage(
222
            $colony,
223
            $commodity,
224
            $amount
225
        );
226
227
        $this->clearTorpedo->clearTorpedoStorage($wrapper);
228
229
        $game->addInformationf(sprintf(_('%d Einheiten folgender Ware konnten recycelt werden: %s'), $amount, $commodity->getName()));
230
    }
231
232
    public function performSessionCheck(): bool
233
    {
234
        return false;
235
    }
236
}
237