Passed
Push — master ( 6b02b9...a180a6 )
by Nico
26:39 queued 18:43
created

StarSystemCreation::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 1
b 0
f 0
nc 1
nop 8
dl 0
loc 19
ccs 0
cts 9
cp 0
crap 2
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Component\StarSystem;
6
7
use RuntimeException;
8
use Stu\Component\Colony\ColonyCreationInterface;
9
use Stu\Component\Colony\ColonyTypeEnum;
10
use Stu\Module\Control\StuRandom;
11
use Stu\Module\Logging\LoggerUtilFactoryInterface;
12
use Stu\Module\Logging\LoggerUtilInterface;
13
use Stu\Orm\Entity\MapFieldTypeInterface;
14
use Stu\Orm\Entity\MapInterface;
15
use Stu\Orm\Entity\MassCenterTypeInterface;
16
use Stu\Orm\Entity\StarSystemInterface;
17
use Stu\Orm\Entity\StarSystemMapInterface;
18
use Stu\Orm\Entity\StarSystemTypeInterface;
19
use Stu\Orm\Repository\MapFieldTypeRepositoryInterface;
20
use Stu\Orm\Repository\MapRepositoryInterface;
21
use Stu\Orm\Repository\StarSystemMapRepositoryInterface;
22
use Stu\Orm\Repository\StarSystemRepositoryInterface;
23
use Stu\StarsystemGenerator\StarsystemGeneratorInterface;
24
use Stu\StarsystemGenerator\SystemMapDataInterface;
25
26
//TODO unit tests
27
final class StarSystemCreation implements StarSystemCreationInterface
28
{
29
    private StarSystemRepositoryInterface $starSystemRepository;
30
31
    private MapRepositoryInterface $mapRepository;
32
33
    private StarSystemMapRepositoryInterface $starSystemMapRepository;
34
35
    private MapFieldTypeRepositoryInterface $mapFieldTypeRepository;
36
37
    private StarsystemGeneratorInterface $starsystemGenerator;
38
39
    private ColonyCreationInterface $colonyCreation;
40
41
    private StuRandom $stuRandom;
42
43
    private LoggerUtilInterface $loggerUtil;
44
45
    /** @var array<int, MapFieldTypeInterface> */
46
    private array $fieldTypeCache = [];
47
48
    public function __construct(
49
        StarSystemRepositoryInterface $starSystemRepository,
50
        MapRepositoryInterface $mapRepository,
51
        StarSystemMapRepositoryInterface $starSystemMapRepository,
52
        MapFieldTypeRepositoryInterface $mapFieldTypeRepository,
53
        StarsystemGeneratorInterface $starsystemGenerator,
54
        ColonyCreationInterface $colonyCreation,
55
        StuRandom $stuRandom,
56
        LoggerUtilFactoryInterface $loggerUtilFactory
57
    ) {
58
        $this->starSystemRepository = $starSystemRepository;
59
        $this->mapRepository = $mapRepository;
60
        $this->starSystemMapRepository = $starSystemMapRepository;
61
        $this->mapFieldTypeRepository = $mapFieldTypeRepository;
62
        $this->starsystemGenerator = $starsystemGenerator;
63
        $this->colonyCreation = $colonyCreation;
64
        $this->stuRandom = $stuRandom;
65
66
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
67
    }
68
69
    public function recreateStarSystem(MapInterface $map, string $randomSystemName): ?StarSystemInterface
70
    {
71
        //$this->loggerUtil->init('SysGen', LoggerEnum::LEVEL_ERROR);
72
73
        $this->loggerUtil->log(sprintf('recreating for map: %s', $map->getSectorString()));
74
75
        $systemType = $map->getStarSystemType();
76
77
        if ($systemType === null) {
78
            throw new RuntimeException(sprintf('no system type configured on mapId %d', $map->getId()));
79
        }
80
81
        $this->loggerUtil->log(sprintf('systemType: %d, isGenerateable: %s', $systemType->getId(), $systemType->getIsGenerateable() ? 'true' : 'false'));
82
83
        if (
84
            $systemType->getIsGenerateable() === null
85
            || $systemType->getIsGenerateable() === false
86
        ) {
87
            return null;
88
        }
89
90
        $firstMassCenterType = $systemType->getFirstMassCenterType();
91
        $secondMassCenterType = $systemType->getSecondMassCenterType();
92
93
        if ($firstMassCenterType === null) {
94
            throw new RuntimeException(sprintf('first mass center is null, systemTypeId %d', $systemType->getId()));
95
        }
96
97
        $systemMapData = $this->starsystemGenerator->generate(
98
            $systemType->getId(),
99
            $this->getMassCenterFields($firstMassCenterType),
100
            $secondMassCenterType === null ? null : $this->getMassCenterFields($secondMassCenterType)
101
        );
102
103
        $starSystem = $this->getStarSystem($map);
104
        $this->initializeStarSystem($systemType, $map, $starSystem, $systemMapData, $randomSystemName);
105
        $this->starSystemRepository->save($starSystem);
106
107
        return $starSystem;
108
    }
109
110
    private function initializeStarSystem(
111
        StarSystemTypeInterface $systemType,
112
        MapInterface $map,
113
        StarSystemInterface $starSystem,
114
        SystemMapDataInterface $mapData,
115
        string $randomSystemName
116
    ): void {
117
        $starSystem->setCx($map->getCx());
118
        $starSystem->setCy($map->getCy());
119
        $starSystem->setType($systemType);
120
        $starSystem->setName($randomSystemName);
121
        $starSystem->setMaxX($mapData->getWidth());
122
        $starSystem->setMaxY($mapData->getHeight());
123
        $starSystem->setBonusFieldAmount($this->stuRandom->rand(0, 3, true, 2));
124
125
        $planetMoonIdentifiers = $this->createSystemMapEntries($starSystem, $mapData);
126
127
        $this->createColonies($starSystem, $planetMoonIdentifiers);
128
    }
129
130
    /**
131
     * @return array<string, string>
132
     */
133
    private function createSystemMapEntries(
134
        StarSystemInterface $starSystem,
135
        SystemMapDataInterface $mapData
136
    ): array {
137
        $fieldData = $mapData->getFieldData();
138
139
        $planetMoonIdentifiers = [];
140
141
        for ($y = 1; $y <= $mapData->getHeight(); $y++) {
142
            for ($x = 1; $x <= $mapData->getWidth(); $x++) {
143
                $index = $x + ($y - 1) * $mapData->getWidth();
144
145
                $identifier = $this->createSystemMap(
146
                    $index,
147
                    $x,
148
                    $y,
149
                    $fieldData[$index],
150
                    $starSystem,
151
                    $mapData
152
                );
153
154
                if ($identifier !== null) {
155
                    $planetMoonIdentifiers[sprintf('%d_%d', $x, $y)] = $identifier;
156
                }
157
            }
158
        }
159
160
        return $planetMoonIdentifiers;
161
    }
162
163
    /**
164
     * @param array<string, string> $planetMoonIdentifiers
165
     */
166
    private function createColonies(StarSystemInterface $starSystem, array $planetMoonIdentifiers): void
167
    {
168
        /**
169
         * @var array<StarSystemMapInterface>
170
         */
171
        $systemMapsWithoutColony = array_filter(
172
            $starSystem->getFields()->toArray(),
173
            fn (StarSystemMapInterface $systemMap) => $systemMap->getFieldType()->getColonyClass() !== null
174
        );
175
176
        foreach ($systemMapsWithoutColony as $systemMap) {
177
            $identifier = $planetMoonIdentifiers[sprintf('%d_%d', $systemMap->getSx(), $systemMap->getSy())];
178
            $this->colonyCreation->create($systemMap, $identifier);
179
        }
180
    }
181
182
    private function createSystemMap(
183
        int $index,
184
        int $x,
185
        int $y,
186
        int $fieldId,
187
        StarSystemInterface $starSystem,
188
        SystemMapDataInterface $mapData
189
    ): ?string {
190
191
        $systemMap = $this->starSystemMapRepository->prototype();
192
        $systemMap->setSx($x);
193
        $systemMap->setSy($y);
194
        $systemMap->setSystem($starSystem);
195
        $systemMap->setFieldType($this->getFieldType($fieldId));
196
197
        $this->starSystemMapRepository->save($systemMap);
198
        $starSystem->getFields()->add($systemMap);
199
200
        $colonyClass = $systemMap->getFieldType()->getColonyClass();
201
        if ($colonyClass !== null) {
202
            if ($colonyClass->getType() === ColonyTypeEnum::COLONY_TYPE_ASTEROID) {
203
                $identifer = sprintf('%s %s', $colonyClass->getName(), $starSystem->getName());
204
            } else {
205
                $identifer = sprintf('%s %s', $starSystem->getName(), $mapData->getIdentifier($index));
206
            }
207
208
            return $identifer;
209
        }
210
211
        return null;
212
    }
213
214
    private function getFieldType(int $fieldId): MapFieldTypeInterface
215
    {
216
        if (!array_key_exists($fieldId, $this->fieldTypeCache)) {
217
            $fieldType = $this->mapFieldTypeRepository->find($fieldId === 0 ? 1 : $fieldId);
218
219
            if ($fieldType === null) {
220
                throw new RuntimeException(sprintf('fieldId %d does not exist', $fieldId));
221
            }
222
            $this->fieldTypeCache[$fieldId] = $fieldType;
223
        }
224
225
        return $this->fieldTypeCache[$fieldId];
226
    }
227
228
    private function getStarSystem(MapInterface $map): StarSystemInterface
229
    {
230
        $starSystem = $map->getSystem();
231
        if ($starSystem === null) {
232
            $starSystem = $this->starSystemRepository->prototype();
233
            $map->setSystem($starSystem);
234
            $this->mapRepository->save($map);
235
        } else {
236
            $this->starSystemMapRepository->truncateByStarSystem($starSystem);
237
            $starSystem->getFields()->clear();
238
        }
239
240
        return $starSystem;
241
    }
242
243
    /**
244
     * @return array<int, int>
245
     */
246
    private function getMassCenterFields(MassCenterTypeInterface $massCenterType): array
247
    {
248
        $result = [];
249
250
        $firstId = $massCenterType->getFirstFieldType()->getId();
251
252
        for ($i = 0; $i < (int)pow($massCenterType->getSize(), 2); $i++) {
253
            $result[] = $firstId + $i;
254
        }
255
256
        return $result;
257
    }
258
}
259