Passed
Push — master ( 61a757...a989ff )
by
unknown
04:38 queued 10s
created

ContestModel::getPcode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
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
use App\Models\Rating\RatingCalculator;
9
use Auth;
10
use Cache;
11
use Log;
12
13
class ContestModel extends Model
14
{
15
    protected $tableName='contest';
16
    protected $table='contest';
17
    protected $primaryKey='cid';
18
    const DELETED_AT=null;
19
    const UPDATED_AT=null;
20
    const CREATED_AT=null;
21
22
    public $rule=["Unknown", "ICPC", "OI", "Custom ICPC", "Custom OI"];
23
24
    public function calcLength($a, $b)
25
    {
26
        $s=strtotime($b)-strtotime($a);
27
        $h=intval($s / 3600);
28
        $m=round(($s-$h * 3600) / 60);
29
        if ($m==60) {
30
            $h++;
31
            $m=0;
32
        }
33
        if ($m==0 && $h==0) {
34
            $text="$s Seconds";
35
        } elseif ($m==0) {
36
            $text="$h Hours";
37
        } elseif ($h==0) {
38
            $text="$m Minutes";
39
        } else {
40
            $text="$h Hours $m Minutes";
41
        }
42
        return $text;
43
    }
44
45
    public function canViewContest($cid, $uid)
46
    {
47
        $contest_detail=DB::table($this->tableName)->where([
48
            "cid"=>$cid
49
        ])->first();
50
51
        if ($contest_detail["public"]==1) {
52
            return $contest_detail;
53
        } else {
54
            // group contest
55
            if ($uid==0) {
56
                return [];
57
            }
58
            $group_info=DB::table("group_member")->where([
59
                "uid"=>$uid,
60
                "gid"=>$contest_detail['gid'],
61
                ["role", ">", 0]
62
            ])->first();
63
            return empty($group_info) ? [] : $contest_detail;
64
        }
65
    }
66
67
    public function basic($cid)
68
    {
69
        return DB::table($this->tableName)->where([
70
            "cid"=>$cid
71
        ])->first();
72
    }
73
74
    public function detail($cid, $uid=0)
75
    {
76
        $contest_clearance=$this->judgeOutSideClearance($cid, $uid);
77
        $contest_detail=$this->basic($cid);
78
79
        if ($contest_clearance==0) {
80
            return [
81
                "ret"=>1000,
82
                "desc"=>"You have no right to view this contest.",
83
                "data"=>null
84
            ];
85
        } else {
86
            $contest_detail["rule_parsed"]=$this->rule[$contest_detail["rule"]];
87
            $contest_detail["date_parsed"]=[
88
                "date"=>date_format(date_create($contest_detail["begin_time"]), 'j'),
89
                "month_year"=>date_format(date_create($contest_detail["begin_time"]), 'M, Y'),
90
            ];
91
            $contest_detail["length"]=$this->calcLength($contest_detail["begin_time"], $contest_detail["end_time"]);
92
            $contest_detail["description_parsed"]=clean(Markdown::convertToHtml($contest_detail["description"]));
93
            $contest_detail["group_info"]=DB::table("group")->where(["gid"=>$contest_detail["gid"]])->first();
94
            $contest_detail["problem_count"]=DB::table("contest_problem")->where(["cid"=>$cid])->count();
95
            return [
96
                "ret"=>200,
97
                "desc"=>"succeed",
98
                "data"=>[
99
                    "contest_detail"=>$contest_detail
100
                ]
101
            ];
102
        }
103
    }
104
105
    public function gid($cid)
106
    {
107
        return DB::table($this->tableName)->where([
108
            "cid"=>$cid
109
        ])->first()["gid"];
110
    }
111
112
    public function grantAccess($uid, $cid, $audit=0)
113
    {
114
        return DB::table('contest_participant')->insert([
115
            "cid"=>$cid,
116
            "uid"=>$uid,
117
            "audit"=>$audit
118
        ]);
119
    }
120
121
    public function listByGroup($gid)
122
    {
123
        // $contest_list=DB::table($this->tableName)->where([
124
        //     "gid"=>$gid
125
        // ])->orderBy('begin_time', 'desc')->get()->all();
126
        $preQuery=DB::table($this->tableName);
127
        $paginator=$preQuery->where('gid','=',$gid)->orderBy('begin_time', 'desc')->paginate(10);
128
        $contest_list=$paginator->all();
129
        if(empty($contest_list)){
130
            return null;
131
        }
132
133
        foreach ($contest_list as &$c) {
134
            $c["rule_parsed"]=$this->rule[$c["rule"]];
135
            $c["date_parsed"]=[
136
                "date"=>date_format(date_create($c["begin_time"]), 'j'),
137
                "month_year"=>date_format(date_create($c["begin_time"]), 'M, Y'),
138
            ];
139
            $c["length"]=$this->calcLength($c["begin_time"], $c["end_time"]);
140
        }
141
        return [
142
            'paginator' => $paginator,
143
            'contest_list' => $contest_list,
144
        ];
145
    }
146
147
    public function rule($cid)
148
    {
149
        return DB::table($this->tableName)->where([
150
            "cid"=>$cid
151
        ])->first()["rule"];
152
    }
153
154
    public function list($uid)
155
    {
156
        if ($uid) {
157
            //$paginator=DB::select('SELECT DISTINCT contest.* FROM group_member inner join contest on group_member.gid=contest.gid left join contest_participant on contest.cid=contest_participant.cid where (public=1 and audit=1) or (group_member.uid=:uid and group_member.role>0 and (contest_participant.uid=:uidd or ISNULL(contest_participant.uid)) and (registration=0 or (registration=1 and not ISNULL(contest_participant.uid))))',["uid"=>$uid,"uidd"=>$uid])->paginate(10);
158
            $paginator=DB::table('group_member')
159
                ->distinct()
160
                ->select('contest.*')
161
                ->join('contest', 'group_member.gid', '=', 'contest.gid')
162
                ->leftJoin('contest_participant', 'contest.cid', '=', 'contest_participant.cid')
163
                ->where(
164
                    function ($query) {
165
                        $query->where('public', 1)
166
                              ->where('audit_status', 1);
167
                    }
168
                )
169
                ->orWhere(
170
                    function ($query) use ($uid) {
171
                        $query->where('group_member.uid', $uid)
172
                                ->where('group_member.role', '>', 0);
173
                            //     ->where(function ($query) use ($uid) {
174
                            //         $query->where('contest_participant.uid', $uid)
175
                            //               ->orWhereNull('contest_participant.uid');
176
                            //     })
177
                            //   ->where(function ($query) {
178
                            //       $query->where('registration', 0)
179
                            //                     ->orWhere(function ($query) {
180
                            //                         $query->where('registration', 1)
181
                            //                               ->whereNotNull('contest_participant.uid');
182
                            //                     });
183
                            //   });
184
                    }
185
                )
186
                ->orderBy('contest.begin_time', 'desc')
187
                ->paginate(10, ['contest.cid']);
188
189
        /*  $paginator=DB::table($this->tableName)->where([
190
             "public"=>1,
191
             "audit_status"=>1
192
         ])->orderBy('begin_time', 'desc')->paginate(10); */
193
        } else {
194
            $paginator=DB::table($this->tableName)->where([
195
                "public"=>1,
196
                "audit_status"=>1
197
            ])->orderBy('begin_time', 'desc')->paginate(10);
198
        }
199
        $contest_list=$paginator->all();
200
        foreach ($contest_list as &$c) {
201
            $c["rule_parsed"]=$this->rule[$c["rule"]];
202
            $c["date_parsed"]=[
203
                "date"=>date_format(date_create($c["begin_time"]), 'j'),
204
                "month_year"=>date_format(date_create($c["begin_time"]), 'M, Y'),
205
            ];
206
            $c["length"]=$this->calcLength($c["begin_time"], $c["end_time"]);
207
        }
208
        return [
209
            'contents' => $contest_list,
210
            'paginator' => $paginator
211
        ];
212
    }
213
214
    public function featured()
215
    {
216
        $featured=DB::table($this->tableName)->where([
217
            "public"=>1,
218
            "audit_status"=>1,
219
            "featured"=>1
220
        ])->orderBy('begin_time', 'desc')->first();
221
222
        if (!empty($featured)) {
223
            $featured["rule_parsed"]=$this->rule[$featured["rule"]];
224
            $featured["date_parsed"]=[
225
                "date"=>date_format(date_create($featured["begin_time"]), 'j'),
226
                "month_year"=>date_format(date_create($featured["begin_time"]), 'M, Y'),
227
            ];
228
            $featured["length"]=$this->calcLength($featured["begin_time"], $featured["end_time"]);
229
            return $featured;
230
        } else {
231
            return null;
232
        }
233
    }
234
235
    public function registContest($cid,$uid)
236
    {
237
        $registered=DB::table("contest_participant")->where([
238
            "cid"=>$cid,
239
            "uid"=>$uid
240
        ])->first();
241
242
        if(empty($registered)){
243
            DB::table("contest_participant")->insert([
244
                "cid"=>$cid,
245
                "uid"=>$uid,
246
                "audit"=>1
247
            ]);
248
            return true;
249
        }
250
        return false;
251
    }
252
253
    public function remainingTime($cid)
254
    {
255
        $end_time=DB::table($this->tableName)->where([
256
            "cid"=>$cid
257
        ])->select("end_time")->first()["end_time"];
258
        $end_time=strtotime($end_time);
259
        $cur_time=time();
260
        return $end_time-$cur_time;
261
    }
262
263
    public function intToChr($index, $start=65)
264
    {
265
        $str='';
266
        if (floor($index / 26)>0) {
267
            $str.=$this->intToChr(floor($index / 26)-1);
268
        }
269
        return $str.chr($index % 26+$start);
270
    }
271
272
    public function contestProblems($cid, $uid)
273
    {
274
        $submissionModel=new SubmissionModel();
275
276
        $contest_rule=$this->contestRule($cid);
277
278
        $problemSet=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
279
            "cid"=>$cid
280
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
281
282
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
283
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
0 ignored issues
show
Unused Code introduced by
The assignment to $end_time is dead and can be removed.
Loading history...
284
285
        foreach ($problemSet as &$p) {
286
            if ($contest_rule==1) {
287
                $prob_stat=DB::table("submission")->select(
288
                    DB::raw("count(sid) as submission_count"),
289
                    DB::raw("sum(verdict='accepted') as passed_count"),
290
                    DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
291
                )->where([
292
                    "pid"=>$p["pid"],
293
                    "cid"=>$cid
294
                ])->where("submission_date", "<", $frozen_time)->first();
295
296
                if ($prob_stat["submission_count"]==0) {
297
                    $p["submission_count"]=0;
298
                    $p["passed_count"]=0;
299
                    $p["ac_rate"]=0;
300
                } else {
301
                    $p["submission_count"]=$prob_stat["submission_count"];
302
                    $p["passed_count"]=$prob_stat["passed_count"];
303
                    $p["ac_rate"]=round($prob_stat["ac_rate"], 2);
304
                }
305
            } else {
306
                $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $uid);
307
                $p["points"]=$prob_stat["points"];
308
                $p["score"]=empty($prob_stat["score_parsed"]) ? 0 : $prob_stat["score_parsed"];
309
            }
310
            $prob_status=$submissionModel->getProblemStatus($p["pid"], $uid, $cid);
311
            if (empty($prob_status)) {
312
                $p["prob_status"]=[
313
                    "icon"=>"checkbox-blank-circle-outline",
314
                    "color"=>"wemd-grey-text"
315
                ];
316
            } else {
317
                $p["prob_status"]=[
318
                    "icon"=>$prob_status["verdict"]=="Accepted" ? "checkbox-blank-circle" : "cisco-webex",
319
                    "color"=>$prob_status["color"]
320
                ];
321
            }
322
        }
323
324
        return $problemSet;
325
    }
326
327
    public function getPid($cid, $ncode)
328
    {
329
        return DB::table("contest_problem")->where([
330
            "cid"=>$cid,
331
            "ncode"=>$ncode
332
        ])->select("contest_problem.pid")->first()["pid"];
333
    }
334
335
    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

335
    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...
336
    {
337
        return DB::table("problem")->where([
338
            "cid"=>$cid
339
        ])->select("contest_problem.pid")->first()["pcode"];
340
    }
341
342
    public function getCustomInfo($cid)
343
    {
344
        $basic_info=DB::table($this->tableName)->where([
345
            "cid"=>$cid
346
        ])->select("verified", "custom_icon", "custom_title")->first();
347
        return $basic_info["verified"] ? ((is_null($basic_info["custom_icon"]) && is_null($basic_info["custom_title"])) ?null:$basic_info) : null;
348
    }
349
350
351
    public function formatTime($seconds)
352
    {
353
        if ($seconds>3600) {
354
            $hours=intval($seconds / 3600);
355
            $minutes=$seconds % 3600;
356
            $time=$hours.":".gmstrftime('%M:%S', $minutes);
357
        } else {
358
            $time=gmstrftime('%H:%M:%S', $seconds);
359
        }
360
        return $time;
361
    }
362
363
    public function contestProblemInfoOI($cid, $pid, $uid)
364
    {
365
        $ret=[
366
            "color"=>"",
367
            "score"=>null,
368
            "score_parsed"=>"",
369
            "solved"=>0,
370
            "points"=>DB::table("contest_problem")->where([
371
                "pid"=>$pid,
372
                "cid"=>$cid
373
            ])->first()["points"]
374
        ];
375
376
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
377
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
0 ignored issues
show
Unused Code introduced by
The assignment to $end_time is dead and can be removed.
Loading history...
378
379
        $highest_record=DB::table("submission")->where([
380
            "cid"=>$cid,
381
            "pid"=>$pid,
382
            "uid"=>$uid
383
        ])->where("submission_date", "<", $frozen_time)->orderBy('score', 'desc')->first();
384
385
        if (!empty($highest_record)) {
386
            $ret["score"]=$highest_record["score"];
387
388
            $tot_score=DB::table("problem")->where([
389
                "pid"=>$pid
390
            ])->first()["tot_score"];
391
392
            $ret["color"]=($ret["score"]==$tot_score) ? "wemd-teal-text" : "wemd-green-text";
393
            $ret["solved"]=($ret["score"]==$tot_score) ? 1 : 0;
394
            $ret["score_parsed"]=$ret["score"] / $tot_score * ($ret["points"]);
395
        }
396
        return $ret;
397
    }
398
399
    public function isFrozen($cid)
400
    {
401
        $frozen=DB::table("contest")->where(["cid"=>$cid])->select("froze_length", DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first();
402
        if (empty($frozen["froze_length"])) {
403
            return false;
404
        } else {
405
            return time()>$frozen["frozen_time"];
406
        }
407
    }
408
409
    public function contestProblemInfoACM($cid, $pid, $uid)
410
    {
411
        $ret=[
412
            "color"=>"",
413
            "solved"=>0,
414
            "solved_time"=>"",
415
            "solved_time_parsed"=>"",
416
            "wrong_doings"=>0,
417
            "color"=>"",
418
        ];
419
420
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
421
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
0 ignored issues
show
Unused Code introduced by
The assignment to $end_time is dead and can be removed.
Loading history...
422
423
        $ac_record=DB::table("submission")->where([
424
            "cid"=>$cid,
425
            "pid"=>$pid,
426
            "uid"=>$uid,
427
            "verdict"=>"Accepted"
428
        ])->where("submission_date", "<", $frozen_time)->orderBy('submission_date', 'asc')->first();
429
430
        if (!empty($ac_record)) {
431
            $ret["solved"]=1;
432
433
            $ret["solved_time"]=$ac_record["submission_date"]-strtotime(DB::table($this->tableName)->where([
434
                "cid"=>$cid
435
            ])->first()["begin_time"]);
436
437
            $ret["solved_time_parsed"]=$this->formatTime($ret["solved_time"]);
438
439
            $ret["wrong_doings"]=DB::table("submission")->where([
440
                "cid"=>$cid,
441
                "pid"=>$pid,
442
                "uid"=>$uid
443
            ])->whereIn('verdict', [
444
                'Runtime Error',
445
                'Wrong Answer',
446
                'Time Limit Exceed',
447
                'Real Time Limit Exceed',
448
                'Memory Limit Exceed',
449
                'Presentation Error',
450
                'Output Limit Exceeded'
451
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
452
453
            $others_first=DB::table("submission")->where([
454
                "cid"=>$cid,
455
                "pid"=>$pid,
456
                "verdict"=>"Accepted"
457
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
458
459
            $ret["color"]=$others_first ? "wemd-green-text" : "wemd-teal-text";
460
        } else {
461
            $ret["wrong_doings"]=DB::table("submission")->where([
462
                "cid"=>$cid,
463
                "pid"=>$pid,
464
                "uid"=>$uid
465
            ])->whereIn('verdict', [
466
                'Runtime Error',
467
                'Wrong Answer',
468
                'Time Limit Exceed',
469
                'Real Time Limit Exceed',
470
                'Memory Limit Exceed',
471
                'Presentation Error',
472
                'Output Limit Exceeded'
473
            ])->where("submission_date", "<", $frozen_time)->count();
474
        }
475
476
        return $ret;
477
    }
478
479
    public function contestRankCache($cid)
480
    {
481
        // if(Cache::tags(['contest','rank'])->get($cid)!=null) return Cache::tags(['contest','rank'])->get($cid);
482
        $ret=[];
483
484
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
485
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
486
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
0 ignored issues
show
Unused Code introduced by
The assignment to $end_time is dead and can be removed.
Loading history...
487
488
        if ($contest_info["registration"]) {
489
            $submissionUsers=DB::table("contest_participant")->where([
490
                "cid"=>$cid,
491
                "audit"=>1
492
            ])->select('uid')->get()->all();
493
        } else {
494
            // Those who submitted are participants
495
            $submissionUsers=DB::table("submission")->where([
496
                "cid"=>$cid
497
            ])->where(
498
                "submission_date",
499
                "<",
500
                $frozen_time
501
            )->select('uid')->groupBy('uid')->get()->all();
502
        }
503
504
        $problemSet=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
505
            "cid"=>$cid
506
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
507
508
        if ($contest_info["rule"]==1) {
509
            // ACM/ICPC Mode
510
            foreach ($submissionUsers as $s) {
511
                $prob_detail=[];
512
                $totPen=0;
513
                $totScore=0;
514
                foreach ($problemSet as $p) {
515
                    $prob_stat=$this->contestProblemInfoACM($cid, $p["pid"], $s["uid"]);
516
                    $prob_detail[]=[
517
                        "ncode"=>$p["ncode"],
518
                        "pid"=>$p["pid"],
519
                        "color"=>$prob_stat["color"],
520
                        "wrong_doings"=>$prob_stat["wrong_doings"],
521
                        "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
522
                    ];
523
                    if ($prob_stat["solved"]) {
524
                        $totPen+=$prob_stat["wrong_doings"] * 20;
525
                        $totPen+=$prob_stat["solved_time"] / 60;
526
                        $totScore+=$prob_stat["solved"];
527
                    }
528
                }
529
                $ret[]=[
530
                    "uid" => $s["uid"],
531
                    "name" => DB::table("users")->where([
532
                        "id"=>$s["uid"]
533
                    ])->first()["name"],
534
                    "nick_name" => DB::table("group_member")->where([
535
                        "uid" => $s["uid"],
536
                        "gid" => $contest_info["gid"]
537
                    ])->where("role", ">", 0)->first()["nick_name"],
538
                    "score" => $totScore,
539
                    "penalty" => $totPen,
540
                    "problem_detail" => $prob_detail
541
                ];
542
            }
543
            usort($ret, function ($a, $b) {
544
                if ($a["score"]==$b["score"]) {
545
                    if ($a["penalty"]==$b["penalty"]) {
546
                        return 0;
547
                    } elseif (($a["penalty"]>$b["penalty"])) {
548
                        return 1;
549
                    } else {
550
                        return -1;
551
                    }
552
                } elseif ($a["score"]>$b["score"]) {
553
                    return -1;
554
                } else {
555
                    return 1;
556
                }
557
            });
558
        } elseif ($contest_info["rule"]==2) {
559
            // OI Mode
560
            foreach ($submissionUsers as $s) {
561
                $prob_detail=[];
562
                $totScore=0;
563
                $totSolved=0;
564
                foreach ($problemSet as $p) {
565
                    $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $s["uid"]);
566
                    $prob_detail[]=[
567
                        "ncode"=>$p["ncode"],
568
                        "pid"=>$p["pid"],
569
                        "color"=>$prob_stat["color"],
570
                        "score"=>$prob_stat["score"],
571
                        "score_parsed"=>$prob_stat["score_parsed"]
572
                    ];
573
                    $totSolved+=$prob_stat["solved"];
574
                    $totScore+=intval($prob_stat["score_parsed"]);
575
                }
576
                $ret[]=[
577
                    "uid" => $s["uid"],
578
                    "name" => DB::table("users")->where([
579
                        "id"=>$s["uid"]
580
                    ])->first()["name"],
581
                    "nick_name" => DB::table("group_member")->where([
582
                        "uid" => $s["uid"],
583
                        "gid" => $contest_info["gid"]
584
                    ])->where("role", ">", 0)->first()["nick_name"],
585
                    "score" => $totScore,
586
                    "solved" => $totSolved,
587
                    "problem_detail" => $prob_detail
588
                ];
589
            }
590
            usort($ret, function ($a, $b) {
591
                if ($a["score"]==$b["score"]) {
592
                    if ($a["solved"]==$b["solved"]) {
593
                        return 0;
594
                    } elseif (($a["solved"]<$b["solved"])) {
595
                        return 1;
596
                    } else {
597
                        return -1;
598
                    }
599
                } elseif ($a["score"]>$b["score"]) {
600
                    return -1;
601
                } else {
602
                    return 1;
603
                }
604
            });
605
        }
606
607
        Cache::tags(['contest', 'rank'])->put($cid, $ret, 60);
608
609
        return $ret;
610
    }
611
612
    public function contestRank($cid, $uid)
613
    {
614
        // [ToDo] If the current user's in the organizer group show nick name
615
        // [ToDo] The participants determination
616
        // [ToDo] Frozen Time
617
        // [ToDo] Performance Opt
618
        // [Todo] Ajaxization - Should have done in controller
619
        // [Todo] Authorization ( Public / Private ) - Should have done in controller
620
621
        $ret=[];
0 ignored issues
show
Unused Code introduced by
The assignment to $ret is dead and can be removed.
Loading history...
622
623
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
624
625
        $user_in_group=!empty(DB::table("group_member")->where([
626
            "uid" => $uid,
627
            "gid" => $contest_info["gid"]
628
        ])->where("role", ">", 0)->first());
629
630
        $contestRankRaw=Cache::tags(['contest', 'rank'])->get($cid);
631
632
        if ($contestRankRaw==null) {
633
            $contestRankRaw=$this->contestRankCache($cid);
634
        }
635
636
        $ret=$contestRankRaw;
637
638
        foreach ($ret as $r) {
639
            if (!$user_in_group) {
640
                $r["nick_name"]='';
641
            }
642
        }
643
644
        return $ret;
645
    }
646
647
    public function getRejudgeQueue($cid)
648
    {
649
        $problemModel=new ProblemModel();
650
        $submissionModel=new SubmissionModel();
0 ignored issues
show
Unused Code introduced by
The assignment to $submissionModel is dead and can be removed.
Loading history...
651
        $compilerModel=new CompilerModel();
652
653
        $tempQueue=DB::table("submission")->where([
654
            "cid"=>$cid
655
        ])->whereIn('verdict', [
656
            'Runtime Error',
657
            'Wrong Answer',
658
            'Time Limit Exceed',
659
            'Real Time Limit Exceed',
660
            'Memory Limit Exceed',
661
            'Presentation Error',
662
            'Output Limit Exceeded'
663
        ])->get()->all();
664
665
        foreach ($tempQueue as &$t) {
666
            $lang=$compilerModel->detail($t["coid"]);
667
            $probBasic=$problemModel->basic($t["pid"]);
668
            $t["oj"]=$problemModel->ocode($t["pid"]);
669
            $t["lang"]=$lang['lcode'];
670
            $t["cid"]=$probBasic["contest_id"];
671
            $t["iid"]=$probBasic["index_id"];
672
            $t["pcode"]=$probBasic["pcode"];
673
            $t["contest"]=$cid;
674
        }
675
676
        return $tempQueue;
677
    }
678
679
    public function getClarificationList($cid)
680
    {
681
        return DB::table("contest_clarification")->where([
682
            "cid"=>$cid
683
        ])->where(function ($query) {
684
            $query->where([
685
                "public"=>1
686
            ])->orWhere([
687
                "uid" => Auth::user()->id
688
            ]);
689
        })->orderBy('create_time', 'desc')->get()->all();
690
    }
691
692
    public function fetchClarification($cid)
693
    {
694
        return DB::table("contest_clarification")->where([
695
            "cid"=>$cid,
696
            "type"=>0,
697
            "public"=>1
698
        ])->whereBetween(
699
            'create_time',
700
            [
701
                date("Y-m-d H:i:s", time()-59),
702
                date("Y-m-d H:i:s")
703
            ]
704
        )->first();
705
    }
706
707
    public function getlatestClarification($cid)
708
    {
709
        return DB::table("contest_clarification")->where([
710
            "cid"=>$cid,
711
            "type"=>0,
712
            "public"=>1
713
        ])->orderBy('create_time', 'desc')->first();
714
    }
715
716
    public function getClarificationDetail($ccid)
717
    {
718
        return DB::table("contest_clarification")->where([
719
            "ccid"=>$ccid,
720
            "public"=>1
721
        ])->first();
722
    }
723
724
    public function requestClarification($cid, $title, $content, $uid)
725
    {
726
        return DB::table("contest_clarification")->insertGetId([
727
            "cid"=>$cid,
728
            "type"=>1,
729
            "title"=>$title,
730
            "content"=>$content,
731
            "public"=>"0",
732
            "uid"=>$uid,
733
            "create_time"=>date("Y-m-d H:i:s")
734
        ]);
735
    }
736
737
    public function isContestEnded($cid)
738
    {
739
        return DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
740
    }
741
742
    public function isContestRunning($cid)
743
    {
744
        return DB::table("contest")->where("cid", $cid)->where("begin_time", "<", date("Y-m-d H:i:s"))->where("end_time", ">", date("Y-m-d H:i:s"))->count();
745
    }
746
747
    public function formatSubmitTime($date)
748
    {
749
        $periods=["second", "minute", "hour", "day", "week", "month", "year", "decade"];
750
        $lengths=["60", "60", "24", "7", "4.35", "12", "10"];
751
752
        $now=time();
753
        $unix_date=strtotime($date);
754
755
        if (empty($unix_date)) {
756
            return "Bad date";
757
        }
758
759
        if ($now>$unix_date) {
760
            $difference=$now-$unix_date;
761
            $tense="ago";
762
        } else {
763
            $difference=$unix_date-$now;
764
            $tense="from now";
765
        }
766
767
        for ($j=0; $difference>=$lengths[$j] && $j<count($lengths)-1; $j++) {
768
            $difference/=$lengths[$j];
769
        }
770
771
        $difference=round($difference);
772
773
        if ($difference!=1) {
774
            $periods[$j].="s";
775
        }
776
777
        return "$difference $periods[$j] {$tense}";
778
    }
779
780
    public function formatAbsTime($sec)
781
    {
782
        $periods=["second", "minute", "hour", "day", "week", "month", "year", "decade"];
783
        $lengths=["60", "60", "24", "7", "4.35", "12", "10"];
784
785
786
        $difference=$sec;
787
788
        for ($j=0; $difference>=$lengths[$j] && $j<count($lengths)-1; $j++) {
789
            $difference/=$lengths[$j];
790
        }
791
792
        $difference=round($difference);
793
794
        if ($difference!=1) {
795
            $periods[$j].="s";
796
        }
797
798
        return "$difference $periods[$j]";
799
    }
800
801
    public function frozenTime($cid)
802
    {
803
        $basicInfo=$this->basic($cid);
804
        return $this->formatAbsTime($basicInfo["froze_length"]);
805
    }
806
807
808
    public function getContestRecord($cid)
809
    {
810
        $basicInfo=$this->basic($cid);
811
        $problemSet_temp=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
812
            "cid"=>$cid
813
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title", "points", "tot_score")->get()->all();
814
        $problemSet=[];
815
        foreach ($problemSet_temp as $p) {
816
            $problemSet[(string) $p["pid"]]=["ncode"=>$p["ncode"], "points"=>$p["points"], "tot_score"=>$p["tot_score"]];
817
        }
818
819
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
820
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
821
        $contestEnd=time()>$end_time;
822
823
        if ($basicInfo["status_visibility"]==2) {
824
            // View all
825
            $paginator=DB::table("submission")->where([
826
                'cid'=>$cid
827
            ])->where(
828
                "submission_date",
829
                "<",
830
                $end_time
831
            )->join(
832
                "users",
833
                "users.id",
834
                "=",
835
                "submission.uid"
836
            )->where(function ($query) use ($frozen_time) {
837
                $query->where(
838
                    "submission_date",
839
                    "<",
840
                    $frozen_time
841
                )->orWhere(
842
                    'uid',
843
                    Auth::user()->id
844
                );
845
            })->select(
846
                "sid",
847
                "uid",
848
                "pid",
849
                "name",
850
                "color",
851
                "verdict",
852
                "time",
853
                "memory",
854
                "language",
855
                "score",
856
                "submission_date",
857
                "share"
858
            )->orderBy(
859
                'submission_date',
860
                'desc'
861
            )->paginate(50);
862
        } elseif ($basicInfo["status_visibility"]==1) {
863
            $paginator=DB::table("submission")->where([
864
                'cid'=>$cid,
865
                'uid'=>Auth::user()->id
866
            ])->where(
867
                "submission_date",
868
                "<",
869
                $end_time
870
            )->join(
871
                "users",
872
                "users.id",
873
                "=",
874
                "submission.uid"
875
            )->select(
876
                "sid",
877
                "uid",
878
                "pid",
879
                "name",
880
                "color",
881
                "verdict",
882
                "time",
883
                "memory",
884
                "language",
885
                "score",
886
                "submission_date",
887
                "share"
888
            )->orderBy(
889
                'submission_date',
890
                'desc'
891
            )->paginate(50);
892
        } else {
893
            return [
894
                "paginator"=>null,
895
                "records"=>[]
896
            ];
897
        }
898
899
        $records=$paginator->all();
900
        foreach ($records as &$r) {
901
            $r["submission_date_parsed"]=$this->formatSubmitTime(date('Y-m-d H:i:s', $r["submission_date"]));
902
            $r["submission_date"]=date('Y-m-d H:i:s', $r["submission_date"]);
903
            $r["nick_name"]="";
904
            $r["ncode"]=$problemSet[(string) $r["pid"]]["ncode"];
905
            if ($r["verdict"]=="Partially Accepted") {
906
                $score_parsed=round($r["score"] / $problemSet[(string) $r["pid"]]["tot_score"] * $problemSet[(string) $r["pid"]]["points"], 1);
907
                $r["verdict"].=" ($score_parsed)";
908
            }
909
            if (!$contestEnd) {
910
                $r["share"]=0;
911
            }
912
        }
913
        return [
914
            "paginator"=>$paginator,
915
            "records"=>$records
916
        ];
917
    }
918
919
    public function registration($cid, $uid=0)
920
    {
921
        if ($uid==0) {
922
            return [];
923
        }
924
925
926
        return DB::table("contest_participant")->where([
927
            "cid" => $cid,
928
            "uid" => $uid,
929
            "audit" => 1
930
        ])->first();
931
    }
932
933
    public function judgeClearance($cid, $uid=0)
934
    {
935
        if ($uid==0) {
936
            return 0;
937
        }
938
939
        $contest_started=DB::table("contest")->where("cid", $cid)->where("begin_time", "<", date("Y-m-d H:i:s"))->count();
940
        $contest_ended=DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
941
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
942
943
        if (!$contest_started) {
944
            // not started or do not exist
945
            return 0;
946
        }
947
948
        if ($contest_info["public"]) {
949
            //public
950
            if ($contest_ended) {
951
                return 1;
952
            } else {
953
                if ($contest_info["registration"]) {
954
                    // check if uid in registration, temp return 3
955
                    $isParticipant=DB::table("contest_participant")->where([
956
                        "cid" => $cid,
957
                        "uid" => $uid,
958
                        "audit" => 1
959
                    ])->count();
960
                    if ($isParticipant) {
961
                        return 2;
962
                    } else {
963
                        return 0;
964
                    }
965
                } else {
966
                    return 2;
967
                }
968
            }
969
        } else {
970
            //private
971
            $isMember=DB::table("group_member")->where([
972
                "gid"=> $contest_info["gid"],
973
                "uid"=> $uid
974
            ])->where("role", ">", 0)->count();
975
            if (!$isMember) {
976
                return 0;
977
            } else {
978
                if ($contest_info["registration"]) {
979
                    // check if uid in registration, temp return 3
980
                    $isParticipant=DB::table("contest_participant")->where([
981
                        "cid" => $cid,
982
                        "uid" => $uid,
983
                        "audit" => 1
984
                    ])->count();
985
                    if ($isParticipant) {
986
                        return 2;
987
                    } else {
988
                        return 0;
989
                    }
990
                } else {
991
                    return 2;
992
                }
993
            }
994
        }
995
    }
996
997
    public function judgeOutsideClearance($cid, $uid=0)
998
    {
999
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
1000
        if (empty($contest_info)) {
1001
            return 0;
1002
        }
1003
        if ($contest_info["public"]) {
1004
            return 1;
1005
        } else {
1006
            if ($uid==0) {
1007
                return 0;
1008
            }
1009
            return DB::table("group_member")->where([
1010
                "gid"=> $contest_info["gid"],
1011
                "uid"=> $uid
1012
            ])->where("role", ">", 0)->count() ? 1 : 0;
1013
        }
1014
    }
1015
1016
    public function contestName($cid)
1017
    {
1018
        return DB::table("contest")->where("cid", $cid)->select("name")->first()["name"];
1019
    }
1020
1021
    public function contestRule($cid)
1022
    {
1023
        return DB::table("contest")->where("cid", $cid)->select("rule")->first()["rule"];
1024
    }
1025
1026
    public function updateProfessionalRate($cid)
1027
    {
1028
        $basic=$this->basic($cid);
1029
        if($basic["rated"]&&!$basic["is_rated"]){
1030
            $ratingCalculator=new RatingCalculator($cid);
1031
            if($ratingCalculator->calculate()){
1032
                $ratingCalculator->storage();
1033
                return true;
1034
            }else{
1035
                return false;
1036
            }
1037
        } else {
1038
            return false;
1039
        }
1040
    }
1041
1042
    public function arrangeContest($gid, $config, $problems)
1043
    {
1044
        DB::transaction(function () use ($gid, $config, $problems) {
1045
            $cid=DB::table($this->tableName)->insertGetId([
1046
                "gid"=>$gid,
1047
                "name"=>$config["name"],
1048
                "verified"=>0, //todo
1049
                "rated"=>0,
1050
                "anticheated"=>0,
1051
                "featured"=>0,
1052
                "description"=>$config["description"],
1053
                "rule"=>1, //todo
1054
                "begin_time"=>$config["begin_time"],
1055
                "end_time"=>$config["end_time"],
1056
                "public"=>0, //todo
1057
                "registration"=>0, //todo
1058
                "registration_due"=>null, //todo
1059
                "registant_type"=>0, //todo
1060
                "froze_length"=>0, //todo
1061
                "status_visibility"=>2, //todo
1062
                "create_time"=>date("Y-m-d H:i:s"),
1063
                "audit_status"=>1                       //todo
1064
            ]);
1065
1066
            foreach ($problems as $p) {
1067
                $pid=DB::table("problem")->where(["pcode"=>$p["pcode"]])->select("pid")->first()["pid"];
1068
                DB::table("contest_problem")->insert([
1069
                    "cid"=>$cid,
1070
                    "number"=>$p["number"],
1071
                    "ncode"=>$this->intToChr($p["number"]-1),
1072
                    "pid"=>$pid,
1073
                    "alias"=>"",
1074
                    "points"=>$p["points"]
1075
                ]);
1076
            }
1077
        }, 5);
1078
    }
1079
1080
    public function updateContestRankTable($cid,$sub){
1081
        $lock = Cache::lock("contestrank$cid",10);
1082
        try{
1083
            if($lock->get()){
1084
                if(Cache::tags(['contest','rank'])->get($cid) != null){
1085
                    $chache = Cache::tags(['contest','data'])->get($cid);
1086
                    $ret = Cache::tags(['contest','rank'])->get($cid);
1087
                    if (time() > $chache['frozen_time'])
1088
                        return;
1089
1090
                    $id = 0;
1091
1092
                    foreach($chache['problemSet'] as $key => $p){
1093
                        if ($p['pid'] == $sub['pid']){
1094
                            $chache['problemSet'][$key]['cpid'] = $key;
1095
                            $id = $key;
1096
                        }
1097
                    }
1098
1099
                    $ret = $this->updateContestRankDetail($chache['contest_info'],$chache['problemSet'][$id],$cid,$sub['uid'],$ret);
1100
                    $ret = $this->sortContestRankTable($chache['contest_info'],$cid,$ret);
1101
1102
                    Cache::tags(['contest', 'rank'])->put($cid, $ret);
1103
                }
1104
                else{
1105
                    $ret=[];
1106
                    $chache=[];
1107
                    $chache['contest_info']=DB::table("contest")->where("cid", $cid)->first();
1108
                    $chache['problemSet']=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
1109
                        "cid"=>$cid
1110
                    ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
1111
                    $chache['frozen_time']=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
1112
                    $chache['end_time']=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
1113
1114
                    Cache::tags(['contest', 'data'])->put($cid, $chache);
1115
1116
                    if ($chache['contest_info']["registration"]) {
1117
                        $submissionUsers=DB::table("contest_participant")->where([
1118
                            "cid"=>$cid,
1119
                            "audit"=>1
1120
                        ])->select('uid')->get()->all();
1121
                    }else{
1122
                        $submissionUsers=DB::table("submission")->where([
1123
                            "cid"=>$cid
1124
                        ])->where(
1125
                            "submission_date",
1126
                            "<",
1127
                            $chache['frozen_time']
1128
                        )->select('uid')->groupBy('uid')->get()->all();
1129
                    }
1130
                    foreach ($submissionUsers as $s) {
1131
                        foreach ($chache['problemSet'] as $key => $p) {
1132
                            $p['cpid'] = $key;
1133
                            $ret = $this->updateContestRankDetail($chache['contest_info'],$p,$cid,$s['uid'],$ret);
1134
                        }
1135
                    }
1136
                    $ret = $this->sortContestRankTable($chache['contest_info'],$cid,$ret);
1137
                    Cache::tags(['contest', 'rank'])->put($cid, $ret);
1138
                }
1139
            }
1140
        }catch(LockTimeoutException $e){
0 ignored issues
show
Bug introduced by
The type App\Models\LockTimeoutException 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...
1141
            Log::warning("Contest Rank Lock Timed Out");
1142
        }finally{
1143
            optional($lock)->release();
1144
        }
1145
    }
1146
1147
    public function sortContestRankTable($contest_info,$cid,$ret){
0 ignored issues
show
Unused Code introduced by
The parameter $cid 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

1147
    public function sortContestRankTable($contest_info,/** @scrutinizer ignore-unused */ $cid,$ret){

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...
1148
        if ($contest_info["rule"]==1){
1149
            usort($ret, function ($a, $b) {
1150
                if ($a["score"]==$b["score"]) {
1151
                    if ($a["penalty"]==$b["penalty"]) {
1152
                        return 0;
1153
                    } elseif (($a["penalty"]>$b["penalty"])) {
1154
                        return 1;
1155
                    } else {
1156
                        return -1;
1157
                    }
1158
                } elseif ($a["score"]>$b["score"]) {
1159
                    return -1;
1160
                } else {
1161
                    return 1;
1162
                }
1163
            });
1164
        }else if ($contest_info["rule"]==2){
1165
            usort($ret, function ($a, $b) {
1166
                if ($a["score"]==$b["score"]) {
1167
                    if ($a["solved"]==$b["solved"]) {
1168
                        return 0;
1169
                    } elseif (($a["solved"]<$b["solved"])) {
1170
                        return 1;
1171
                    } else {
1172
                        return -1;
1173
                    }
1174
                } elseif ($a["score"]>$b["score"]) {
1175
                    return -1;
1176
                } else {
1177
                    return 1;
1178
                }
1179
            });
1180
        }
1181
        return $ret;
1182
    }
1183
1184
    public function updateContestRankDetail($contest_info,$problem,$cid,$uid,$ret){
1185
        $id = count($ret);
1186
        foreach($ret as $key => $r){
1187
            if($r['uid'] == $uid)
1188
                $id = $key;
1189
        }
1190
        if ($contest_info["rule"]==1) {
1191
            // ACM/ICPC Mode
1192
                $prob_detail = $ret[$id]['problem_detail'];
1193
                $totPen=$ret[$id]['penalty'];
1194
                $totScore=$ret[$id]['score'];
1195
1196
                $prob_stat=$this->contestProblemInfoACM($cid, $problem["pid"], $uid);
1197
1198
                $prob_detail[$problem['cpid']]=[
1199
                    "ncode"=>$problem["ncode"],
1200
                    "pid"=>$problem["pid"],
1201
                    "color"=>$prob_stat["color"],
1202
                    "wrong_doings"=>$prob_stat["wrong_doings"],
1203
                    "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
1204
                ];
1205
                if ($prob_stat["solved"]) {
1206
                    $totPen+=$prob_stat["wrong_doings"] * 20;
1207
                    $totPen+=$prob_stat["solved_time"] / 60;
1208
                    $totScore+=$prob_stat["solved"];
1209
                }
1210
1211
                $ret[$id]=[
1212
                    "uid" => $uid,
1213
                    "name" => DB::table("users")->where([
1214
                        "id"=>$uid
1215
                    ])->first()["name"],
1216
                    "nick_name" => DB::table("group_member")->where([
1217
                        "uid" => $uid,
1218
                        "gid" => $contest_info["gid"]
1219
                    ])->where("role", ">", 0)->first()["nick_name"],
1220
                    "score" => $totScore,
1221
                    "penalty" => $totPen,
1222
                    "problem_detail" => $prob_detail
1223
                ];
1224
        } elseif ($contest_info["rule"]==2) {
1225
            // OI Mode
1226
            $prob_detail = $ret[$id]['problem_detail'];
1227
            $totScore=$ret[$id]['score'];
1228
            $totSolved=$ret[$id]['solved'];
1229
1230
            $prob_stat=$this->contestProblemInfoOI($cid, $problem["pid"], $uid);
1231
            $prob_detail[$problem['cpid']]=[
1232
                "ncode"=>$problem["ncode"],
1233
                "pid"=>$problem["pid"],
1234
                "color"=>$prob_stat["color"],
1235
                "score"=>$prob_stat["score"],
1236
                "score_parsed"=>$prob_stat["score_parsed"]
1237
            ];
1238
            $totSolved+=$prob_stat["solved"];
1239
            $totScore+=intval($prob_stat["score_parsed"]);
1240
1241
            $ret[$id]=[
1242
                "uid" => $uid,
1243
                "name" => DB::table("users")->where([
1244
                    "id"=> $uid
1245
                ])->first()["name"],
1246
                "nick_name" => DB::table("group_member")->where([
1247
                    "uid" => $uid,
1248
                    "gid" => $contest_info["gid"]
1249
                ])->where("role", ">", 0)->first()["nick_name"],
1250
                "score" => $totScore,
1251
                "solved" => $totSolved,
1252
                "problem_detail" => $prob_detail
1253
            ];
1254
        }
1255
        return $ret;
1256
    }
1257
}
1258