UpdatePlayerChartRankHandler::__invoke()   F
last analyzed

Complexity

Conditions 16
Paths 723

Size

Total Lines 145
Code Lines 92

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 92
nc 723
nop 1
dl 0
loc 145
rs 1.6023
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace VideoGamesRecords\CoreBundle\MessageHandler\Player;
6
7
use Doctrine\ORM\EntityManagerInterface;
8
use Doctrine\ORM\Exception\ORMException;
9
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
10
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
11
use Symfony\Component\Messenger\Exception\ExceptionInterface;
12
use Symfony\Component\Messenger\MessageBusInterface;
13
use VideoGamesRecords\CoreBundle\DataProvider\Ranking\Player\PlayerChartRankingProvider;
0 ignored issues
show
Bug introduced by
The type VideoGamesRecords\CoreBu...yerChartRankingProvider 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 VideoGamesRecords\CoreBundle\Entity\Chart;
15
use VideoGamesRecords\CoreBundle\Entity\PlayerChart;
16
use VideoGamesRecords\CoreBundle\Event\PlayerChartUpdated;
17
use VideoGamesRecords\CoreBundle\Message\Player\UpdatePlayerChartRank;
18
use VideoGamesRecords\CoreBundle\Message\Player\UpdatePlayerGroupRank;
19
use VideoGamesRecords\CoreBundle\Message\Team\UpdateTeamChartRank;
20
use VideoGamesRecords\CoreBundle\Tools\Ranking;
21
use Zenstruck\Messenger\Monitor\Stamp\DescriptionStamp;
0 ignored issues
show
Bug introduced by
The type Zenstruck\Messenger\Monitor\Stamp\DescriptionStamp 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...
22
23
#[AsMessageHandler]
24
readonly class UpdatePlayerChartRankHandler
25
{
26
    public function __construct(
27
        private EntityManagerInterface $em,
28
        private EventDispatcherInterface $eventDispatcher,
29
        private PlayerChartRankingProvider $playerChartRankingProvider,
30
        private MessageBusInterface $bus
31
    ) {
32
    }
33
34
    /**
35
     * @throws ORMException
36
     * @throws ExceptionInterface
37
     */
38
    public function __invoke(UpdatePlayerChartRank $updatePlayerChartRank): array
39
    {
40
        /** @var Chart $chart */
41
        $chart = $this->em->getRepository('VideoGamesRecords\CoreBundle\Entity\Chart')
42
            ->find($updatePlayerChartRank->getChartId());
43
        if (null == $chart) {
44
            return ['error' => 'chart not found'];
45
        }
46
47
        $ranking = $this->playerChartRankingProvider->getRanking(
48
            $chart,
49
            ['orderBy' => PlayerChartRankingProvider::ORDER_BY_SCORE]
50
        );
51
        $pointsChart = Ranking::chartPointProvider(count($ranking));
52
53
        $topScoreLibValue = '';
54
        $previousLibValue = '';
55
        $rank = 1;
56
        $nbEqual = 1;
57
        $playerChartEqual = [];
58
        $platforms = [];
59
        $result = $this->getPlatforms($chart);
60
61
        foreach ($result as $row) {
62
            $platforms[$row['id']] = [
63
                'count' => $row['nb'],
64
                'points' => Ranking::platformPointProvider($row['nb']),
65
                'previousLibValue' => '',
66
                'rank' => 0,
67
                'nbEqual' => 1,
68
                'playerChartEqual' => [],
69
            ];
70
        }
71
72
        foreach ($ranking as $k => $item) {
73
            $libValue = '';
74
            /** @var PlayerChart $playerChart */
75
            $playerChart = $item[0];
76
77
            // Lost position ?
78
            $oldRank = $playerChart->getRank();
79
            $oldNbEqual = $playerChart->getNbEqual();
80
            $playerChart->setIsTopScore(false);
81
82
            foreach ($chart->getLibs() as $lib) {
83
                $libValue .= $item['value_' . $lib->getId()] . '/';
84
            }
85
            if ($k === 0) {
86
                // Premier élément => topScore
87
                $playerChart->setIsTopScore(true);
88
                $topScoreLibValue = $libValue;
89
            } else {
90
                if ($libValue === $topScoreLibValue) {
91
                    $playerChart->setIsTopScore(true);
92
                }
93
                if ($previousLibValue === $libValue) {
94
                    ++$nbEqual;
95
                } else {
96
                    $rank += $nbEqual;
97
                    $nbEqual = 1;
98
                    $playerChartEqual = [];
99
                }
100
            }
101
            // Platform point
102
            if ($playerChart->getPlatform() != null) {
103
                $idPlatForm = $playerChart->getPlatform()->getId();
104
                if ($platforms[$idPlatForm]['previousLibValue'] === $libValue) {
105
                    ++$platforms[$idPlatForm]['nbEqual'];
106
                } else {
107
                    $platforms[$idPlatForm]['rank'] += $platforms[$idPlatForm]['nbEqual'];
108
                    $platforms[$idPlatForm]['nbEqual'] = 1;
109
                    $platforms[$idPlatForm]['playerChartEqual'] = [];
110
                }
111
                $platforms[$idPlatForm]['playerChartEqual'][] = $playerChart;
112
            }
113
114
            $playerChartEqual[] = $playerChart;
115
116
            $playerChart->setNbEqual($nbEqual);
117
            $playerChart->setRank($rank);
118
            $playerChart->setPointChart((int) (
119
                array_sum(
120
                    array_slice(array_values($pointsChart), $playerChart->getRank() - 1, $playerChart->getNbEqual())
121
                ) / $playerChart->getNbEqual()
122
            ));
123
124
            if ($nbEqual > 1) {
125
                // Pour les égalités déjà passées on met à jour le nbEqual et l'attribution des points
126
                foreach ($playerChartEqual as $playerChartToModify) {
127
                    $playerChartToModify->setNbEqual($nbEqual);
128
                    $playerChartToModify->setPointChart($playerChart->getPointChart());
129
                }
130
            }
131
132
            if ($playerChart->getPlatform() != null) {
133
                $idPlatForm = $playerChart->getPlatform()->getId();
134
                $playerChart->setPointPlatform((int) (
135
                    array_sum(
136
                        array_slice(
137
                            array_values($platforms[$idPlatForm]['points']),
138
                            $platforms[$idPlatForm]['rank'] - 1,
139
                            $platforms[$idPlatForm]['nbEqual']
140
                        )
141
                    ) / $platforms[$idPlatForm]['nbEqual']
142
                ));
143
                if ($platforms[$idPlatForm]['nbEqual'] > 1) {
144
                    // Pour les égalités déjà passées on met à jour le nbEqual et l'attribution des points
145
                    foreach ($platforms[$idPlatForm]['playerChartEqual'] as $playerChartToModify) {
146
                        $playerChartToModify
147
                            ->setPointPlatform($playerChart->getPointPlatform());
148
                    }
149
                }
150
            } else {
151
                $playerChart->setPointPlatform(0);
152
            }
153
154
            $this->eventDispatcher->dispatch(new PlayerChartUpdated($playerChart, $oldRank, $oldNbEqual));
155
156
            $previousLibValue = $libValue;
157
158
            // Platform point
159
            if ($playerChart->getPlatform() != null) {
160
                $platforms[$playerChart->getPlatform()->getId()]['previousLibValue'] = $libValue;
161
            }
162
        }
163
        $this->em->flush();
164
165
        $this->bus->dispatch(
166
            new UpdatePlayerGroupRank($chart->getGroup()->getId()),
0 ignored issues
show
Bug introduced by
It seems like $chart->getGroup()->getId() can also be of type null; however, parameter $groupId of VideoGamesRecords\CoreBu...roupRank::__construct() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

166
            new UpdatePlayerGroupRank(/** @scrutinizer ignore-type */ $chart->getGroup()->getId()),
Loading history...
167
            [
168
                new DescriptionStamp(
169
                    sprintf('Update player-ranking for group [%d]', $chart->getGroup()->getId())
170
                )
171
            ]
172
        );
173
        $this->bus->dispatch(
174
            new UpdateTeamChartRank($chart->getId()),
0 ignored issues
show
Bug introduced by
It seems like $chart->getId() can also be of type null; however, parameter $chartId of VideoGamesRecords\CoreBu...hartRank::__construct() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

174
            new UpdateTeamChartRank(/** @scrutinizer ignore-type */ $chart->getId()),
Loading history...
175
            [
176
                new DescriptionStamp(
177
                    sprintf('Update team-ranking for chart [%d]', $chart->getId())
178
                )
179
            ]
180
        );
181
182
        return ['success' => true];
183
    }
184
185
186
    /**
187
     * @param Chart $chart
188
     * @return int|mixed|string
189
     */
190
    private function getPlatforms(Chart $chart): mixed
191
    {
192
        $query = $this->em->createQuery("
193
            SELECT
194
                 p.id,
195
                 COUNT(pc) as nb
196
            FROM VideoGamesRecords\CoreBundle\Entity\PlayerChart pc
197
            INNER JOIN pc.platform p
198
            WHERE pc.chart = :chart
199
            GROUP BY p.id");
200
201
        $query->setParameter('chart', $chart);
202
        return $query->getResult(2);
203
    }
204
}
205