MapRepository::getShipSubspaceLayerData()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 52
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 3
eloc 24
c 2
b 0
f 0
nc 4
nop 5
dl 0
loc 52
ccs 0
cts 24
cp 0
crap 12
rs 9.536

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