Passed
Pull Request — master (#1801)
by Nico
23:50
created

BeamUtil::isDockTransfer()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 2
nc 5
nop 2
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Lib\Transfer;
6
7
use RuntimeException;
8
use Stu\Component\Colony\Storage\ColonyStorageManagerInterface;
9
use Stu\Component\Ship\Storage\ShipStorageManagerInterface;
10
use Stu\Lib\Information\InformationWrapper;
11
use Stu\Module\Ship\Lib\ShipWrapperInterface;
12
use Stu\Orm\Entity\ColonyInterface;
13
use Stu\Orm\Entity\CommodityInterface;
14
use Stu\Orm\Entity\ShipInterface;
15
use Stu\Orm\Repository\ColonyRepositoryInterface;
16
17
final class BeamUtil implements BeamUtilInterface
18
{
19
    private ShipStorageManagerInterface $shipStorageManager;
20
21
    private ColonyStorageManagerInterface $colonyStorageManager;
22
23
    private ColonyRepositoryInterface $colonyRepository;
24
25 11
    public function __construct(
26
        ShipStorageManagerInterface $shipStorageManager,
27
        ColonyStorageManagerInterface $colonyStorageManager,
28
        ColonyRepositoryInterface $colonyRepository
29
    ) {
30 11
        $this->shipStorageManager = $shipStorageManager;
31 11
        $this->colonyStorageManager = $colonyStorageManager;
32 11
        $this->colonyRepository = $colonyRepository;
33
    }
34
35 11
    public function transferCommodity(
36
        int $commodityId,
37
        string|int $wantedAmount,
38
        ShipWrapperInterface|ColonyInterface $subject,
39
        ShipInterface|ColonyInterface $source,
40
        ShipInterface|ColonyInterface $target,
41
        InformationWrapper $informations
42
    ): bool {
43
44 11
        $sourceStorage =  $source->getStorage()[$commodityId] ?? null;
45 11
        if ($sourceStorage === null) {
46 1
            return false;
47
        }
48
49 10
        $commodity = $sourceStorage->getCommodity();
50 10
        if (!$commodity->isBeamable($source->getUser(), $target->getUser())) {
51 1
            $informations->addInformationf(_('%s ist nicht beambar'), $commodity->getName());
52 1
            return false;
53
        }
54
55 9
        $isDockTransfer = $this->isDockTransfer($source, $target);
56
57 9
        $availableEps = $this->getAvailableEps($subject);
58 9
        if (!$isDockTransfer && $availableEps < 1) {
59 1
            return false;
60
        }
61
62 8
        if ($wantedAmount === "max") {
63 1
            $amount = $sourceStorage->getAmount();
64 7
        } else if (!is_numeric($wantedAmount)) {
65 1
            return false;
66
        } else {
67 6
            $amount =  (int)$wantedAmount;
68
        }
69
70 7
        if ($amount < 1) {
71 1
            return false;
72
        }
73
74 6
        if ($target->getStorageSum() >= $target->getMaxStorage()) {
75 1
            return false;
76
        }
77
78 5
        $amount = min($amount, $sourceStorage->getAmount());
79 5
        $transferAmount = $commodity->getTransferCount() * $this->getBeamFactor($subject);
80
81 5
        if (!$isDockTransfer && ceil($amount / $transferAmount) > $availableEps) {
82 3
            $amount = $availableEps * $transferAmount;
83
        }
84
85 5
        if ($target->getStorageSum() + $amount > $target->getMaxStorage()) {
86 1
            $amount = $target->getMaxStorage() - $target->getStorageSum();
87
        }
88
89 5
        $epsUsage = $isDockTransfer ? 0 : (int)ceil($amount / $transferAmount);
90
91 5
        $informations->addInformationf(
92 5
            _('%d %s (Energieverbrauch: %d)'),
93 5
            $amount,
94 5
            $commodity->getName(),
95 5
            $epsUsage
96 5
        );
97
98 5
        $this->lowerSourceStorage($amount, $commodity, $source);
99 5
        $this->upperTargetStorage($amount, $commodity, $target);
100 5
        $this->consumeEps($epsUsage, $subject);
101
102 5
        return true;
103
    }
104
105 9
    public function isDockTransfer(
106
        ShipInterface|ColonyInterface $source,
107
        ShipInterface|ColonyInterface $target
108
    ): bool {
109 9
        return $source instanceof ShipInterface && $target instanceof ShipInterface
110 9
            && ($source->getDockedTo() === $target || $target->getDockedTo() === $source);
111
    }
112
113 5
    private function getBeamFactor(ShipWrapperInterface|ColonyInterface $subject): int
114
    {
115 5
        if ($subject instanceof ShipWrapperInterface) {
116 1
            return $subject->get()->getBeamFactor();
117
        }
118
119 4
        return $subject->getBeamFactor();
120
    }
121
122 9
    private function getAvailableEps(ShipWrapperInterface|ColonyInterface $subject): int
123
    {
124 9
        if ($subject instanceof ShipWrapperInterface) {
125 1
            $epsSystem = $subject->getEpsSystemData();
126
127 1
            return $epsSystem === null ? 0 : $epsSystem->getEps();
128
        }
129
130 8
        return $subject->getEps();
131
    }
132
133 5
    private function lowerSourceStorage(
134
        int $amount,
135
        CommodityInterface $commodity,
136
        ShipInterface|ColonyInterface $source
137
    ): void {
138 5
        if ($source instanceof ShipInterface) {
139 1
            $this->shipStorageManager->lowerStorage($source, $commodity,  $amount);
140
        } else {
141 4
            $this->colonyStorageManager->lowerStorage($source, $commodity,  $amount);
142
        }
143
    }
144
145 5
    private function upperTargetStorage(
146
        int $amount,
147
        CommodityInterface $commodity,
148
        ShipInterface|ColonyInterface $target
149
    ): void {
150 5
        if ($target instanceof ShipInterface) {
151 4
            $this->shipStorageManager->upperStorage($target, $commodity,  $amount);
152
        } else {
153 1
            $this->colonyStorageManager->upperStorage($target, $commodity,  $amount);
154
        }
155
    }
156
157 5
    private function consumeEps(int $epsUsage, ShipWrapperInterface|ColonyInterface $subject): void
158
    {
159 5
        if ($epsUsage === 0) {
160
            return;
161
        }
162
163 5
        if ($subject instanceof ShipWrapperInterface) {
164 1
            $epsSystem = $subject->getEpsSystemData();
165 1
            if ($epsSystem === null) {
166
                throw new RuntimeException('this should not happen');
167
            }
168 1
            $epsSystem->lowerEps($epsUsage)->update();
169
        } else {
170 4
            $subject->lowerEps($epsUsage);
171 4
            $this->colonyRepository->save($subject);
172
        }
173
    }
174
}
175