LeaderboardController::updateReward()   B
last analyzed

Complexity

Conditions 11
Paths 58

Size

Total Lines 52
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 31
c 1
b 0
f 0
nc 58
nop 2
dl 0
loc 52
rs 7.3166

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
        if ($request->filled('player_id')) { // If specific player
73
            
74
            $scoreCount = $scoresCol->count();
75
            $myScoreCol = $scoresCol->where('player_id', $request->query('player_id'));
76
77
            if ($myScoreCol->count() > 0) { // If my score is previously uploaded
78
                
79
                $myRank = 1;
80
81
                for ($i = 0; $i < $scoreCount; $i++) {
82
                    if ($scoresCol[$i]->player_id == $request->query('player_id')) {
83
                        $myRank = $i + 1;
84
                        break;
85
                    }
86
                }
87
88
                $myScoreCol->first()->rank = $myRank;
89
                
90
                $aboveScoresCol = $scoresCol->slice(max(0, $myRank - 21), min($myRank - 1, 20));
91
                $aboveRank = ($aboveScoresCol->count() >= 20) ? ($myRank - 20) : 1;
92
                foreach ($aboveScoresCol as $aboveScore) {
93
                    $aboveScore->rank = $aboveRank;
94
                    $aboveRank++;
95
                }
96
97
                $belowScoresCol = $scoresCol->slice($myRank, 20);
98
                $belowRank = $myRank + 1;
99
                foreach ($belowScoresCol as $belowScore) {
100
                    $belowScore->rank = $belowRank;
101
                    $belowRank++;
102
                }
103
                $scores = $aboveScoresCol->merge($myScoreCol)->merge($belowScoresCol);
104
                
105
            } else { // If no my score yet, just show the last 20 rows
106
                
107
                $scoresCol = $scoresCol->slice(-20, 20);
108
                $rank = max(1, $scoreCount - 19);
109
                foreach ($scoresCol as $score) {
110
                    $score->rank = $rank;
111
                    $rank++;
112
                }
113
114
                $scores = $scoresCol->toArray();
115
                
116
                $player = Player::find($request->query('player_id'));
117
                $myScore = ["player_id" => $request->query('player_id'), "name" => $player->name, "score" => "0"];
118
                
119
                $scores = array_merge($scores, [$myScore]);
120
                
121
            }
122
            
123
        } else { // If no specific player, show the first 20 rows
124
            
125
            $scoresCol = $scoresCol->slice(0, 20);
126
            // Manually add rank 1~20
127
            $rank = 1;
128
            foreach ($scoresCol as $score) {
129
                $score->rank = $rank;
130
                $rank++;
131
            }
132
            
133
            $scores = $scoresCol->toArray();
134
            
135
        }
136
137
        return $scores;
138
    }
139
    
140
    /**
141
     * Display the an array of highscores of the current leaderboard timescop.
142
     *
143
     * @param  int  $id
144
     * @return \Illuminate\Http\Response
145
     */
146
    public function showHighscores(Request $request, $id)
147
    {
148
        try {
149
            $leaderboard = Leaderboard::findOrFail($id);
150
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
151
            return response(['error' => 'Leaderboard not found.'], 400);
152
        }
153
154
        $scoresCol = $leaderboard->currentTimescope->orderedScoresByHighscore;
155
        $scoresCount = $scoresCol->count();
156
        
157
        $topScoresCol = $scoresCol->slice(0, 20);
158
        $rank = 1;
159
        foreach ($topScoresCol as $score) {
160
            $score->rank = $rank;
161
            $rank++;
162
        }
163
        $scores = $topScoresCol->toArray();
164
            
165
        if ($request->filled('player_id')) { // If specific player, add he/she at the end
166
            
167
            $myScoreCol = $scoresCol->where('player_id', $request->query('player_id'));
168
169
            $myHighscore = 0;
170
            $myRank = $scoresCount + 1;
171
            
172
            if ($myScoreCol->count() > 0) { // If my score is previously uploaded
173
                
174
                for ($i = 0; $i < $scoresCount; $i++) {
175
                    if ($scoresCol[$i]->player_id == $request->query('player_id')) {
176
                        $myHighscore = $scoresCol[$i]->highscore;
177
                        $myRank = $i + 1;
178
                        break;
179
                    }
180
                }
181
                
182
                if ($myRank <= 20) { // Ignore attach my highscore row if my rank is within 20 already
183
                    return $scores;
184
                }
185
            }
186
            
187
            $player = Player::find($request->query('player_id'));
188
            $myHighscoreRow = ["player_id" => $request->query('player_id'), "name" => $player->name, "highscore" => $myHighscore, "rank" => $myRank];
189
            $scores = array_merge($scores, [$myHighscoreRow]);
190
            
191
        } else { // If no specific player, show the first 20 rows
192
            
193
            $scoresCol = $scoresCol->slice(0, 20);
194
            // Manually add rank 1~20
195
            $rank = 1;
196
            foreach ($scoresCol as $score) {
197
                $score->rank = $rank;
198
                $rank++;
199
            }
200
            
201
            $scores = $scoresCol->toArray();
202
            
203
        }
204
        
205
        return $scores;
206
    }
207
    
208
    /**
209
     * Display the rewards of highscores of the current leaderboard timescope.
210
     *
211
     * @param  int  $id
212
     * @return \Illuminate\Http\Response
213
     */
214
    public function showRewards(Request $request, $id)
215
    {
216
        $validator = Validator::make($request->all(), [
217
            'player_id' => 'required|numeric',
218
        ]);
219
        if ($validator->fails()) {
220
            return response($validator->messages(), 400);
221
        }
222
223
        try {
224
            $leaderboard = Leaderboard::findOrFail($id);
225
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
226
            return response(['error' => 'Leaderboard not found.'], 400);
227
        }
228
        $leaderboardTimescope = $leaderboard->currentTimescope;
229
        
230
        $result = [];
231
        
232
        // Get rewarded score
233
        $leaderboardPlayerReward = LeaderboardPlayerReward::find($leaderboardTimescope->id, $request->query('player_id'));
234
        if ($leaderboardPlayerReward) { // Show the score of the obtained score reward (current timescope period)
235
            $result['rewarded_score'] = $leaderboardPlayerReward->score_sum;
236
        }
237
238
        $lastScoreSumRank = 0; $lastHighscoreRank = 0;
239
        // Get last rank
240
        $rankReward = LeaderboardPlayerReward::find($leaderboardTimescope->id, $request->player_id);
241
        if (!$rankReward) { // Not yet obtained rank reward (last timescope period)
242
            $lastLeaderboardTimescope = $leaderboardTimescope->previous();
243
            if ($lastLeaderboardTimescope != null) {
244
                $lastScore = LeaderboardScore::find($lastLeaderboardTimescope->id, $request->player_id);
245
                if ($lastScore) { // Has last my score
246
                    $lastScoreSumRank = LeaderboardScore::where('leaderboard_timescope_id', $lastLeaderboardTimescope->id)->where('score_sum', '>', $lastScore->score_sum)->count() + 1;
247
                    $lastHighscoreRank = LeaderboardScore::where('leaderboard_timescope_id', $lastLeaderboardTimescope->id)->where('highscore', '>', $lastScore->highscore)->count() + 1;
248
                }
249
            }
250
        }
251
        
252
        if ($lastScoreSumRank > 0) {
253
            $result['last_score_sum_rank'] = $lastScoreSumRank;
254
        }
255
        if ($lastHighscoreRank > 0) {
256
            $result['last_highscore_rank'] = $lastHighscoreRank;
257
        }
258
        
259
        if (empty($result)) {
260
            $result = ['success' => 1];
261
        }
262
        
263
        return response($result, 200);
264
    }
265
266
    /**
267
     * Update or add a specified leaderboard score resource in storage for a player .
268
     *
269
     * @param  Request  $request
270
     * @param  int  $id
271
     * @return \Illuminate\Http\Response
272
     */
273
    public function updateScore(Request $request, $id)
274
    {
275
        $validator = Validator::make($request->all(), [
276
            'player_id' => 'required|numeric',
277
            'score' => 'required|numeric',
278
        ]);
279
        if ($validator->fails()) {
280
            return response($validator->messages(), 400);
281
        }
282
283
        try {
284
            $leaderboard = Leaderboard::findOrFail($id);
285
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
286
            return response(['error' => 'Leaderboard not found.'], 400);
287
        }
288
        $leaderboardTimescope = $leaderboard->currentTimescope;
289
290
        $score = LeaderboardScore::firstOrNew(['leaderboard_timescope_id' => $leaderboardTimescope->id, 'player_id' => $request->player_id]);
291
        
292
        if ($leaderboard->sum_score) { // Only perform score sum if leaderboard sum_score set to true
293
            $score->score_sum += $score->score_sum;
294
            if ($request->score > $score->highscore) { // Update the highscore only when the score is higher
295
                $score->highscore = $request->score;
296
            }
297
            $score->save();
298
        } else if ($request->score > $score->highscore) { // Only perform highscore check when score is higher than highscore
299
            $score->highscore = $request->score;
300
            $score->save();
301
        }
302
303
        return response($score, 200);
304
    }
305
306
    /**
307
     * Update or add a specified leaderboard reward resource in storage for a player.
308
     *
309
     * @param  Request  $request
310
     * @param  int  $id
311
     * @return \Illuminate\Http\Response
312
     */
313
    public function updateReward(Request $request, $id)
314
    {
315
        $validator = Validator::make($request->all(), [
316
            'player_id' => 'required|numeric',
317
        ]);
318
        if ($validator->fails()) {
319
            return response($validator->messages(), 400);
320
        }
321
322
        try {
323
            $leaderboard = Leaderboard::findOrFail($id);
324
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
325
            return response(['error' => 'Leaderboard not found.'], 400);
326
        }
327
        $leaderboardTimescope = $leaderboard->currentTimescope;
328
        
329
        $score = LeaderboardScore::where('leaderboard_timescope_id', $leaderboardTimescope->id)->where('player_id', $request->player_id)->first();
330
331
        if ($score && $score->score_sum > 0) { // If player score is already existed and having score_sum
332
            $scoreSumRewards = $leaderboard->scoreSumRewards();
333
            $rewardedScoreSum = 0;
334
            foreach ($scoreSumRewards as $scoreSumReward) {
335
                if ($scoreSumReward->score_sum <= $score->score_sum) {
336
                    $rewardedScoreSum = $scoreSumReward->score;
337
                    break;
338
                }
339
            }
340
            $playerReward = LeaderboardPlayerReward::where('player_id', $request->player_id)->where('leaderboard_timescope_id', $leaderboardTimescope->id)->whereNotNull('score_sum');
341
            if (!$playerReward) {
342
                $playerReward = LeaderboardPlayerReward::make(['leaderboard_timescope_id' => $leaderboardTimescope->id, 'player_id' => $request->player_id]);
343
            }
344
            $playerReward->score_sum = $rewardedScoreSum;
345
            $playerReward->save();
346
        }
347
348
        // Rank reward only report to last LeaderboardTimescope
349
350
        // dd ($leaderboardTimescope->previous());
351
        if ($leaderboardTimescope->previous() != null) {
352
            $leaderboardTimescope = $leaderboardTimescope->previous();
353
        }
354
355
        $playerReward = LeaderboardPlayerReward::firstOrNew(['player_id' => $request->player_id, 'leaderboard_timescope_id' => $leaderboardTimescope->id]);
356
        if ($request->has('rank')) {
357
            $playerReward->score_sum_rank = $request->rank;
358
        }
359
        if ($request->has('highscore_rank')) {
360
            $playerReward->highscore_rank = $request->highscore_rank;
361
        }
362
        $playerReward->save();
363
364
        return response($playerReward, 200);
365
    }
366
367
}
368