Passed
Pull Request — master (#1816)
by Nico
31:00
created

CallForSupportBehaviour::isNewSupportEligible()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 9
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 17
ccs 0
cts 11
cp 0
crap 6
rs 9.9666
1
<?php
2
3
namespace Stu\Lib\Pirate\Behaviour;
4
5
use RuntimeException;
6
use Stu\Lib\Map\DistanceCalculationInterface;
7
use Stu\Lib\Pirate\Component\PirateNavigationInterface;
8
use Stu\Lib\Pirate\Component\ReloadMinimalEpsInterface;
9
use Stu\Lib\Pirate\PirateBehaviourEnum;
10
use Stu\Lib\Pirate\PirateCreationInterface;
11
use Stu\Module\Ship\Lib\FleetWrapperInterface;
12
use Stu\Lib\Pirate\PirateReactionInterface;
13
use Stu\Lib\Pirate\PirateReactionMetadata;
14
use Stu\Lib\Pirate\PirateReactionTriggerEnum;
15
use Stu\Module\Control\StuRandom;
16
use Stu\Module\Logging\LoggerUtilFactoryInterface;
17
use Stu\Module\Logging\PirateLoggerInterface;
18
use Stu\Module\PlayerSetting\Lib\UserEnum;
19
use Stu\Module\Ship\Lib\ShipWrapperFactoryInterface;
20
use Stu\Orm\Entity\FleetInterface;
21
use Stu\Orm\Entity\ShipInterface;
22
use Stu\Orm\Repository\FleetRepositoryInterface;
23
use Stu\Orm\Repository\ShipRepositoryInterface;
24
25
class CallForSupportBehaviour implements PirateBehaviourInterface
26
{
27
    private PirateLoggerInterface $logger;
28
29
    public function __construct(
30
        private ShipRepositoryInterface $shipRepository,
31
        private PirateCreationInterface $pirateCreation,
32
        private DistanceCalculationInterface $distanceCalculation,
33
        private ReloadMinimalEpsInterface $reloadMinimalEps,
34
        private PirateNavigationInterface $pirateNavigation,
35
        private ShipWrapperFactoryInterface $shipWrapperFactory,
36
        private FleetRepositoryInterface $fleetRepository,
37
        private StuRandom $stuRandom,
38
        LoggerUtilFactoryInterface $loggerUtilFactory
39
    ) {
40
        $this->logger = $loggerUtilFactory->getPirateLogger();
41
    }
42
43
    public function action(
44
        FleetWrapperInterface $fleet,
45
        PirateReactionInterface $pirateReaction,
46
        PirateReactionMetadata $reactionMetadata,
47
        ?ShipInterface $triggerShip
48
    ): ?PirateBehaviourEnum {
49
50
        $leadWrapper = $fleet->getLeadWrapper();
51
        $leadShip = $leadWrapper->get();
52
53
        $supportFleet = $this->getSupportFleet($leadShip, $reactionMetadata);
54
55
        if ($supportFleet === null) {
56
            return PirateBehaviourEnum::SEARCH_FRIEND;
57
        }
58
59
        $pirateReaction->react(
60
            $supportFleet,
61
            PirateReactionTriggerEnum::ON_SUPPORT_CALL,
62
            $leadShip,
63
            $reactionMetadata
64
        );
65
66
        return null;
67
    }
68
69
    private function getSupportFleet(ShipInterface $leadShip, PirateReactionMetadata $reactionMetadata): ?FleetInterface
70
    {
71
        $friends = $this->shipRepository->getPirateFriends($leadShip);
72
73
        $filteredFriends = array_filter(
74
            $friends,
75
            fn (ShipInterface $friend) =>
76
            !$friend->isDestroyed()
77
                && $friend->isFleetLeader()
78
                && $friend->getCurrentMapField() !== $leadShip->getCurrentMapField()
79
        );
80
81
        usort(
82
            $filteredFriends,
83
            fn (ShipInterface $a, ShipInterface $b) =>
84
            $this->distanceCalculation->shipToShipDistance($leadShip, $a) - $this->distanceCalculation->shipToShipDistance($leadShip, $b)
85
        );
86
87
88
        $closestFriend = current($filteredFriends);
89
        if (!$closestFriend) {
90
            return $this->createSupportFleet($leadShip, $reactionMetadata);
91
        }
92
93
        $supportFleet = $closestFriend->getFleet();
94
        if ($supportFleet === null) {
95
            throw new RuntimeException('pirate ships should always be in fleet');
96
        }
97
98
        $this->logger->logf(
99
            '    calling already existing support fleet %s (%d) to %s',
100
            $supportFleet->getId(),
101
            $supportFleet->getName(),
102
            $leadShip->getSectorString()
103
        );
104
105
        $fleetWrapper = $this->shipWrapperFactory->wrapFleet($supportFleet);
106
107
        $this->reloadMinimalEps->reload($fleetWrapper, 75);
108
        if (!$this->pirateNavigation->navigateToTarget($fleetWrapper, $leadShip->getCurrentMapField())) {
109
            return $this->createSupportFleet($leadShip, $reactionMetadata);
110
        }
111
112
        $this->logger->logf(
113
            '    already existing support fleet (%d) "%s" reached here %s',
114
            $supportFleet->getId(),
115
            $supportFleet->getName(),
116
            $supportFleet->getLeadShip()->getSectorString()
117
        );
118
119
        return $supportFleet;
120
    }
121
122
    private function createSupportFleet(ShipInterface $leadShip, PirateReactionMetadata $reactionMetadata): ?FleetInterface
123
    {
124
        if (!$this->isNewSupportEligible($reactionMetadata)) {
125
            $this->logger->log('....support creation not eligible');
126
            return null;
127
        }
128
129
        $supportFleet = $this->pirateCreation->createPirateFleet($leadShip);
130
        $this->logger->logf(
131
            '    created support fleet %d "%s" here %s',
132
            $supportFleet->getId(),
133
            $supportFleet->getName(),
134
            $supportFleet->getLeadShip()->getSectorString()
135
        );
136
137
        return $supportFleet;
138
    }
139
140
141
    private function isNewSupportEligible(PirateReactionMetadata $reactionMetadata): bool
142
    {
143
        $supportCallAmount = $reactionMetadata->getReactionAmount(PirateBehaviourEnum::CALL_FOR_SUPPORT);
144
145
        if ($supportCallAmount <= 1) {
146
            $currentPirateFleetAmount = $this->fleetRepository->getCountByUser(UserEnum::USER_NPC_KAZON);
147
148
            $this->logger->logf(
149
                '....supportCallAmount: %d, currentPirateFleetAmount: %d',
150
                $supportCallAmount,
151
                $currentPirateFleetAmount
152
            );
153
154
            return $this->stuRandom->rand(1, max(1, $currentPirateFleetAmount)) == 1;
155
        }
156
157
        return true;
158
    }
159
}
160