Passed
Push — dev ( 4e8c32...b675a8 )
by Nico
14:19
created

getClosestColonizableColonyDistance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 1
dl 0
loc 10
ccs 0
cts 6
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Orm\Repository;
6
7
use Doctrine\ORM\EntityRepository;
8
use Doctrine\ORM\Query\ResultSetMapping;
9
use Doctrine\ORM\NoResultException;
10
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...
11
use Stu\Component\Game\TimeConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Game\TimeConstants 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...
12
use Stu\Module\Commodity\CommodityTypeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Commodity\CommodityTypeEnum 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...
13
use Stu\Module\PlayerSetting\Lib\UserEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\PlayerSetting\Lib\UserEnum 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...
14
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface;
15
use Stu\Orm\Entity\Colony;
16
use Stu\Orm\Entity\ColonyClass;
17
use Stu\Orm\Entity\ColonyInterface;
18
use Stu\Orm\Entity\Layer;
19
use Stu\Orm\Entity\LayerInterface;
20
use Stu\Orm\Entity\Location;
21
use Stu\Orm\Entity\Map;
22
use Stu\Orm\Entity\MapInterface;
23
use Stu\Orm\Entity\MapRegionSettlement;
24
use Stu\Orm\Entity\PirateWrath;
25
use Stu\Orm\Entity\StarSystem;
26
use Stu\Orm\Entity\StarSystemMap;
27
use Stu\Orm\Entity\StarSystemMapInterface;
28
use Stu\Orm\Entity\SpacecraftInterface;
29
use Stu\Orm\Entity\User;
30
use Stu\Orm\Entity\UserInterface;
31
32
/**
33
 * @extends EntityRepository<Colony>
34
 */
35
final class ColonyRepository extends EntityRepository implements ColonyRepositoryInterface
36
{
37
    #[Override]
38
    public function prototype(): ColonyInterface
39
    {
40
        return new Colony();
41
    }
42
43
    #[Override]
44
    public function save(ColonyInterface $colony): void
45
    {
46
        $em = $this->getEntityManager();
47
48
        $em->persist($colony);
49
    }
50
51
    #[Override]
52
    public function delete(ColonyInterface $colony): void
53
    {
54
        $em = $this->getEntityManager();
55
56
        $em->remove($colony);
57
        $em->flush(); //TODO really neccessary?
58
    }
59
60 2
    #[Override]
61
    public function getAmountByUser(UserInterface $user, int $colonyType): int
62
    {
63 2
        return (int) $this->getEntityManager()
64 2
            ->createQuery(
65 2
                sprintf(
66 2
                    'SELECT count(c.id) from %s c WHERE c.user_id = :userId AND c.colonies_classes_id IN (
67
                        SELECT cc.id FROM %s cc WHERE cc.type = :type
68 2
                    )',
69 2
                    Colony::class,
70 2
                    ColonyClass::class
71 2
                )
72 2
            )
73 2
            ->setParameters([
74 2
                'userId' => $user,
75 2
                'type' => $colonyType
76 2
            ])
77 2
            ->getSingleScalarResult();
78
    }
79
80
    #[Override]
81
    public function getStartingByFaction(int $factionId): array
82
    {
83
        return $this->getEntityManager()
84
            ->createQuery(
85
                sprintf(
86
                    'SELECT c FROM %s c INDEX BY c.id
87
                     JOIN %s sm
88
                     WITH c.starsystem_map_id = sm.id
89
                     WHERE c.user_id = :userId AND c.colonies_classes_id IN (
90
                        SELECT pt.id FROM %s pt WHERE pt.allow_start = :allowStart
91
                    ) AND sm.systems_id IN (
92
                        SELECT m.systems_id FROM %s m WHERE m.systems_id > 0 AND m.admin_region_id IN (
93
                            SELECT mrs.region_id from %s mrs WHERE mrs.faction_id = :factionId
94
                        ) AND m.id IN (SELECT l.id FROM %s l WHERE l.layer_id IN (SELECT ly.id FROM %s ly WHERE ly.is_colonizable = :true))
95
                    )',
96
                    Colony::class,
97
                    StarSystemMap::class,
98
                    ColonyClass::class,
99
                    Map::class,
100
                    MapRegionSettlement::class,
101
                    Location::class,
102
                    Layer::class
103
                )
104
            )
105
            ->setParameters([
106
                'allowStart' => 1,
107
                'userId' => UserEnum::USER_NOONE,
108
                'factionId' => $factionId,
109
                'true' => true
110
            ])
111
            ->getResult();
112
    }
113
114
    #[Override]
115
    public function getByPosition(StarSystemMapInterface $sysmap): ?ColonyInterface
116
    {
117
        return $this->findOneBy([
118
            'starsystem_map_id' => $sysmap->getId()
119
        ]);
120
    }
121
122
    #[Override]
123
    public function getForeignColoniesInBroadcastRange(
124
        StarSystemMapInterface $systemMap,
125
        UserInterface $user
126
    ): array {
127
        return $this->getEntityManager()
128
            ->createQuery(
129
                sprintf(
130
                    'SELECT c FROM %s c
131
                     JOIN %s sm
132
                     WITH c.starsystem_map_id = sm.id
133
                     WHERE c.user_id NOT IN (:ignoreIds)
134
                     AND sm.systems_id = :systemId
135
                     AND sm.sx BETWEEN (:sx - 1) AND (:sx + 1)
136
                     AND sm.sy BETWEEN (:sy - 1) AND (:sy + 1)',
137
                    Colony::class,
138
                    StarSystemMap::class
139
                )
140
            )
141
            ->setParameters([
142
                'ignoreIds' => [$user->getId(), UserEnum::USER_NOONE],
143
                'systemId' => $systemMap->getSystem()->getId(),
144
                'sx' => $systemMap->getSx(),
145
                'sy' => $systemMap->getSy()
146
            ])
147
            ->getResult();
148
    }
149
150
    #[Override]
151
    public function getByBatchGroup(int $batchGroup, int $batchGroupCount): iterable
152
    {
153
        return $this->getEntityManager()
154
            ->createQuery(
155
                sprintf(
156
                    'SELECT c FROM %s c
157
                    WHERE MOD(c.user_id, :groupCount) + 1 = :groupId
158
                    AND c.user_id != :userId',
159
                    Colony::class
160
                )
161
            )
162
            ->setParameters([
163
                'groupId' => $batchGroup,
164
                'groupCount' => $batchGroupCount,
165
                'userId' => UserEnum::USER_NOONE
166
            ])
167
            ->getResult();
168
    }
169
170
    #[Override]
171
    public function getColonized(): iterable
172
    {
173
        return $this->getEntityManager()
174
            ->createQuery(
175
                sprintf(
176
                    'SELECT c FROM %s c WHERE c.user_id != :userId',
177
                    Colony::class
178
                )
179
            )
180
            ->setParameters([
181
                'userId' => UserEnum::USER_NOONE,
182
            ])
183
            ->getResult();
184
    }
185
186 1
    #[Override]
187
    public function getColoniesNetWorth(): array
188
    {
189 1
        $rsm = new ResultSetMapping();
190 1
        $rsm->addScalarResult('user_id', 'user_id', 'integer');
191 1
        $rsm->addScalarResult('commodity_id', 'commodity_id', 'integer');
192 1
        $rsm->addScalarResult('sum', 'sum', 'integer');
193
194 1
        return $this->getEntityManager()
195 1
            ->createNativeQuery(
196 1
                'SELECT u.id as user_id, bc.commodity_id AS commodity_id, SUM(bc.count) AS sum
197
                FROM stu_user u
198
                JOIN stu_colonies c
199
                ON u.id = c.user_id 
200
                JOIN stu_colonies_fielddata cf
201
                ON cf.colonies_id = c.id
202
                JOIN stu_buildings_cost bc 
203
                ON cf.buildings_id = bc.buildings_id 
204
                WHERE u.id >= :firstUserId
205
                AND cf.buildings_id IS NOT NULL
206
                AND cf.aktiv = 1
207 1
                GROUP BY u.id, bc.commodity_id',
208 1
                $rsm
209 1
            )
210 1
            ->setParameters(['firstUserId' => UserEnum::USER_FIRST_ID])
211 1
            ->getResult();
212
    }
213
214 1
    #[Override]
215
    public function getColoniesProductionNetWorth(): array
216
    {
217 1
        $rsm = new ResultSetMapping();
218 1
        $rsm->addScalarResult('user_id', 'user_id', 'integer');
219 1
        $rsm->addScalarResult('commodity_id', 'commodity_id', 'integer');
220 1
        $rsm->addScalarResult('sum', 'sum', 'integer');
221
222 1
        return $this->getEntityManager()
223 1
            ->createNativeQuery(
224 1
                'SELECT c.user_id, bc.commodity_id, SUM(bc.count) AS sum
225
                FROM stu_colonies c
226
                JOIN stu_colonies_fielddata cf
227
                ON cf.colonies_id = c.id 
228
                JOIN stu_buildings_commodity bc
229
                ON cf.buildings_id = bc.buildings_id
230
                JOIN stu_commodity co
231
                ON bc.commodity_id = co.id
232
                WHERE co.type = :typeStandard
233
                AND co.name != \'Latinum\'
234
                AND bc.count > 0
235
                AND cf.aktiv = 1
236 1
                GROUP BY c.user_id, bc.commodity_id',
237 1
                $rsm
238 1
            )
239 1
            ->setParameters(['typeStandard' => CommodityTypeEnum::COMMODITY_TYPE_STANDARD])
240 1
            ->getResult();
241
    }
242
243
    #[Override]
244
    public function getSatisfiedWorkerTop10(): array
245
    {
246
        $rsm = new ResultSetMapping();
247
        $rsm->addScalarResult('user_id', 'user_id', 'integer');
248
        $rsm->addScalarResult('satisfied', 'satisfied', 'integer');
249
250
        return $this->getEntityManager()
251
            ->createNativeQuery(
252
                'SELECT user_id, SUM(satisfied) AS satisfied
253
                FROM ( SELECT c.user_id,
254
                            LEAST( COALESCE(c.bev_work, 0),
255
                            ( SELECT COALESCE(SUM(bc.count), 0)
256
                                FROM stu_colonies_fielddata cf
257
                                JOIN stu_buildings b
258
                                ON cf.buildings_id = b.id
259
                                JOIN stu_buildings_commodity bc
260
                                ON b.id = bc.buildings_id
261
                                WHERE cf.colonies_id = c.id
262
                                AND bc.commodity_id = :lifeStandard
263
                                AND cf.aktiv = 1
264
                            )) AS satisfied
265
                        FROM stu_colonies c
266
                        WHERE c.user_id >= :firstUserId) AS colonies
267
                GROUP BY user_id
268
                ORDER BY 2 DESC
269
                LIMIT 10',
270
                $rsm
271
            )
272
            ->setParameters([
273
                'firstUserId' => UserEnum::USER_FIRST_ID,
274
                'lifeStandard' => CommodityTypeEnum::COMMODITY_EFFECT_LIFE_STANDARD
275
            ])
276
            ->getResult();
277
    }
278
279
    #[Override]
280
    public function getPirateTargets(SpacecraftWrapperInterface $wrapper): array
281
    {
282
        $layer = $wrapper->get()->getLayer();
283
        if ($layer === null) {
284
            return [];
285
        }
286
287
        $location = $wrapper->get()->getLocation();
288
        $range = $wrapper->getSensorRange() * 2;
289
290
        return $this->getEntityManager()->createQuery(
291
            sprintf(
292
                'SELECT c FROM %s c
293
                JOIN %s sm
294
                WITH c.starsystem_map_id = sm.id
295
                JOIN %s s
296
                WITH sm.systems_id = s.id
297
                JOIN %s m
298
                WITH s.id = m.systems_id
299
                JOIN %s l
300
                WITH m.id = l.id
301
                JOIN %s u
302
                WITH c.user_id = u.id
303
                LEFT JOIN %s w
304
                WITH u.id = w.user_id
305
                WHERE l.cx BETWEEN :minX AND :maxX
306
                AND l.cy BETWEEN :minY AND :maxY
307
                AND l.layer_id = :layer
308
                AND u.id >= :firstUserId
309
                AND u.state >= :stateActive
310
                AND u.creation < :fourMonthEarlier
311
                AND (u.vac_active = :false OR u.vac_request_date > :vacationThreshold)
312
                AND COALESCE(w.protection_timeout, 0) < :currentTime',
313
                Colony::class,
314
                StarSystemMap::class,
315
                StarSystem::class,
316
                Map::class,
317
                Location::class,
318
                User::class,
319
                PirateWrath::class
320
            )
321
        )
322
            ->setParameters([
323
                'minX' => $location->getCx() - $range,
324
                'maxX' => $location->getCx() + $range,
325
                'minY' => $location->getCy() - $range,
326
                'maxY' => $location->getCy() + $range,
327
                'layer' => $layer,
328
                'firstUserId' => UserEnum::USER_FIRST_ID,
329
                'stateActive' => UserEnum::USER_STATE_ACTIVE,
330
                'fourMonthEarlier' => time() - TimeConstants::EIGHT_WEEKS_IN_SECONDS,
331
                'false' => false,
332
                'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS,
333
                'currentTime' => time()
334
            ])
335
            ->getResult();
336
    }
337
338
    #[Override]
339
    public function getClosestColonizableColonyDistance(SpacecraftWrapperInterface $wrapper): ?int
340
    {
341
        $spacecraft = $wrapper->get();
342
        $location = $spacecraft->getLocation();
343
344
        if ($location instanceof StarSystemMapInterface) {
345
            return $this->getClosestColonizableColonyInSystem($spacecraft);
346
        } else {
347
            return $this->getClosestSystemWithColonizableColonies($spacecraft);
348
        }
349
    }
350
351
    private function getClosestColonizableColonyInSystem(SpacecraftInterface $spacecraft): ?int
352
    {
353
        $systemMap = $spacecraft->getStarsystemMap();
354
        if ($systemMap === null) {
355
            return null;
356
        }
357
358
        $currentColony = $systemMap->getColony();
359
        if (
360
            $currentColony !== null &&
361
            $currentColony->getUserId() === UserEnum::USER_NOONE &&
362
            $currentColony->getColonyClass()->getAllowStart()
363
        ) {
364
            return null;
365
        }
366
367
        try {
368
            $result = $this->getEntityManager()->createQuery(
369
                sprintf(
370
                    'SELECT MIN(ABS(sm.sx - :sx) + ABS(sm.sy - :sy)) as distance
371
                FROM %s c
372
                JOIN %s sm
373
                WITH c.starsystem_map_id = sm.id
374
                JOIN %s cc
375
                WITH c.colonies_classes_id = cc.id
376
                WHERE c.user_id = :nooneUserId
377
                AND cc.allow_start = :allowStart
378
                AND sm.systems_id = :systemId
379
                AND sm.id != :currentMapId',
380
                    Colony::class,
381
                    StarSystemMap::class,
382
                    ColonyClass::class
383
                )
384
            )
385
                ->setParameters([
386
                    'sx' => $systemMap->getSx(),
387
                    'sy' => $systemMap->getSy(),
388
                    'systemId' => $systemMap->getSystemId(),
389
                    'currentMapId' => $systemMap->getId(),
390
                    'nooneUserId' => UserEnum::USER_NOONE,
391
                    'allowStart' => true
392
                ])
393
                ->getSingleScalarResult();
394
395
            return $result > 0 ? (int)$result : null;
396
        } catch (NoResultException) {
397
            return null;
398
        }
399
    }
400
401
402
    private function getClosestSystemWithColonizableColonies(SpacecraftInterface $spacecraft): ?int
403
    {
404
        $currentLocation = $spacecraft->getLocation();
405
        $currentX = $currentLocation->getCx();
406
        $currentY = $currentLocation->getCy();
407
        $currentLayer = $currentLocation->getLayer();
408
409
        if ($currentLayer === null) {
410
            return null;
411
        }
412
413
        $currentLayerId = $currentLayer->getId();
414
415
        try {
416
            $result = $this->getEntityManager()->createQuery(
417
                sprintf(
418
                    'SELECT MIN(ABS(l.cx - :currentX) + ABS(l.cy - :currentY)) as distance
419
                FROM %s c
420
                JOIN %s sm
421
                WITH c.starsystem_map_id = sm.id
422
                JOIN %s s
423
                WITH sm.systems_id = s.id
424
                JOIN %s m
425
                WITH s.id = m.systems_id
426
                JOIN %s l
427
                WITH m.id = l.id
428
                JOIN %s cc
429
                WITH c.colonies_classes_id = cc.id
430
                WHERE c.user_id = :nooneUserId
431
                AND cc.allow_start = :allowStart
432
                AND l.layer_id = :currentLayerId',
433
                    Colony::class,
434
                    StarSystemMap::class,
435
                    StarSystem::class,
436
                    Map::class,
437
                    Location::class,
438
                    ColonyClass::class
439
                )
440
            )
441
                ->setParameters([
442
                    'currentX' => $currentX,
443
                    'currentY' => $currentY,
444
                    'currentLayerId' => $currentLayerId,
445
                    'nooneUserId' => UserEnum::USER_NOONE,
446
                    'allowStart' => true
447
                ])
448
                ->getSingleScalarResult();
449
450
            return $result > 0 ? (int)$result : null;
451
        } catch (NoResultException) {
452
            return null;
453
        }
454
    }
455
}
456