Passed
Push — dev ( 7914d2...bbc331 )
by Janko
10:29
created

ColonyRepository::getColoniesNetWorth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 22
nc 1
nop 0
dl 0
loc 26
ccs 13
cts 13
cp 1
crap 1
rs 9.568
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 Doctrine\ORM\NoResultException;
10
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...
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\Module\Commodity\CommodityTypeEnum;
0 ignored issues
show
Bug introduced by
The type Stu\Module\Commodity\CommodityTypeEnum 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...
13
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...
14
use Stu\Module\Spacecraft\Lib\SpacecraftWrapperInterface;
15
use Stu\Orm\Entity\Colony;
16
use Stu\Orm\Entity\ColonyChangeable;
17
use Stu\Orm\Entity\ColonyClass;
18
use Stu\Orm\Entity\Layer;
19
use Stu\Orm\Entity\Location;
20
use Stu\Orm\Entity\Map;
21
use Stu\Orm\Entity\MapRegionSettlement;
22
use Stu\Orm\Entity\PirateWrath;
23
use Stu\Orm\Entity\StarSystem;
24
use Stu\Orm\Entity\StarSystemMap;
25
use Stu\Orm\Entity\Spacecraft;
26
use Stu\Orm\Entity\User;
27
use Stu\Orm\Entity\UserRegistration;
28
29
/**
30
 * @extends EntityRepository<Colony>
31
 */
32
final class ColonyRepository extends EntityRepository implements ColonyRepositoryInterface
33
{
34
    #[Override]
35
    public function prototype(): Colony
36
    {
37
        $colony = new Colony();
38
        $changeable = new ColonyChangeable($colony);
39
        $colony->setChangeable($changeable);
40
41
        return $colony;
42
    }
43
44
    #[Override]
45
    public function save(Colony $colony): void
46
    {
47
        $em = $this->getEntityManager();
48
49
        $em->persist($colony);
50
    }
51
52
    #[Override]
53
    public function delete(Colony $colony): void
54
    {
55
        $em = $this->getEntityManager();
56
57
        $em->remove($colony);
58
        $em->flush(); //TODO really neccessary?
59
    }
60
61 2
    #[Override]
62
    public function getAmountByUser(User $user, int $colonyType): int
63
    {
64 2
        return (int) $this->getEntityManager()
65 2
            ->createQuery(
66 2
                sprintf(
67 2
                    'SELECT count(c.id) from %s c WHERE c.user_id = :userId AND c.colonyClass IN (
68
                        SELECT cc FROM %s cc WHERE cc.type = :type
69 2
                    )',
70 2
                    Colony::class,
71 2
                    ColonyClass::class
72 2
                )
73 2
            )
74 2
            ->setParameters([
75 2
                'userId' => $user,
76 2
                'type' => $colonyType
77 2
            ])
78 2
            ->getSingleScalarResult();
79
    }
80
81
    #[Override]
82
    public function getStartingByFaction(int $factionId): array
83
    {
84
        return $this->getEntityManager()
85
            ->createQuery(
86
                sprintf(
87
                    'SELECT c FROM %s c INDEX BY c.id
88
                     JOIN %s sm
89
                     WITH c.starsystem_map = sm
90
                     WHERE c.user_id = :userId AND c.colonyClass IN (
91
                        SELECT cc FROM %s cc WHERE cc.allow_start = :allowStart
92
                    ) AND sm.systems_id IN (
93
                        SELECT m.systems_id FROM %s m WHERE m.systems_id > 0 AND m.admin_region_id IN (
94
                            SELECT mrs.region_id from %s mrs WHERE mrs.faction_id = :factionId
95
                        ) AND m.id IN (SELECT l.id FROM %s l WHERE l.layer_id IN (SELECT ly.id FROM %s ly WHERE ly.is_colonizable = :true))
96
                    )',
97
                    Colony::class,
98
                    StarSystemMap::class,
99
                    ColonyClass::class,
100
                    Map::class,
101
                    MapRegionSettlement::class,
102
                    Location::class,
103
                    Layer::class
104
                )
105
            )
106
            ->setParameters([
107
                'allowStart' => 1,
108
                'userId' => UserEnum::USER_NOONE,
109
                'factionId' => $factionId,
110
                'true' => true
111
            ])
112
            ->getResult();
113
    }
114
115
    #[Override]
116
    public function getForeignColoniesInBroadcastRange(
117
        StarSystemMap $systemMap,
118
        User $user
119
    ): array {
120
        return $this->getEntityManager()
121
            ->createQuery(
122
                sprintf(
123
                    'SELECT c FROM %s c
124
                     JOIN %s sm
125
                     WITH c.starsystem_map = sm
126
                     WHERE c.user_id NOT IN (:ignoreIds)
127
                     AND sm.systems_id = :systemId
128
                     AND sm.sx BETWEEN (:sx - 1) AND (:sx + 1)
129
                     AND sm.sy BETWEEN (:sy - 1) AND (:sy + 1)',
130
                    Colony::class,
131
                    StarSystemMap::class
132
                )
133
            )
134
            ->setParameters([
135
                'ignoreIds' => [$user->getId(), UserEnum::USER_NOONE],
136
                'systemId' => $systemMap->getSystem()->getId(),
137
                'sx' => $systemMap->getSx(),
138
                'sy' => $systemMap->getSy()
139
            ])
140
            ->getResult();
141
    }
142
143
    #[Override]
144
    public function getByBatchGroup(int $batchGroup, int $batchGroupCount): array
145
    {
146
        return $this->getEntityManager()
147
            ->createQuery(
148
                sprintf(
149
                    'SELECT c FROM %s c
150
                    WHERE MOD(c.user_id, :groupCount) + 1 = :groupId
151
                    AND c.user_id != :userId',
152
                    Colony::class
153
                )
154
            )
155
            ->setParameters([
156
                'groupId' => $batchGroup,
157
                'groupCount' => $batchGroupCount,
158
                'userId' => UserEnum::USER_NOONE
159
            ])
160
            ->getResult();
161
    }
162
163
    #[Override]
164
    public function getColonized(): array
165
    {
166
        return $this->getEntityManager()
167
            ->createQuery(
168
                sprintf(
169
                    'SELECT c FROM %s c WHERE c.user_id != :userId',
170
                    Colony::class
171
                )
172
            )
173
            ->setParameters([
174
                'userId' => UserEnum::USER_NOONE,
175
            ])
176
            ->getResult();
177
    }
178
179 1
    #[Override]
180
    public function getColoniesNetWorth(): array
181
    {
182 1
        $rsm = new ResultSetMapping();
183 1
        $rsm->addScalarResult('user_id', 'user_id', 'integer');
184 1
        $rsm->addScalarResult('commodity_id', 'commodity_id', 'integer');
185 1
        $rsm->addScalarResult('sum', 'sum', 'integer');
186
187 1
        return $this->getEntityManager()
188 1
            ->createNativeQuery(
189 1
                'SELECT u.id as user_id, bc.commodity_id AS commodity_id, SUM(bc.count) AS sum
190
                FROM stu_user u
191
                JOIN stu_colony c
192
                ON u.id = c.user_id 
193
                JOIN stu_colonies_fielddata cf
194
                ON cf.colonies_id = c.id
195
                JOIN stu_buildings_cost bc 
196
                ON cf.buildings_id = bc.buildings_id 
197
                WHERE u.id >= :firstUserId
198
                AND cf.buildings_id IS NOT NULL
199
                AND cf.aktiv = 1
200 1
                GROUP BY u.id, bc.commodity_id',
201 1
                $rsm
202 1
            )
203 1
            ->setParameters(['firstUserId' => UserEnum::USER_FIRST_ID])
204 1
            ->getResult();
205
    }
206
207 1
    #[Override]
208
    public function getColoniesProductionNetWorth(): array
209
    {
210 1
        $rsm = new ResultSetMapping();
211 1
        $rsm->addScalarResult('user_id', 'user_id', 'integer');
212 1
        $rsm->addScalarResult('commodity_id', 'commodity_id', 'integer');
213 1
        $rsm->addScalarResult('sum', 'sum', 'integer');
214
215 1
        return $this->getEntityManager()
216 1
            ->createNativeQuery(
217 1
                'SELECT c.user_id, bc.commodity_id, SUM(bc.count) AS sum
218
                FROM stu_colony c
219
                JOIN stu_colonies_fielddata cf
220
                ON cf.colonies_id = c.id 
221
                JOIN stu_buildings_commodity bc
222
                ON cf.buildings_id = bc.buildings_id
223
                JOIN stu_commodity co
224
                ON bc.commodity_id = co.id
225
                WHERE co.type = :typeStandard
226
                AND co.name != \'Latinum\'
227
                AND bc.count > 0
228
                AND cf.aktiv = 1
229 1
                GROUP BY c.user_id, bc.commodity_id',
230 1
                $rsm
231 1
            )
232 1
            ->setParameters(['typeStandard' => CommodityTypeEnum::COMMODITY_TYPE_STANDARD])
233 1
            ->getResult();
234
    }
235
236
    #[Override]
237
    public function getSatisfiedWorkerTop10(): array
238
    {
239
        $rsm = new ResultSetMapping();
240
        $rsm->addScalarResult('user_id', 'user_id', 'integer');
241
        $rsm->addScalarResult('satisfied', 'satisfied', 'integer');
242
243
        return $this->getEntityManager()
244
            ->createNativeQuery(
245
                'SELECT user_id, SUM(satisfied) AS satisfied
246
                FROM ( SELECT c.user_id,
247
                            LEAST( COALESCE(c.bev_work, 0),
248
                            ( SELECT COALESCE(SUM(bc.count), 0)
249
                                FROM stu_colonies_fielddata cf
250
                                JOIN stu_buildings b
251
                                ON cf.buildings_id = b.id
252
                                JOIN stu_buildings_commodity bc
253
                                ON b.id = bc.buildings_id
254
                                WHERE cf.colonies_id = c.id
255
                                AND bc.commodity_id = :lifeStandard
256
                                AND cf.aktiv = 1
257
                            )) AS satisfied
258
                        FROM stu_colony c
259
                        WHERE c.user_id >= :firstUserId) AS colonies
260
                GROUP BY user_id
261
                ORDER BY 2 DESC
262
                LIMIT 10',
263
                $rsm
264
            )
265
            ->setParameters([
266
                'firstUserId' => UserEnum::USER_FIRST_ID,
267
                'lifeStandard' => CommodityTypeEnum::COMMODITY_EFFECT_LIFE_STANDARD
268
            ])
269
            ->getResult();
270
    }
271
272
    #[Override]
273
    public function getPirateTargets(SpacecraftWrapperInterface $wrapper): array
274
    {
275
        $layer = $wrapper->get()->getLayer();
276
        if ($layer === null) {
277
            return [];
278
        }
279
280
        $location = $wrapper->get()->getLocation();
281
        $range = $wrapper->getLssSystemData()?->getSensorRange() ?? 0;
282
283
        return $this->getEntityManager()->createQuery(
284
            sprintf(
285
                'SELECT c FROM %s c
286
                JOIN %s sm
287
                WITH c.starsystem_map = sm
288
                JOIN %s s
289
                WITH sm.systems_id = s.id
290
                JOIN %s m
291
                WITH s.id = m.systems_id
292
                JOIN %s l
293
                WITH m.id = l.id
294
                JOIN %s u
295
                WITH c.user = u
296
                JOIN %s ur
297
                WITH ur.user = u
298
                LEFT JOIN %s w
299
                WITH u = w.user
300
                WHERE l.cx BETWEEN :minX AND :maxX
301
                AND l.cy BETWEEN :minY AND :maxY
302
                AND l.layer_id = :layer
303
                AND u.id >= :firstUserId
304
                AND u.state >= :stateActive
305
                AND ur.creation < :fourMonthEarlier
306
                AND (u.vac_active = :false OR u.vac_request_date > :vacationThreshold)
307
                AND COALESCE(w.protection_timeout, 0) < :currentTime',
308
                Colony::class,
309
                StarSystemMap::class,
310
                StarSystem::class,
311
                Map::class,
312
                Location::class,
313
                User::class,
314
                UserRegistration::class,
315
                PirateWrath::class
316
            )
317
        )
318
            ->setParameters([
319
                'minX' => $location->getCx() - $range,
320
                'maxX' => $location->getCx() + $range,
321
                'minY' => $location->getCy() - $range,
322
                'maxY' => $location->getCy() + $range,
323
                'layer' => $layer,
324
                'firstUserId' => UserEnum::USER_FIRST_ID,
325
                'stateActive' => UserEnum::USER_STATE_ACTIVE,
326
                'fourMonthEarlier' => time() - TimeConstants::EIGHT_WEEKS_IN_SECONDS,
327
                'false' => false,
328
                'vacationThreshold' => time() - UserEnum::VACATION_DELAY_IN_SECONDS,
329
                'currentTime' => time()
330
            ])
331
            ->getResult();
332
    }
333
334
    #[Override]
335
    public function getClosestColonizableColonyDistance(SpacecraftWrapperInterface $wrapper): ?int
336
    {
337
        $spacecraft = $wrapper->get();
338
        $location = $spacecraft->getLocation();
339
340
        if ($location instanceof StarSystemMap) {
341
            return $this->getClosestColonizableColonyInSystem($spacecraft);
342
        } else {
343
            return $this->getClosestSystemWithColonizableColonies($spacecraft);
344
        }
345
    }
346
347
    private function getClosestColonizableColonyInSystem(Spacecraft $spacecraft): ?int
348
    {
349
        $systemMap = $spacecraft->getStarsystemMap();
350
        if ($systemMap === null) {
351
            return null;
352
        }
353
354
        $currentColony = $systemMap->getColony();
355
        if (
356
            $currentColony !== null &&
357
            $currentColony->getUserId() === UserEnum::USER_NOONE &&
358
            $currentColony->getColonyClass()->getAllowStart()
359
        ) {
360
            return null;
361
        }
362
363
        try {
364
            $result = $this->getEntityManager()->createQuery(
365
                sprintf(
366
                    'SELECT MIN(ABS(sm.sx - :sx) + ABS(sm.sy - :sy)) as distance
367
                        FROM %s c
368
                        JOIN %s sm
369
                        WITH c.starsystem_map = sm
370
                        JOIN %s cc
371
                        WITH c.colonyClass = cc
372
                        WHERE c.user_id = :nooneUserId
373
                        AND cc.allow_start = :allowStart
374
                        AND sm.systems_id = :systemId
375
                        AND sm.id != :currentMapId',
376
                    Colony::class,
377
                    StarSystemMap::class,
378
                    ColonyClass::class
379
                )
380
            )
381
                ->setParameters([
382
                    'sx' => $systemMap->getSx(),
383
                    'sy' => $systemMap->getSy(),
384
                    'systemId' => $systemMap->getSystemId(),
385
                    'currentMapId' => $systemMap->getId(),
386
                    'nooneUserId' => UserEnum::USER_NOONE,
387
                    'allowStart' => true
388
                ])
389
                ->getSingleScalarResult();
390
391
            return $result > 0 ? (int)$result : null;
392
        } catch (NoResultException) {
393
            return null;
394
        }
395
    }
396
397
398
    private function getClosestSystemWithColonizableColonies(Spacecraft $spacecraft): ?int
399
    {
400
        $currentLocation = $spacecraft->getLocation();
401
        $currentX = $currentLocation->getCx();
402
        $currentY = $currentLocation->getCy();
403
        $currentLayer = $currentLocation->getLayer();
404
405
        if ($currentLayer === null) {
406
            return null;
407
        }
408
409
        $currentLayerId = $currentLayer->getId();
410
411
        try {
412
            $result = $this->getEntityManager()->createQuery(
413
                sprintf(
414
                    'SELECT MIN(ABS(l.cx - :currentX) + ABS(l.cy - :currentY)) as distance
415
                        FROM %s c
416
                        JOIN %s sm
417
                        WITH c.starsystem_map = sm
418
                        JOIN %s s
419
                        WITH sm.systems_id = s.id
420
                        JOIN %s m
421
                        WITH s.id = m.systems_id
422
                        JOIN %s l
423
                        WITH m.id = l.id
424
                        JOIN %s cc
425
                        WITH c.colonyClass = cc
426
                        WHERE c.user_id = :nooneUserId
427
                        AND cc.allow_start = :allowStart
428
                        AND l.layer_id = :currentLayerId',
429
                    Colony::class,
430
                    StarSystemMap::class,
431
                    StarSystem::class,
432
                    Map::class,
433
                    Location::class,
434
                    ColonyClass::class
435
                )
436
            )
437
                ->setParameters([
438
                    'currentX' => $currentX,
439
                    'currentY' => $currentY,
440
                    'currentLayerId' => $currentLayerId,
441
                    'nooneUserId' => UserEnum::USER_NOONE,
442
                    'allowStart' => true
443
                ])
444
                ->getSingleScalarResult();
445
446
            return $result > 0 ? (int)$result : null;
447
        } catch (NoResultException) {
448
            return null;
449
        }
450
    }
451
}
452