Passed
Pull Request — dev (#2038)
by Janko
10:55
created

CrewCreator::createCrewAssignment()   B

Complexity

Conditions 9
Paths 13

Size

Total Lines 46
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
eloc 28
nc 13
nop 3
dl 0
loc 46
ccs 0
cts 30
cp 0
crap 90
rs 8.0555
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Module\Crew\Lib;
6
7
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use RuntimeException;
9
use Stu\Component\Crew\CrewGenderEnum;
10
use Stu\Component\Crew\CrewOriginException;
11
use Stu\Component\Crew\CrewPositionEnum;
12
use Stu\Orm\Entity\ColonyInterface;
13
use Stu\Orm\Entity\CrewAssignmentInterface;
14
use Stu\Orm\Entity\SpacecraftInterface;
15
use Stu\Orm\Entity\UserInterface;
16
use Stu\Orm\Repository\CrewRaceRepositoryInterface;
17
use Stu\Orm\Repository\CrewRepositoryInterface;
18
use Stu\Orm\Repository\CrewAssignmentRepositoryInterface;
19
use Stu\Orm\Repository\ShipRumpCategoryRoleCrewRepositoryInterface;
20
21
final class CrewCreator implements CrewCreatorInterface
22
{
23 1
    public function __construct(
24
        private CrewRaceRepositoryInterface $crewRaceRepository,
25
        private ShipRumpCategoryRoleCrewRepositoryInterface $shipRumpCategoryRoleCrewRepository,
26
        private CrewAssignmentRepositoryInterface $shipCrewRepository,
27
        private CrewRepositoryInterface $crewRepository
28 1
    ) {}
29
30
    #[Override]
31
    public function create(UserInterface $user, ?ColonyInterface $colony = null): CrewAssignmentInterface
32
    {
33
        $arr = [];
34
        $raceList = $this->crewRaceRepository->getByFaction((int)$user->getFactionId());
35
        foreach ($raceList as $obj) {
36
            $min = key($arr) + 1;
37
            $amount = range($min, $min + $obj->getChance());
38
            array_walk(
39
                $amount,
40
                function (&$value) use ($obj): void {
41
                    $value = $obj->getId();
42
                }
43
            );
44
            $arr = [...$arr, ...$amount];
45
        }
46
        $race = $this->crewRaceRepository->find($arr[array_rand($arr)]);
47
48
        $gender = random_int(1, 100) > $race->getMaleRatio() ? CrewGenderEnum::FEMALE : CrewGenderEnum::MALE;
49
50
        $crew = $this->crewRepository->prototype();
51
52
        $crew->setUser($user);
53
        $crew->setName('Crew');
54
        $crew->setRace($race);
0 ignored issues
show
Bug introduced by
It seems like $race can also be of type null; however, parameter $crewRace of Stu\Orm\Entity\CrewInterface::setRace() does only seem to accept Stu\Orm\Entity\CrewRaceInterface, maybe add an additional type check? ( Ignorable by Annotation )

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

54
        $crew->setRace(/** @scrutinizer ignore-type */ $race);
Loading history...
55
        $crew->setGender($gender);
56
        $this->crewRepository->save($crew);
57
58
        $crewAssignment = $this->shipCrewRepository->prototype();
59
        $crewAssignment->setUser($user);
60
        $crewAssignment->setCrew($crew);
61
        if ($colony !== null) {
62
            $crewAssignment->setColony($colony);
63
            $colony->getCrewAssignments()->add($crewAssignment);
64
        }
65
        $this->shipCrewRepository->save($crewAssignment);
66
67
        return $crewAssignment;
68
    }
69
70
    #[Override]
71
    public function createCrewAssignments(
72
        SpacecraftInterface $spacecraft,
73
        ColonyInterface|SpacecraftInterface $crewProvider,
74
        ?int $amount = null
75
    ): void {
76
        $crewToSetup = $amount ?? $spacecraft->getBuildPlan()->getCrew();
77
78
        foreach (CrewPositionEnum::getOrder() as $position) {
79
            $createdcount = 1;
80
            $slot = $position === CrewPositionEnum::CREWMAN ? 'getJob6Crew' : 'getJob' . $position->value . 'Crew';
81
            $config = $this->shipRumpCategoryRoleCrewRepository->getByShipRumpCategoryAndRole(
82
                $spacecraft->getRump()->getShipRumpCategory()->getId(),
83
                $spacecraft->getRump()->getShipRumpRole()->getId()
84
            );
85
            if ($config === null) {
86
                throw new RuntimeException(sprintf(
87
                    'no rump category role crew for rumpCategoryId: %d, rumpRoleId: %d',
88
                    $spacecraft->getRump()->getShipRumpCategory()->getId()->value,
89
                    $spacecraft->getRump()->getShipRumpRole()->getId()->value
90
                ));
91
            }
92
93
            while ($crewToSetup > 0 && ($position === CrewPositionEnum::CREWMAN || $createdcount <= $config->$slot())) {
94
                $createdcount++;
95
                $crewToSetup--;
96
97
                $crewAssignment = $this->getCrewByType($position, $crewProvider);
98
                if ($crewAssignment === null) {
99
                    $crewAssignment = $this->getCrew($crewProvider);
100
                }
101
102
                if ($crewAssignment === null) {
103
                    throw new CrewOriginException('no assignable crew found');
104
                }
105
106
                $crewAssignment->setSpacecraft($spacecraft);
107
                $crewAssignment->setColony(null);
108
                $crewAssignment->setTradepost(null);
109
                $crewAssignment->setUser($spacecraft->getUser());
110
                $crewAssignment->setPosition($position);
111
112
                $spacecraft->getCrewAssignments()->add($crewAssignment);
113
114
                $this->shipCrewRepository->save($crewAssignment);
115
            }
116
        }
117
    }
118
119
    private function getCrewByType(
120
        CrewPositionEnum $position,
121
        ColonyInterface|SpacecraftInterface $crewProvider
122
    ): ?CrewAssignmentInterface {
123
124
        $filteredCrewAssignments = $crewProvider
125
            ->getCrewAssignments()
126
            ->filter(fn(CrewAssignmentInterface $assignment): bool => $assignment->getCrew()->isSkilledAt($position))
127
            ->toArray();
128
129
        if ($filteredCrewAssignments === []) {
130
            return null;
131
        }
132
133
        usort(
134
            $filteredCrewAssignments,
135
            fn(CrewAssignmentInterface $a, CrewAssignmentInterface $b): int =>
136
            $b->getCrew()->getSkills()->get($position->value)->getExpertise() - $a->getCrew()->getSkills()->get($position->value)->getExpertise()
137
        );
138
139
140
        $crewAssignment = current($filteredCrewAssignments);
141
        $crewProvider->getCrewAssignments()->removeElement($crewAssignment);
142
143
        return $crewAssignment;
144
    }
145
146
    private function getCrew(ColonyInterface|SpacecraftInterface $crewProvider): ?CrewAssignmentInterface
147
    {
148
        $crewAssignments = $crewProvider->getCrewAssignments();
149
        if ($crewAssignments->isEmpty()) {
150
            return null;
151
        }
152
153
        /** @var CrewAssignmentInterface $random */
154
        $random = $crewAssignments->get(array_rand($crewAssignments->toArray()));
0 ignored issues
show
Bug introduced by
It seems like array_rand($crewAssignments->toArray()) can also be of type array; however, parameter $key of Doctrine\Common\Collecti...adableCollection::get() does only seem to accept integer|string, maybe add an additional type check? ( Ignorable by Annotation )

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

154
        $random = $crewAssignments->get(/** @scrutinizer ignore-type */ array_rand($crewAssignments->toArray()));
Loading history...
155
156
        $crewAssignments->removeElement($random);
157
158
        return $random;
159
    }
160
}
161