Test Setup Failed
Push — master ( 49d290...bfe50e )
by John
04:15
created

ContestModel::contestRank()   F

Complexity

Conditions 19
Paths 6

Size

Total Lines 134
Code Lines 99

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 99
nc 6
nop 2
dl 0
loc 134
rs 3.6351
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
namespace App\Models;
4
5
use GrahamCampbell\Markdown\Facades\Markdown;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Facades\DB;
8
9
class ContestModel extends Model
10
{
11
    protected $tableName = 'contest';
12
    public $rule = ["Unknown","ACM","OI","Custom ACM","Custom OI"];
13
14
    public function calcLength($a, $b)
15
    {
16
        $s=strtotime($b)-strtotime($a);
17
        $h=intval($s/3600);
18
        $m=round(($s-$h*3600)/60);
19
        if ($m==60) {
20
            $h++;
21
            $m=0;
22
        }
23
        if ($m==0 && $h==0) {
24
            $text="$s Seconds";
25
        } elseif ($m==0) {
26
            $text="$h Hours";
27
        } elseif ($h==0) {
28
            $text="$m Minutes";
29
        } else {
30
            $text="$h Hours $m Minutes";
31
        }
32
        return $text;
33
    }
34
35
    public function canViewContest($cid, $uid)
36
    {
37
        $contest_detail = DB::table($this->tableName)->where([
38
            "cid"=>$cid
39
        ])->first();
40
41
        if ($contest_detail["public"]==1) {
42
            return $contest_detail;
43
        } else {
44
            // group contest
45
            if ($uid==0) {
46
                return [];
47
            }
48
            $group_info = DB::table("group_member")->where([
49
                "uid"=>$uid,
50
                "gid"=>$contest_detail['gid'],
51
                ["role",">",0]
52
            ])->first();
53
            return empty($group_info) ? [] : $contest_detail;
54
        }
55
    }
56
57
    public function detail($cid, $uid = 0)
58
    {
59
        $contest_clearance = $this->judgeOutSideClearance($cid, $uid);
60
        $contest_detail = DB::table($this->tableName)->where([
61
            "cid"=>$cid
62
        ])->first();
63
64
        if ($contest_clearance==0) {
65
            return [
66
                "ret"=>1000,
67
                "desc"=>"You have no right to view this contest.",
68
                "data"=>null
69
            ];
70
        } else {
71
            $contest_detail["rule_parsed"]=$this->rule[$contest_detail["rule"]];
72
            $contest_detail["date_parsed"]=[
73
                "date"=>date_format(date_create($contest_detail["begin_time"]), 'j'),
74
                "month_year"=>date_format(date_create($contest_detail["begin_time"]), 'M, Y'),
75
            ];
76
            $contest_detail["length"]=$this->calcLength($contest_detail["begin_time"], $contest_detail["end_time"]);
77
            $contest_detail["description_parsed"]=clean(Markdown::convertToHtml($contest_detail["description"]));
78
            $contest_detail["group_info"]=DB::table("group")->where(["gid"=>$contest_detail["gid"]])->first();
79
            $contest_detail["problem_count"]=DB::table("contest_problem")->where(["cid"=>$cid])->count();
80
            return [
81
                "ret"=>200,
82
                "desc"=>"succeed",
83
                "data"=>[
84
                    "contest_detail"=>$contest_detail
85
                ]
86
            ];
87
        }
88
    }
89
90
    public function listByGroup($gid)
91
    {
92
        $contest_list = DB::table($this->tableName)->where([
93
            "gid"=>$gid
94
        ])->orderBy('begin_time', 'desc')->get()->all();
95
96
        foreach ($contest_list as &$c) {
97
            $c["rule_parsed"]=$this->rule[$c["rule"]];
98
            $c["date_parsed"]=[
99
                "date"=>date_format(date_create($c["begin_time"]), 'j'),
100
                "month_year"=>date_format(date_create($c["begin_time"]), 'M, Y'),
101
            ];
102
            $c["length"]=$this->calcLength($c["begin_time"], $c["end_time"]);
103
        }
104
        return $contest_list;
105
    }
106
107
    public function rule($cid)
108
    {
109
        return DB::table($this->tableName)->where([
110
            "cid"=>$cid
111
        ])->first()["rule"];
112
    }
113
114
    public function list()
115
    {
116
        $contest_list = DB::table($this->tableName)->where([
117
            "public"=>1,
118
            "audit_status"=>1
119
        ])->orderBy('begin_time', 'desc')->get()->all();
120
121
        foreach ($contest_list as &$c) {
122
            $c["rule_parsed"]=$this->rule[$c["rule"]];
123
            $c["date_parsed"]=[
124
                "date"=>date_format(date_create($c["begin_time"]), 'j'),
125
                "month_year"=>date_format(date_create($c["begin_time"]), 'M, Y'),
126
            ];
127
            $c["length"]=$this->calcLength($c["begin_time"], $c["end_time"]);
128
        }
129
        return $contest_list;
130
    }
131
132
    public function featured()
133
    {
134
        $featured = DB::table($this->tableName)->where([
135
            "public"=>1,
136
            "audit_status"=>1,
137
            "featured"=>1
138
        ])->orderBy('begin_time', 'desc')->first();
139
140
        $featured["rule_parsed"]=$this->rule[$featured["rule"]];
141
        $featured["date_parsed"]=[
142
            "date"=>date_format(date_create($featured["begin_time"]), 'j'),
143
            "month_year"=>date_format(date_create($featured["begin_time"]), 'M, Y'),
144
        ];
145
        $featured["length"]=$this->calcLength($featured["begin_time"], $featured["end_time"]);
146
        return $featured;
147
    }
148
149
    public function remainingTime($cid)
150
    {
151
        $end_time = DB::table($this->tableName)->where([
152
            "cid"=>$cid
153
        ])->select("end_time")->first()["end_time"];
154
        $end_time=strtotime($end_time);
155
        $cur_time=time();
156
        return $end_time-$cur_time;
157
    }
158
159
    public function intToChr($index, $start = 65)
160
    {
161
        $str = '';
162
        if (floor($index / 26) > 0) {
163
            $str .= $this->intToChr(floor($index / 26)-1);
164
        }
165
        return $str . chr($index % 26 + $start);
166
    }
167
168
    public function contestProblems($cid, $uid)
169
    {
170
        $submissionModel=new SubmissionModel();
171
172
        $contest_rule = $this->contestRule($cid);
173
174
        $problemSet = DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
175
            "cid"=>$cid
176
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
177
178
        foreach ($problemSet as &$p) {
179
            $frozen_time = strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
180
            if ($contest_rule==1) {
181
                $prob_stat = DB::table("submission")->select(
182
                    DB::raw("count(sid) as submission_count"),
183
                    DB::raw("sum(verdict='accepted') as passed_count"),
184
                    DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
185
                )->where([
186
                    "pid"=>$p["pid"],
187
                    "cid"=>$cid
188
                ])->where("submission_date", "<", $frozen_time)->first();
189
190
                if ($prob_stat["submission_count"]==0) {
191
                    $p["submission_count"]=0;
192
                    $p["passed_count"]=0;
193
                    $p["ac_rate"]=0;
194
                } else {
195
                    $p["submission_count"]=$prob_stat["submission_count"];
196
                    $p["passed_count"]=$prob_stat["passed_count"];
197
                    $p["ac_rate"]=round($prob_stat["ac_rate"], 2);
198
                }
199
            } else {
200
                $prob_stat = $this->contestProblemInfoOI($cid,$p["pid"],$uid);
201
                $p["points"] = $prob_stat["points"];
202
                $p["score"] = empty($prob_stat["score_parsed"])?0:$prob_stat["score_parsed"];
203
            }
204
            $prob_status=$submissionModel->getProblemStatus($p["pid"], $uid, $cid);
205
            if (empty($prob_status)) {
206
                $p["prob_status"]=[
207
                    "icon"=>"checkbox-blank-circle-outline",
208
                    "color"=>"wemd-grey-text"
209
                ];
210
            } else {
211
                $p["prob_status"]=[
212
                    "icon"=>$prob_status["verdict"]=="Accepted" ? "checkbox-blank-circle" : "cisco-webex",
213
                    "color"=>$prob_status["color"]
214
                ];
215
            }
216
        }
217
218
        return $problemSet;
219
    }
220
221
    public function getPid($cid, $ncode)
222
    {
223
        return DB::table("contest_problem")->where([
224
            "cid"=>$cid,
225
            "ncode"=>$ncode
226
        ])->select("contest_problem.pid")->first()["pid"];
227
    }
228
229
    public function getPcode($cid, $ncode)
0 ignored issues
show
Unused Code introduced by
The parameter $ncode is not used and could be removed. ( Ignorable by Annotation )

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

229
    public function getPcode($cid, /** @scrutinizer ignore-unused */ $ncode)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
230
    {
231
        return DB::table("problem")->where([
232
            "cid"=>$cid
233
        ])->select("contest_problem.pid")->first()["pcode"];
234
    }
235
236
    public function getCustomInfo($cid)
237
    {
238
        $basic_info = DB::table($this->tableName)->where([
239
            "cid"=>$cid
240
        ])->select("verified", "gid")->first();
241
        return $basic_info["verified"] ? DB::table("group")->where([
242
            "gid"=>$basic_info["gid"]
243
        ])->select("custom_icon", "custom_title", "gcode")->first() : null;
244
    }
245
246
247
    public function formatTime($seconds)
248
    {
249
        if ($seconds >3600) {
250
            $hours =intval($seconds/3600);
251
            $minutes = $seconds % 3600;
252
            $time = $hours.":".gmstrftime('%M:%S', $minutes);
253
        } else {
254
            $time = gmstrftime('%H:%M:%S', $seconds);
255
        }
256
        return $time;
257
    }
258
259
    public function contestProblemInfoOI($cid, $pid, $uid)
260
    {
261
        $ret=[
262
            "color"=>"",
263
            "score"=>null,
264
            "score_parsed"=>"",
265
            "points"=>DB::table("contest_problem")->where([
266
                "pid"=>$pid,
267
                "cid"=>$cid
268
            ])->first()["points"]
269
        ];
270
271
        $frozen_time = strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
272
273
        $highest_record = DB::table("submission")->where([
274
            "cid"=>$cid,
275
            "pid"=>$pid,
276
            "uid"=>$uid
277
        ])->where("submission_date", "<", $frozen_time)->orderBy('score', 'desc')->first();
278
279
        if (!empty($highest_record)) {
280
            $ret["score"]=$highest_record["score"];
281
282
            $tot_score=DB::table("problem")->where([
283
                "pid"=>$pid
284
            ])->first()["tot_score"];
285
286
            $ret["color"]=($ret["score"]==$tot_score)?"wemd-teal-text":"wemd-green-text";
287
            $ret["solved"]=($ret["score"]==$tot_score)?1:0;
288
            $ret["score_parsed"]=$ret["score"]/$tot_score*($ret["points"]);
289
        }
290
        return $ret;
291
    }
292
293
    public function contestProblemInfoACM($cid, $pid, $uid)
294
    {
295
        $ret=[
296
            "color"=>"",
297
            "solved"=>0,
298
            "solved_time"=>"",
299
            "solved_time_parsed"=>"",
300
            "wrong_doings"=>0,
301
            "color"=>"",
302
        ];
303
304
        $frozen_time = strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
305
306
        $ac_record = DB::table("submission")->where([
307
            "cid"=>$cid,
308
            "pid"=>$pid,
309
            "uid"=>$uid,
310
            "verdict"=>"Accepted"
311
        ])->where("submission_date", "<", $frozen_time)->orderBy('submission_date', 'asc')->first();
312
313
        if (!empty($ac_record)) {
314
            $ret["solved"]=1;
315
316
            $ret["solved_time"]=$ac_record["submission_date"] - strtotime(DB::table($this->tableName)->where([
317
                "cid"=>$cid
318
            ])->first()["begin_time"]);
319
320
            $ret["solved_time_parsed"]=$this->formatTime($ret["solved_time"]);
321
322
            $ret["wrong_doings"] = DB::table("submission")->where([
323
                "cid"=>$cid,
324
                "pid"=>$pid,
325
                "uid"=>$uid
326
            ])->whereIn('verdict', [
327
                'Runtime Error',
328
                'Wrong Answer',
329
                'Time Limit Exceed',
330
                'Real Time Limit Exceed',
331
                'Memory Limit Exceed',
332
                'Presentation Error',
333
                'Output Limit Exceeded'
334
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
335
336
            $others_first = DB::table("submission")->where([
337
                "cid"=>$cid,
338
                "pid"=>$pid,
339
                "verdict"=>"Accepted"
340
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
341
342
            $ret["color"]=$others_first?"wemd-green-text":"wemd-teal-text";
343
        } else {
344
            $ret["wrong_doings"] = DB::table("submission")->where([
345
                "cid"=>$cid,
346
                "pid"=>$pid,
347
                "uid"=>$uid
348
            ])->whereIn('verdict', [
349
                'Runtime Error',
350
                'Wrong Answer',
351
                'Time Limit Exceed',
352
                'Real Time Limit Exceed',
353
                'Memory Limit Exceed',
354
                'Presentation Error',
355
                'Output Limit Exceeded'
356
            ])->where("submission_date", "<", $frozen_time)->count();
357
        }
358
359
        return $ret;
360
    }
361
362
    public function contestRank($cid, $uid)
363
    {
364
        // [ToDo] If the current user's in the organizer group show nick name
365
        // [ToDo] The participants determination
366
        // [ToDo] Frozen Time
367
        // [ToDo] Performance Opt
368
        // [Todo] Ajaxization - Should have done in controller
369
        // [Todo] Authorization ( Public / Private ) - Should have done in controller
370
371
        $ret=[];
372
373
        $contest_info = DB::table("contest")->where("cid", $cid)->first();
374
375
        $user_in_group = !empty(DB::table("group_member")->where([
376
            "uid" => $uid,
377
            "gid" => $contest_info["gid"]
378
        ])->where("role",">",0)->first());
379
380
        if ($contest_info["registration"]) {
381
            $submissionUsers = DB::table("contest_participant")->where([
382
                "cid"=>$cid,
383
                "audit"=>1
384
            ])->select('uid')->get()->all();
385
        } else {
386
            // Those who submitted are participants
387
            $submissionUsers = DB::table("submission")->where([
388
                "cid"=>$cid
389
            ])->select('uid')->groupBy('uid')->get()->all();
390
        }
391
392
        $problemSet = DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
393
            "cid"=>$cid
394
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
395
396
        if ($contest_info["rule"]==1) {
397
            // ACM/ICPC Mode
398
            foreach ($submissionUsers as $s) {
399
                $prob_detail=[];
400
                $totPen=0;
401
                $totScore=0;
402
                foreach ($problemSet as $p) {
403
                    $prob_stat=$this->contestProblemInfoACM($cid, $p["pid"], $s["uid"]);
404
                    $prob_detail[]=[
405
                        "ncode"=>$p["ncode"],
406
                        "pid"=>$p["pid"],
407
                        "color"=>$prob_stat["color"],
408
                        "wrong_doings"=>$prob_stat["wrong_doings"],
409
                        "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
410
                    ];
411
                    if ($prob_stat["solved"]) {
412
                        $totPen+=$prob_stat["wrong_doings"]*20;
413
                        $totPen+=$prob_stat["solved_time"]/60;
414
                        $totScore+=$prob_stat["solved"];
415
                    }
416
                }
417
                $ret[]=[
418
                    "uid" => $s["uid"],
419
                    "name" => DB::table("users")->where([
420
                        "id"=>$s["uid"]
421
                    ])->first()["name"],
422
                    "nick_name" => $user_in_group ? DB::table("group_member")->where([
423
                        "uid" => $s["uid"],
424
                        "gid" => $contest_info["gid"]
425
                    ])->where("role", ">", 0)->first()["nick_name"] : "",
426
                    "score" => $totScore,
427
                    "penalty" => $totPen,
428
                    "problem_detail" => $prob_detail
429
                ];
430
            }
431
            usort($ret, function ($a, $b) {
432
                if ($a["score"]==$b["score"]) {
433
                    if ($a["penalty"]==$b["penalty"]) {
434
                        return 0;
435
                    } elseif (($a["penalty"]>$b["penalty"])) {
436
                        return 1;
437
                    } else {
438
                        return -1;
439
                    }
440
                } elseif ($a["score"]>$b["score"]) {
441
                    return -1;
442
                } else {
443
                    return 1;
444
                }
445
            });
446
        } else if ($contest_info["rule"]==2) {
447
            // OI Mode
448
            foreach ($submissionUsers as $s) {
449
                $prob_detail=[];
450
                $totScore=0;
451
                $totSolved=0;
452
                foreach ($problemSet as $p) {
453
                    $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $s["uid"]);
454
                    $prob_detail[]=[
455
                        "ncode"=>$p["ncode"],
456
                        "pid"=>$p["pid"],
457
                        "color"=>$prob_stat["color"],
458
                        "score"=>$prob_stat["score"],
459
                        "score_parsed"=>$prob_stat["score_parsed"]
460
                    ];
461
                    $totSolved+=$prob_stat["solved"];
462
                    $totScore+=intval($prob_stat["score_parsed"]);
463
                }
464
                $ret[]=[
465
                    "uid" => $s["uid"],
466
                    "name" => DB::table("users")->where([
467
                        "id"=>$s["uid"]
468
                    ])->first()["name"],
469
                    "nick_name" => $user_in_group ? DB::table("group_member")->where([
470
                        "uid" => $s["uid"],
471
                        "gid" => $contest_info["gid"]
472
                    ])->where("role", ">", 0)->first()["nick_name"] : "",
473
                    "score" => $totSolved,
474
                    "solved" => 0,
475
                    "problem_detail" => $prob_detail
476
                ];
477
            }
478
            usort($ret, function ($a, $b) {
479
                if ($a["score"]==$b["score"]) {
480
                    if ($a["solved"]==$b["solved"]) {
481
                        return 0;
482
                    } elseif (($a["solved"]<$b["solved"])) {
483
                        return 1;
484
                    } else {
485
                        return -1;
486
                    }
487
                } elseif ($a["score"]>$b["score"]) {
488
                    return -1;
489
                } else {
490
                    return 1;
491
                }
492
            });
493
        }
494
495
        return $ret;
496
    }
497
498
    public function getClarificationList($cid)
499
    {
500
        return DB::table("contest_clarification")->where([
501
            "cid"=>$cid,
502
            "public"=>1
503
        ])->orderBy('create_time', 'desc')->get()->all();
504
    }
505
506
    public function getClarificationDetail($ccid)
507
    {
508
        return DB::table("contest_clarification")->where([
509
            "ccid"=>$ccid,
510
            "public"=>1
511
        ])->first();
512
    }
513
514
    public function isContestEnded($cid)
515
    {
516
        return DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
517
    }
518
519
    public function judgeClearance($cid, $uid = 0)
520
    {
521
        if ($uid==0) {
522
            return 0;
523
        }
524
        $contest_started = DB::table("contest")->where("cid", $cid)->where("begin_time", "<", date("Y-m-d H:i:s"))->count();
525
        $contest_ended = DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
0 ignored issues
show
Unused Code introduced by
The assignment to $contest_ended is dead and can be removed.
Loading history...
526
        if ($contest_started) {
527
            // judge if qualified
528
            // return 1 if view access, can only view
529
            // return 2 if participant access, can submit code
530
            // return 3 if admin access, can create announcements
531
            $contest_info = DB::table("contest")->where("cid", $cid)->first();
532
            if ($contest_info["registration"]) {
533
                // check if uid in registration, temp return 3
534
                return 2;
535
            } else {
536
                if ($contest_info["public"]) {
537
                    return 2;
538
                } else {
539
                    return DB::table("group_member")->where([
540
                        "gid"=> $contest_info["gid"],
541
                        "uid"=> $uid
542
                    ])->where("role", ">", 0)->count() ? 2 : 0;
543
                }
544
            }
545
        } else {
546
            // not started or do not exist
547
            return 0;
548
        }
549
    }
550
551
    public function judgeOutsideClearance($cid, $uid = 0)
552
    {
553
        $contest_info = DB::table("contest")->where("cid", $cid)->first();
554
        if (empty($contest_info)) {
555
            return 0;
556
        }
557
        if ($contest_info["public"]) {
558
            return 1;
559
        } else {
560
            if ($uid==0) {
561
                return 0;
562
            }
563
            return DB::table("group_member")->where([
564
                "gid"=> $contest_info["gid"],
565
                "uid"=> $uid
566
            ])->where("role", ">", 0)->count() ? 1 : 0;
567
        }
568
    }
569
570
    public function contestName($cid)
571
    {
572
        return DB::table("contest")->where("cid", $cid)->select("name")->first()["name"];
573
    }
574
575
    public function contestRule($cid)
576
    {
577
        return DB::table("contest")->where("cid", $cid)->select("rule")->first()["rule"];
578
    }
579
580
    public function arrangeContest($gid, $config, $problems)
581
    {
582
        DB::transaction(function () use ($gid, $config, $problems) {
583
            $cid = DB::table($this->tableName)->insertGetId([
584
                "gid"=>$gid,
585
                "name"=>$config["name"],
586
                "verified"=>0,                          //todo
587
                "rated"=>0,
588
                "anticheated"=>0,
589
                "featured"=>0,
590
                "description"=>$config["description"],
591
                "rule"=>1,                              //todo
592
                "begin_time"=>$config["begin_time"],
593
                "end_time"=>$config["end_time"],
594
                "public"=>0,                            //todo
595
                "registration"=>0,                      //todo
596
                "registration_due"=>null,               //todo
597
                "registant_type"=>0,                    //todo
598
                "froze_length"=>0,                      //todo
599
                "status_visibility"=>3,                 //todo
600
                "create_time"=>date("Y-m-d H:i:s"),
601
                "audit_status"=>1                       //todo
602
            ]);
603
604
            foreach ($problems as $p) {
605
                $pid=DB::table("problem")->where(["pcode"=>$p["pcode"]])->select("pid")->first()["pid"];
606
                DB::table("contest_problem")->insert([
607
                    "cid"=>$cid,
608
                    "number"=>$p["number"],
609
                    "ncode"=>$this->intToChr($p["number"]-1),
610
                    "pid"=>$pid,
611
                    "alias"=>"",
612
                    "points"=>0
613
                ]);
614
            }
615
        }, 5);
616
    }
617
}
618