Test Setup Failed
Pull Request — master (#1689)
by Nico
11:14
created

BeamUtil::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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