Passed
Push — main ( 8ead35...8419ca )
by Richard
05:14
created

LeaderboardController::showScoreSums()   C

Complexity

Conditions 12
Paths 19

Size

Total Lines 80
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 12
eloc 47
c 2
b 0
f 0
nc 19
nop 2
dl 0
loc 80
rs 6.9666

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
namespace Furic\Leaderboards\Http\Controllers;
4
5
use App\Http\Controllers\Controller;
0 ignored issues
show
Bug introduced by
The type App\Http\Controllers\Controller 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...
6
use Illuminate\Http\Request;
7
use Validator;
8
use Furic\GameEssentials\Models\Player;
9
use Furic\Leaderboards\Models\Leaderboard;
10
use Furic\Leaderboards\Models\LeaderboardPlayerReward;
11
use Furic\Leaderboards\Models\LeaderboardReward;
12
use Furic\Leaderboards\Models\LeaderboardScore;
13
use Furic\Leaderboards\Models\LeaderboardTimescope;
14
15
class LeaderboardController extends Controller
16
{
17
18
    /**
19
     * Display the specified leaderboard resource.
20
     *
21
     * @param  int  $id
22
     * @return \Illuminate\Http\Response
23
     */
24
    public function show($id)
25
    {
26
        try {
27
            return response(Leaderboard::findOrFail($id), 200);
28
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
29
            return response(['error' => 'Leaderboard not found.'], 400);
30
        }
31
    }
32
33
    /**
34
     * Display the specified leaderboard current timescope data array.
35
     *
36
     * @param  int  $id
37
     * @return \Illuminate\Http\Response
38
     */
39
    public function showCurrent(Request $request, $id)
40
    {
41
        try {
42
            $leaderboard = Leaderboard::findOrFail($id);
43
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
44
            return response(['error' => 'Leaderboard not found.'], 400);
45
        }
46
47
        $result = ['end_at' => $leaderboard->currentTimescope->end_at];
48
        $result['score_sum_rewards'] = $leaderboard->scoreSumRewards();
49
        $result['score_sum_rank_rewards'] = $leaderboard->scoreSumRankRewards();
50
        $result['highscore_rank_rewards'] = $leaderboard->highscoreRankRewards();
51
        $result['utc'] = date('Y-m-d H:i:s');
52
53
        return response($result, 200);
54
    }
55
56
    /**
57
     * Display the an array of score-sums of the current leaderboard timescope.
58
     *
59
     * @param  int  $id
60
     * @return \Illuminate\Http\Response
61
     */
62
    public function showScoreSums(Request $request, $id)
63
    {
64
        try {
65
            $leaderboard = Leaderboard::findOrFail($id);
66
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
67
            return response(['error' => 'Leaderboard not found.'], 400);
68
        }
69
70
        $scoresCol = $leaderboard->currentTimescope->orderedScoresByScoreSum;
71
72
        $limit = 20;
73
        if ($request->input('limit'))
74
            $limit = $request->limit;
75
76
        if ($request->filled('player_id')) { // If specific player
77
            
78
            $scoreCount = $scoresCol->count();
79
            $myScoreCol = $scoresCol->where('player_id', $request->query('player_id'));
80
81
            if ($myScoreCol->count() > 0) { // If my score is previously uploaded
82
                
83
                $myRank = 1;
84
85
                for ($i = 0; $i < $scoreCount; $i++) {
86
                    if ($scoresCol[$i]->player_id == $request->query('player_id')) {
87
                        $myRank = $i + 1;
88
                        break;
89
                    }
90
                }
91
92
                $myScoreCol->first()->rank = $myRank;
93
                
94
                $aboveScoresCol = $scoresCol->slice(max(0, $myRank - $limit + 1), min($myRank - 1, $limit));
95
                $aboveRank = ($aboveScoresCol->count() >= $limit) ? ($myRank - $limit) : 1;
96
                foreach ($aboveScoresCol as $aboveScore) {
97
                    $aboveScore->rank = $aboveRank;
98
                    $aboveRank++;
99
                }
100
101
                $belowScoresCol = $scoresCol->slice($myRank, $limit);
102
                $belowRank = $myRank + 1;
103
                foreach ($belowScoresCol as $belowScore) {
104
                    $belowScore->rank = $belowRank;
105
                    $belowRank++;
106
                }
107
                $scores = $aboveScoresCol->merge($myScoreCol)->merge($belowScoresCol);
108
                
109
            } else { // If no my score yet, just show the last 20 rows
110
                
111
                $scoresCol = $scoresCol->slice(-$limit, $limit);
112
                $rank = max(1, $scoreCount - limit - 1);
0 ignored issues
show
Bug introduced by
The constant Furic\Leaderboards\Http\Controllers\limit was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
113
                foreach ($scoresCol as $score) {
114
                    $score->rank = $rank;
115
                    $rank++;
116
                }
117
118
                $scores = $scoresCol->toArray();
119
                
120
                $player = Player::find($request->query('player_id'));
121
                $myScore = ["player_id" => $request->query('player_id'), "name" => $player->name, "score" => "0"];
122
                
123
                $scores = array_merge($scores, [$myScore]);
124
                
125
            }
126
            
127
        } else { // If no specific player, show the first <limit> rows
128
            
129
            $scoresCol = $scoresCol->slice(0, $limit);
130
            // Manually add rank 1 ~ <limit>
131
            $rank = 1;
132
            foreach ($scoresCol as $score) {
133
                $score->rank = $rank;
134
                $rank++;
135
            }
136
            
137
            $scores = $scoresCol->toArray();
138
            
139
        }
140
141
        return $scores;
142
    }
143
    
144
    /**
145
     * Display the an array of highscores of the current leaderboard timescop.
146
     *
147
     * @param  int  $id
148
     * @return \Illuminate\Http\Response
149
     */
150
    public function showHighscores(Request $request, $id)
151
    {
152
        try {
153
            $leaderboard = Leaderboard::findOrFail($id);
154
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
155
            return response(['error' => 'Leaderboard not found.'], 400);
156
        }
157
158
        $scoresCol = $leaderboard->currentTimescope->orderedScoresByHighscore;
159
        $scoresCount = $scoresCol->count();
160
161
        $limit = 20;
162
        if ($request->input('limit'))
163
            $limit = $request->limit;
164
        
165
        $topScoresCol = $scoresCol->slice(0, $limit);
166
        $rank = 1;
167
        foreach ($topScoresCol as $score) {
168
            $score->rank = $rank;
169
            $rank++;
170
        }
171
        $scores = $topScoresCol->toArray();
172
            
173
        if ($request->filled('player_id')) { // If specific player, add he/she at the end
174
            
175
            $myScoreCol = $scoresCol->where('player_id', $request->query('player_id'));
176
177
            $myHighscore = 0;
178
            $myRank = $scoresCount + 1;
179
            
180
            if ($myScoreCol->count() > 0) { // If my score is previously uploaded
181
                
182
                for ($i = 0; $i < $scoresCount; $i++) {
183
                    if ($scoresCol[$i]->player_id == $request->query('player_id')) {
184
                        $myHighscore = $scoresCol[$i]->highscore;
185
                        $myRank = $i + 1;
186
                        break;
187
                    }
188
                }
189
                
190
                if ($myRank <= $limit) { // Ignore attach my highscore row if my rank is within <limit> already
191
                    return $scores;
192
                }
193
            }
194
            
195
            $player = Player::find($request->query('player_id'));
196
            $myHighscoreRow = ["player_id" => $request->query('player_id'), "name" => $player->name, "highscore" => $myHighscore, "rank" => $myRank];
197
            $scores = array_merge($scores, [$myHighscoreRow]);
198
            
199
        } else { // If no specific player, show the first <limit> rows
200
            
201
            $scoresCol = $scoresCol->slice(0, $limit);
202
            // Manually add rank 1 ~ <limit>
203
            $rank = 1;
204
            foreach ($scoresCol as $score) {
205
                $score->rank = $rank;
206
                $rank++;
207
            }
208
            
209
            $scores = $scoresCol->toArray();
210
            
211
        }
212
        
213
        return $scores;
214
    }
215
    
216
    /**
217
     * Display the rewards of highscores of the current leaderboard timescope.
218
     *
219
     * @param  int  $id
220
     * @return \Illuminate\Http\Response
221
     */
222
    public function showRewards(Request $request, $id)
223
    {
224
        $validator = Validator::make($request->all(), [
225
            'player_id' => 'required|numeric',
226
        ]);
227
        if ($validator->fails()) {
228
            return response($validator->messages(), 400);
229
        }
230
231
        try {
232
            $leaderboard = Leaderboard::findOrFail($id);
233
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
234
            return response(['error' => 'Leaderboard not found.'], 400);
235
        }
236
        $leaderboardTimescope = $leaderboard->currentTimescope;
237
        
238
        $result = [];
239
        
240
        // Get rewarded score
241
        $leaderboardPlayerReward = LeaderboardPlayerReward::find($leaderboardTimescope->id, $request->query('player_id'));
242
        if ($leaderboardPlayerReward) { // Show the score of the obtained score reward (current timescope period)
243
            $result['rewarded_score_sum'] = $leaderboardPlayerReward->score_sum;
244
        }
245
246
        $lastScoreSumRank = 0; $lastHighscoreRank = 0;
247
        $lastLeaderboardTimescope = $leaderboardTimescope->previous();
248
        if ($lastLeaderboardTimescope != null) { // Never has the previous leaderboard timescope? ignore
249
            // Check if already redeemed
250
            $playerReward = LeaderboardPlayerReward::find($lastLeaderboardTimescope->id, $request->player_id);
251
            if (!$playerReward) { // Not yet obtained player reward (last timescope period), do a score check
252
                $lastScore = LeaderboardScore::find($lastLeaderboardTimescope->id, $request->player_id);
253
                if ($lastScore) { // Has last my score
254
                    $lastScoreSumRank = LeaderboardScore::where('leaderboard_timescope_id', $lastLeaderboardTimescope->id)->where('score_sum', '>', $lastScore->score_sum)->count() + 1;
255
                    $lastHighscoreRank = LeaderboardScore::where('leaderboard_timescope_id', $lastLeaderboardTimescope->id)->where('highscore', '>', $lastScore->highscore)->count() + 1;
256
                }
257
            }
258
            if ($playerReward) { // Unset the ranks if already redeemed
259
                if ($playerReward->score_sum_rank) {
260
                    $lastScoreSumRank = 0;
261
                }
262
                if ($playerReward->highscore_rank) {
263
                    $lastHighscoreRank = 0;
264
                }
265
            }
266
        }
267
        
268
        if ($lastScoreSumRank > 0) {
269
            $result['last_score_sum_rank'] = $lastScoreSumRank;
270
        }
271
        if ($lastHighscoreRank > 0) {
272
            $result['last_highscore_rank'] = $lastHighscoreRank;
273
        }
274
        
275
        if (empty($result)) {
276
            $result = ['success' => 1];
277
        }
278
        
279
        return response($result, 200);
280
    }
281
282
    /**
283
     * Update or add a specified leaderboard score resource in storage for a player .
284
     *
285
     * @param  Request  $request
286
     * @param  int  $id
287
     * @return \Illuminate\Http\Response
288
     */
289
    public function updateScore(Request $request, $id)
290
    {
291
        $validator = Validator::make($request->all(), [
292
            'player_id' => 'required|numeric',
293
            'score' => 'required|numeric',
294
        ]);
295
        if ($validator->fails()) {
296
            return response($validator->messages(), 400);
297
        }
298
299
        try {
300
            $leaderboard = Leaderboard::findOrFail($id);
301
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
302
            return response(['error' => 'Leaderboard not found.'], 400);
303
        }
304
        $leaderboardTimescope = $leaderboard->currentTimescope;
305
306
        $score = LeaderboardScore::firstOrNew(['leaderboard_timescope_id' => $leaderboardTimescope->id, 'player_id' => $request->player_id]);
307
        
308
        if ($leaderboard->sum_score) { // Only perform score sum if leaderboard sum_score set to true
309
            $score->score_sum += $score->score_sum;
310
            if ($request->score > $score->highscore) { // Update the highscore only when the score is higher
311
                $score->highscore = $request->score;
312
            }
313
            $score->save();
314
        } else if ($request->score > $score->highscore) { // Only perform highscore check when score is higher than highscore
315
            $score->highscore = $request->score;
316
            $score->save();
317
        }
318
319
        return response($score, 200);
320
    }
321
322
    /**
323
     * Update or add a specified leaderboard reward resource in storage for a player.
324
     *
325
     * @param  Request  $request
326
     * @param  int  $id
327
     * @return \Illuminate\Http\Response
328
     */
329
    public function updateReward(Request $request, $id)
330
    {
331
        $validator = Validator::make($request->all(), [
332
            'player_id' => 'required|numeric',
333
        ]);
334
        if ($validator->fails()) {
335
            return response($validator->messages(), 400);
336
        }
337
338
        try {
339
            $leaderboard = Leaderboard::findOrFail($id);
340
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
341
            return response(['error' => 'Leaderboard not found.'], 400);
342
        }
343
        $leaderboardTimescope = $leaderboard->currentTimescope;
344
        
345
        $score = LeaderboardScore::where('leaderboard_timescope_id', $leaderboardTimescope->id)->where('player_id', $request->player_id)->first();
346
347
        // Score-sum reward report to current LeaderboardTimescope
348
349
        if ($request->has('score_sum')) {
350
            if ($score && $score->score_sum > 0) { // If player score is already existed and having score_sum
351
                $scoreSumRewards = $leaderboard->scoreSumRewards();
352
                $rewardedScoreSum = 0;
353
                foreach ($scoreSumRewards as $scoreSumReward) {
354
                    if ($scoreSumReward->score_sum <= $score->score_sum) {
355
                        $rewardedScoreSum = $scoreSumReward->score;
356
                        break;
357
                    }
358
                }
359
                $playerReward = LeaderboardPlayerReward::where('player_id', $request->player_id)->where('leaderboard_timescope_id', $leaderboardTimescope->id)->whereNotNull('score_sum');
360
                if (!$playerReward) {
361
                    $playerReward = LeaderboardPlayerReward::make(['leaderboard_timescope_id' => $leaderboardTimescope->id, 'player_id' => $request->player_id]);
362
                }
363
                $playerReward->score_sum = $rewardedScoreSum;
364
                $playerReward->save();
365
            }
366
        }
367
368
        // Ranking rewards only report to last LeaderboardTimescope
369
370
        if ($leaderboardTimescope->previous() != null) {
371
            $leaderboardTimescope = $leaderboardTimescope->previous();
372
        }
373
374
        $playerReward = LeaderboardPlayerReward::firstOrNew(['player_id' => $request->player_id, 'leaderboard_timescope_id' => $leaderboardTimescope->id]);
375
        if ($request->has('score_sum_rank')) {
376
            $playerReward->score_sum_rank = $request->rank;
377
        }
378
        if ($request->has('highscore_rank')) {
379
            $playerReward->highscore_rank = $request->highscore_rank;
380
        }
381
        $playerReward->save();
382
383
        return response($playerReward, 200);
384
    }
385
386
}
387