Passed
Push — master ( 37217b...efdda9 )
by Nico
19:16 queued 09:28
created

StarSystemCreation::recreateStarSystem()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 39
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 22
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 39
ccs 0
cts 23
cp 0
crap 56
rs 8.6346
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Component\StarSystem;
6
7
use RuntimeException;
8
use Stu\Module\Control\StuRandom;
9
use Stu\Module\Logging\LoggerEnum;
10
use Stu\Module\Logging\LoggerUtilFactoryInterface;
11
use Stu\Module\Logging\LoggerUtilInterface;
12
use Stu\Orm\Entity\MapFieldTypeInterface;
13
use Stu\Orm\Entity\MapInterface;
14
use Stu\Orm\Entity\MassCenterTypeInterface;
15
use Stu\Orm\Entity\StarSystemInterface;
16
use Stu\Orm\Entity\StarSystemTypeInterface;
17
use Stu\Orm\Repository\MapFieldTypeRepositoryInterface;
18
use Stu\Orm\Repository\MapRepositoryInterface;
19
use Stu\Orm\Repository\StarSystemMapRepositoryInterface;
20
use Stu\Orm\Repository\StarSystemRepositoryInterface;
21
use Stu\StarsystemGenerator\StarsystemGeneratorInterface;
22
use Stu\StarsystemGenerator\SystemMapDataInterface;
23
24
//TODO unit tests
25
final class StarSystemCreation implements StarSystemCreationInterface
26
{
27
    private StarSystemRepositoryInterface $starSystemRepository;
28
29
    private MapRepositoryInterface $mapRepository;
30
31
    private StarSystemMapRepositoryInterface $starSystemMapRepository;
32
33
    private MapFieldTypeRepositoryInterface $mapFieldTypeRepository;
34
35
    private StarsystemGeneratorInterface $starsystemGenerator;
36
37
    private StuRandom $stuRandom;
38
39
    private LoggerUtilInterface $loggerUtil;
40
41
    /** @var array<int, MapFieldTypeInterface> */
42
    private array $fieldTypeCache = [];
43
44
    public function __construct(
45
        StarSystemRepositoryInterface $starSystemRepository,
46
        MapRepositoryInterface $mapRepository,
47
        StarSystemMapRepositoryInterface $starSystemMapRepository,
48
        MapFieldTypeRepositoryInterface $mapFieldTypeRepository,
49
        StarsystemGeneratorInterface $starsystemGenerator,
50
        StuRandom $stuRandom,
51
        LoggerUtilFactoryInterface $loggerUtilFactory
52
    ) {
53
        $this->starSystemRepository = $starSystemRepository;
54
        $this->mapRepository = $mapRepository;
55
        $this->starSystemMapRepository = $starSystemMapRepository;
56
        $this->mapFieldTypeRepository = $mapFieldTypeRepository;
57
        $this->starsystemGenerator = $starsystemGenerator;
58
        $this->stuRandom = $stuRandom;
59
60
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
61
    }
62
63
    public function recreateStarSystem(MapInterface $map, string $randomSystemName): ?StarSystemInterface
64
    {
65
        $this->loggerUtil->init('SysGen', LoggerEnum::LEVEL_ERROR);
66
67
        $this->loggerUtil->log(sprintf('recreating for map: %s', $map->getSectorString()));
68
69
        $systemType = $map->getStarSystemType();
70
71
        if ($systemType === null) {
72
            throw new RuntimeException(sprintf('no system type configured on mapId %d', $map->getId()));
73
        }
74
75
        $this->loggerUtil->log(sprintf('systemType: %d, isGenerateable: %s', $systemType->getId(), $systemType->getIsGenerateable() ? 'true' : 'false'));
76
77
        if (
78
            $systemType->getIsGenerateable() === null
79
            || $systemType->getIsGenerateable() === false
80
        ) {
81
            return null;
82
        }
83
84
        $firstMassCenterType = $systemType->getFirstMassCenterType();
85
        $secondMassCenterType = $systemType->getSecondMassCenterType();
86
87
        if ($firstMassCenterType === null) {
88
            throw new RuntimeException(sprintf('first mass center is null, systemTypeId %d', $systemType->getId()));
89
        }
90
91
        $systemMapData = $this->starsystemGenerator->generate(
92
            $systemType->getId(),
93
            $this->getMassCenterFields($firstMassCenterType),
94
            $secondMassCenterType === null ? null : $this->getMassCenterFields($secondMassCenterType)
95
        );
96
97
        $starSystem = $this->getStarSystem($map);
98
        $this->initializeStarSystem($systemType, $map, $starSystem, $systemMapData, $randomSystemName);
99
        $this->starSystemRepository->save($starSystem);
100
101
        return $starSystem;
102
    }
103
104
    private function initializeStarSystem(
105
        StarSystemTypeInterface $systemType,
106
        MapInterface $map,
107
        StarSystemInterface $starSystem,
108
        SystemMapDataInterface $mapData,
109
        string $randomSystemName
110
    ): void {
111
        $starSystem->setCx($map->getCx());
112
        $starSystem->setCy($map->getCy());
113
        $starSystem->setType($systemType);
114
        $starSystem->setName($randomSystemName);
115
        $starSystem->setMaxX($mapData->getWidth());
116
        $starSystem->setMaxY($mapData->getHeight());
117
        $starSystem->setBonusFieldAmount($this->stuRandom->rand(0, 3, true, 2));
118
        $this->createSystemMapEntries($starSystem, $mapData);
119
    }
120
121
    private function createSystemMapEntries(
122
        StarSystemInterface $starSystem,
123
        SystemMapDataInterface $mapData
124
    ): void {
125
        $fieldData = $mapData->getFieldData();
126
127
        for ($y = 1; $y <= $mapData->getHeight(); $y++) {
128
            for ($x = 1; $x <= $mapData->getWidth(); $x++) {
129
                $index = $x + ($y - 1) * $mapData->getWidth();
130
131
                $this->createSystemMap($x, $y, $fieldData[$index], $starSystem);
132
            }
133
        }
134
    }
135
136
    private function createSystemMap(int $x, int $y, int $fieldId, StarSystemInterface $starSystem): void
137
    {
138
        $systemMap = $this->starSystemMapRepository->prototype();
139
        $systemMap->setSx($x);
140
        $systemMap->setSy($y);
141
        $systemMap->setSystem($starSystem);
142
        $systemMap->setFieldType($this->getFieldType($fieldId));
143
144
        $this->starSystemMapRepository->save($systemMap);
145
146
        $starSystem->getFields()->add($systemMap);
147
    }
148
149
    private function getFieldType(int $fieldId): MapFieldTypeInterface
150
    {
151
        if (!array_key_exists($fieldId, $this->fieldTypeCache)) {
152
            $fieldType = $this->mapFieldTypeRepository->find($fieldId === 0 ? 1 : $fieldId);
153
154
            if ($fieldType === null) {
155
                throw new RuntimeException(sprintf('fieldId %d does not exist', $fieldId));
156
            }
157
            $this->fieldTypeCache[$fieldId] = $fieldType;
158
        }
159
160
        return $this->fieldTypeCache[$fieldId];
161
    }
162
163
    private function getStarSystem(MapInterface $map): StarSystemInterface
164
    {
165
        $starSystem = $map->getSystem();
166
        if ($starSystem === null) {
167
            $starSystem = $this->starSystemRepository->prototype();
168
            $map->setSystem($starSystem);
169
            $this->mapRepository->save($map);
170
        } else {
171
            $this->starSystemMapRepository->truncateByStarSystem($starSystem);
172
            $starSystem->getFields()->clear();
173
        }
174
175
        return $starSystem;
176
    }
177
178
    /**
179
     * @return array<int, int>
180
     */
181
    private function getMassCenterFields(MassCenterTypeInterface $massCenterType): array
182
    {
183
        $result = [];
184
185
        $firstId = $massCenterType->getFirstFieldType()->getId();
186
187
        for ($i = 0; $i < (int)pow($massCenterType->getSize(), 2); $i++) {
188
            $result[] = $firstId + $i;
189
        }
190
191
        return $result;
192
    }
193
}
194