MapRepository::getWithEmptySystem()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 15
nc 1
nop 1
dl 0
loc 20
ccs 0
cts 14
cp 0
crap 2
rs 9.7666
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 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...
10
use RuntimeException;
11
use Stu\Component\Ship\FlightSignatureVisibilityEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\FlightSignatureVisibilityEnum 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\Component\Spacecraft\System\SpacecraftSystemTypeEnum;
13
use Stu\Lib\Map\VisualPanel\PanelBoundaries;
14
use Stu\Module\PlayerSetting\Lib\UserSettingEnum;
15
use Stu\Module\Starmap\Lib\ExploreableStarMap;
16
use Stu\Orm\Entity\Layer;
17
use Stu\Orm\Entity\Location;
18
use Stu\Orm\Entity\Map;
19
use Stu\Orm\Entity\User;
20
use Stu\Orm\Entity\MapRegionSettlement;
21
use Stu\Orm\Entity\StarSystemMap;
22
23
24
/**
25
 * @extends EntityRepository<Map>
26
 */
27
final class MapRepository extends EntityRepository implements MapRepositoryInterface
28
{
29 1
    #[Override]
30
    public function getAmountByLayer(Layer $layer): int
31
    {
32 1
        return $this->count([
33 1
            'layer_id' => $layer->getId()
34 1
        ]);
35
    }
36
37
    #[Override]
38
    public function getAllOrdered(int $layerId): array
39
    {
40
        return $this->getEntityManager()
41
            ->createQuery(
42
                sprintf(
43
                    'SELECT m FROM %s m
44
                    JOIN %s l
45
                    WITH m.id = l.id
46
                    WHERE l.layer_id = :layerId
47
                    ORDER BY l.cy, l.cx',
48
                    Map::class,
49
                    Location::class
50
                )
51
            )
52
            ->setParameters([
53
                'layerId' => $layerId
54
            ])
55
            ->getResult();
56
    }
57
58
    #[Override]
59
    public function getAllWithSystem(int $layerId): array
60
    {
61
        return $this->getEntityManager()
62
            ->createQuery(
63
                sprintf(
64
                    'SELECT m FROM %s m INDEX BY m.id
65
                    JOIN %s l
66
                    WITH m.id = l.id
67
                    WHERE l.layer_id = :layerId
68
                    AND m.systems_id IS NOT null',
69
                    Map::class,
70
                    Location::class
71
                )
72
            )
73
            ->setParameters([
74
                'layerId' => $layerId
75
            ])
76
            ->getResult();
77
    }
78
79
    #[Override]
80
    public function getAllWithoutSystem(int $layerId): array
81
    {
82
        return $this->getEntityManager()
83
            ->createQuery(
84
                sprintf(
85
                    'SELECT m FROM %s m INDEX BY m.id
86
                    JOIN %s l
87
                    WITH m.id = l.id
88
                    WHERE l.layer_id = :layerId
89
                    AND m.systems_id IS null',
90
                    Map::class,
91
                    Location::class
92
                )
93
            )
94
            ->setParameters([
95
                'layerId' => $layerId
96
            ])
97
            ->getResult();
98
    }
99
100 6
    #[Override]
101
    public function getByCoordinates(?Layer $layer, int $cx, int $cy): ?Map
102
    {
103 6
        if ($layer === null) {
104
            return null;
105
        }
106
107 6
        return $this->findOneBy([
108 6
            'layer_id' => $layer->getId(),
109 6
            'cx' => $cx,
110 6
            'cy' => $cy
111 6
        ]);
112
    }
113
114
    #[Override]
115
    public function getByBoundaries(PanelBoundaries $boundaries): array
116
    {
117
        return $this->getByCoordinateRange(
118
            $boundaries->getParentId(),
119
            $boundaries->getMinX(),
120
            $boundaries->getMaxX(),
121
            $boundaries->getMinY(),
122
            $boundaries->getMaxY()
123
        );
124
    }
125
126 3
    #[Override]
127
    public function getByCoordinateRange(
128
        int $layerId,
129
        int $startCx,
130
        int $endCx,
131
        int $startCy,
132
        int $endCy,
133
        bool $sortAscending = true
134
    ): array {
135 3
        return $this->getEntityManager()
136 3
            ->createQuery(
137 3
                sprintf(
138 3
                    'SELECT m FROM %s m
139
                    JOIN %s l
140
                    WITH m.id = l.id
141
                    WHERE l.cx BETWEEN :startCx AND :endCx
142
                    AND l.cy BETWEEN :startCy AND :endCy
143
                    AND l.layer_id = :layerId
144 3
                    ORDER BY l.cy %3$s, l.cx %3$s',
145 3
                    Map::class,
146 3
                    Location::class,
147 3
                    $sortAscending ? 'ASC' : 'DESC'
148 3
                )
149 3
            )
150 3
            ->setParameters([
151 3
                'layerId' => $layerId,
152 3
                'startCx' => $startCx,
153 3
                'endCx' => $endCx,
154 3
                'startCy' => $startCy,
155 3
                'endCy' => $endCy
156 3
            ])
157 3
            ->getResult();
158
    }
159
160
    #[Override]
161
    public function save(Map $map): void
162
    {
163
        $em = $this->getEntityManager();
164
165
        $em->persist($map);
166
    }
167
168 1
    #[Override]
169
    public function getNormalBorderData(PanelBoundaries $boundaries, ResultSetMapping $rsm): array
170
    {
171 1
        return $this->getEntityManager()->createNativeQuery(
172 1
            'SELECT l.cx AS x, l.cy AS y
173
            FROM stu_map m
174
            JOIN stu_location l
175
            ON m.id = l.id
176
            WHERE l.cx BETWEEN :xStart AND :xEnd
177
            AND l.cy BETWEEN :yStart AND :yEnd
178 1
            AND l.layer_id = :layerId',
179 1
            $rsm
180 1
        )->setParameters([
181 1
            'xStart' => $boundaries->getMinX(),
182 1
            'xEnd' => $boundaries->getMaxX(),
183 1
            'yStart' => $boundaries->getMinY(),
184 1
            'yEnd' => $boundaries->getMaxY(),
185 1
            'layerId' => $boundaries->getParentId()
186 1
        ])->getResult();
187
    }
188
189
    #[Override]
190
    public function getCartographingData(PanelBoundaries $boundaries, ResultSetMapping $rsm, array $locations): array
191
    {
192
193
        return $this->getEntityManager()->createNativeQuery(
194
            'SELECT DISTINCT 
195
                    l.cx AS x, 
196
                    l.cy AS y, 
197
                    CASE 
198
                        WHEN l.id IN (:fieldIds) THEN TRUE ELSE FALSE
199
                    END AS cartographing,
200
                    (SELECT mft.complementary_color FROM stu_map_ftypes mft where mft.id = l.field_id) AS complementary_color
201
                FROM stu_location l
202
                WHERE l.cx BETWEEN :xStart AND :xEnd
203
                AND l.cy BETWEEN :yStart AND :yEnd
204
                AND l.layer_id = :layerId
205
                ORDER BY cartographing DESC',
206
            $rsm
207
        )->setParameters([
208
            'xStart' => $boundaries->getMinX(),
209
            'xEnd' => $boundaries->getMaxX(),
210
            'yStart' => $boundaries->getMinY(),
211
            'yEnd' => $boundaries->getMaxY(),
212
            'layerId' => $boundaries->getParentId(),
213
            'fieldIds' => $locations
214
        ])->getResult();
215
    }
216
217
218
    #[Override]
219
    public function getRegionBorderData(PanelBoundaries $boundaries, ResultSetMapping $rsm): array
220
    {
221
        return $this->getEntityManager()->createNativeQuery(
222
            'SELECT l.cx AS x, l.cy AS y,
223
                (SELECT al.rgb_code FROM stu_alliances al
224
                    JOIN stu_user u ON al.id = u.allys_id
225
                    JOIN stu_spacecraft sc ON u.id = sc.user_id
226
                    JOIN stu_station s ON sc.id = s.id
227
                    JOIN stu_map ma ON ma.influence_area_id = s.influence_area_id
228
                    WHERE ma.id = m.id AND ma.bordertype_id IS NULL AND ma.admin_region_id IS NULL)
229
                            AS allycolor,
230
                (SELECT COALESCE(us.value, \'\') FROM stu_user u
231
                    LEFT JOIN stu_user_setting us ON u.id = us.user_id
232
                    JOIN stu_spacecraft sc ON u.id = sc.user_id
233
                    JOIN stu_station s ON sc.id = s.id
234
                    JOIN stu_map mu ON mu.influence_area_id = s.influence_area_id
235
                    WHERE us.setting = :rgbCodeSetting
236
                    AND mu.id = m.id AND mu.bordertype_id IS NULL AND mu.admin_region_id IS NULL)
237
                        as usercolor,
238
                (SELECT mbt.color FROM stu_map_bordertypes mbt
239
                    JOIN stu_map mb ON mb.bordertype_id = mbt.id
240
                    WHERE mb.id = m.id AND mb.bordertype_id IS NOT NULL)
241
                        AS factioncolor
242
            FROM stu_map m
243
            JOIN stu_location l
244
            ON m.id = l.id
245
            WHERE l.cx BETWEEN :xStart AND :xEnd
246
            AND l.cy BETWEEN :yStart AND :yEnd
247
            AND l.layer_id = :layerId',
248
            $rsm
249
        )->setParameters([
250
            'xStart' => $boundaries->getMinX(),
251
            'xEnd' => $boundaries->getMaxX(),
252
            'yStart' => $boundaries->getMinY(),
253
            'yEnd' => $boundaries->getMaxY(),
254
            'layerId' => $boundaries->getParentId(),
255
            'rgbCodeSetting' => UserSettingEnum::RGB_CODE->value
256
        ])->getResult();
257
    }
258
259
    #[Override]
260
    public function getImpassableBorderData(PanelBoundaries $boundaries, User $user, ResultSetMapping $rsm): array
261
    {
262
        return $this->getEntityManager()->createNativeQuery(
263
            'SELECT DISTINCT 
264
                l.cx AS x, 
265
                l.cy AS y,
266
                CASE 
267
                    WHEN mf.passable = FALSE 
268
                         AND EXISTS (
269
                            SELECT 1 
270
                            FROM stu_database_user du
271
                            JOIN stu_database_entrys de ON du.database_id = de.id
272
                            WHERE du.user_id = :userId
273
                            AND de.id = r.database_id
274
                         ) 
275
                    THEN FALSE
276
                    ELSE TRUE
277
                END AS impassable,
278
                    (SELECT mft.complementary_color FROM stu_map_ftypes mft where mft.id = l.field_id) AS complementary_color
279
            FROM stu_location l
280
            LEFT JOIN stu_map_ftypes mf ON l.field_id = mf.id
281
            LEFT JOIN stu_map m ON l.id = m.id
282
            LEFT JOIN stu_map_regions r ON m.region_id = r.id
283
            WHERE l.cx BETWEEN :xStart AND :xEnd
284
              AND l.cy BETWEEN :yStart AND :yEnd
285
              AND l.layer_id = :layerId',
286
            $rsm
287
        )->setParameters([
288
            'xStart' => $boundaries->getMinX(),
289
            'xEnd' => $boundaries->getMaxX(),
290
            'yStart' => $boundaries->getMinY(),
291
            'yEnd' => $boundaries->getMaxY(),
292
            'layerId' => $boundaries->getParentId(),
293
            'userId' => $user->getId()
294
        ])->getResult();
295
    }
296
297
298
    #[Override]
299
    public function getAnomalyData(PanelBoundaries $boundaries, ResultSetMapping $rsm): array
300
    {
301
        return $this->getEntityManager()->createNativeQuery(
302
            'SELECT l.cx AS x, l.cy AS y,
303
                (SELECT array_to_string(array(SELECT a.anomaly_type_id FROM stu_anomaly a WHERE a.location_id = m.id), \',\')) as anomalytypes
304
            FROM stu_map m
305
            JOIN stu_location l
306
            ON m.id = l.id
307
            WHERE l.cx BETWEEN :xStart AND :xEnd
308
            AND l.cy BETWEEN :yStart AND :yEnd
309
            AND l.layer_id = :layerId',
310
            $rsm
311
        )->setParameters([
312
            'xStart' => $boundaries->getMinX(),
313
            'xEnd' => $boundaries->getMaxX(),
314
            'yStart' => $boundaries->getMinY(),
315
            'yEnd' => $boundaries->getMaxY(),
316
            'layerId' => $boundaries->getParentId(),
317
        ])->getResult();
318
    }
319
320 1
    #[Override]
321
    public function getLssBlockadeLocations(PanelBoundaries $boundaries): array
322
    {
323 1
        $rsm = new ResultSetMapping();
324 1
        $rsm->addScalarResult('cx', 'x', 'integer');
325 1
        $rsm->addScalarResult('cy', 'y', 'integer');
326 1
        $rsm->addScalarResult('effects', 'effects', 'string');
327
328 1
        return $this->getEntityManager()->createNativeQuery(
329 1
            'WITH bbox AS (
330
                SELECT id, field_id, cx, cy
331
                FROM stu_location
332
                WHERE layer_id = :layerId
333
                AND  cx BETWEEN :xStart AND :xEnd
334
                AND  cy BETWEEN :yStart AND :yEnd
335
                and discr = \'map\'
336
            )
337
            SELECT  l.cx, l.cy, mft.effects
338
            FROM bbox l
339
            JOIN stu_map_ftypes mft ON mft.id = l.field_id
340 1
            JOIN stu_map m ON m.id = l.id',
341 1
            $rsm
342 1
        )->setParameters([
343 1
            'xStart' => $boundaries->getMinX(),
344 1
            'xEnd' => $boundaries->getMaxX(),
345 1
            'yStart' => $boundaries->getMinY(),
346 1
            'yEnd' => $boundaries->getMaxY(),
347 1
            'layerId' => $boundaries->getParentId()
348 1
        ])->getResult();
349
    }
350
351 1
    #[Override]
352
    public function getSpacecraftCountLayerData(PanelBoundaries $boundaries, ResultSetMapping $rsm): array
353
    {
354 1
        return $this->getEntityManager()->createNativeQuery(
355 1
            'SELECT l.cx as x, l.cy AS y, mft.effects as effects,
356
                (SELECT count(DISTINCT b.id) FROM stu_spacecraft b
357
                    JOIN stu_location l2
358
                    ON b.location_id = l2.id
359
                    WHERE l2.layer_id = l.layer_id 
360
                    AND l2.cx = l.cx
361
                    AND l2.cy = l.cy
362
                    AND NOT EXISTS (SELECT ss.id
363
                                        FROM stu_spacecraft_system ss
364
                                        WHERE b.id = ss.spacecraft_id
365
                                        AND ss.system_type = :cloakSystemId
366
                                        AND ss.mode > 1)) AS spacecraftcount,
367
                (SELECT count(DISTINCT c.id) FROM stu_spacecraft c
368
                    JOIN stu_location l2
369
                    ON c.location_id = l2.id
370
                    WHERE l2.layer_id = l.layer_id 
371
                    AND l2.cx = l.cx
372
                    AND l2.cy = l.cy
373
                    AND EXISTS (SELECT ss2.id
374
                                        FROM stu_spacecraft_system ss2
375
                                        WHERE c.id = ss2.spacecraft_id
376
                                        AND ss2.system_type = :cloakSystemId
377
                                        AND ss2.mode > 1)) AS cloakcount
378
            FROM stu_map m
379
            JOIN stu_location l
380
            ON m.id = l.id
381
            JOIN stu_map_ftypes mft
382
            ON l.field_id = mft.id
383
            WHERE l.cx BETWEEN :xStart AND :xEnd
384
            AND l.cy BETWEEN :yStart AND :yEnd
385 1
            AND l.layer_id = :layerId',
386 1
            $rsm
387 1
        )->setParameters([
388 1
            'xStart' => $boundaries->getMinX(),
389 1
            'xEnd' => $boundaries->getMaxX(),
390 1
            'yStart' => $boundaries->getMinY(),
391 1
            'yEnd' => $boundaries->getMaxY(),
392 1
            'layerId' => $boundaries->getParentId(),
393 1
            'cloakSystemId' => SpacecraftSystemTypeEnum::CLOAK->value
394 1
        ])->getResult();
395
    }
396
397
398 1
    #[Override]
399
    public function getMapLayerData(PanelBoundaries $boundaries, ResultSetMapping $rsm): array
400
    {
401 1
        return $this->getEntityManager()->createNativeQuery(
402 1
            'SELECT l.cx as x, l.cy AS y, ft.type
403
                FROM stu_map m
404
                JOIN stu_location l
405
                ON m.id = l.id
406
                JOIN stu_map_ftypes ft ON ft.id = l.field_id
407
                WHERE l.cx BETWEEN :xStart AND :xEnd AND l.cy BETWEEN :yStart AND :yEnd
408 1
                AND l.layer_id = :layerId',
409 1
            $rsm
410 1
        )->setParameters([
411 1
            'xStart' => $boundaries->getMinX(),
412 1
            'xEnd' => $boundaries->getMaxX(),
413 1
            'yStart' => $boundaries->getMinY(),
414 1
            'yEnd' => $boundaries->getMaxY(),
415 1
            'layerId' => $boundaries->getParentId(),
416 1
        ])->getResult();
417
    }
418
419
    #[Override]
420
    public function getUserSpacecraftCountLayerData(PanelBoundaries $boundaries, int $userId, ResultSetMapping $rsm): array
421
    {
422
        return $this->getEntityManager()->createNativeQuery(
423
            'SELECT l.cx as x, l.cy as y,
424
            (SELECT count(distinct s.id)
425
                FROM stu_spacecraft s
426
                JOIN stu_location spl
427
                ON s.location_id = spl.id
428
                WHERE spl.cx = l.cx
429
                AND spl.cy = l.cy
430
                AND spl.layer_id = l.layer_id
431
                AND s.user_id = :userId) as spacecraftcount
432
            FROM stu_map m
433
            JOIN stu_location l
434
            ON m.id = l.id
435
            WHERE l.cx BETWEEN :xStart AND :xEnd
436
            AND l.cy BETWEEN :yStart AND :yEnd
437
            AND l.layer_id = :layerId',
438
            $rsm
439
        )->setParameters([
440
            'xStart' => $boundaries->getMinX(),
441
            'xEnd' => $boundaries->getMaxX(),
442
            'yStart' => $boundaries->getMinY(),
443
            'yEnd' => $boundaries->getMaxY(),
444
            'layerId' => $boundaries->getParentId(),
445
            'userId' => $userId
446
        ])->getResult();
447
    }
448
449
    #[Override]
450
    public function getAllianceSpacecraftCountLayerData(PanelBoundaries $boundaries, int $allianceId, ResultSetMapping $rsm): array
451
    {
452
        return $this->getEntityManager()->createNativeQuery(
453
            'SELECT l.cx as x, l.cy as y,
454
             (SELECT count(distinct s.id)
455
                    FROM stu_spacecraft s
456
                    JOIN stu_location spl
457
                    ON s.location_id = spl.id
458
                    JOIN stu_user u
459
                    ON s.user_id = u.id
460
                    WHERE spl.cx = l.cx
461
                    AND spl.cy = l.cy
462
                    AND spl.layer_id = l.layer_id
463
                    AND u.allys_id = :allyId) as spacecraftcount
464
            FROM stu_map m
465
            JOIN stu_location l
466
            ON m.id = l.id
467
            WHERE l.cx BETWEEN :xStart AND :xEnd
468
            AND l.cy BETWEEN :yStart AND :yEnd
469
            AND l.layer_id = :layerId',
470
            $rsm
471
        )->setParameters([
472
            'xStart' => $boundaries->getMinX(),
473
            'xEnd' => $boundaries->getMaxX(),
474
            'yStart' => $boundaries->getMinY(),
475
            'yEnd' => $boundaries->getMaxY(),
476
            'layerId' => $boundaries->getParentId(),
477
            'allyId' => $allianceId
478
        ])->getResult();
479
    }
480
481
    #[Override]
482
    public function getSpacecraftCountLayerDataForSpacecraft(PanelBoundaries $boundaries, int $spacecraftId, ResultSetMapping $rsm): array
483
    {
484
        return $this->getEntityManager()->createNativeQuery(
485
            'SELECT l.cx as x, l.cy as y,
486
            (SELECT count(distinct s.id)
487
                FROM stu_spacecraft s
488
                JOIN stu_location spl
489
                ON s.location_id = spl.id
490
                WHERE spl.cx = l.cx
491
                AND spl.cy = l.cy
492
                AND spl.layer_id = l.layer_id
493
                AND s.id = :spacecraftId) as spacecraftcount
494
            FROM stu_map m
495
            JOIN stu_location l
496
            ON m.id = l.id
497
            WHERE l.cx BETWEEN :xStart AND :xEnd
498
            AND l.cy BETWEEN :yStart AND :yEnd
499
            AND l.layer_id = :layerId',
500
            $rsm
501
        )->setParameters([
502
            'xStart' => $boundaries->getMinX(),
503
            'xEnd' => $boundaries->getMaxX(),
504
            'yStart' => $boundaries->getMinY(),
505
            'yEnd' => $boundaries->getMaxY(),
506
            'layerId' => $boundaries->getParentId(),
507
            'spacecraftId' => $spacecraftId
508
        ])->getResult();
509
    }
510
511 3
    #[Override]
512
    public function getExplored(int $userId, int $layerId, int $startX, int $endX, int $cy): array
513
    {
514 3
        $rsm = new ResultSetMapping();
515 3
        $rsm->addEntityResult(ExploreableStarMap::class, 'm');
516 3
        $rsm->addFieldResult('m', 'id', 'id');
517 3
        $rsm->addFieldResult('m', 'cx', 'cx');
518 3
        $rsm->addFieldResult('m', 'cy', 'cy');
519 3
        $rsm->addFieldResult('m', 'field_id', 'field_id');
520 3
        $rsm->addFieldResult('m', 'bordertype_id', 'bordertype_id');
521 3
        $rsm->addFieldResult('m', 'user_id', 'user_id');
522 3
        $rsm->addFieldResult('m', 'mapped', 'mapped');
523 3
        $rsm->addFieldResult('m', 'system_name', 'system_name');
524 3
        $rsm->addFieldResult('m', 'influence_area_id', 'influence_area_id');
525 3
        $rsm->addFieldResult('m', 'region_id', 'region_id');
526 3
        $rsm->addFieldResult('m', 'tradepost_id', 'tradepost_id');
527 3
        $rsm->addFieldResult('m', 'region_description', 'region_description');
528 3
        $rsm->addFieldResult('m', 'layer_id', 'layer_id');
529
530 3
        return $this->getEntityManager()
531 3
            ->createNativeQuery(
532 3
                'SELECT m.id, l.cx, l.cy, l.field_id, m.systems_id, m.bordertype_id, um.user_id,
533
                    dbu.database_id as mapped, m.influence_area_id as influence_area_id, m.admin_region_id as region_id,
534
                    sys.name as system_name, l.layer_id,
535
                    (SELECT tp.id FROM stu_spacecraft s JOIN stu_trade_posts tp ON s.id = tp.station_id WHERE s.location_id = m.id) as tradepost_id,
536
                    (SELECT mr.description FROM stu_map_regions mr JOIN stu_database_user dbu on dbu.user_id = :userId and mr.database_id = dbu.database_id WHERE m.region_id = mr.id) as region_description
537
                FROM stu_map m
538
                JOIN stu_location l
539
                ON m.id = l.id
540
                LEFT JOIN stu_user_map um
541
                    ON um.cx = l.cx AND um.cy = l.cy AND um.user_id = :userId AND um.layer_id = l.layer_id
542
                LEFT JOIN stu_systems sys
543
                    ON m.systems_id = sys.id
544
                LEFT JOIN stu_database_user dbu
545
                    ON dbu.user_id = :userId
546
                    AND sys.database_id = dbu.database_id
547
                WHERE l.cx BETWEEN :startX AND :endX
548
                AND l.cy = :cy
549
                AND l.layer_id = :layerId
550 3
                ORDER BY l.cx ASC',
551 3
                $rsm
552 3
            )
553 3
            ->setParameters([
554 3
                'layerId' => $layerId,
555 3
                'userId' => $userId,
556 3
                'startX' => $startX,
557 3
                'endX' => $endX,
558 3
                'cy' => $cy
559 3
            ])
560 3
            ->getResult();
561
    }
562
563
    #[Override]
564
    public function getWithEmptySystem(Layer $layer): array
565
    {
566
        return $this->getEntityManager()
567
            ->createQuery(
568
                sprintf(
569
                    'SELECT m from %s m
570
                    JOIN %s l
571
                    WITH m.id = l.id
572
                    WHERE m.system_type_id IS NOT NULL
573
                    AND m.systems_id IS NULL
574
                    AND l.layer = :layer',
575
                    Map::class,
576
                    Location::class
577
                )
578
            )
579
            ->setParameters([
580
                'layer' => $layer
581
            ])
582
            ->getResult();
583
    }
584
585
    #[Override]
586
    public function getRandomMapIdsForAstroMeasurement(int $regionId, int $maxPercentage, int $location): array
587
    {
588
        $rsm = new ResultSetMapping();
589
        $rsm->addScalarResult('id', 'id', 'integer');
590
591
        $mapIdResultSet = $this->getEntityManager()
592
            ->createNativeQuery(
593
                "SELECT m.id
594
                FROM stu_map m
595
                JOIN stu_location l ON m.id = l.id
596
                JOIN stu_map_ftypes mf ON l.field_id = mf.id
597
                WHERE m.region_id = :regionId
598
                AND 
599
                    mf.passable = :true
600
                    AND NOT EXISTS (
601
                        SELECT 1
602
                        FROM jsonb_array_elements_text(mf.effects::jsonb) AS elem
603
                        WHERE elem = 'NO_MEASUREPOINT'
604
                    
605
                )
606
                AND m.id != :loc
607
                ORDER BY RANDOM()",
608
                $rsm
609
            )
610
            ->setParameters([
611
                'regionId' => $regionId,
612
                'loc' => $location,
613
                'true' => true
614
            ])
615
            ->getResult();
616
617
        $amount = (int)ceil(count($mapIdResultSet) * $maxPercentage / 100);
618
        $subset = array_slice($mapIdResultSet, 0, $amount);
619
620
        return array_map(fn(array $data) => $data['id'], $subset);
621
    }
622
623 3
    #[Override]
624
    public function getRandomPassableUnoccupiedWithoutDamage(Layer $layer, bool $isAtBorder = false): Map
625
    {
626 3
        $rsm = new ResultSetMapping();
627 3
        $rsm->addScalarResult('id', 'id', 'integer');
628
629 3
        $borderCriteria = $isAtBorder ?
630 3
            sprintf(
631 3
                'AND (l.cx in (1, %d) OR l.cy in (1, %d))',
632 3
                $layer->getWidth(),
633 3
                $layer->getHeight()
634 3
            ) : '';
635
636 3
        $randomMapId =  (int)$this->getEntityManager()
637 3
            ->createNativeQuery(
638 3
                sprintf(
639 3
                    'SELECT m.id
640
                    FROM stu_map m
641
                    JOIN stu_location l
642
                    ON m.id = l.id
643
                    JOIN stu_map_ftypes mft
644
                    ON l.field_id = mft.id
645
                    WHERE NOT EXISTS (SELECT s.id FROM stu_spacecraft s WHERE s.location_id = m.id)
646
                    AND l.layer_id = :layerId
647
                    AND mft.x_damage = 0
648
                    AND mft.passable = :true
649
                    %s
650
                    ORDER BY RANDOM()
651 3
                    LIMIT 1',
652 3
                    $borderCriteria
653 3
                ),
654 3
                $rsm
655 3
            )
656 3
            ->setParameters([
657 3
                'layerId' => $layer->getId(),
658 3
                'true' => true
659 3
            ])
660 3
            ->getSingleScalarResult();
661
662 3
        $map = $this->find($randomMapId);
663 3
        if ($map === null) {
664
            throw new RuntimeException('this should not happen');
665
        }
666
667 3
        return $map;
668
    }
669
670
    #[Override]
671
    public function getIgnoringSubspaceLayerData(PanelBoundaries $boundaries, int $ignoreUserId, int $time, ResultSetMapping $rsm): array
672
    {
673
        $maxAge = $time - FlightSignatureVisibilityEnum::SIG_VISIBILITY_UNCLOAKED;
674
675
        return $this->getEntityManager()->createNativeQuery(
676
            'SELECT l.cx AS x, l.cy AS y, mft.effects as effects,
677
                (SELECT count(distinct fs1.ship_id) from stu_flight_sig fs1
678
                WHERE fs1.location_id = l.id
679
                AND fs1.user_id != :ignoreUserId
680
                AND (fs1.from_direction = 1 OR fs1.to_direction = 1)
681
                AND fs1.time > :timeThreshold) as d1c,
682
                (SELECT count(distinct fs2.ship_id) from stu_flight_sig fs2
683
                WHERE fs2.location_id = l.id
684
                AND fs2.user_id !=:ignoreUserId
685
                AND (fs2.from_direction = 2 OR fs2.to_direction = 2)
686
                AND fs2.time > :timeThreshold) as d2c,
687
                (SELECT count(distinct fs3.ship_id) from stu_flight_sig fs3
688
                WHERE fs3.location_id = l.id
689
                AND fs3.user_id != :ignoreUserId
690
                AND (fs3.from_direction = 3 OR fs3.to_direction = 3)
691
                AND fs3.time > :timeThreshold) as d3c,
692
                (SELECT count(distinct fs4.ship_id) from stu_flight_sig fs4
693
                WHERE fs4.location_id = l.id
694
                AND fs4.user_id != :ignoreUserId
695
                AND (fs4.from_direction = 4 OR fs4.to_direction = 4)
696
                AND fs4.time > :timeThreshold) as d4c 
697
                FROM stu_location l
698
                JOIN stu_map m
699
                ON l.id = m.id
700
                JOIN stu_map_ftypes mft
701
                ON l.field_id = mft.id
702
                WHERE l.cx BETWEEN :xStart AND :xEnd
703
                AND l.cy BETWEEN :yStart AND :yEnd
704
                AND l.layer_id = :layerId',
705
            $rsm
706
        )->setParameters([
707
            'xStart' => $boundaries->getMinX(),
708
            'xEnd' => $boundaries->getMaxX(),
709
            'yStart' => $boundaries->getMinY(),
710
            'yEnd' => $boundaries->getMaxY(),
711
            'layerId' => $boundaries->getParentId(),
712
            'ignoreUserId' => $ignoreUserId,
713
            'timeThreshold' => $maxAge
714
        ])->getResult();
715
    }
716
717
    #[Override]
718
    public function getSubspaceLayerData(PanelBoundaries $boundaries, ResultSetMapping $rsm): array
719
    {
720
        return $this->getEntityManager()->createNativeQuery(
721
            'SELECT l.cx as x, l.cy as y, mft.effects as effects,
722
            (SELECT count(distinct fs1.ship_id) from stu_flight_sig fs1
723
                WHERE fs1.location_id = l.id
724
                AND (fs1.from_direction = 1 OR fs1.to_direction = 1)) as d1c,
725
            (SELECT count(distinct fs2.ship_id) from stu_flight_sig fs2
726
                WHERE fs2.location_id = l.id
727
                AND (fs2.from_direction = 2 OR fs2.to_direction = 2)) as d2c,
728
            (SELECT count(distinct fs3.ship_id) from stu_flight_sig fs3
729
                WHERE fs3.location_id = l.id
730
                AND (fs3.from_direction = 3 OR fs3.to_direction = 3)) as d3c,
731
            (SELECT count(distinct fs4.ship_id) from stu_flight_sig fs4
732
                WHERE fs4.location_id = l.id
733
                AND (fs4.from_direction = 4 OR fs4.to_direction = 4)) as d4c 
734
            FROM stu_location l
735
            JOIN stu_map_ftypes mft
736
            ON l.field_id = mft.id
737
            WHERE l.cx BETWEEN :xStart AND :xEnd
738
            AND l.cy BETWEEN :yStart AND :yEnd
739
            AND l.layer_id = :layerId',
740
            $rsm
741
        )->setParameters([
742
            'xStart' => $boundaries->getMinX(),
743
            'xEnd' => $boundaries->getMaxX(),
744
            'yStart' => $boundaries->getMinY(),
745
            'yEnd' => $boundaries->getMaxY(),
746
            'layerId' => $boundaries->getParentId()
747
        ])->getResult();
748
    }
749
750
    #[Override]
751
    public function getUserSubspaceLayerData(PanelBoundaries $boundaries, int $userId, ResultSetMapping $rsm): array
752
    {
753
        return $this->getEntityManager()->createNativeQuery(
754
            'SELECT l.cx as x, l.cy as y,
755
            (SELECT count(distinct fs1.ship_id) from stu_flight_sig fs1
756
                WHERE fs1.location_id = l.id
757
                AND fs1.user_id = :userId
758
                AND (fs1.from_direction = 1 OR fs1.to_direction = 1)) as d1c,
759
            (SELECT count(distinct fs2.ship_id) from stu_flight_sig fs2
760
                WHERE fs2.location_id = l.id
761
                AND fs2.user_id = :userId
762
                AND (fs2.from_direction = 2 OR fs2.to_direction = 2)) as d2c,
763
            (SELECT count(distinct fs3.ship_id) from stu_flight_sig fs3
764
                WHERE fs3.location_id = l.id
765
                AND fs3.user_id = :userId
766
                AND (fs3.from_direction = 3 OR fs3.to_direction = 3)) as d3c,
767
            (SELECT count(distinct fs4.ship_id) from stu_flight_sig fs4
768
                WHERE fs4.location_id = l.id
769
                AND fs4.user_id = :userId
770
                AND (fs4.from_direction = 4 OR fs4.to_direction = 4)) as d4c 
771
            FROM stu_location l
772
            WHERE l.cx BETWEEN :xStart AND :xEnd
773
            AND l.cy BETWEEN :yStart AND :yEnd
774
            AND l.layer_id = :layerId',
775
            $rsm
776
        )->setParameters([
777
            'xStart' => $boundaries->getMinX(),
778
            'xEnd' => $boundaries->getMaxX(),
779
            'yStart' => $boundaries->getMinY(),
780
            'yEnd' => $boundaries->getMaxY(),
781
            'layerId' => $boundaries->getParentId(),
782
            'userId' => $userId
783
        ])->getResult();
784
    }
785
    /**
786
     * @return array<int, string>
787
     */
788
    private function getDynamicQueryConditions(bool $cloaked_check, ?int $rumpId): array
789
    {
790
        $conditions = ['', '', '', ''];
791
792
        if ($cloaked_check) {
793
            $conditions[0] = 'AND fs1.is_cloaked = :false';
794
            $conditions[1] = 'AND fs2.is_cloaked = :false';
795
            $conditions[2] = 'AND fs3.is_cloaked = :false';
796
            $conditions[3] = 'AND fs4.is_cloaked = :false';
797
        }
798
799
        if ($rumpId !== null) {
800
            $conditions[0] .= ' AND fs1.rump_id = :rumpId';
801
            $conditions[1] .= ' AND fs2.rump_id = :rumpId';
802
            $conditions[2] .= ' AND fs3.rump_id = :rumpId';
803
            $conditions[3] .= ' AND fs4.rump_id = :rumpId';
804
        }
805
806
        return $conditions;
807
    }
808
    #[Override]
809
    public function getShipSubspaceLayerData(PanelBoundaries $boundaries, int $shipId, int $time, ResultSetMapping $rsm, bool $cloaked_check = false, ?int $rumpId = null): array
810
    {
811
        $maxAge = $time - FlightSignatureVisibilityEnum::SIG_VISIBILITY_UNCLOAKED;
812
        $conditions = $this->getDynamicQueryConditions($cloaked_check, $rumpId);
813
814
        $query = $this->getEntityManager()->createNativeQuery(
815
            'SELECT l.cx as x, l.cy as y,
816
                (SELECT count(distinct fs1.ship_id) from stu_flight_sig fs1
817
                    WHERE fs1.location_id = l.id
818
                    AND fs1.ship_id = :shipId
819
                    AND fs1.time > :timeThreshold
820
                    ' . $conditions[0] . '
821
                    AND (fs1.from_direction = 1 OR fs1.to_direction = 1)) as d1c,
822
                (SELECT count(distinct fs2.ship_id) from stu_flight_sig fs2
823
                    WHERE fs2.location_id = l.id
824
                    AND fs2.ship_id = :shipId
825
                    AND fs2.time > :timeThreshold
826
                    ' . $conditions[1] . '
827
                    AND (fs2.from_direction = 2 OR fs2.to_direction = 2)) as d2c,
828
                (SELECT count(distinct fs3.ship_id) from stu_flight_sig fs3
829
                    WHERE fs3.location_id = l.id
830
                    AND fs3.ship_id = :shipId
831
                    AND fs3.time > :timeThreshold
832
                    ' . $conditions[2] . '
833
                    AND (fs3.from_direction = 3 OR fs3.to_direction = 3)) as d3c,
834
                (SELECT count(distinct fs4.ship_id) from stu_flight_sig fs4
835
                    WHERE fs4.location_id = l.id
836
                    AND fs4.ship_id = :shipId
837
                    AND fs4.time > :timeThreshold
838
                    ' . $conditions[3] . '
839
                    AND (fs4.from_direction = 4 OR fs4.to_direction = 4)) as d4c 
840
                FROM stu_location l
841
                WHERE l.cx BETWEEN :xStart AND :xEnd
842
                AND l.cy BETWEEN :yStart AND :yEnd
843
                AND l.layer_id = :layerId',
844
            $rsm
845
        );
846
847
        $parameters = [
848
            'xStart' => $boundaries->getMinX(),
849
            'xEnd' => $boundaries->getMaxX(),
850
            'yStart' => $boundaries->getMinY(),
851
            'yEnd' => $boundaries->getMaxY(),
852
            'layerId' => $boundaries->getParentId(),
853
            'shipId' => $shipId,
854
            'timeThreshold' => $maxAge,
855
        ];
856
857
        if ($cloaked_check) {
858
            $parameters['false'] = false;
859
        }
860
861
        if ($rumpId !== null) {
862
            $parameters['rumpId'] = $rumpId;
863
        }
864
865
        return $query->setParameters($parameters)->getResult();
866
    }
867
868
    #[Override]
869
    public function getAllianceSubspaceLayerData(PanelBoundaries $boundaries, int $allianceId, ResultSetMapping $rsm): array
870
    {
871
        return $this->getEntityManager()->createNativeQuery(
872
            'SELECT l.id, l.cx as x, l.cy as y,
873
            (SELECT count(distinct fs1.ship_id) from stu_flight_sig fs1
874
                JOIN stu_user u1 ON fs1.user_id = u1.id
875
                WHERE fs1.location_id = l.id
876
                AND u1.allys_id = :allyId
877
                AND (fs1.from_direction = 1 OR fs1.to_direction = 1)) as d1c,
878
            (SELECT count(distinct fs2.ship_id) from stu_flight_sig fs2
879
                JOIN stu_user u2 ON fs2.user_id = u2.id
880
                WHERE fs2.location_id = l.id
881
                AND u2.allys_id = :allyId
882
                AND (fs2.from_direction = 2 OR fs2.to_direction = 2)) as d2c,
883
            (SELECT count(distinct fs3.ship_id) from stu_flight_sig fs3
884
                JOIN stu_user u3 ON fs3.user_id = u3.id
885
                WHERE fs3.location_id = l.id
886
                AND u3.allys_id = :allyId
887
                AND (fs3.from_direction = 3 OR fs3.to_direction = 3)) as d3c,
888
            (SELECT count(distinct fs4.ship_id) from stu_flight_sig fs4
889
                JOIN stu_user u4 ON fs4.user_id = u4.id
890
                WHERE fs4.location_id = l.id
891
                AND u4.allys_id = :allyId
892
                AND (fs4.from_direction = 4 OR fs4.to_direction = 4)) as d4c 
893
            FROM stu_location l
894
            WHERE l.cx BETWEEN :xStart AND :xEnd
895
            AND l.cy BETWEEN :yStart AND :yEnd
896
            AND l.layer_id = :layerId',
897
            $rsm
898
        )->setParameters([
899
            'xStart' => $boundaries->getMinX(),
900
            'xEnd' => $boundaries->getMaxX(),
901
            'yStart' => $boundaries->getMinY(),
902
            'yEnd' => $boundaries->getMaxY(),
903
            'layerId' => $boundaries->getParentId(),
904
            'allyId' => $allianceId
905
        ])->getResult();
906
    }
907
908 1
    public function getUniqueInfluenceAreaIds(int $layerId): array
909
    {
910 1
        $rsm = new ResultSetMapping();
911 1
        $rsm->addScalarResult('influence_area_id', 'influence_area_id', 'integer');
912
913 1
        $query = $this->getEntityManager()->createNativeQuery(
914 1
            'SELECT DISTINCT m.influence_area_id
915
            FROM stu_map m
916
            JOIN stu_location l ON m.id = l.id
917
            WHERE m.influence_area_id IS NOT NULL
918
            AND l.layer_id = :layerId
919 1
            ORDER BY m.influence_area_id ASC',
920 1
            $rsm
921 1
        )->setParameters([
922 1
            'layerId' => $layerId
923 1
        ]);
924
925 1
        return array_map('intval', array_column($query->getResult(), 'influence_area_id'));
926
    }
927
928
    #[Override]
929
    public function isAdminRegionUserRegion(int $locationId, int $factionId): bool
930
    {
931
        $result = $this->getEntityManager()
932
            ->createQuery(
933
                sprintf(
934
                    'SELECT COUNT(mrs.id) FROM %s m
935
            JOIN %s ssm WITH m.systems_id = ssm.systems_id
936
            JOIN %s mrs WITH m.admin_region_id = mrs.region_id
937
            WHERE ssm.id = :locationId
938
            AND mrs.faction_id = :factionId
939
            AND m.admin_region_id IS NOT NULL',
940
                    Map::class,
941
                    StarSystemMap::class,
942
                    MapRegionSettlement::class
943
                )
944
            )
945
            ->setParameters([
946
                'locationId' => $locationId,
947
                'factionId' => $factionId
948
            ])
949
            ->getSingleScalarResult();
950
951
        return $result > 0;
952
    }
953
}
954