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

StarSystemCreation::initializeStarSystem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
c 1
b 0
f 0
nc 1
nop 5
dl 0
loc 18
ccs 0
cts 10
cp 0
crap 2
rs 9.9666
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