Passed
Push — master ( 1d5530...fba2a1 )
by Nico
56:37 queued 25:57
created

ShipRepository::addTShipItemFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 24
nc 1
nop 1
dl 0
loc 26
ccs 0
cts 25
cp 0
crap 2
rs 9.536
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Orm\Repository;
6
7
use Doctrine\ORM\EntityRepository;
8
use Doctrine\ORM\Query\ResultSetMapping;
9
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Stu\Component\Anomaly\Type\AnomalyTypeEnum;
11
use Stu\Component\Game\TimeConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Game\TimeConstants was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Stu\Component\Ship\ShipAlertStateEnum;
13
use Stu\Component\Ship\ShipRumpEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\ShipRumpEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Stu\Component\Ship\ShipStateEnum;
15
use Stu\Component\Ship\SpacecraftTypeEnum;
16
use Stu\Component\Ship\System\ShipSystemModeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Ship\System\ShipSystemModeEnum 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...
17
use Stu\Component\Ship\System\ShipSystemTypeEnum;
18
use Stu\Module\PlayerSetting\Lib\UserEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\PlayerSetting\Lib\UserEnum was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
use Stu\Module\Ship\Lib\ShipRumpSpecialAbilityEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Ship\Lib\ShipRumpSpecialAbilityEnum 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...
20
use Stu\Module\Ship\Lib\TFleetShipItem;
21
use Stu\Module\Ship\Lib\TShipItem;
22
use Stu\Orm\Entity\Anomaly;
23
use Stu\Orm\Entity\Crew;
24
use Stu\Orm\Entity\Fleet;
25
use Stu\Orm\Entity\Location;
26
use Stu\Orm\Entity\LocationInterface;
27
use Stu\Orm\Entity\Map;
28
use Stu\Orm\Entity\MapInterface;
29
use Stu\Orm\Entity\PirateWrath;
30
use Stu\Orm\Entity\Ship;
31
use Stu\Orm\Entity\ShipBuildplan;
32
use Stu\Orm\Entity\ShipCrew;
33
use Stu\Orm\Entity\ShipInterface;
34
use Stu\Orm\Entity\ShipRump;
35
use Stu\Orm\Entity\ShipRumpSpecial;
36
use Stu\Orm\Entity\ShipSystem;
37
use Stu\Orm\Entity\StarSystemMap;
38
use Stu\Orm\Entity\StarSystemMapInterface;
39
use Stu\Orm\Entity\Storage;
40
use Stu\Orm\Entity\User;
41
use Stu\Orm\Entity\UserInterface;
42
43
/**
44
 * @extends EntityRepository<Ship>
45
 */
46
final class ShipRepository extends EntityRepository implements ShipRepositoryInterface
47
{
48
    #[Override]
49
    public function prototype(): ShipInterface
50
    {
51
        return new Ship();
52
    }
53
54
    #[Override]
55
    public function save(ShipInterface $post): void
56
    {
57
        $em = $this->getEntityManager();
58
59
        $em->persist($post);
60
    }
61
62
    #[Override]
63
    public function delete(ShipInterface $post): void
64
    {
65
        $em = $this->getEntityManager();
66
67
        $em->remove($post);
68
    }
69
70
    #[Override]
71
    public function getAmountByUserAndSpecialAbility(
72
        int $userId,
73
        int $specialAbilityId
74
    ): int {
75
        return (int) $this->getEntityManager()->createQuery(
76
            sprintf(
77
                'SELECT COUNT(s)
78
                FROM %s s
79
                JOIN %s bp
80
                WITH s.plans_id = bp.id
81
                WHERE s.user_id = :userId AND s.rumps_id IN (
82
                    SELECT rs.rumps_id FROM %s rs WHERE rs.special = :specialAbilityId
83
                )
84
                %s',
85
                Ship::class,
86
                ShipBuildplan::class,
87
                ShipRumpSpecial::class,
88
                $specialAbilityId === ShipRumpSpecialAbilityEnum::COLONIZE ? 'AND bp.crew = 0' : ''
89
            )
90
        )->setParameters([
91
            'userId' => $userId,
92
            'specialAbilityId' => $specialAbilityId,
93
        ])->getSingleScalarResult();
94
    }
95
96
    #[Override]
97
    public function getAmountByUserAndRump(int $userId, int $shipRumpId): int
98
    {
99
        return $this->count([
100
            'user_id' => $userId,
101
            'rumps_id' => $shipRumpId,
102
        ]);
103
    }
104
105
    #[Override]
106
    public function getByUser(UserInterface $user): iterable
107
    {
108
        return $this->findBy([
109
            'user_id' => $user,
110
        ]);
111
    }
112
113
    #[Override]
114
    public function getByUserAndRump(int $userId, int $rumpId): array
115
    {
116
        return $this->findBy([
117
            'user_id' => $userId,
118
            'rumps_id' => $rumpId
119
        ], [
120
            'location_id' => 'asc',
121
            'fleets_id' => 'asc',
122
            'is_fleet_leader' => 'desc'
123
        ]);
124
    }
125
126
    #[Override]
127
    public function getPossibleFleetMembers(ShipInterface $fleetLeader): iterable
128
    {
129
        return $this->getEntityManager()->createQuery(
130
            sprintf(
131
                'SELECT s FROM %s s
132
                WHERE s.location = :location
133
                AND s.fleets_id IS NULL
134
                AND s.user_id = :userId
135
                AND s.type = :type
136
                ORDER BY s.rumps_id ASC, s.name ASC',
137
                Ship::class
138
            )
139
        )->setParameters([
140
            'userId' => $fleetLeader->getUser()->getId(),
141
            'type' => SpacecraftTypeEnum::SPACECRAFT_TYPE_SHIP->value,
142
            'location' => $fleetLeader->getLocation(),
143
        ])->getResult();
144
    }
145
146
    #[Override]
147
    public function getByLocationAndUser(LocationInterface $location, UserInterface $user): array
148
    {
149
        return $this->findBy([
150
            'type' => SpacecraftTypeEnum::SPACECRAFT_TYPE_SHIP,
151
            'user' => $user,
152
            'location' => $location,
153
        ], [
154
            'fleets_id' => 'desc',
155
            'is_fleet_leader' => 'desc',
156
            'id' => 'desc'
157
        ]);
158
    }
159
160
    #[Override]
161
    public function getByLocation(LocationInterface $location): array
162
    {
163
        return $this->getEntityManager()
164
            ->createQuery(
165
                sprintf(
166
                    'SELECT s FROM %s s
167
                    LEFT JOIN %s f
168
                    WITH s.fleets_id = f.id
169
                    JOIN %s r
170
                    WITH s.rumps_id = r.id
171
                    WHERE s.location = :location
172
                    AND NOT EXISTS (SELECT ss.id
173
                                        FROM %s ss
174
                                        WHERE s.id = ss.ship_id
175
                                        AND ss.system_type = :systemId
176
                                        AND ss.mode > 1)
177
                    ORDER BY s.is_destroyed ASC, f.sort DESC, f.id DESC, s.is_fleet_leader DESC,
178
                    r.category_id ASC, r.role_id ASC, r.id ASC, s.name ASC',
179
                    Ship::class,
180
                    Fleet::class,
181
                    ShipRump::class,
182
                    ShipSystem::class
183
                )
184
            )
185
            ->setParameters([
186
                'location' => $location,
187
                'systemId' => ShipSystemTypeEnum::SYSTEM_CLOAK->value
188
            ])
189
            ->getResult();
190
    }
191
192
    #[Override]
193
    public function getForeignStationsInBroadcastRange(ShipInterface $ship): array
194
    {
195
        $layer = $ship->getLayer();
196
        $systemMap = $ship->getStarsystemMap();
197
        $map = $ship->getMap();
198
199
        return $this->getEntityManager()
200
            ->createQuery(
201
                sprintf(
202
                    'SELECT s FROM %s s
203
                     LEFT JOIN %s m
204
                     WITH s.location_id = m.id
205
                     LEFT JOIN %s l
206
                     WITH m.id = l.id
207
                     LEFT JOIN %s sm
208
                     WITH s.location_id = sm.id
209
                     WHERE s.user_id NOT IN (:ignoreIds)
210
                     AND s.type = :spacecraftType
211
                     AND (:layerId = 0 OR (l.layer_id = :layerId
212
                        AND l.cx BETWEEN (:cx - 1) AND (:cx + 1)
213
                        AND l.cy BETWEEN (:cy - 1) AND (:cy + 1)))
214
                     AND (:systemId = 0 OR (sm.systems_id = :systemId
215
                        AND sm.sx BETWEEN (:sx - 1) AND (:sx + 1)
216
                        AND sm.sy BETWEEN (:sy - 1) AND (:sy + 1)))',
217
                    Ship::class,
218
                    Map::class,
219
                    Location::class,
220
                    StarSystemMap::class
221
                )
222
            )
223
            ->setParameters([
224
                'ignoreIds' => [$ship->getUser()->getId(), UserEnum::USER_NOONE],
225
                'spacecraftType' => SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION->value,
226
                'systemId' => $systemMap === null ? 0 : $systemMap->getSystem()->getId(),
227
                'sx' => $systemMap === null ? 0 : $systemMap->getSx(),
228
                'sy' => $systemMap === null ? 0 : $systemMap->getSy(),
229
                'layerId' => ($systemMap !== null || $layer === null) ? 0 : $layer->getId(),
230
                'cx' => ($systemMap !== null || $map === null) ? 0 : $map->getCx(),
231
                'cy' => ($systemMap !== null || $map === null) ? 0 : $map->getCy()
232
            ])
233
            ->getResult();
234
    }
235
236
    #[Override]
237
    public function getTradePostsWithoutDatabaseEntry(): iterable
238
    {
239
        return $this->getEntityManager()->createQuery(
240
            sprintf(
241
                'SELECT s FROM %s s WHERE s.database_id is null AND s.trade_post_id > 0',
242
                Ship::class
243
            )
244
        )->getResult();
245
    }
246
247
    #[Override]
248
    public function getByUserAndFleetAndType(int $userId, ?int $fleetId, SpacecraftTypeEnum $type): array
249
    {
250
        return $this->findBy(
251
            [
252
                'user_id' => $userId,
253
                'fleets_id' => $fleetId,
254
                'type' => $type->value,
255
            ],
256
            $type === SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION ? ['max_huelle' => 'desc', 'id' => 'asc'] : ['id' => 'asc']
257
        );
258
    }
259
260
    #[Override]
261
    public function getByUplink(int $userId): array
262
    {
263
        return $this->getEntityManager()->createQuery(
264
            sprintf(
265
                'SELECT s FROM %s s
266
                JOIN %s sc
267
                WITH s.id = sc.ship_id
268
                JOIN %s c
269
                WITH sc.crew_id = c.id
270
                JOIN %s ss
271
                WITH ss.ship_id = s.id
272
                JOIN %s u
273
                WITH s.user_id = u.id
274
                WHERE s.user_id != :userId
275
                AND c.user_id = :userId
276
                AND ss.system_type = :systemType
277
                AND ss.mode >= :mode
278
                AND (u.vac_active = false OR u.vac_request_date > :vacationThreshold)',
279
                Ship::class,
280
                ShipCrew::class,
281
                Crew::class,
282
                ShipSystem::class,
283
                User::class
284
            )
285
        )->setParameters([
286
            'userId' => $userId,
287
            'systemType' => ShipSystemTypeEnum::SYSTEM_UPLINK->value,
288
            'mode' => ShipSystemModeEnum::MODE_ON,
289
            'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS
290
        ])
291
            ->getResult();
292
    }
293
294
    #[Override]
295
    public function getWithTradeLicensePayment(
296
        int $userId,
297
        int $tradePostShipId,
298
        int $commodityId,
299
        int $amount
300
    ): iterable {
301
        return $this->getEntityManager()->createQuery(
302
            sprintf(
303
                'SELECT s FROM %s s WHERE s.user_id = :userId AND s.dock = :tradePostShipId AND s.id IN (
304
                    SELECT st.ship_id FROM %s st WHERE st.commodity_id = :commodityId AND st.count >= :amount
305
                )',
306
                Ship::class,
307
                Storage::class
308
            )
309
        )->setParameters([
310
            'userId' => $userId,
311
            'tradePostShipId' => $tradePostShipId,
312
            'commodityId' => $commodityId,
313
            'amount' => $amount,
314
        ])->getResult();
315
    }
316
317
    #[Override]
318
    public function getSuitableForShildRegeneration(int $regenerationThreshold): iterable
319
    {
320
        return $this->getEntityManager()->createQuery(
321
            sprintf(
322
                'SELECT s FROM %s s
323
                JOIN %s ss
324
                WITH s.id = ss.ship_id
325
                JOIN %s bp
326
                WITH s.plans_id = bp.id
327
                WHERE ss.system_type = :shieldType
328
                AND ss.mode < :modeOn
329
                AND s.is_destroyed = :destroyedState
330
                AND s.schilde<s.max_schilde
331
                AND s.shield_regeneration_timer <= :regenerationThreshold
332
                AND (SELECT count(sc.id) FROM %s sc WHERE s.id = sc.ship_id) >= bp.crew
333
                AND NOT EXISTS (SELECT a FROM %s a
334
                                WHERE a.location_id = s.location_id
335
                                AND a.anomaly_type_id = :anomalyType
336
                                AND a.remaining_ticks > 0)',
337
                Ship::class,
338
                ShipSystem::class,
339
                ShipBuildplan::class,
340
                ShipCrew::class,
341
                Anomaly::class
342
            )
343
        )->setParameters([
344
            'shieldType' => ShipSystemTypeEnum::SYSTEM_SHIELDS->value,
345
            'modeOn' => ShipSystemModeEnum::MODE_ON,
346
            'regenerationThreshold' => $regenerationThreshold,
347
            'destroyedState' => 0,
348
            'anomalyType' => AnomalyTypeEnum::SUBSPACE_ELLIPSE
349
        ])->getResult();
350
    }
351
352
    #[Override]
353
    public function getEscapePods(): iterable
354
    {
355
        return $this->getEntityManager()->createQuery(
356
            sprintf(
357
                'SELECT s FROM %s s
358
                LEFT JOIN %s sr
359
                WITH s.rumps_id = sr.id
360
                WHERE sr.category_id = :categoryId',
361
                Ship::class,
362
                ShipRump::class
363
            )
364
        )->setParameters([
365
            'categoryId' => ShipRumpEnum::SHIP_CATEGORY_ESCAPE_PODS
366
        ])->getResult();
367
    }
368
369
    #[Override]
370
    public function getEscapePodsByCrewOwner(int $userId): iterable
371
    {
372
        return $this->getEntityManager()->createQuery(
373
            sprintf(
374
                'SELECT s FROM %s s
375
                LEFT JOIN %s sr
376
                WITH s.rumps_id = sr.id
377
                LEFT JOIN %s sc
378
                WITH sc.ship_id = s.id
379
                WHERE sr.category_id = :categoryId
380
                AND sc.user_id = :userId',
381
                Ship::class,
382
                ShipRump::class,
383
                ShipCrew::class
384
            )
385
        )->setParameters([
386
            'categoryId' => ShipRumpEnum::SHIP_CATEGORY_ESCAPE_PODS,
387
            'userId' => $userId
388
        ])->getResult();
389
    }
390
391
    #[Override]
392
    public function getDebrisFields(): iterable
393
    {
394
        return $this->findBy([
395
            'is_destroyed' => true,
396
        ]);
397
    }
398
399
    #[Override]
400
    public function getStationConstructions(): iterable
401
    {
402
        return $this->getEntityManager()->createQuery(
403
            sprintf(
404
                'SELECT s FROM %s s
405
                JOIN %s r
406
                WITH s.rumps_id = r.id
407
                WHERE s.user_id > :firstUserId
408
                AND r.category_id = :catId',
409
                Ship::class,
410
                ShipRump::class
411
            )
412
        )->setParameters([
413
            'catId' => ShipRumpEnum::SHIP_CATEGORY_CONSTRUCTION,
414
            'firstUserId' => UserEnum::USER_FIRST_ID
415
        ])
416
            ->getResult();
417
    }
418
419
    #[Override]
420
    public function getPlayerShipsForTick(): iterable
421
    {
422
        return $this->getEntityManager()->createQuery(
423
            sprintf(
424
                'SELECT s
425
                FROM %s s
426
                JOIN %s p
427
                WITH s.plans_id = p.id
428
                JOIN %s u
429
                WITH s.user_id = u.id
430
                WHERE s.user_id > :firstUserId
431
                AND (   ((SELECT count(sc.id)
432
                        FROM %s sc
433
                        WHERE sc.ship_id = s.id) > 0)
434
                    OR
435
                        (s.state IN (:scrapping, :underConstruction))
436
                    OR
437
                        (p.crew = 0))
438
                AND (u.vac_active = false OR u.vac_request_date > :vacationThreshold)',
439
                Ship::class,
440
                ShipBuildplan::class,
441
                User::class,
442
                ShipCrew::class
443
            )
444
        )->setParameters([
445
            'underConstruction' => ShipStateEnum::SHIP_STATE_UNDER_CONSTRUCTION,
446
            'scrapping' => ShipStateEnum::SHIP_STATE_UNDER_SCRAPPING,
447
            'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS,
448
            'firstUserId' => UserEnum::USER_FIRST_ID
449
        ])->toIterable();
450
    }
451
452
    #[Override]
453
    public function getNpcShipsForTick(): iterable
454
    {
455
        return $this->getEntityManager()->createQuery(
456
            sprintf(
457
                'SELECT s FROM %s s WHERE s.user_id BETWEEN 2 AND (:firstUserId - 1)',
458
                Ship::class
459
            )
460
        )->setParameter('firstUserId', UserEnum::USER_FIRST_ID)->getResult();
461
    }
462
463
    #[Override]
464
    public function getFleetShipsScannerResults(
465
        ShipInterface $ship,
466
        bool $showCloaked = false,
467
        MapInterface|StarSystemMapInterface|null $field = null
468
    ): array {
469
470
        $rsm = new ResultSetMapping();
471
        $rsm->addEntityResult(TFleetShipItem::class, 's');
472
        $rsm->addFieldResult('s', 'fleetname', 'fleet_name');
473
        $rsm->addFieldResult('s', 'isdefending', 'is_defending');
474
        $rsm->addFieldResult('s', 'isblocking', 'is_blocking');
475
        $this->addTShipItemFields($rsm);
476
477
        $location = $field ?? $ship->getLocation();
478
479
        $query = $this->getEntityManager()->createNativeQuery(
480
            sprintf(
481
                'SELECT f.id as fleetid, f.name as fleetname, f.defended_colony_id is not null as isdefending,
482
                    f.blocked_colony_id is not null as isblocking, s.id as shipid, s.rumps_id as rumpid, s.former_rumps_id as formerrumpid,
483
                    ss.mode as warpstate, twd.mode as tractorwarpstate, COALESCE(ss2.mode,0) as cloakstate, ss3.mode as shieldstate,
484
                    COALESCE(ss4.status,0) as uplinkstate, s.is_destroyed as isdestroyed, s.type as spacecrafttype, s.name as shipname,
485
                    s.huelle as hull, s.max_huelle as maxhull, s.schilde as shield, s.holding_web_id as webid, tw.finished_time as webfinishtime,
486
                    u.id as userid, u.username, r.category_id as rumpcategoryid, r.name as rumpname, r.role_id as rumproleid,
487
                    (SELECT count(*) > 0 FROM stu_ship_log sl WHERE sl.ship_id = s.id AND sl.is_private = false) as haslogbook,
488
                    (SELECT count(*) > 0 FROM stu_crew_assign ca WHERE ca.ship_id = s.id) as hascrew
489
                FROM stu_ships s
490
                LEFT JOIN stu_ship_system ss
491
                ON s.id = ss.ship_id
492
                AND ss.system_type = :warpdriveType
493
                LEFT JOIN stu_ships tractor
494
                ON tractor.tractored_ship_id = s.id
495
                LEFT JOIN stu_ship_system twd
496
                ON tractor.id = twd.ship_id
497
                AND twd.system_type = :warpdriveType
498
                LEFT JOIN stu_ship_system ss2
499
                ON s.id = ss2.ship_id
500
                AND ss2.system_type = :cloakType
501
                LEFT JOIN stu_ship_system ss3
502
                ON s.id = ss3.ship_id
503
                AND ss3.system_type = :shieldType
504
                LEFT JOIN stu_ship_system ss4
505
                ON s.id = ss4.ship_id
506
                AND ss4.system_type = :uplinkType
507
                JOIN stu_rumps r
508
                ON s.rumps_id = r.id
509
                JOIN stu_fleets f
510
                ON s.fleets_id = f.id
511
                LEFT OUTER JOIN stu_tholian_web tw
512
                ON s.holding_web_id = tw.id
513
                JOIN stu_user u
514
                ON s.user_id = u.id
515
                WHERE s.location_id = :locationId
516
                AND s.id != :ignoreId
517
                %s
518
                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',
519
                $showCloaked ? '' : sprintf(' AND (s.user_id = %d OR COALESCE(ss2.mode,0) < %d) ', $ship->getUser()->getId(), ShipSystemModeEnum::MODE_ON)
520
            ),
521
            $rsm
522
        )->setParameters([
523
            'locationId' => $location->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

523
            'locationId' => $location->/** @scrutinizer ignore-call */ 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...
524
            'ignoreId' => $ship->getId(),
525
            'cloakType' => ShipSystemTypeEnum::SYSTEM_CLOAK->value,
526
            'warpdriveType' => ShipSystemTypeEnum::SYSTEM_WARPDRIVE->value,
527
            'shieldType' => ShipSystemTypeEnum::SYSTEM_SHIELDS->value,
528
            'uplinkType' => ShipSystemTypeEnum::SYSTEM_UPLINK->value
529
        ]);
530
531
        return $query->getResult();
532
    }
533
534
    #[Override]
535
    public function getSingleShipScannerResults(
536
        ShipInterface $ship,
537
        array $types,
538
        bool $showCloaked = false,
539
        MapInterface|StarSystemMapInterface|null $field = null
540
    ): array {
541
542
        $rsm = new ResultSetMapping();
543
        $rsm->addEntityResult(TShipItem::class, 's');
544
        $this->addTShipItemFields($rsm);
545
546
        $location = $field ?? $ship->getLocation();
547
548
        $query = $this->getEntityManager()->createNativeQuery(
549
            sprintf(
550
                '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,
551
                    twd.mode as tractorwarpstate, COALESCE(ss2.mode,0) as cloakstate, ss3.mode as shieldstate, COALESCE(ss4.status,0) as uplinkstate,
552
                    s.is_destroyed as isdestroyed, s.type as spacecrafttype, s.name as shipname, s.huelle as hull, s.max_huelle as maxhull,
553
                    s.schilde as shield, s.holding_web_id as webid, tw.finished_time as webfinishtime, u.id as userid, u.username,
554
                    r.category_id as rumpcategoryid, r.name as rumpname, r.role_id as rumproleid,
555
                    (SELECT count(*) > 0 FROM stu_ship_log sl WHERE sl.ship_id = s.id AND sl.is_private = false) as haslogbook,
556
                    (SELECT count(*) > 0 FROM stu_crew_assign ca WHERE ca.ship_id = s.id) as hascrew
557
                FROM stu_ships s
558
                LEFT JOIN stu_ship_system ss
559
                ON s.id = ss.ship_id
560
                AND ss.system_type = :warpdriveType
561
                LEFT JOIN stu_ships tractor
562
                ON tractor.tractored_ship_id = s.id
563
                LEFT JOIN stu_ship_system twd
564
                ON tractor.id = twd.ship_id
565
                AND twd.system_type = :warpdriveType
566
                LEFT JOIN stu_ship_system ss2
567
                ON s.id = ss2.ship_id
568
                AND ss2.system_type = :cloakType
569
                LEFT JOIN stu_ship_system ss3
570
                ON s.id = ss3.ship_id
571
                AND ss3.system_type = :shieldType
572
                LEFT JOIN stu_ship_system ss4
573
                ON s.id = ss4.ship_id
574
                AND ss4.system_type = :uplinkType
575
                JOIN stu_rumps r
576
                ON s.rumps_id = r.id
577
                LEFT OUTER JOIN stu_tholian_web tw
578
                ON s.holding_web_id = tw.id
579
                JOIN stu_user u
580
                ON s.user_id = u.id
581
                WHERE s.location_id = :locationId
582
                AND s.id != :ignoreId
583
                AND s.fleets_id IS NULL
584
                AND s.type IN (:types)
585
                %s
586
                ORDER BY r.category_id ASC, r.role_id ASC, r.id ASC, s.name ASC',
587
                $showCloaked ? '' : sprintf(' AND (s.user_id = %d OR COALESCE(ss2.mode,0) < %d) ', $ship->getUser()->getId(), ShipSystemModeEnum::MODE_ON)
588
            ),
589
            $rsm
590
        )->setParameters([
591
            'locationId' => $location->getId(),
592
            'ignoreId' => $ship->getId(),
593
            'types' => $types,
594
            'cloakType' => ShipSystemTypeEnum::SYSTEM_CLOAK->value,
595
            'warpdriveType' => ShipSystemTypeEnum::SYSTEM_WARPDRIVE->value,
596
            'shieldType' => ShipSystemTypeEnum::SYSTEM_SHIELDS->value,
597
            'uplinkType' => ShipSystemTypeEnum::SYSTEM_UPLINK->value
598
        ]);
599
600
        return $query->getResult();
601
    }
602
603
    private function addTShipItemFields(ResultSetMapping $rsm): void
604
    {
605
        $rsm->addFieldResult('s', 'shipid', 'ship_id');
606
        $rsm->addFieldResult('s', 'fleetid', 'fleet_id');
607
        $rsm->addFieldResult('s', 'rumpid', 'rump_id');
608
        $rsm->addFieldResult('s', 'formerrumpid', 'former_rump_id');
609
        $rsm->addFieldResult('s', 'warpstate', 'warp_state');
610
        $rsm->addFieldResult('s', 'tractorwarpstate', 'tractor_warp_state');
611
        $rsm->addFieldResult('s', 'cloakstate', 'cloak_state');
612
        $rsm->addFieldResult('s', 'shieldstate', 'shield_state');
613
        $rsm->addFieldResult('s', 'uplinkstate', 'uplink_state');
614
        $rsm->addFieldResult('s', 'isdestroyed', 'is_destroyed');
615
        $rsm->addFieldResult('s', 'spacecrafttype', 'spacecraft_type');
616
        $rsm->addFieldResult('s', 'shipname', 'ship_name');
617
        $rsm->addFieldResult('s', 'hull', 'hull');
618
        $rsm->addFieldResult('s', 'maxhull', 'max_hull');
619
        $rsm->addFieldResult('s', 'shield', 'shield');
620
        $rsm->addFieldResult('s', 'webid', 'web_id');
621
        $rsm->addFieldResult('s', 'webfinishtime', 'web_finish_time');
622
        $rsm->addFieldResult('s', 'userid', 'user_id');
623
        $rsm->addFieldResult('s', 'username', 'user_name');
624
        $rsm->addFieldResult('s', 'rumpcategoryid', 'rump_category_id');
625
        $rsm->addFieldResult('s', 'rumpname', 'rump_name');
626
        $rsm->addFieldResult('s', 'rumproleid', 'rump_role_id');
627
        $rsm->addFieldResult('s', 'haslogbook', 'has_logbook');
628
        $rsm->addFieldResult('s', 'hascrew', 'has_crew');
629
    }
630
631
    #[Override]
632
    public function isCloakedShipAtShipLocation(
633
        ShipInterface $ship
634
    ): bool {
635
636
        $result = $this->getEntityManager()->createQuery(
637
            sprintf(
638
                'SELECT COUNT(s.id) FROM %s s
639
                    WHERE s.location = :location
640
                    AND EXISTS (SELECT ss.id
641
                            FROM %s ss
642
                            WHERE s = ss.ship
643
                            AND ss.system_type = %d
644
                            AND ss.mode > 1)
645
                    AND s.user != :ignoreUser',
646
                Ship::class,
647
                ShipSystem::class,
648
                ShipSystemTypeEnum::SYSTEM_CLOAK->value
649
            )
650
        )->setParameters([
651
            'location' => $ship->getLocation(),
652
            'ignoreUser' => $ship->getUser()
653
        ])->getSingleScalarResult();
654
655
        return $result > 0;
656
    }
657
658
    #[Override]
659
    public function getRandomShipIdWithCrewByUser(int $userId): ?int
660
    {
661
        $rsm = new ResultSetMapping();
662
        $rsm->addScalarResult('id', 'id', 'integer');
663
664
        $result = $this->getEntityManager()
665
            ->createNativeQuery(
666
                'SELECT s.id as id FROM stu_ships s
667
                WHERE s.user_id = :userId
668
                AND EXISTS (SELECT sc.id
669
                            FROM stu_crew_assign sc
670
                            WHERE s.id = sc.ship_id)
671
                ORDER BY RANDOM()
672
                LIMIT 1',
673
                $rsm
674
            )
675
            ->setParameters([
676
                'userId' => $userId
677
            ])
678
            ->getOneOrNullResult();
679
680
        return $result != null ? $result['id'] : null;
681
    }
682
683
    #[Override]
684
    public function isBaseOnLocation(ShipInterface $ship): bool
685
    {
686
        $query = $this->getEntityManager()->createQuery(
687
            sprintf(
688
                'SELECT COUNT(s.id) FROM %s s
689
                WHERE s.location = :location
690
                AND s.type = :type',
691
                Ship::class
692
            )
693
        )->setParameters([
694
            'location' => $ship->getLocation(),
695
            'type' => SpacecraftTypeEnum::SPACECRAFT_TYPE_STATION->value
696
        ]);
697
698
        return $query->getSingleScalarResult() > 0;
699
    }
700
701
    #[Override]
702
    public function getStationsByUser(int $userId): array
703
    {
704
        return $this->getEntityManager()
705
            ->createQuery(
706
                sprintf(
707
                    'SELECT s
708
                    FROM %s s
709
                    JOIN %s r
710
                    WITH s.rumps_id = r.id
711
                    WHERE s.user_id = :userId
712
                    AND r.category_id = :categoryId',
713
                    Ship::class,
714
                    ShipRump::class
715
                )
716
            )
717
            ->setParameters([
718
                'userId' => $userId,
719
                'categoryId' => ShipRumpEnum::SHIP_CATEGORY_STATION
720
            ])
721
            ->getResult();
722
    }
723
724
    #[Override]
725
    public function getAllDockedShips(): array
726
    {
727
        return $this->getEntityManager()->createQuery(
728
            sprintf(
729
                'SELECT s FROM %s s
730
                WHERE s.dock IS NOT NULL',
731
                Ship::class
732
            )
733
        )->getResult();
734
    }
735
736
    #[Override]
737
    public function getAllTractoringShips(): array
738
    {
739
        return $this->getEntityManager()->createQuery(
740
            sprintf(
741
                'SELECT s FROM %s s
742
                WHERE s.tractored_ship_id IS NOT NULL',
743
                Ship::class
744
            )
745
        )->getResult();
746
    }
747
748
    #[Override]
749
    public function getPirateTargets(ShipInterface $ship): array
750
    {
751
        $layer = $ship->getLayer();
752
        if ($layer === null) {
753
            return [];
754
        }
755
756
        $location = $ship->getLocation();
757
        $range = $ship->getSensorRange() * 2;
758
759
        return $this->getEntityManager()->createQuery(
760
            sprintf(
761
                'SELECT s FROM %s s
762
                JOIN %s l
763
                WITH s.location = l.id
764
                JOIN %s u
765
                WITH s.user_id = u.id
766
                LEFT JOIN %s w
767
                WITH u.id = w.user_id
768
                WHERE l.layer_id = :layerId
769
                AND l.cx BETWEEN :minX AND :maxX
770
                AND l.cy BETWEEN :minY AND :maxY
771
                AND s.type = :shipType
772
                AND (s.fleets_id IS NULL OR s.is_fleet_leader = true)
773
                AND u.id >= :firstUserId
774
                AND u.state >= :stateActive
775
                AND u.creation < :eightWeeksEarlier
776
                AND (u.vac_active = false OR u.vac_request_date > :vacationThreshold)
777
                AND COALESCE(w.protection_timeout, 0) < :currentTime',
778
                Ship::class,
779
                Location::class,
780
                User::class,
781
                PirateWrath::class
782
            )
783
        )
784
            ->setParameters([
785
                'minX' => $location->getCx() - $range,
786
                'maxX' => $location->getCx() + $range,
787
                'minY' => $location->getCy() - $range,
788
                'maxY' => $location->getCy() + $range,
789
                'layerId' => $layer->getId(),
790
                'shipType' => SpacecraftTypeEnum::SPACECRAFT_TYPE_SHIP->value,
791
                'firstUserId' => UserEnum::USER_FIRST_ID,
792
                'stateActive' => UserEnum::USER_STATE_ACTIVE,
793
                'eightWeeksEarlier' => time() - TimeConstants::EIGHT_WEEKS_IN_SECONDS,
794
                'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS,
795
                'currentTime' => time()
796
            ])
797
            ->getResult();
798
    }
799
800
    #[Override]
801
    public function getPirateFriends(ShipInterface $ship): array
802
    {
803
        $layer = $ship->getLayer();
804
        if ($layer === null) {
805
            return [];
806
        }
807
808
        $location = $ship->getLocation();
809
        $range = $ship->getSensorRange() * 3;
810
811
        return $this->getEntityManager()->createQuery(
812
            sprintf(
813
                'SELECT s FROM %s s
814
                JOIN %s l
815
                WITH s.location_id = l.id
816
                WHERE l.layer_id = :layerId
817
                AND l.cx BETWEEN :minX AND :maxX
818
                AND l.cy BETWEEN :minY AND :maxY
819
                AND s.id != :shipId
820
                AND s.user_id = :kazonUserId',
821
                Ship::class,
822
                Location::class
823
            )
824
        )
825
            ->setParameters([
826
                'minX' => $location->getCx() - $range,
827
                'maxX' => $location->getCx() + $range,
828
                'minY' => $location->getCy() - $range,
829
                'maxY' => $location->getCy() + $range,
830
                'layerId' => $layer->getId(),
831
                'shipId' => $ship->getId(),
832
                'kazonUserId' => UserEnum::USER_NPC_KAZON
833
            ])
834
            ->getResult();
835
    }
836
837
    #[Override]
838
    public function truncateAllShips(): void
839
    {
840
        $this->getEntityManager()->createQuery(
841
            sprintf(
842
                'DELETE FROM %s s',
843
                Ship::class
844
            )
845
        )->execute();
846
    }
847
}
848