Passed
Pull Request — master (#1713)
by Nico
25:36
created

ShipRepository::getByLocationAndUser()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 1
nop 3
dl 0
loc 10
ccs 0
cts 9
cp 0
crap 12
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Orm\Repository;
6
7
use Doctrine\ORM\EntityRepository;
8
use Doctrine\ORM\Query\ResultSetMapping;
9
use Stu\Component\Anomaly\Type\AnomalyTypeEnum;
10
use Stu\Component\Building\BuildingEnum;
11
use Stu\Component\Ship\FlightSignatureVisibilityEnum;
12
use Stu\Component\Ship\ShipAlertStateEnum;
13
use Stu\Component\Ship\ShipRumpEnum;
14
use Stu\Component\Ship\ShipStateEnum;
15
use Stu\Component\Ship\SpacecraftTypeEnum;
16
use Stu\Component\Ship\System\ShipSystemModeEnum;
17
use Stu\Component\Ship\System\ShipSystemTypeEnum;
18
use Stu\Lib\Map\VisualPanel\VisualPanelEntryData;
19
use Stu\Module\PlayerSetting\Lib\UserEnum;
20
use Stu\Module\Ship\Lib\ShipRumpSpecialAbilityEnum;
21
use Stu\Module\Ship\Lib\TFleetShipItem;
22
use Stu\Module\Ship\Lib\TShipItem;
23
use Stu\Orm\Entity\Anomaly;
24
use Stu\Orm\Entity\Crew;
25
use Stu\Orm\Entity\Fleet;
26
use Stu\Orm\Entity\Map;
27
use Stu\Orm\Entity\MapInterface;
28
use Stu\Orm\Entity\Ship;
29
use Stu\Orm\Entity\ShipBuildplan;
30
use Stu\Orm\Entity\ShipCrew;
31
use Stu\Orm\Entity\ShipInterface;
32
use Stu\Orm\Entity\ShipRump;
33
use Stu\Orm\Entity\ShipRumpSpecial;
34
use Stu\Orm\Entity\ShipSystem;
35
use Stu\Orm\Entity\StarSystemInterface;
36
use Stu\Orm\Entity\StarSystemMap;
37
use Stu\Orm\Entity\StarSystemMapInterface;
38
use Stu\Orm\Entity\Storage;
39
use Stu\Orm\Entity\User;
40
use Stu\Orm\Entity\UserInterface;
41
42
/**
43
 * @extends EntityRepository<Ship>
44
 */
45
final class ShipRepository extends EntityRepository implements ShipRepositoryInterface
46
{
47
    public function prototype(): ShipInterface
48
    {
49
        return new Ship();
50
    }
51
52
    public function save(ShipInterface $post): void
53
    {
54
        $em = $this->getEntityManager();
55
56
        $em->persist($post);
57
    }
58
59
    public function delete(ShipInterface $post): void
60
    {
61
        $em = $this->getEntityManager();
62
63
        $em->remove($post);
64
    }
65
66
    public function getAmountByUserAndSpecialAbility(
67
        int $userId,
68
        int $specialAbilityId
69
    ): int {
70
        return (int) $this->getEntityManager()->createQuery(
71
            sprintf(
72
                'SELECT COUNT(s)
73
                FROM %s s
74
                JOIN %s bp
75
                WITH s.plans_id = bp.id
76
                WHERE s.user_id = :userId AND s.rumps_id IN (
77
                    SELECT rs.rumps_id FROM %s rs WHERE rs.special = :specialAbilityId
78
                )
79
                %s',
80
                Ship::class,
81
                ShipBuildplan::class,
82
                ShipRumpSpecial::class,
83
                $specialAbilityId === ShipRumpSpecialAbilityEnum::COLONIZE ? 'AND bp.crew = 0' : ''
84
            )
85
        )->setParameters([
86
            'userId' => $userId,
87
            'specialAbilityId' => $specialAbilityId,
88
        ])->getSingleScalarResult();
89
    }
90
91
    public function getAmountByUserAndRump(int $userId, int $shipRumpId): int
92
    {
93
        return $this->count([
94
            'user_id' => $userId,
95
            'rumps_id' => $shipRumpId,
96
        ]);
97
    }
98
99
    public function getByUser(UserInterface $user): iterable
100
    {
101
        return $this->findBy([
102
            'user_id' => $user,
103
        ]);
104
    }
105
106
    public function getByUserAndRump(int $userId, int $rumpId): array
107
    {
108
        return $this->findBy([
109
            'user_id' => $userId,
110
            'rumps_id' => $rumpId
111
        ], [
112
            'map_id' => 'asc',
113
            'starsystem_map_id' => 'asc',
114
            'fleets_id' => 'asc',
115
            'is_fleet_leader' => 'desc'
116
        ]);
117
    }
118
119
    public function getPossibleFleetMembers(ShipInterface $fleetLeader): iterable
120
    {
121
        $isSystem = $fleetLeader->getSystem() !== null;
122
123
        return $this->getEntityManager()->createQuery(
124
            sprintf(
125
                'SELECT s FROM %s s
126
                WHERE s.%s = :mapId
127
                AND s.fleets_id IS NULL
128
                AND s.user_id = :userId
129
                AND s.type = :type
130
                ORDER BY s.rumps_id ASC, s.name ASC',
131
                Ship::class,
132
                $isSystem ? 'starsystem_map_id' : 'map_id'
133
            )
134
        )->setParameters([
135
            'userId' => $fleetLeader->getUser()->getId(),
136
            'type' => SpacecraftTypeEnum::SPACECRAFT_TYPE_SHIP,
137
            'mapId' => $isSystem ? $fleetLeader->getStarsystemMap()->getId() : $fleetLeader->getMap()->getId()
138
        ])->getResult();
139
    }
140
141
    public function getByLocationAndUser(?StarSystemMapInterface $starSystemMap, ?MapInterface $map, UserInterface $user): array
142
    {
143
        return $this->findBy([
144
            'user_id' => $user->getId(),
145
            'starsystem_map_id' => $starSystemMap !== null ? $starSystemMap->getId() : null,
146
            'map_id' => $map !== null ? $map->getId() : null
147
        ], [
148
            'fleets_id' => 'desc',
149
            'is_fleet_leader' => 'desc',
150
            'id' => 'desc'
151
        ]);
152
    }
153
154
    public function getByLocation(
155
        ?StarSystemMapInterface $starSystemMap,
156
        ?MapInterface $map
157
    ): array {
158
        return $this->getEntityManager()
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->getEntityM...K->value))->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
159
            ->createQuery(
160
                sprintf(
161
                    'SELECT s FROM %s s
162
                    LEFT JOIN %s f
163
                    WITH s.fleets_id = f.id
164
                    JOIN %s r
165
                    WITH s.rumps_id = r.id
166
                    WHERE s.%s = :mapId
167
                    AND NOT EXISTS (SELECT ss.id
168
                                        FROM %s ss
169
                                        WHERE s.id = ss.ship_id
170
                                        AND ss.system_type = :systemId
171
                                        AND ss.mode > 1)
172
                    ORDER BY s.is_destroyed ASC, f.sort DESC, f.id DESC, s.is_fleet_leader DESC,
173
                    r.category_id ASC, r.role_id ASC, r.id ASC, s.name ASC',
174
                    Ship::class,
175
                    Fleet::class,
176
                    ShipRump::class,
177
                    $starSystemMap === null ? 'map_id' : 'starsystem_map_id',
178
                    ShipSystem::class
179
                )
180
            )
181
            ->setParameters([
182
                'mapId' => $starSystemMap === null ? $map->getId() : $starSystemMap->getId(),
0 ignored issues
show
Bug introduced by
The method getId() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

182
                'mapId' => $starSystemMap === null ? $map->/** @scrutinizer ignore-call */ getId() : $starSystemMap->getId(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
183
                'systemId' => ShipSystemTypeEnum::SYSTEM_CLOAK->value
184
            ])
185
            ->getResult();
186
    }
187
188
    public function getForeignStationsInBroadcastRange(ShipInterface $ship): array
189
    {
190
        $systemMap = $ship->getStarsystemMap();
191
        $map = $ship->getMap();
192
193
        return $this->getEntityManager()
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->getEntityM...>getCy()))->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
194
            ->createQuery(
195
                sprintf(
196
                    'SELECT s FROM %s s
197
                     LEFT JOIN %s m
198
                     WITH s.map_id = m.id
199
                     LEFT JOIN %s sm
200
                     WITH s.starsystem_map_id = sm.id
201
                     WHERE s.user_id NOT IN (:ignoreIds)
202
                     AND s.type = :spacecraftType
203
                     AND (:cx = 0 OR (m.cx BETWEEN (:cx - 1) AND (:cx + 1)
204
                        AND m.cy BETWEEN (:cy - 1) AND (:cy + 1)))
205
                     AND (:systemId = 0 OR (sm.systems_id = :systemId
206
                        AND sm.sx BETWEEN (:sx - 1) AND (:sx + 1)
207
                        AND sm.sy BETWEEN (:sy - 1) AND (:sy + 1)))',
208
                    Ship::class,
209
                    Map::class,
210
                    StarSystemMap::class
211
                )
212
            )
213
            ->setParameters([
214
                'ignoreIds' => [$ship->getUser()->getId(), UserEnum::USER_NOONE],
215
                'spacecraftType' => SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION,
216
                'systemId' => $systemMap === null ? 0 : $systemMap->getSystem()->getId(),
217
                'sx' => $systemMap === null ? 0 : $systemMap->getSx(),
218
                'sy' => $systemMap === null ? 0 : $systemMap->getSy(),
219
                'cx' => $map === null ? 0 : $map->getCx(),
220
                'cy' => $map === null ? 0 : $map->getCy()
221
            ])
222
            ->getResult();
223
    }
224
225
    public function getShipsForAlertRed(
226
        ShipInterface $ship
227
    ): iterable {
228
        $isSystem = $ship->getSystem() !== null;
229
230
        return $this->getEntityManager()->createQuery(
231
            sprintf(
232
                'SELECT s FROM %s s
233
                JOIN %s u
234
                WITH s.user_id = u.id
235
                WHERE s.alvl = :alertRed
236
                AND s.user_id != :ignoreId
237
                AND s.%s = :mapId
238
                AND NOT EXISTS (SELECT ss.id
239
                                FROM %s ss
240
                                WHERE s.id = ss.ship_id
241
                                AND ss.system_type = :cloakSystemId
242
                                AND ss.mode > 1)
243
                AND NOT EXISTS (SELECT ss2.id
244
                                FROM %s ss2
245
                                WHERE s.id = ss2.ship_id
246
                                AND ss2.system_type = :warpSystemId
247
                                AND ss2.mode > 1)
248
                AND (u.vac_active = false OR u.vac_request_date > :vacationThreshold)',
249
                Ship::class,
250
                User::class,
251
                $isSystem ? 'starsystem_map_id' : 'map_id',
252
                ShipSystem::class,
253
                ShipSystem::class
254
            )
255
        )->setParameters([
256
            'alertRed' => ShipAlertStateEnum::ALERT_RED,
257
            'mapId' => $isSystem ? $ship->getStarsystemMap()->getId() : $ship->getMap()->getId(),
258
            'ignoreId' => $ship->getUser()->getId(),
259
            'cloakSystemId' => ShipSystemTypeEnum::SYSTEM_CLOAK->value,
260
            'warpSystemId' => ShipSystemTypeEnum::SYSTEM_WARPDRIVE->value,
261
            'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS
262
        ])->getResult();
263
    }
264
265
    public function getTradePostsWithoutDatabaseEntry(): iterable
266
    {
267
        return $this->getEntityManager()->createQuery(
268
            sprintf(
269
                'SELECT s FROM %s s WHERE s.database_id is null AND s.trade_post_id > 0',
270
                Ship::class
271
            )
272
        )->getResult();
273
    }
274
275
    public function getByUserAndFleetAndType(int $userId, ?int $fleetId, int $type): array
276
    {
277
        return $this->findBy(
278
            [
279
                'user_id' => $userId,
280
                'fleets_id' => $fleetId,
281
                'type' => $type,
282
            ],
283
            $type === SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION ? ['max_huelle' => 'desc', 'id' => 'asc'] : ['id' => 'asc']
284
        );
285
    }
286
287
    public function getByUplink(int $userId): array
288
    {
289
        return $this->getEntityManager()->createQuery(
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->getEntityM..._SECONDS))->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
290
            sprintf(
291
                'SELECT s FROM %s s
292
                JOIN %s sc
293
                WITH s.id = sc.ship_id
294
                JOIN %s c
295
                WITH sc.crew_id = c.id
296
                JOIN %s ss
297
                WITH ss.ship_id = s.id
298
                JOIN %s u
299
                WITH s.user_id = u.id
300
                WHERE s.user_id != :userId
301
                AND c.user_id = :userId
302
                AND ss.system_type = :systemType
303
                AND ss.mode >= :mode
304
                AND (u.vac_active = false OR u.vac_request_date > :vacationThreshold)',
305
                Ship::class,
306
                ShipCrew::class,
307
                Crew::class,
308
                ShipSystem::class,
309
                User::class
310
            )
311
        )->setParameters([
312
            'userId' => $userId,
313
            'systemType' => ShipSystemTypeEnum::SYSTEM_UPLINK->value,
314
            'mode' => ShipSystemModeEnum::MODE_ON,
315
            'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS
316
        ])
317
            ->getResult();
318
    }
319
320
    public function getWithTradeLicensePayment(
321
        int $userId,
322
        int $tradePostShipId,
323
        int $commodityId,
324
        int $amount
325
    ): iterable {
326
        return $this->getEntityManager()->createQuery(
327
            sprintf(
328
                'SELECT s FROM %s s WHERE s.user_id = :userId AND s.dock = :tradePostShipId AND s.id IN (
329
                    SELECT st.ship_id FROM %s st WHERE st.commodity_id = :commodityId AND st.count >= :amount
330
                )',
331
                Ship::class,
332
                Storage::class
333
            )
334
        )->setParameters([
335
            'userId' => $userId,
336
            'tradePostShipId' => $tradePostShipId,
337
            'commodityId' => $commodityId,
338
            'amount' => $amount,
339
        ])->getResult();
340
    }
341
342
    public function getSuitableForShildRegeneration(int $regenerationThreshold): iterable
343
    {
344
        return $this->getEntityManager()->createQuery(
345
            sprintf(
346
                'SELECT s FROM %s s
347
                JOIN %s ss
348
                WITH s.id = ss.ship_id
349
                JOIN %s bp
350
                WITH s.plans_id = bp.id
351
                WHERE ss.system_type = :shieldType
352
                AND ss.mode < :modeOn
353
                AND s.is_destroyed = :destroyedState
354
                AND s.schilde<s.max_schilde
355
                AND s.shield_regeneration_timer <= :regenerationThreshold
356
                AND (SELECT count(sc.id) FROM %s sc WHERE s.id = sc.ship_id) >= bp.crew
357
                AND NOT EXISTS (SELECT a FROM %s a WHERE (a.map_id = s.map_id or a.starsystem_map_id = s.starsystem_map_id) AND a.anomaly_type_id = :anomalyType AND a.remaining_ticks > 0)',
358
                Ship::class,
359
                ShipSystem::class,
360
                ShipBuildplan::class,
361
                ShipCrew::class,
362
                Anomaly::class
363
            )
364
        )->setParameters([
365
            'shieldType' => ShipSystemTypeEnum::SYSTEM_SHIELDS->value,
366
            'modeOn' => ShipSystemModeEnum::MODE_ON,
367
            'regenerationThreshold' => $regenerationThreshold,
368
            'destroyedState' => 0,
369
            'anomalyType' => AnomalyTypeEnum::SUBSPACE_ELLIPSE
370
        ])->getResult();
371
    }
372
373
    public function getEscapePods(): iterable
374
    {
375
        return $this->getEntityManager()->createQuery(
376
            sprintf(
377
                'SELECT s FROM %s s
378
                LEFT JOIN %s sr
379
                WITH s.rumps_id = sr.id
380
                WHERE sr.category_id = :categoryId',
381
                Ship::class,
382
                ShipRump::class
383
            )
384
        )->setParameters([
385
            'categoryId' => ShipRumpEnum::SHIP_CATEGORY_ESCAPE_PODS
386
        ])->getResult();
387
    }
388
389
    public function getEscapePodsByCrewOwner(int $userId): iterable
390
    {
391
        return $this->getEntityManager()->createQuery(
392
            sprintf(
393
                'SELECT s FROM %s s
394
                LEFT JOIN %s sr
395
                WITH s.rumps_id = sr.id
396
                LEFT JOIN %s sc
397
                WITH sc.ship_id = s.id
398
                WHERE sr.category_id = :categoryId
399
                AND sc.user_id = :userId',
400
                Ship::class,
401
                ShipRump::class,
402
                ShipCrew::class
403
            )
404
        )->setParameters([
405
            'categoryId' => ShipRumpEnum::SHIP_CATEGORY_ESCAPE_PODS,
406
            'userId' => $userId
407
        ])->getResult();
408
    }
409
410
    public function getDebrisFields(): iterable
411
    {
412
        return $this->findBy([
413
            'is_destroyed' => true,
414
        ]);
415
    }
416
417
    public function getStationConstructions(): iterable
418
    {
419
        return $this->getEntityManager()->createQuery(
420
            sprintf(
421
                'SELECT s FROM %s s
422
                JOIN %s r
423
                WITH s.rumps_id = r.id
424
                WHERE s.user_id > :firstUserId
425
                AND r.category_id = :catId',
426
                Ship::class,
427
                ShipRump::class
428
            )
429
        )->setParameters([
430
            'catId' => ShipRumpEnum::SHIP_CATEGORY_CONSTRUCTION,
431
            'firstUserId' => UserEnum::USER_FIRST_ID
432
        ])
433
            ->getResult();
434
    }
435
436
    public function getPlayerShipsForTick(): iterable
437
    {
438
        return $this->getEntityManager()->createQuery(
439
            sprintf(
440
                'SELECT s
441
                FROM %s s
442
                JOIN %s p
443
                WITH s.plans_id = p.id
444
                JOIN %s u
445
                WITH s.user_id = u.id
446
                WHERE s.user_id > :firstUserId
447
                AND (   ((SELECT count(sc.id)
448
                        FROM %s sc
449
                        WHERE sc.ship_id = s.id) > 0)
450
                    OR
451
                        (s.state IN (:scrapping, :underConstruction))
452
                    OR
453
                        (p.crew = 0))
454
                AND (u.vac_active = false OR u.vac_request_date > :vacationThreshold)',
455
                Ship::class,
456
                ShipBuildplan::class,
457
                User::class,
458
                ShipCrew::class
459
            )
460
        )->setParameters([
461
            'underConstruction' => ShipStateEnum::SHIP_STATE_UNDER_CONSTRUCTION,
462
            'scrapping' => ShipStateEnum::SHIP_STATE_UNDER_SCRAPPING,
463
            'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS,
464
            'firstUserId' => UserEnum::USER_FIRST_ID
465
        ])->toIterable();
466
    }
467
468
    public function getNpcShipsForTick(): iterable
469
    {
470
        return $this->getEntityManager()->createQuery(
471
            sprintf(
472
                'SELECT s FROM %s s WHERE s.user_id BETWEEN 2 AND (:firstUserId - 1)',
473
                Ship::class
474
            )
475
        )->setParameter('firstUserId', UserEnum::USER_FIRST_ID)->getResult();
476
    }
477
478
    private const FLIGHT_SIGNATURE_STAR_COUNT =
479
    ',(select count(distinct fs1.ship_id) from stu_flight_sig fs1
480
    where fs1.starsystem_map_id = a.id
481
    AND fs1.user_id != %1$d
482
    AND (fs1.from_direction = 1 OR fs1.to_direction = 1)
483
    AND fs1.time > %2$d) as d1c,
484
    (select count(distinct fs2.ship_id) from stu_flight_sig fs2
485
    where fs2.starsystem_map_id = a.id
486
    AND fs2.user_id != %1$d
487
    AND (fs2.from_direction = 2 OR fs2.to_direction = 2)
488
    AND fs2.time > %2$d) as d2c,
489
    (select count(distinct fs3.ship_id) from stu_flight_sig fs3
490
    where fs3.starsystem_map_id = a.id
491
    AND fs3.user_id != %1$d
492
    AND (fs3.from_direction = 3 OR fs3.to_direction = 3)
493
    AND fs3.time > %2$d) as d3c,
494
    (select count(distinct fs4.ship_id) from stu_flight_sig fs4
495
    where fs4.starsystem_map_id = a.id
496
    AND fs4.user_id != %1$d
497
    AND (fs4.from_direction = 4 OR fs4.to_direction = 4)
498
    AND fs4.time > %2$d) as d4c ';
499
500
    public function getSensorResultInnerSystem(
501
        ShipInterface $ship,
502
        int $ignoreId,
503
        StarSystemInterface $system = null
504
    ): array {
505
        $doSubspace = $ship->getSubspaceState();
506
        $map = $ship->getStarsystemMap();
507
        $sensorRange = $ship->getSensorRange();
508
509
        $rsm = new ResultSetMapping();
510
        $rsm->addEntityResult(VisualPanelEntryData::class, 'd');
511
        $rsm->addFieldResult('d', 'posx', 'posx');
512
        $rsm->addFieldResult('d', 'posy', 'posy');
513
        $rsm->addFieldResult('d', 'shipcount', 'shipcount');
514
        $rsm->addFieldResult('d', 'cloakcount', 'cloakcount');
515
        $rsm->addFieldResult('d', 'type', 'type');
516
        $rsm->addFieldResult('d', 'shieldstate', 'shieldstate');
517
        $rsm->addFieldResult('d', 'sysid', 'sysid');
518
519
        if ($doSubspace) {
520
            $rsm->addFieldResult('d', 'd1c', 'd1c');
521
            $rsm->addFieldResult('d', 'd2c', 'd2c');
522
            $rsm->addFieldResult('d', 'd3c', 'd3c');
523
            $rsm->addFieldResult('d', 'd4c', 'd4c');
524
525
            $maxAge = time() - FlightSignatureVisibilityEnum::SIG_VISIBILITY_UNCLOAKED;
526
        }
527
528
        return $this->getEntityManager()->createNativeQuery(
529
            sprintf(
530
                'SELECT a.id, a.sx as posx, a.sy AS posy, a.systems_id AS sysid, d.type,
531
                (SELECT count(DISTINCT b.id) FROM stu_ships b
532
                    WHERE a.id = b.starsystem_map_id
533
                    AND NOT EXISTS (SELECT ss.id
534
                                        FROM stu_ship_system ss
535
                                        WHERE b.id = ss.ship_id
536
                                        AND ss.system_type = :systemId
537
                                        AND ss.mode > 1)) AS shipcount,
538
                (SELECT count(DISTINCT c.id) FROM stu_ships c
539
                    WHERE a.id = c.starsystem_map_id
540
                    AND EXISTS (SELECT ss2.id
541
                                        FROM stu_ship_system ss2
542
                                        WHERE c.id = ss2.ship_id
543
                                        AND ss2.system_type = :systemId
544
                                        AND ss2.mode > 1)) AS cloakcount,
545
                (SELECT COUNT(cfd) > 0
546
                    FROM stu_colonies col
547
                    JOIN stu_colonies_fielddata cfd
548
                    ON col.id = cfd.colonies_id
549
                    WHERE a.id = col.starsystem_map_id
550
                    AND cfd.aktiv = :active
551
                    AND cfd.buildings_id IN (
552
                        SELECT bf.buildings_id
553
                        FROM stu_buildings_functions bf
554
                        WHERE bf.function = :shieldBuilding)) AS shieldstate
555
                %s
556
                FROM stu_sys_map a
557
                LEFT JOIN stu_map_ftypes d ON d.id = a.field_id
558
                WHERE a.systems_id = :starSystemId AND a.sx BETWEEN :sxStart AND :sxEnd AND a.sy BETWEEN :syStart AND :syEnd
559
                GROUP BY a.sy, a.sx, a.id, d.type ORDER BY a.sy,a.sx',
560
                $doSubspace ? sprintf(self::FLIGHT_SIGNATURE_STAR_COUNT, $ignoreId, $maxAge) : ''
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $maxAge does not seem to be defined for all execution paths leading up to this point.
Loading history...
561
            ),
562
            $rsm
563
        )->setParameters([
564
            'starSystemId' => $system !== null ? $system->getId() : $ship->getStarsystemMap()->getSystem()->getId(),
565
            'sxStart' => $system !== null ? 1 : $map->getSx() - $sensorRange,
566
            'sxEnd' => $system !== null ? $system->getMaxX() : $map->getSx() + $sensorRange,
567
            'syStart' => $system !== null ? 1 : $map->getSy() - $sensorRange,
568
            'syEnd' => $system !== null ? $system->getMaxY() : $map->getSy() + $sensorRange,
569
            'systemId' => ShipSystemTypeEnum::SYSTEM_CLOAK->value,
570
            'active' => 1,
571
            'shieldBuilding' => BuildingEnum::BUILDING_FUNCTION_SHIELD_GENERATOR
572
        ])->getResult();
573
    }
574
575
    private const FLIGHT_SIGNATURE_MAP_COUNT =
576
    ',(select count(distinct fs1.ship_id) from stu_flight_sig fs1
577
    where fs1.map_id = a.id
578
    AND fs1.user_id != %1$d
579
    AND (fs1.from_direction = 1 OR fs1.to_direction = 1)
580
    AND fs1.time > %2$d) as d1c,
581
    (select count(distinct fs2.ship_id) from stu_flight_sig fs2
582
    where fs2.map_id = a.id
583
    AND fs2.user_id != %1$d
584
    AND (fs2.from_direction = 2 OR fs2.to_direction = 2)
585
    AND fs2.time > %2$d) as d2c,
586
    (select count(distinct fs3.ship_id) from stu_flight_sig fs3
587
    where fs3.map_id = a.id
588
    AND fs3.user_id != %1$d
589
    AND (fs3.from_direction = 3 OR fs3.to_direction = 3)
590
    AND fs3.time > %2$d) as d3c,
591
    (select count(distinct fs4.ship_id) from stu_flight_sig fs4
592
    where fs4.map_id = a.id
593
    AND fs4.user_id != %1$d
594
    AND (fs4.from_direction = 4 OR fs4.to_direction = 4)
595
    AND fs4.time > %2$d) as d4c ';
596
597
    public function getSensorResultOuterSystem(int $cx, int $cy, int $layerId, int $sensorRange, bool $doSubspace, int $ignoreId): array
598
    {
599
        $rsm = new ResultSetMapping();
600
        $rsm->addEntityResult(VisualPanelEntryData::class, 'd');
601
        $rsm->addFieldResult('d', 'posx', 'posx');
602
        $rsm->addFieldResult('d', 'posy', 'posy');
603
        $rsm->addFieldResult('d', 'shipcount', 'shipcount');
604
        $rsm->addFieldResult('d', 'cloakcount', 'cloakcount');
605
        $rsm->addFieldResult('d', 'type', 'type');
606
        $rsm->addFieldResult('d', 'allycolor', 'allycolor');
607
        $rsm->addFieldResult('d', 'usercolor', 'usercolor');
608
        $rsm->addFieldResult('d', 'factioncolor', 'factioncolor');
609
610
        if ($doSubspace) {
611
            $rsm->addFieldResult('d', 'd1c', 'd1c');
612
            $rsm->addFieldResult('d', 'd2c', 'd2c');
613
            $rsm->addFieldResult('d', 'd3c', 'd3c');
614
            $rsm->addFieldResult('d', 'd4c', 'd4c');
615
616
            $maxAge = time() - FlightSignatureVisibilityEnum::SIG_VISIBILITY_UNCLOAKED;
617
        }
618
619
        //TODO increase performance of allycolor/usercolor/factioncolor calculation
620
        return $this->getEntityManager()->createNativeQuery(
621
            sprintf(
622
                'SELECT a.id, a.cx AS posx,a.cy AS posy, d.type,
623
                (SELECT count(DISTINCT b.id) FROM stu_ships b
624
                    WHERE b.cx = a.cx AND b.cy = a.cy AND b.layer_id = a.layer_id
625
                    AND NOT EXISTS (SELECT ss.id
626
                                        FROM stu_ship_system ss
627
                                        WHERE b.id = ss.ship_id
628
                                        AND ss.system_type = :systemId
629
                                        AND ss.mode > 1)) AS shipcount,
630
                (SELECT count(DISTINCT c.id) FROM stu_ships c
631
                    WHERE c.map_id = a.id
632
                    AND EXISTS (SELECT ss2.id
633
                                        FROM stu_ship_system ss2
634
                                        WHERE c.id = ss2.ship_id
635
                                        AND ss2.system_type = :systemId
636
                                        AND ss2.mode > 1)) AS cloakcount,
637
				(SELECT al.rgb_code FROM stu_alliances al
638
					JOIN stu_user u ON al.id = u.allys_id
639
						JOIN stu_ships s ON u.id = s.user_id
640
							JOIN stu_map m ON m.influence_area_id = s.influence_area_id
641
							WHERE m.id = a.id AND m.bordertype_id IS NULL AND m.admin_region_id IS NULL)
642
							AS allycolor,
643
				(SELECT u.rgb_code FROM stu_user u
644
					JOIN stu_ships s ON u.id = s.user_id
645
						JOIN stu_map m ON m.influence_area_id = s.influence_area_id
646
						WHERE m.id = a.id AND m.bordertype_id IS NULL AND m.admin_region_id IS NULL)
647
						as usercolor,
648
				(SELECT mb.color FROM stu_map_bordertypes mb
649
					JOIN stu_map m ON m.bordertype_id = mb.id
650
						WHERE m.id = a.id AND m.bordertype_id IS NOT NULL)
651
						AS factioncolor
652
                %s
653
                FROM stu_map a
654
                LEFT JOIN stu_map_ftypes d ON d.id = a.field_id
655
                WHERE a.cx BETWEEN :sxStart AND :sxEnd
656
                AND a.cy BETWEEN :syStart AND :syEnd
657
                AND a.layer_id = :layerId
658
                GROUP BY a.cy, a.cx, a.id, d.type, a.field_id ORDER BY a.cy, a.cx',
659
                $doSubspace ? sprintf(self::FLIGHT_SIGNATURE_MAP_COUNT, $ignoreId, $maxAge) : ''
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $maxAge does not seem to be defined for all execution paths leading up to this point.
Loading history...
660
            ),
661
            $rsm
662
        )->setParameters([
663
            'sxStart' => $cx - $sensorRange,
664
            'sxEnd' => $cx + $sensorRange,
665
            'syStart' => $cy - $sensorRange,
666
            'syEnd' => $cy + $sensorRange,
667
            'layerId' => $layerId,
668
            'systemId' => ShipSystemTypeEnum::SYSTEM_CLOAK->value
669
        ])->getResult();
670
    }
671
672
    private const ADMIN_SIGNATURE_MAP_COUNT =
673
    ',(select count(distinct fs1.ship_id) from stu_flight_sig fs1
674
    where fs1.map_id = a.id
675
    AND (fs1.from_direction = 1 OR fs1.to_direction = 1)) as d1c,
676
    (select count(distinct fs2.ship_id) from stu_flight_sig fs2
677
    where fs2.map_id = a.id
678
    AND (fs2.from_direction = 2 OR fs2.to_direction = 2)) as d2c,
679
    (select count(distinct fs3.ship_id) from stu_flight_sig fs3
680
    where fs3.map_id = a.id
681
    AND (fs3.from_direction = 3 OR fs3.to_direction = 3)) as d3c,
682
    (select count(distinct fs4.ship_id) from stu_flight_sig fs4
683
    where fs4.map_id = a.id
684
    AND (fs4.from_direction = 4 OR fs4.to_direction = 4)) as d4c ';
685
686
    public function getSignaturesOuterSystem(int $minx, int $maxx, int $miny, int $maxy, int $layerId): array
687
    {
688
        $rsm = new ResultSetMapping();
689
690
        $rsm->addEntityResult(VisualPanelEntryData::class, 'd');
691
        $rsm->addFieldResult('d', 'posx', 'posx');
692
        $rsm->addFieldResult('d', 'posy', 'posy');
693
        $rsm->addFieldResult('d', 'shipcount', 'shipcount');
694
        $rsm->addFieldResult('d', 'type', 'type');
695
696
        $rsm->addFieldResult('d', 'd1c', 'd1c');
697
        $rsm->addFieldResult('d', 'd2c', 'd2c');
698
        $rsm->addFieldResult('d', 'd3c', 'd3c');
699
        $rsm->addFieldResult('d', 'd4c', 'd4c');
700
701
        return $this->getEntityManager()->createNativeQuery(
702
            sprintf(
703
                'SELECT a.id, a.cx as posx,a.cy as posy, d.type,
704
                    (SELECT count(distinct b.id)
705
                        FROM stu_ships b
706
                        WHERE b.cx = a.cx AND b.cy = a.cy AND b.layer_id = a.layer_id) as shipcount
707
                %s
708
                FROM stu_map a
709
                LEFT JOIN stu_map_ftypes d ON d.id = a.field_id
710
                WHERE a.cx BETWEEN :sxStart AND :sxEnd
711
                AND a.cy BETWEEN :syStart AND :syEnd
712
                AND a.layer_id = :layerId
713
                GROUP BY a.cy, a.cx, a.id, d.type, a.field_id ORDER BY a.cy, a.cx',
714
                self::ADMIN_SIGNATURE_MAP_COUNT
715
            ),
716
            $rsm
717
        )->setParameters([
718
            'sxStart' => $minx,
719
            'sxEnd' => $maxx,
720
            'syStart' => $miny,
721
            'syEnd' => $maxy,
722
            'layerId' => $layerId
723
        ])->getResult();
724
    }
725
726
    private const ADMIN_SIGNATURE_MAP_COUNT_USER =
727
    ',(select count(distinct fs1.ship_id) from stu_flight_sig fs1
728
    where fs1.map_id = a.id
729
    AND fs1.user_id = %1$d
730
    AND (fs1.from_direction = 1 OR fs1.to_direction = 1)
731
    AND fs1.time > %2$d) as d1c,
732
    (select count(distinct fs2.ship_id) from stu_flight_sig fs2
733
    where fs2.map_id = a.id
734
    AND fs2.user_id = %1$d
735
    AND (fs2.from_direction = 2 OR fs2.to_direction = 2)
736
    AND fs2.time > %2$d) as d2c,
737
    (select count(distinct fs3.ship_id) from stu_flight_sig fs3
738
    where fs3.map_id = a.id
739
    AND fs3.user_id = %1$d
740
    AND (fs3.from_direction = 3 OR fs3.to_direction = 3)
741
    AND fs3.time > %2$d) as d3c,
742
    (select count(distinct fs4.ship_id) from stu_flight_sig fs4
743
    where fs4.map_id = a.id
744
    AND fs4.user_id = %1$d
745
    AND (fs4.from_direction = 4 OR fs4.to_direction = 4)
746
    AND fs4.time > %2$d) as d4c ';
747
748
    public function getSignaturesOuterSystemOfUser(int $minx, int $maxx, int $miny, int $maxy, int $layerId, int $userId): array
749
    {
750
        $rsm = new ResultSetMapping();
751
752
        $rsm->addEntityResult(VisualPanelEntryData::class, 'd');
753
        $rsm->addFieldResult('d', 'posx', 'posx');
754
        $rsm->addFieldResult('d', 'posy', 'posy');
755
        $rsm->addFieldResult('d', 'shipcount', 'shipcount');
756
        $rsm->addFieldResult('d', 'type', 'type');
757
758
        $rsm->addFieldResult('d', 'd1c', 'd1c');
759
        $rsm->addFieldResult('d', 'd2c', 'd2c');
760
        $rsm->addFieldResult('d', 'd3c', 'd3c');
761
        $rsm->addFieldResult('d', 'd4c', 'd4c');
762
763
        return $this->getEntityManager()->createNativeQuery(
764
            sprintf(
765
                'SELECT a.id, a.cx as posx,a.cy as posy, d.type,
766
                    (SELECT count(distinct b.id)
767
                        FROM stu_ships b
768
                        WHERE b.cx = a.cx AND b.cy = a.cy AND b.layer_id = a.layer_id
769
                        AND b.user_id = :userId) as shipcount
770
                %s
771
                FROM stu_map a
772
                LEFT JOIN stu_map_ftypes d ON d.id = a.field_id
773
                WHERE a.cx BETWEEN :sxStart AND :sxEnd
774
                AND a.cy BETWEEN :syStart AND :syEnd
775
                AND a.layer_id = :layerId
776
                GROUP BY a.cy, a.cx, a.id, d.type, a.field_id ORDER BY a.cy, a.cx',
777
                sprintf(self::ADMIN_SIGNATURE_MAP_COUNT_USER, $userId, 0)
778
            ),
779
            $rsm
780
        )->setParameters([
781
            'sxStart' => $minx,
782
            'sxEnd' => $maxx,
783
            'syStart' => $miny,
784
            'syEnd' => $maxy,
785
            'layerId' => $layerId,
786
            'userId' => $userId
787
        ])->getResult();
788
    }
789
790
    private const ADMIN_SIGNATURE_MAP_COUNT_ALLY =
791
    ',(select count(distinct fs1.ship_id) from stu_flight_sig fs1
792
    JOIN stu_user u1 ON fs1.user_id = u1.id
793
    WHERE fs1.map_id = a.id
794
    AND u1.allys_id = %1$d
795
    AND (fs1.from_direction = 1 OR fs1.to_direction = 1)
796
    AND fs1.time > %2$d) as d1c,
797
    (select count(distinct fs2.ship_id) from stu_flight_sig fs2
798
    JOIN stu_user u2 ON fs2.user_id = u2.id
799
    WHERE fs2.map_id = a.id
800
    AND u2.allys_id = %1$d
801
    AND (fs2.from_direction = 2 OR fs2.to_direction = 2)
802
    AND fs2.time > %2$d) as d2c,
803
    (select count(distinct fs3.ship_id) from stu_flight_sig fs3
804
    JOIN stu_user u3 ON fs3.user_id = u3.id
805
    WHERE fs3.map_id = a.id
806
    AND u3.allys_id = %1$d
807
    AND (fs3.from_direction = 3 OR fs3.to_direction = 3)
808
    AND fs3.time > %2$d) as d3c,
809
    (select count(distinct fs4.ship_id) from stu_flight_sig fs4
810
    JOIN stu_user u4 ON fs4.user_id = u4.id
811
    WHERE fs4.map_id = a.id
812
    AND u4.allys_id = %1$d
813
    AND (fs4.from_direction = 4 OR fs4.to_direction = 4)
814
    AND fs4.time > %2$d) as d4c ';
815
816
    public function getSignaturesOuterSystemOfAlly(int $minx, int $maxx, int $miny, int $maxy, int $layerId, int $allyId): array
817
    {
818
        $rsm = new ResultSetMapping();
819
        $rsm->addEntityResult(VisualPanelEntryData::class, 'd');
820
        $rsm->addFieldResult('d', 'posx', 'posx');
821
        $rsm->addFieldResult('d', 'posy', 'posy');
822
        $rsm->addFieldResult('d', 'shipcount', 'shipcount');
823
        $rsm->addFieldResult('d', 'type', 'type');
824
825
        $rsm->addFieldResult('d', 'd1c', 'd1c');
826
        $rsm->addFieldResult('d', 'd2c', 'd2c');
827
        $rsm->addFieldResult('d', 'd3c', 'd3c');
828
        $rsm->addFieldResult('d', 'd4c', 'd4c');
829
830
        return $this->getEntityManager()->createNativeQuery(
831
            sprintf(
832
                'SELECT a.id, a.cx as posx,a.cy as posy, d.type,
833
                    (SELECT count(distinct b.id)
834
                        FROM stu_ships b
835
                        JOIN stu_user u ON b.user_id = u.id
836
                        WHERE b.cx = a.cx AND b.cy = a.cy AND b.layer_id = a.layer_id
837
                        AND u.allys_id = :allyId) as shipcount
838
                %s
839
                FROM stu_map a
840
                LEFT JOIN stu_map_ftypes d ON d.id = a.field_id
841
                WHERE a.cx BETWEEN :sxStart AND :sxEnd
842
                AND a.cy BETWEEN :syStart AND :syEnd
843
                AND a.layer_id = :layerId
844
                GROUP BY a.cy, a.cx, a.id, d.type, a.field_id ORDER BY a.cy, a.cx',
845
                sprintf(self::ADMIN_SIGNATURE_MAP_COUNT_ALLY, $allyId, 0)
846
            ),
847
            $rsm
848
        )->setParameters([
849
            'sxStart' => $minx,
850
            'sxEnd' => $maxx,
851
            'syStart' => $miny,
852
            'syEnd' => $maxy,
853
            'layerId' => $layerId,
854
            'allyId' => $allyId
855
        ])->getResult();
856
    }
857
858
    public function getFleetShipsScannerResults(
859
        ShipInterface $ship,
860
        bool $showCloaked = false,
861
        int $mapId = null,
862
        int $sysMapId = null
863
    ): array {
864
        $isSystem = $sysMapId !== null || ($mapId === null && $ship->getSystem() !== null);
865
866
        $rsm = new ResultSetMapping();
867
        $rsm->addEntityResult(TFleetShipItem::class, 's');
868
        $rsm->addFieldResult('s', 'fleetname', 'fleet_name');
869
        $rsm->addFieldResult('s', 'isdefending', 'is_defending');
870
        $rsm->addFieldResult('s', 'isblocking', 'is_blocking');
871
        $this->addTShipItemFields($rsm);
872
873
        return $this->getEntityManager()->createNativeQuery(
874
            sprintf(
875
                'SELECT f.id as fleetid, f.name as fleetname, f.defended_colony_id is not null as isdefending,
876
                    f.blocked_colony_id is not null as isblocking, s.id as shipid, s.rumps_id as rumpid, s.former_rumps_id as formerrumpid,
877
                    ss.mode as warpstate, COALESCE(ss2.mode,0) as cloakstate, ss3.mode as shieldstate, COALESCE(ss4.status,0) as uplinkstate, s.is_destroyed as isdestroyed,
878
                    s.type as spacecrafttype, s.name as shipname, s.huelle as hull, s.max_huelle as maxhull, s.schilde as shield, s.holding_web_id as webid, tw.finished_time as webfinishtime,
879
                    u.id as userid, u.username, r.category_id as rumpcategoryid, r.name as rumpname, r.role_id as rumproleid,
880
                    (SELECT count(*) > 0 FROM stu_ship_log sl WHERE sl.ship_id = s.id AND sl.is_private = false) as haslogbook,
881
                    (SELECT count(*) > 0 FROM stu_crew_assign ca WHERE ca.ship_id = s.id) as hascrew
882
                FROM stu_ships s
883
                LEFT JOIN stu_ship_system ss
884
                ON s.id = ss.ship_id
885
                AND ss.system_type = :warpdriveType
886
                LEFT JOIN stu_ship_system ss2
887
                ON s.id = ss2.ship_id
888
                AND ss2.system_type = :cloakType
889
                LEFT JOIN stu_ship_system ss3
890
                ON s.id = ss3.ship_id
891
                AND ss3.system_type = :shieldType
892
                LEFT JOIN stu_ship_system ss4
893
                ON s.id = ss4.ship_id
894
                AND ss4.system_type = :uplinkType
895
                JOIN stu_rumps r
896
                ON s.rumps_id = r.id
897
                JOIN stu_fleets f
898
                ON s.fleets_id = f.id
899
                LEFT OUTER JOIN stu_tholian_web tw
900
                ON s.holding_web_id = tw.id
901
                JOIN stu_user u
902
                ON s.user_id = u.id
903
                WHERE s.%s = :fieldId
904
                AND s.id != :ignoreId
905
                %s
906
                ORDER BY f.sort DESC, f.id DESC, (CASE WHEN s.is_fleet_leader THEN 0 ELSE 1 END), r.category_id ASC, r.role_id ASC, r.id ASC, s.name ASC',
907
                $isSystem ? 'starsystem_map_id' : 'map_id',
908
                $showCloaked ? '' : sprintf(' AND (s.user_id = %d OR COALESCE(ss2.mode,0) < %d) ', $ship->getUser()->getId(), ShipSystemModeEnum::MODE_ON)
909
            ),
910
            $rsm
911
        )->setParameters([
912
            'fieldId' => $mapId ?? $sysMapId ?? ($isSystem ? $ship->getStarsystemMap()->getId() : $ship->getMap()->getId()),
913
            'ignoreId' => $ship->getId(),
914
            'cloakType' => ShipSystemTypeEnum::SYSTEM_CLOAK->value,
915
            'warpdriveType' => ShipSystemTypeEnum::SYSTEM_WARPDRIVE->value,
916
            'shieldType' => ShipSystemTypeEnum::SYSTEM_SHIELDS->value,
917
            'uplinkType' => ShipSystemTypeEnum::SYSTEM_UPLINK->value
918
        ])->getResult();
919
    }
920
921
    public function getSingleShipScannerResults(
922
        ShipInterface $ship,
923
        array $types,
924
        bool $showCloaked = false,
925
        int $mapId = null,
926
        int $sysMapId = null
927
    ): array {
928
        $isSystem = $sysMapId !== null || ($mapId === null && $ship->getSystem() !== null);
929
930
        $rsm = new ResultSetMapping();
931
        $rsm->addEntityResult(TShipItem::class, 's');
932
        $this->addTShipItemFields($rsm);
933
934
        return $this->getEntityManager()->createNativeQuery(
935
            sprintf(
936
                'SELECT s.id as shipid, s.fleets_id as fleetid, s.rumps_id as rumpid , s.former_rumps_id as formerrumpid, ss.mode as warpstate, COALESCE(ss2.mode,0) as cloakstate,
937
                    ss3.mode as shieldstate, COALESCE(ss4.status,0) as uplinkstate, s.is_destroyed as isdestroyed, s.type as spacecrafttype, s.name as shipname,
938
                    s.huelle as hull, s.max_huelle as maxhull, s.schilde as shield, s.holding_web_id as webid, tw.finished_time as webfinishtime, u.id as userid, u.username,
939
                    r.category_id as rumpcategoryid, r.name as rumpname, r.role_id as rumproleid,
940
                    (SELECT count(*) > 0 FROM stu_ship_log sl WHERE sl.ship_id = s.id AND sl.is_private = false) as haslogbook,
941
                    (SELECT count(*) > 0 FROM stu_crew_assign ca WHERE ca.ship_id = s.id) as hascrew
942
                FROM stu_ships s
943
                LEFT JOIN stu_ship_system ss
944
                ON s.id = ss.ship_id
945
                AND ss.system_type = :warpdriveType
946
                LEFT JOIN stu_ship_system ss2
947
                ON s.id = ss2.ship_id
948
                AND ss2.system_type = :cloakType
949
                LEFT JOIN stu_ship_system ss3
950
                ON s.id = ss3.ship_id
951
                AND ss3.system_type = :shieldType
952
                LEFT JOIN stu_ship_system ss4
953
                ON s.id = ss4.ship_id
954
                AND ss4.system_type = :uplinkType
955
                JOIN stu_rumps r
956
                ON s.rumps_id = r.id
957
                LEFT OUTER JOIN stu_tholian_web tw
958
                ON s.holding_web_id = tw.id
959
                JOIN stu_user u
960
                ON s.user_id = u.id
961
                WHERE s.%s = :fieldId
962
                AND s.id != :ignoreId
963
                AND s.fleets_id IS NULL
964
                AND s.type IN (:types)
965
                %s
966
                ORDER BY r.category_id ASC, r.role_id ASC, r.id ASC, s.name ASC',
967
                $isSystem ? 'starsystem_map_id' : 'map_id',
968
                $showCloaked ? '' : sprintf(' AND (s.user_id = %d OR COALESCE(ss2.mode,0) < %d) ', $ship->getUser()->getId(), ShipSystemModeEnum::MODE_ON)
969
            ),
970
            $rsm
971
        )->setParameters([
972
            'fieldId' => $mapId ?? $sysMapId ?? ($isSystem ? $ship->getStarsystemMap()->getId() : $ship->getMap()->getId()),
973
            'ignoreId' => $ship->getId(),
974
            'types' => $types,
975
            'cloakType' => ShipSystemTypeEnum::SYSTEM_CLOAK->value,
976
            'warpdriveType' => ShipSystemTypeEnum::SYSTEM_WARPDRIVE->value,
977
            'shieldType' => ShipSystemTypeEnum::SYSTEM_SHIELDS->value,
978
            'uplinkType' => ShipSystemTypeEnum::SYSTEM_UPLINK->value
979
        ])->getResult();
980
    }
981
982
    private function addTShipItemFields(ResultSetMapping $rsm): void
983
    {
984
        $rsm->addFieldResult('s', 'shipid', 'ship_id');
985
        $rsm->addFieldResult('s', 'fleetid', 'fleet_id');
986
        $rsm->addFieldResult('s', 'rumpid', 'rump_id');
987
        $rsm->addFieldResult('s', 'formerrumpid', 'former_rump_id');
988
        $rsm->addFieldResult('s', 'warpstate', 'warp_state');
989
        $rsm->addFieldResult('s', 'cloakstate', 'cloak_state');
990
        $rsm->addFieldResult('s', 'shieldstate', 'shield_state');
991
        $rsm->addFieldResult('s', 'uplinkstate', 'uplink_state');
992
        $rsm->addFieldResult('s', 'isdestroyed', 'is_destroyed');
993
        $rsm->addFieldResult('s', 'spacecrafttype', 'spacecraft_type');
994
        $rsm->addFieldResult('s', 'shipname', 'ship_name');
995
        $rsm->addFieldResult('s', 'hull', 'hull');
996
        $rsm->addFieldResult('s', 'maxhull', 'max_hull');
997
        $rsm->addFieldResult('s', 'shield', 'shield');
998
        $rsm->addFieldResult('s', 'webid', 'web_id');
999
        $rsm->addFieldResult('s', 'webfinishtime', 'web_finish_time');
1000
        $rsm->addFieldResult('s', 'userid', 'user_id');
1001
        $rsm->addFieldResult('s', 'username', 'user_name');
1002
        $rsm->addFieldResult('s', 'rumpcategoryid', 'rump_category_id');
1003
        $rsm->addFieldResult('s', 'rumpname', 'rump_name');
1004
        $rsm->addFieldResult('s', 'rumproleid', 'rump_role_id');
1005
        $rsm->addFieldResult('s', 'haslogbook', 'has_logbook');
1006
        $rsm->addFieldResult('s', 'hascrew', 'has_crew');
1007
    }
1008
1009
    public function isCloakedShipAtShipLocation(
1010
        ShipInterface $ship
1011
    ): bool {
1012
        return $this->isCloakedShipAtLocation(
1013
            $ship->getStarsystemMap()->getId(),
1014
            $ship->getMap()->getId(),
1015
            $ship->getUser()->getId()
1016
        );
1017
    }
1018
1019
    public function isCloakedShipAtLocation(
1020
        ?int $sysMapId,
1021
        ?int $mapId,
1022
        int $ignoreId
1023
    ): bool {
1024
        $cloakSql = sprintf(
1025
            ' AND EXISTS (SELECT ss.id
1026
                            FROM %s ss
1027
                            WHERE s.id = ss.ship_id
1028
                            AND ss.system_type = %d
1029
                            AND ss.mode > 1) ',
1030
            ShipSystem::class,
1031
            ShipSystemTypeEnum::SYSTEM_CLOAK->value
1032
        );
1033
1034
        $result = $this->getEntityManager()->createQuery(
1035
            sprintf(
1036
                'SELECT COUNT(s.id) FROM %s s
1037
                    WHERE s.%s = :fieldId
1038
                    %s
1039
                    AND s.user_id != :ignoreId',
1040
                Ship::class,
1041
                $sysMapId !== null ? 'starsystem_map_id' : 'map_id',
1042
                $cloakSql
1043
            )
1044
        )->setParameters([
1045
            'fieldId' => $mapId ?? $sysMapId,
1046
            'ignoreId' => $ignoreId
1047
        ])->getSingleScalarResult();
1048
1049
        return $result > 0;
1050
    }
1051
1052
    public function getRandomShipIdWithCrewByUser(int $userId): ?int
1053
    {
1054
        $rsm = new ResultSetMapping();
1055
        $rsm->addScalarResult('id', 'id', 'integer');
1056
1057
        $result = $this->getEntityManager()
1058
            ->createNativeQuery(
1059
                'SELECT s.id as id FROM stu_ships s
1060
                WHERE s.user_id = :userId
1061
                AND EXISTS (SELECT sc.id
1062
                            FROM stu_crew_assign sc
1063
                            WHERE s.id = sc.ship_id)
1064
                ORDER BY RANDOM()
1065
                LIMIT 1',
1066
                $rsm
1067
            )
1068
            ->setParameters([
1069
                'userId' => $userId
1070
            ])
1071
            ->getOneOrNullResult();
1072
1073
        return $result != null ? $result['id'] : null;
1074
    }
1075
1076
    public function isBaseOnLocation(ShipInterface $ship): bool
1077
    {
1078
        $isSystem = $ship->getSystem() !== null;
1079
1080
        $query = $this->getEntityManager()->createQuery(
1081
            sprintf(
1082
                'SELECT COUNT(s.id) FROM %s s
1083
                WHERE s.%s = :mapId
1084
                AND s.type = :type',
1085
                Ship::class,
1086
                $isSystem ? 'starsystem_map_id' : 'map_id',
1087
            )
1088
        )->setParameters([
1089
            'mapId' => $isSystem ? $ship->getStarsystemMap()->getId() : $ship->getMap()->getId(),
1090
            'type' => SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION
1091
        ]);
1092
1093
        return $query->getSingleScalarResult() > 0;
1094
    }
1095
1096
    public function getStationsByUser(int $userId): array
1097
    {
1098
        return $this->getEntityManager()
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->getEntityM..._STATION))->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
1099
            ->createQuery(
1100
                sprintf(
1101
                    'SELECT s
1102
                    FROM %s s
1103
                    JOIN %s r
1104
                    WITH s.rumps_id = r.id
1105
                    WHERE s.user_id = :userId
1106
                    AND r.category_id = :categoryId',
1107
                    Ship::class,
1108
                    ShipRump::class
1109
                )
1110
            )
1111
            ->setParameters([
1112
                'userId' => $userId,
1113
                'categoryId' => ShipRumpEnum::SHIP_CATEGORY_STATION
1114
            ])
1115
            ->getResult();
1116
    }
1117
1118
    public function getAllDockedShips(): array
1119
    {
1120
        return $this->getEntityManager()->createQuery(
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->getEntityM...p::class))->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
1121
            sprintf(
1122
                'SELECT s FROM %s s
1123
                WHERE s.dock IS NOT NULL',
1124
                Ship::class
1125
            )
1126
        )->getResult();
1127
    }
1128
1129
    public function getAllTractoringShips(): array
1130
    {
1131
        return $this->getEntityManager()->createQuery(
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->getEntityM...p::class))->getResult() could return the type integer which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
1132
            sprintf(
1133
                'SELECT s FROM %s s
1134
                WHERE s.tractored_ship_id IS NOT NULL',
1135
                Ship::class
1136
            )
1137
        )->getResult();
1138
    }
1139
1140
    public function truncateAllShips(): void
1141
    {
1142
        $this->getEntityManager()->createQuery(
1143
            sprintf(
1144
                'DELETE FROM %s s',
1145
                Ship::class
1146
            )
1147
        )->execute();
1148
    }
1149
}
1150