Test Failed
Pull Request — master (#1772)
by Nico
12:25
created

FightLib::canAttackTarget()   C

Complexity

Conditions 12
Paths 8

Size

Total Lines 44
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 12

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 12
eloc 18
c 1
b 1
f 0
nc 8
nop 3
dl 0
loc 44
ccs 20
cts 20
cp 1
crap 12
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Ship\Lib\Battle;
6
7
use Stu\Component\Ship\Repair\CancelRepairInterface;
8
use Stu\Component\Ship\System\Exception\ShipSystemException;
9
use Stu\Component\Ship\System\ShipSystemManagerInterface;
10
use Stu\Component\Ship\System\ShipSystemTypeEnum;
11
use Stu\Lib\Information\InformationWrapper;
12
use Stu\Module\Ship\Lib\ShipNfsItem;
13
use Stu\Module\Ship\Lib\ShipWrapperInterface;
14
use Stu\Orm\Entity\ShipInterface;
15
use Stu\Orm\Entity\User;
16
17
final class FightLib implements FightLibInterface
18
{
19
    private ShipSystemManagerInterface $shipSystemManager;
20
21
    private CancelRepairInterface $cancelRepair;
22
23
    private AlertLevelBasedReactionInterface $alertLevelBasedReaction;
24
25 44
    public function __construct(
26
        ShipSystemManagerInterface $shipSystemManager,
27
        CancelRepairInterface $cancelRepair,
28
        AlertLevelBasedReactionInterface $alertLevelBasedReaction
29
    ) {
30 44
        $this->shipSystemManager = $shipSystemManager;
31 44
        $this->cancelRepair = $cancelRepair;
32 44
        $this->alertLevelBasedReaction = $alertLevelBasedReaction;
33
    }
34
35 6
    public function ready(ShipWrapperInterface $wrapper): InformationWrapper
36
    {
37 6
        $ship = $wrapper->get();
38
39 6
        $informations = new InformationWrapper();
40
41
        if (
42 6
            $ship->isDestroyed()
43 6
            || $ship->getRump()->isEscapePods()
44
        ) {
45 2
            return $informations;
46
        }
47 4
        if ($ship->getBuildplan() === null) {
48 1
            return $informations;
49
        }
50 3
        if (!$ship->hasEnoughCrew()) {
51 1
            return $informations;
52
        }
53
54 2
        if ($ship->getDockedTo() !== null) {
55 1
            $ship->setDockedTo(null);
56 1
            $informations->addInformation("- Das Schiff hat abgedockt");
57
        }
58
59
        try {
60 2
            $this->shipSystemManager->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_WARPDRIVE);
61 1
        } catch (ShipSystemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
62
        }
63
        try {
64 2
            $this->shipSystemManager->deactivate($wrapper, ShipSystemTypeEnum::SYSTEM_CLOAK);
65 1
        } catch (ShipSystemException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
66
        }
67
68 2
        $this->cancelRepair->cancelRepair($ship);
69
70 2
        $informations->addInformationWrapper($this->alertLevelBasedReaction->react($wrapper));
71
72 2
        if (!$informations->isEmpty()) {
73 1
            $informations->addInformationArray([sprintf(_('Aktionen der %s'), $ship->getName())], true);
74
        }
75
76 2
        return $informations;
77
    }
78
79 1
    public function filterInactiveShips(array $base): array
80
    {
81 1
        return array_filter(
82 1
            $base,
83 1
            fn (ShipWrapperInterface $wrapper): bool => !$wrapper->get()->isDestroyed() && !$wrapper->get()->isDisabled()
84 1
        );
85
    }
86
87 4
    public function canFire(ShipWrapperInterface $wrapper): bool
88
    {
89 4
        $ship = $wrapper->get();
90 4
        if (!$ship->getNbs()) {
91 1
            return false;
92
        }
93 3
        if (!$ship->hasActiveWeapon()) {
94 1
            return false;
95
        }
96
97 2
        $epsSystem = $wrapper->getEpsSystemData();
98 2
        return $epsSystem !== null && $epsSystem->getEps() !== 0;
99
    }
100
101 11
    public function canAttackTarget(
102
        ShipInterface $ship,
103
        ShipInterface|ShipNfsItem $target,
104
        bool $checkActiveWeapons = true
105
    ): bool {
106 11
        if ($checkActiveWeapons && !$ship->hasActiveWeapon()) {
107 1
            return false;
108
        }
109
110
        //can't attack itself
111 10
        if ($target === $ship) {
112 1
            return false;
113
        }
114
115
        //can't attack trumfields
116 9
        if ($target->isTrumfield()) {
117 1
            return false;
118
        }
119
120
        //if tractored, can only attack tractoring ship
121 8
        $tractoringShip = $ship->getTractoringShip();
122 8
        if ($tractoringShip !== null) {
123 3
            return $target->getId() === $tractoringShip->getId();
124
        }
125
126
        //can't attack target under warp
127 5
        if ($target->getWarpState()) {
128 1
            return false;
129
        }
130
131
        //can't attack own target under cloak
132 4
        if (method_exists($target, 'isOwnedByCurrentUser') && $target->isOwnedByCurrentUser() && $target->getCloakState()) {
133 4
            return false;
134 4
        }
135 2
136
137
        //can't attack same fleet
138 2
        $ownFleetId = $ship->getFleetId();
139
        $targetFleetId = $target->getFleetId();
140
        if ($ownFleetId === null || $targetFleetId === null) {
141 8
            return true;
142
        }
143 8
144 8
        return $ownFleetId !== $targetFleetId;
145
    }
146 8
147 8
    public function getAttackersAndDefenders(ShipWrapperInterface $wrapper, ShipWrapperInterface $targetWrapper): array
148 8
    {
149 8
        $attackers = $this->getAttackers($wrapper);
150 8
        $defenders = $this->getDefenders($targetWrapper);
151
152
        return [
153
            $attackers,
154 8
            $defenders,
155
            count($attackers) + count($defenders) > 2
156 8
        ];
157 8
    }
158
159 8
    /** @return array<int, ShipWrapperInterface> */
160 1
    public function getAttackers(ShipWrapperInterface $wrapper): array
161
    {
162 7
        $ship = $wrapper->get();
163
        $fleet = $wrapper->getFleetWrapper();
164
165 8
        if ($ship->isFleetLeader() && $fleet !== null) {
166
            $attackers = $fleet->getShipWrappers();
167
        } else {
168
            $attackers = [$ship->getId() => $wrapper];
169 8
        }
170
171 8
        return $attackers;
172 8
    }
173
174 8
    /** @return array<int, ShipWrapperInterface> */
175 3
    private function getDefenders(ShipWrapperInterface $targetWrapper): array
176
    {
177
        $target = $targetWrapper->get();
178 3
        $targetFleet = $targetWrapper->getFleetWrapper();
179
180 3
        if ($targetFleet !== null) {
181 3
            $defenders = [];
182 3
183
            // only uncloaked defenders fight
184 3
            foreach ($targetFleet->getShipWrappers() as $shipId => $defWrapper) {
185
186
                $defShip = $defWrapper->get();
187
                if (!$defShip->getCloakState()) {
188
                    $defenders[$shipId] = $defWrapper;
189 3
190 3
                    $this->addDockedToAsDefender($targetWrapper, $defenders);
191
                }
192
            }
193 5
194
            // if all defenders were cloaked, they obviously were scanned and enter the fight as a whole fleet
195 5
            if ($defenders === []) {
196
                $defenders = $targetFleet->getShipWrappers();
197
            }
198 8
        } else {
199
            $defenders = [$target->getId() => $targetWrapper];
200
201
            $this->addDockedToAsDefender($targetWrapper, $defenders);
202 8
        }
203
204 8
        return $defenders;
205
    }
206 8
207 8
    /** @param array<int, ShipWrapperInterface> $defenders */
208 8
    private function addDockedToAsDefender(ShipWrapperInterface $targetWrapper, array &$defenders): void
209
    {
210 2
        $dockedToWrapper = $targetWrapper->getDockedToShipWrapper();
211
        if (
212
            $dockedToWrapper !== null
213
            && !$dockedToWrapper->get()->getUser()->isNpc()
214 4
            && $dockedToWrapper->get()->hasActiveWeapon()
215
        ) {
216 4
            $defenders[$dockedToWrapper->get()->getId()] = $dockedToWrapper;
217 4
        }
218 1
    }
219
220
    public function isTargetOutsideFinishedTholianWeb(ShipInterface $ship, ShipInterface $target): bool
221 3
    {
222
        $web = $ship->getHoldingWeb();
223
        if ($web === null) {
224 6
            return false;
225
        }
226 6
227 6
        return $web->isFinished() && ($target->getHoldingWeb() !== $web);
228 6
    }
229 6
230 6
    public static function isBoardingPossible(ShipInterface|ShipNfsItem $ship): bool
231 6
    {
232
        return !(User::isUserNpc($ship->getUserId())
0 ignored issues
show
Deprecated Code introduced by
The function Stu\Orm\Entity\ShipInterface::getUserId() has been deprecated. ( Ignorable by Annotation )

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

232
        return !(User::isUserNpc(/** @scrutinizer ignore-deprecated */ $ship->getUserId())
Loading history...
233
            || $ship->isBase()
234
            || $ship->isTrumfield()
235
            || $ship->getCloakState()
236
            || $ship->getShieldState()
237
            || $ship->getWarpState());
238
    }
239
}