Passed
Pull Request — dev (#2303)
by Janko
05:56
created

MapRepository::getShipSubspaceLayerData()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 72
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 55
c 2
b 0
f 0
nc 4
nop 6
dl 0
loc 72
ccs 0
cts 34
cp 0
crap 12
rs 8.9818

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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