Passed
Push — master ( aa3b71...5e2219 )
by Nico
55:07 queued 26:20
created

AttackShipBehaviour::attackShip()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 2
dl 0
loc 13
ccs 0
cts 10
cp 0
crap 2
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
namespace Stu\Lib\Pirate\Behaviour;
4
5
use Stu\Lib\Map\DistanceCalculationInterface;
6
use Stu\Lib\Pirate\Component\PirateAttackInterface;
7
use Stu\Module\Logging\LoggerUtilFactoryInterface;
8
use Stu\Module\Ship\Lib\Battle\FightLibInterface;
9
use Stu\Module\Ship\Lib\FleetWrapperInterface;
10
use Stu\Lib\Pirate\Component\PirateNavigationInterface;
11
use Stu\Lib\Pirate\PirateBehaviourEnum;
12
use Stu\Lib\Pirate\PirateReactionInterface;
13
use Stu\Module\Logging\PirateLoggerInterface;
14
use Stu\Orm\Entity\ShipInterface;
15
use Stu\Orm\Repository\ShipRepositoryInterface;
16
17
class AttackShipBehaviour implements PirateBehaviourInterface
18
{
19
    private PirateLoggerInterface $logger;
20
21
    public function __construct(
22
        private ShipRepositoryInterface $shipRepository,
23
        private DistanceCalculationInterface $distanceCalculation,
24
        private PirateNavigationInterface $pirateNavigation,
25
        private FightLibInterface $fightLib,
26
        private PirateAttackInterface $pirateAttack,
27
        LoggerUtilFactoryInterface $loggerUtilFactory
28
    ) {
29
        $this->logger = $loggerUtilFactory->getPirateLogger();
30
    }
31
32
    public function action(
33
        FleetWrapperInterface $fleet,
34
        PirateReactionInterface $pirateReaction,
35
        ?ShipInterface $triggerShip
36
    ): ?PirateBehaviourEnum {
37
        $leadWrapper = $fleet->getLeadWrapper();
38
        $leadShip = $leadWrapper->get();
39
40
        $piratePrestige = $this->prestigeOfShipOrFleet($leadShip);
41
42
        $this->logger->log(sprintf('    piratePrestige %d', $piratePrestige));
43
44
        $targets = $this->shipRepository->getPirateTargets($leadShip);
45
46
        $this->logger->log(sprintf('    %d targets in reach', count($targets)));
47
48
        $filteredTargets = array_filter(
49
            $targets,
50
            fn (ShipInterface $target) =>
51
            $this->fightLib->canAttackTarget($leadShip, $target, true, false, false)
52
                && ($target === $triggerShip
53
                    || $this->targetHasEnoughPrestige($piratePrestige, $target))
54
        );
55
56
        $this->logger->log(sprintf('    %d filtered targets in reach', count($filteredTargets)));
57
58
        if (empty($filteredTargets)) {
59
            return null;
60
        }
61
62
        usort(
63
            $filteredTargets,
64
            fn (ShipInterface $a, ShipInterface $b) =>
65
            $this->distanceCalculation->shipToShipDistance($leadShip, $a) - $this->distanceCalculation->shipToShipDistance($leadShip, $b)
66
        );
67
68
        $closestShip = current($filteredTargets);
69
70
        if ($this->pirateNavigation->navigateToTarget($fleet, $closestShip->getCurrentMapField())) {
71
            $this->pirateAttack->attackShip($fleet, $closestShip);
72
        }
73
74
        return null;
75
    }
76
77
    private function targetHasEnoughPrestige(int $piratePrestige, ShipInterface $target): bool
78
    {
79
        $targetPrestige = $this->prestigeOfShipOrFleet($target);
80
        $this->logger->log(sprintf('      targetPrestige %d', $targetPrestige));
81
82
        return $targetPrestige >= 0.33 * $piratePrestige;
83
    }
84
85
    private function prestigeOfShipOrFleet(ShipInterface $ship): int
86
    {
87
        $fleet = $ship->getFleet();
88
        if ($fleet !== null) {
89
            return array_reduce(
90
                $fleet->getShips()->toArray(),
91
                fn (int $value, ShipInterface $fleetShip) => $value + $fleetShip->getRump()->getPrestige(),
92
                0
93
            );
94
        }
95
96
        return $ship->getRump()->getPrestige();
97
    }
98
}
99