Completed
Push — master ( 7eed95...43c4c5 )
by John
21s queued 10s
created

ContestModel::contestProblemInfoACM()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 68
Code Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 55
nc 3
nop 3
dl 0
loc 68
rs 8.9818
c 0
b 0
f 0

How to fix   Long Method   

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
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 gcode($cid)
113
    {
114
        $gid = $this->gid($cid);
115
        return DB::table('group')->where('gid','=',$gid)->first()["gcode"];
116
    }
117
118
    public function runningContest()
119
    {
120
        return DB::select("select * from contest where begin_time < SYSDATE() and end_time > SYSDATE() and vcid != null");
121
    }
122
123
    public function grantAccess($uid, $cid, $audit=0)
124
    {
125
        return DB::table('contest_participant')->insert([
126
            "cid"=>$cid,
127
            "uid"=>$uid,
128
            "audit"=>$audit
129
        ]);
130
    }
131
132
    public function listForSetting($gid)
133
    {
134
        $uid = Auth::user()->id;
135
        $group_contests = DB::table('contest')
136
            ->where('gid',$gid)
137
            ->orderBy('begin_time','desc')
138
            ->get()->all();
139
        $groupModel = new GroupModel();
140
        $group_clearance = $groupModel->judgeClearance($gid,$uid);
141
        foreach ($group_contests as &$contest) {
142
            $contest['is_admin'] = ($contest['assign_uid'] == $uid || $group_clearance == 3);
143
            $contest['begin_stamps'] = strtotime($contest['begin_time']);
144
            $contest['end_stamps'] = strtotime($contest['end_time']);
145
            $contest['status'] = time() >= $contest['end_stamps'] ? 1
146
                : (time() <= $contest['begin_stamps'] ? -1 : 0);
147
            $contest["rule_parsed"]=$this->rule[$contest["rule"]];
148
            $contest["date_parsed"]=[
149
                "date"=>date_format(date_create($contest["begin_time"]), 'j'),
150
                "month_year"=>date_format(date_create($contest["begin_time"]), 'M, Y'),
151
            ];
152
            $contest["length"]=$this->calcLength($contest["begin_time"], $contest["end_time"]);
153
        }
154
        usort($group_contests,function($a,$b){
155
            if($a['is_admin'] == $b['is_admin']){
156
                return $b['begin_stamps'] - $a['begin_stamps'];
157
            }
158
            return $b['is_admin'] - $a['is_admin'];
159
        });
160
        return $group_contests;
161
    }
162
163
    public function listByGroup($gid)
164
    {
165
        // $contest_list=DB::table($this->tableName)->where([
166
        //     "gid"=>$gid
167
        // ])->orderBy('begin_time', 'desc')->get()->all();
168
        $preQuery=DB::table($this->tableName);
169
        $paginator=$preQuery->where('gid','=',$gid)->orderBy('begin_time', 'desc')->paginate(10);
170
        $contest_list=$paginator->all();
171
        if(empty($contest_list)){
172
            return null;
173
        }
174
175
        foreach ($contest_list as &$c) {
176
            $c["rule_parsed"]=$this->rule[$c["rule"]];
177
            $c["date_parsed"]=[
178
                "date"=>date_format(date_create($c["begin_time"]), 'j'),
179
                "month_year"=>date_format(date_create($c["begin_time"]), 'M, Y'),
180
            ];
181
            $c["length"]=$this->calcLength($c["begin_time"], $c["end_time"]);
182
        }
183
        return [
184
            'paginator' => $paginator,
185
            'contest_list' => $contest_list,
186
        ];
187
    }
188
189
    public function rule($cid)
190
    {
191
        return DB::table($this->tableName)->where([
192
            "cid"=>$cid
193
        ])->first()["rule"];
194
    }
195
196
    public function list($filter,$uid)
197
    {
198
        if ($uid) {
199
            //$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);
200
            if ($filter['public']=='1') {
201
                $paginator=DB::table($this->tableName)->where([
202
                    "public"=>1,
203
                    "audit_status"=>1
204
                ])->orderBy('begin_time', 'desc');
205
                if ($filter['rule']) {
206
                    $paginator=$paginator->where(["rule"=>$filter['rule']]);
207
                }
208
                if ($filter['verified']) {
209
                    $paginator=$paginator->where(["verified"=>$filter['verified']]);
210
                }
211
                if ($filter['rated']) {
212
                    $paginator=$paginator->where(["rated"=>$filter['rated']]);
213
                }
214
                if ($filter['anticheated']) {
215
                    $paginator=$paginator->where(["anticheated"=>$filter['anticheated']]);
216
                }
217
                if ($filter['practice']) {
218
                    $paginator=$paginator->where(["practice"=>$filter['practice']]);
219
                }
220
                $paginator = $paginator ->paginate(10);
221
            }elseif($filter['public']=='0'){
222
                $paginator=DB::table('group_member')
223
                ->groupBy('contest.cid')
224
                ->select('contest.*')
225
                ->join('contest', 'group_member.gid', '=', 'contest.gid')
226
                ->leftJoin('contest_participant', 'contest.cid', '=', 'contest_participant.cid')
227
                ->where(
228
                    function ($query) use ($filter,$uid) {
229
                        if ($filter['rule']) {
230
                            $query=$query->where(["rule"=>$filter['rule']]);
231
                        }
232
                        if ($filter['verified']) {
233
                            $query=$query->where(["verified"=>$filter['verified']]);
234
                        }
235
                        if ($filter['rated']) {
236
                            $query=$query->where(["rated"=>$filter['rated']]);
237
                        }
238
                        if ($filter['anticheated']) {
239
                            $query=$query->where(["anticheated"=>$filter['anticheated']]);
240
                        }
241
                        if ($filter['practice']) {
242
                            $query=$query->where(["practice"=>$filter['practice']]);
243
                        }
244
                        $query->where('group_member.uid', $uid)
245
                                ->where('group_member.role', '>', 0)
246
                                ->where(["public"=>0]);
247
                    }
248
                )
249
                ->orderBy('contest.begin_time', 'desc')
250
                ->paginate(10);
251
            }else{
252
                $paginator=DB::table('group_member')
253
                ->groupBy('contest.cid')
254
                ->select('contest.*')
255
                ->join('contest', 'group_member.gid', '=', 'contest.gid')
256
                ->leftJoin('contest_participant', 'contest.cid', '=', 'contest_participant.cid')
257
                ->where(
258
                    function ($query) use ($filter) {
259
                        if ($filter['rule']) {
260
                            $query=$query->where(["rule"=>$filter['rule']]);
261
                        }
262
                        if ($filter['verified']) {
263
                            $query=$query->where(["verified"=>$filter['verified']]);
264
                        }
265
                        if ($filter['rated']) {
266
                            $query=$query->where(["rated"=>$filter['rated']]);
267
                        }
268
                        if ($filter['anticheated']) {
269
                            $query=$query->where(["anticheated"=>$filter['anticheated']]);
270
                        }
271
                        if ($filter['practice']) {
272
                            $query=$query->where(["practice"=>$filter['practice']]);
273
                        }
274
                        $query->where('public', 1)
275
                              ->where('audit_status', 1);
276
                    }
277
                )
278
                ->orWhere(
279
                    function ($query) use ($filter,$uid) {
280
                        if ($filter['rule']) {
281
                            $query=$query->where(["rule"=>$filter['rule']]);
282
                        }
283
                        if ($filter['public']) {
284
                            $query=$query->where(["public"=>$filter['public']]);
285
                        }
286
                        if ($filter['verified']) {
287
                            $query=$query->where(["verified"=>$filter['verified']]);
288
                        }
289
                        if ($filter['rated']) {
290
                            $query=$query->where(["rated"=>$filter['rated']]);
291
                        }
292
                        if ($filter['anticheated']) {
293
                            $query=$query->where(["anticheated"=>$filter['anticheated']]);
294
                        }
295
                        if ($filter['practice']) {
296
                            $query=$query->where(["practice"=>$filter['practice']]);
297
                        }
298
                        $query->where('group_member.uid', $uid)
299
                                ->where('group_member.role', '>', 0);
300
                    }
301
                )
302
                ->orderBy('contest.begin_time', 'desc')
303
                ->paginate(10);
304
            }
305
        } else {
306
            $paginator=DB::table($this->tableName)->where([
307
                "public"=>1,
308
                "audit_status"=>1
309
            ])->orderBy('begin_time', 'desc');
310
            if ($filter['rule']) {
311
                $paginator=$paginator->where(["rule"=>$filter['rule']]);
312
            }
313
            if ($filter['verified']) {
314
                $paginator=$paginator->where(["verified"=>$filter['verified']]);
315
            }
316
            if ($filter['rated']) {
317
                $paginator=$paginator->where(["rated"=>$filter['rated']]);
318
            }
319
            if ($filter['anticheated']) {
320
                $paginator=$paginator->where(["anticheated"=>$filter['anticheated']]);
321
            }
322
            if ($filter['practice']) {
323
                $paginator=$paginator->where(["practice"=>$filter['practice']]);
324
            }
325
            $paginator = $paginator ->paginate(10);
326
        }
327
        $contest_list=$paginator->all();
328
        foreach ($contest_list as &$c) {
329
            $c["rule_parsed"]=$this->rule[$c["rule"]];
330
            $c["date_parsed"]=[
331
                "date"=>date_format(date_create($c["begin_time"]), 'j'),
332
                "month_year"=>date_format(date_create($c["begin_time"]), 'M, Y'),
333
            ];
334
            $c["length"]=$this->calcLength($c["begin_time"], $c["end_time"]);
335
        }
336
        return [
337
            'contents' => $contest_list,
338
            'paginator' => $paginator
339
        ];
340
    }
341
342
    public function featured()
343
    {
344
        $featured=DB::table($this->tableName)->where([
345
            "public"=>1,
346
            "audit_status"=>1,
347
            "featured"=>1
348
        ])->orderBy('begin_time', 'desc')->first();
349
350
        if (!empty($featured)) {
351
            $featured["rule_parsed"]=$this->rule[$featured["rule"]];
352
            $featured["date_parsed"]=[
353
                "date"=>date_format(date_create($featured["begin_time"]), 'j'),
354
                "month_year"=>date_format(date_create($featured["begin_time"]), 'M, Y'),
355
            ];
356
            $featured["length"]=$this->calcLength($featured["begin_time"], $featured["end_time"]);
357
            return $featured;
358
        } else {
359
            return null;
360
        }
361
    }
362
363
    public function registContest($cid,$uid)
364
    {
365
        $registered=DB::table("contest_participant")->where([
366
            "cid"=>$cid,
367
            "uid"=>$uid
368
        ])->first();
369
370
        if(empty($registered)){
371
            DB::table("contest_participant")->insert([
372
                "cid"=>$cid,
373
                "uid"=>$uid,
374
                "audit"=>1
375
            ]);
376
            return true;
377
        }
378
        return false;
379
    }
380
381
    public function remainingTime($cid)
382
    {
383
        $end_time=DB::table($this->tableName)->where([
384
            "cid"=>$cid
385
        ])->select("end_time")->first()["end_time"];
386
        $end_time=strtotime($end_time);
387
        $cur_time=time();
388
        return $end_time-$cur_time;
389
    }
390
391
    public function intToChr($index, $start=65)
392
    {
393
        $str='';
394
        if (floor($index / 26)>0) {
395
            $str.=$this->intToChr(floor($index / 26)-1);
396
        }
397
        return $str.chr($index % 26+$start);
398
    }
399
400
    public function problems($cid)
401
    {
402
        return DB::table('contest_problem')
403
            ->join('problem','contest_problem.pid','=','problem.pid')
404
            ->where('cid',$cid)
405
            ->select('problem.pid as pid','pcode','number')
406
            ->orderBy('number')
407
            ->get()->all();
408
    }
409
410
    public function contestProblems($cid, $uid)
411
    {
412
        $submissionModel=new SubmissionModel();
413
414
        $contest_rule=$this->contestRule($cid);
415
416
        $problemSet=DB::table("contest_problem")
417
        ->join("problem", "contest_problem.pid", "=", "problem.pid")
418
        ->join("contest", "contest_problem.cid", "=", "contest.cid")
419
        ->where([
420
            "contest_problem.cid"=>$cid
421
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title", "contest.gid as gid", "contest.practice as practice")->get()->all();
422
423
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
424
        $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...
425
426
        foreach ($problemSet as &$p) {
427
            if($p['practice']){
428
                $tags = DB::table("group_problem_tag")
429
                ->where('gid',$p['gid'])
430
                ->where('pid',$p['pid'])
431
                ->get()->all();
432
                $tags_arr = [];
433
                if(!empty($tags)){
434
                    foreach ($tags as $value) {
435
                        array_push($tags_arr,$value['tag']);
436
                    }
437
                }
438
                $p['tags'] = $tags_arr;
439
            }
440
            if ($contest_rule==1) {
441
                $prob_stat=DB::table("submission")->select(
442
                    DB::raw("count(sid) as submission_count"),
443
                    DB::raw("sum(verdict='accepted') as passed_count"),
444
                    DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
445
                )->where([
446
                    "pid"=>$p["pid"],
447
                    "cid"=>$cid
448
                ])->where("submission_date", "<", $frozen_time)->first();
449
450
                if ($prob_stat["submission_count"]==0) {
451
                    $p["submission_count"]=0;
452
                    $p["passed_count"]=0;
453
                    $p["ac_rate"]=0;
454
                } else {
455
                    $p["submission_count"]=$prob_stat["submission_count"];
456
                    $p["passed_count"]=$prob_stat["passed_count"];
457
                    $p["ac_rate"]=round($prob_stat["ac_rate"], 2);
458
                }
459
            } else {
460
                $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $uid);
461
                $p["points"]=$prob_stat["points"];
462
                $p["score"]=empty($prob_stat["score_parsed"]) ? 0 : $prob_stat["score_parsed"];
463
            }
464
            $prob_status=$submissionModel->getProblemStatus($p["pid"], $uid, $cid);
465
            if (empty($prob_status)) {
466
                $p["prob_status"]=[
467
                    "icon"=>"checkbox-blank-circle-outline",
468
                    "color"=>"wemd-grey-text"
469
                ];
470
            } else {
471
                $p["prob_status"]=[
472
                    "icon"=>$prob_status["verdict"]=="Accepted" ? "checkbox-blank-circle" : "cisco-webex",
473
                    "color"=>$prob_status["color"]
474
                ];
475
            }
476
477
478
        }
479
480
        return $problemSet;
481
    }
482
483
    public function getPid($cid, $ncode)
484
    {
485
        return DB::table("contest_problem")->where([
486
            "cid"=>$cid,
487
            "ncode"=>$ncode
488
        ])->select("contest_problem.pid")->first()["pid"];
489
    }
490
491
    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

491
    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...
492
    {
493
        return DB::table("problem")->where([
494
            "cid"=>$cid
495
        ])->select("contest_problem.pid")->first()["pcode"];
496
    }
497
498
    public function getCustomInfo($cid)
499
    {
500
        $basic_info=DB::table($this->tableName)->where([
501
            "cid"=>$cid
502
        ])->select("verified", "custom_icon", "custom_title")->first();
503
        return $basic_info["verified"] ? ((is_null($basic_info["custom_icon"]) && is_null($basic_info["custom_title"])) ?null:$basic_info) : null;
504
    }
505
506
507
    public function formatTime($seconds)
508
    {
509
        if ($seconds>3600) {
510
            $hours=intval($seconds / 3600);
511
            $minutes=$seconds % 3600;
512
            $time=$hours.":".gmstrftime('%M:%S', $minutes);
513
        } else {
514
            $time=gmstrftime('%H:%M:%S', $seconds);
515
        }
516
        return $time;
517
    }
518
519
    public function contestProblemInfoOI($cid, $pid, $uid)
520
    {
521
        $ret=[
522
            "color"=>"",
523
            "score"=>null,
524
            "score_parsed"=>"",
525
            "solved"=>0,
526
            "points"=>DB::table("contest_problem")->where([
527
                "pid"=>$pid,
528
                "cid"=>$cid
529
            ])->first()["points"]
530
        ];
531
532
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
533
        $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...
534
535
        $highest_record=DB::table("submission")->where([
536
            "cid"=>$cid,
537
            "pid"=>$pid,
538
            "uid"=>$uid
539
        ])->where("submission_date", "<", $frozen_time)->orderBy('score', 'desc')->first();
540
541
        if (!empty($highest_record)) {
542
            $ret["score"]=$highest_record["score"];
543
544
            $tot_score=DB::table("problem")->where([
545
                "pid"=>$pid
546
            ])->first()["tot_score"];
547
548
            $ret["color"]=($ret["score"]==$tot_score) ? "wemd-teal-text" : "wemd-green-text";
549
            $ret["solved"]=($ret["score"]==$tot_score) ? 1 : 0;
550
            $ret["score_parsed"]=$ret["score"] / $tot_score * ($ret["points"]);
551
        }
552
        return $ret;
553
    }
554
555
    public function isFrozen($cid)
556
    {
557
        $frozen=DB::table("contest")->where(["cid"=>$cid])->select("froze_length", DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first();
558
        if (empty($frozen["froze_length"])) {
559
            return false;
560
        } else {
561
            return time()>$frozen["frozen_time"];
562
        }
563
    }
564
565
    public function contestProblemInfoACM($cid, $pid, $uid)
566
    {
567
        $ret=[
568
            "color"=>"",
569
            "solved"=>0,
570
            "solved_time"=>"",
571
            "solved_time_parsed"=>"",
572
            "wrong_doings"=>0,
573
            "color"=>"",
574
        ];
575
576
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
577
        $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...
578
579
        $ac_record=DB::table("submission")->where([
580
            "cid"=>$cid,
581
            "pid"=>$pid,
582
            "uid"=>$uid,
583
            "verdict"=>"Accepted"
584
        ])->where("submission_date", "<", $frozen_time)->orderBy('submission_date', 'asc')->first();
585
586
        if (!empty($ac_record)) {
587
            $ret["solved"]=1;
588
589
            $ret["solved_time"]=$ac_record["submission_date"]-strtotime(DB::table($this->tableName)->where([
590
                "cid"=>$cid
591
            ])->first()["begin_time"]);
592
593
            $ret["solved_time_parsed"]=$this->formatTime($ret["solved_time"]);
594
595
            $ret["wrong_doings"]=DB::table("submission")->where([
596
                "cid"=>$cid,
597
                "pid"=>$pid,
598
                "uid"=>$uid
599
            ])->whereIn('verdict', [
600
                'Runtime Error',
601
                'Wrong Answer',
602
                'Time Limit Exceed',
603
                'Real Time Limit Exceed',
604
                'Memory Limit Exceed',
605
                'Presentation Error',
606
                'Output Limit Exceeded'
607
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
608
609
            $others_first=DB::table("submission")->where([
610
                "cid"=>$cid,
611
                "pid"=>$pid,
612
                "verdict"=>"Accepted"
613
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
614
615
            $ret["color"]=$others_first ? "wemd-green-text" : "wemd-teal-text";
616
        } else {
617
            $ret["wrong_doings"]=DB::table("submission")->where([
618
                "cid"=>$cid,
619
                "pid"=>$pid,
620
                "uid"=>$uid
621
            ])->whereIn('verdict', [
622
                'Runtime Error',
623
                'Wrong Answer',
624
                'Time Limit Exceed',
625
                'Real Time Limit Exceed',
626
                'Memory Limit Exceed',
627
                'Presentation Error',
628
                'Output Limit Exceeded'
629
            ])->where("submission_date", "<", $frozen_time)->count();
630
        }
631
632
        return $ret;
633
    }
634
635
    public function contestRankCache($cid)
636
    {
637
        // if(Cache::tags(['contest','rank'])->get($cid)!=null) return Cache::tags(['contest','rank'])->get($cid);
638
        $ret=[];
639
640
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
641
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
642
        $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...
643
644
        if ($contest_info["registration"]) {
645
            $submissionUsers=DB::table("contest_participant")->where([
646
                "cid"=>$cid,
647
                "audit"=>1
648
            ])->select('uid')->get()->all();
649
        } else {
650
            // Those who submitted are participants
651
            $submissionUsers=DB::table("submission")->where([
652
                "cid"=>$cid
653
            ])->where(
654
                "submission_date",
655
                "<",
656
                $frozen_time
657
            )->select('uid')->groupBy('uid')->get()->all();
658
        }
659
660
        $problemSet=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
661
            "cid"=>$cid
662
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
663
664
        if ($contest_info["rule"]==1) {
665
            // ACM/ICPC Mode
666
            foreach ($submissionUsers as $s) {
667
                $prob_detail=[];
668
                $totPen=0;
669
                $totScore=0;
670
                foreach ($problemSet as $p) {
671
                    $prob_stat=$this->contestProblemInfoACM($cid, $p["pid"], $s["uid"]);
672
                    $prob_detail[]=[
673
                        "ncode"=>$p["ncode"],
674
                        "pid"=>$p["pid"],
675
                        "color"=>$prob_stat["color"],
676
                        "wrong_doings"=>$prob_stat["wrong_doings"],
677
                        "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
678
                    ];
679
                    if ($prob_stat["solved"]) {
680
                        $totPen+=$prob_stat["wrong_doings"] * 20;
681
                        $totPen+=$prob_stat["solved_time"] / 60;
682
                        $totScore+=$prob_stat["solved"];
683
                    }
684
                }
685
                $ret[]=[
686
                    "uid" => $s["uid"],
687
                    "name" => DB::table("users")->where([
688
                        "id"=>$s["uid"]
689
                    ])->first()["name"],
690
                    "nick_name" => DB::table("group_member")->where([
691
                        "uid" => $s["uid"],
692
                        "gid" => $contest_info["gid"]
693
                    ])->where("role", ">", 0)->first()["nick_name"],
694
                    "score" => $totScore,
695
                    "penalty" => $totPen,
696
                    "problem_detail" => $prob_detail
697
                ];
698
            }
699
            usort($ret, function ($a, $b) {
700
                if ($a["score"]==$b["score"]) {
701
                    if ($a["penalty"]==$b["penalty"]) {
702
                        return 0;
703
                    } elseif (($a["penalty"]>$b["penalty"])) {
704
                        return 1;
705
                    } else {
706
                        return -1;
707
                    }
708
                } elseif ($a["score"]>$b["score"]) {
709
                    return -1;
710
                } else {
711
                    return 1;
712
                }
713
            });
714
        } elseif ($contest_info["rule"]==2) {
715
            // OI Mode
716
            foreach ($submissionUsers as $s) {
717
                $prob_detail=[];
718
                $totScore=0;
719
                $totSolved=0;
720
                foreach ($problemSet as $p) {
721
                    $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $s["uid"]);
722
                    $prob_detail[]=[
723
                        "ncode"=>$p["ncode"],
724
                        "pid"=>$p["pid"],
725
                        "color"=>$prob_stat["color"],
726
                        "score"=>$prob_stat["score"],
727
                        "score_parsed"=>$prob_stat["score_parsed"]
728
                    ];
729
                    $totSolved+=$prob_stat["solved"];
730
                    $totScore+=intval($prob_stat["score_parsed"]);
731
                }
732
                $ret[]=[
733
                    "uid" => $s["uid"],
734
                    "name" => DB::table("users")->where([
735
                        "id"=>$s["uid"]
736
                    ])->first()["name"],
737
                    "nick_name" => DB::table("group_member")->where([
738
                        "uid" => $s["uid"],
739
                        "gid" => $contest_info["gid"]
740
                    ])->where("role", ">", 0)->first()["nick_name"],
741
                    "score" => $totScore,
742
                    "solved" => $totSolved,
743
                    "problem_detail" => $prob_detail
744
                ];
745
            }
746
            usort($ret, function ($a, $b) {
747
                if ($a["score"]==$b["score"]) {
748
                    if ($a["solved"]==$b["solved"]) {
749
                        return 0;
750
                    } elseif (($a["solved"]<$b["solved"])) {
751
                        return 1;
752
                    } else {
753
                        return -1;
754
                    }
755
                } elseif ($a["score"]>$b["score"]) {
756
                    return -1;
757
                } else {
758
                    return 1;
759
                }
760
            });
761
        }
762
763
        Cache::tags(['contest', 'rank'])->put($cid, $ret, 60);
764
765
        return $ret;
766
    }
767
768
    public function contestRank($cid, $uid = 0)
769
    {
770
        // [ToDo] If the current user's in the organizer group show nick name
771
        // [ToDo] The participants determination
772
        // [ToDo] Frozen Time
773
        // [ToDo] Performance Opt
774
        // [Todo] Ajaxization - Should have done in controller
775
        // [Todo] Authorization ( Public / Private ) - Should have done in controller
776
777
        $ret=[];
0 ignored issues
show
Unused Code introduced by
The assignment to $ret is dead and can be removed.
Loading history...
778
779
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
780
781
        $user_in_group=!empty(DB::table("group_member")->where([
782
            "uid" => $uid,
783
            "gid" => $contest_info["gid"]
784
        ])->where("role", ">", 0)->first());
785
786
        $clearance = $this -> judgeClearance($cid, $uid);
787
788
        /** New Version With MySQL */
789
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
790
791
        if(time() < $end_time){
792
            if($clearance == 3){
793
                $contestRankRaw=Cache::tags(['contest', 'rank'])->get("contestAdmin$cid");
794
            }else{
795
                $contestRankRaw=Cache::tags(['contest', 'rank'])->get($cid);
796
            }
797
            if(!isset($contestRankRaw)){
798
                $contestRankRaw=$this->contestRankCache($cid);
799
            }
800
        }else{
801
            if($clearance == 3){
802
                $contestRankRaw=Cache::tags(['contest', 'rank'])->get("contestAdmin$cid");
803
                if (!isset($contestRankRaw)) {
804
                    $contestRankRaw=$this->contestRankCache($cid);
805
                }
806
            }else{
807
                $contestRankRaw=$this->getContestRankFromMySQL($cid);
808
                if(!isset($contestRankRaw)){
809
                    $contestRankRaw=Cache::tags(['contest', 'rank'])->get($cid);
810
                    if(!isset($contestRankRaw)){
811
                        $contestRankRaw=$this->contestRankCache($cid);
812
                    }
813
                    $this->storeContestRankInMySQL($cid, $contestRankRaw);
814
                }
815
            }
816
        }
817
818
        /** Old version */
819
        // if ($contestRankRaw==null) {
820
        //     $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
821
        //     if(time() > $end_time && !Cache::has($cid)){
822
        //         $contestRankRaw=$this->contestRankCache($cid);
823
        //         // Cache::forever($cid, $contestRankRaw);
824
        //     }else{
825
        //         $contestRankRaw=$this->contestRankCache($cid);
826
        //     }
827
        // }
828
        if($contest_info["rule"]==1){
829
            foreach ($contestRankRaw as &$cr) {
830
                $solved = 0;
831
                foreach($cr['problem_detail'] as $pd){
832
                    if(!empty($pd['solved_time_parsed'])){
833
                        $solved ++;
834
                    }
835
                }
836
                $cr['solved'] = $solved;
837
            }
838
        }
839
840
        $ret=$contestRankRaw;
841
842
        foreach ($ret as $r) {
843
            if (!$user_in_group) {
844
                $r["nick_name"]='';
845
            }
846
        }
847
848
        return $ret;
849
    }
850
851
    public function getRejudgeQueue($cid)
852
    {
853
        $problemModel=new ProblemModel();
854
        $submissionModel=new SubmissionModel();
0 ignored issues
show
Unused Code introduced by
The assignment to $submissionModel is dead and can be removed.
Loading history...
855
        $compilerModel=new CompilerModel();
856
857
        $tempQueue=DB::table("submission")->where([
858
            "cid"=>$cid
859
        ])->whereIn('verdict', [
860
            'Runtime Error',
861
            'Wrong Answer',
862
            'Time Limit Exceed',
863
            'Real Time Limit Exceed',
864
            'Memory Limit Exceed',
865
            'Presentation Error',
866
            'Output Limit Exceeded'
867
        ])->get()->all();
868
869
        foreach ($tempQueue as &$t) {
870
            $lang=$compilerModel->detail($t["coid"]);
871
            $probBasic=$problemModel->basic($t["pid"]);
872
            $t["oj"]=$problemModel->ocode($t["pid"]);
873
            $t["lang"]=$lang['lcode'];
874
            $t["cid"]=$probBasic["contest_id"];
875
            $t["iid"]=$probBasic["index_id"];
876
            $t["pcode"]=$probBasic["pcode"];
877
            $t["contest"]=$cid;
878
        }
879
880
        return $tempQueue;
881
    }
882
883
    public function getClarificationList($cid)
884
    {
885
        $uid = Auth::user()->id;
886
        $clearance = $this -> judgeClearance($cid, $uid);
887
        if($clearance == 3){
888
            return DB::table("contest_clarification")->where([
889
                "cid"=>$cid
890
            ])->orderBy('create_time', 'desc')->get()->all();
891
        }else{
892
            return DB::table("contest_clarification")->where([
893
                "cid"=>$cid
894
            ])->where(function ($query) {
895
                $query->where([
896
                    "public"=>1
897
                ])->orWhere([
898
                    "uid" => Auth::user()->id
899
                ]);
900
            })->orderBy('create_time', 'desc')->get()->all();
901
        }
902
    }
903
904
    public function fetchClarification($cid)
905
    {
906
        return DB::table("contest_clarification")->where([
907
            "cid"=>$cid,
908
            "type"=>0,
909
            "public"=>1
910
        ])->whereBetween(
911
            'create_time',
912
            [
913
                date("Y-m-d H:i:s", time()-59),
914
                date("Y-m-d H:i:s")
915
            ]
916
        )->first();
917
    }
918
919
    public function getlatestClarification($cid)
920
    {
921
        return DB::table("contest_clarification")->where([
922
            "cid"=>$cid,
923
            "type"=>0,
924
            "public"=>1
925
        ])->orderBy('create_time', 'desc')->first();
926
    }
927
928
    public function getClarificationDetail($ccid)
929
    {
930
        return DB::table("contest_clarification")->where([
931
            "ccid"=>$ccid,
932
            "public"=>1
933
        ])->first();
934
    }
935
936
    public function requestClarification($cid, $title, $content, $uid)
937
    {
938
        return DB::table("contest_clarification")->insertGetId([
939
            "cid"=>$cid,
940
            "type"=>1,
941
            "title"=>$title,
942
            "content"=>$content,
943
            "public"=>"0",
944
            "uid"=>$uid,
945
            "create_time"=>date("Y-m-d H:i:s")
946
        ]);
947
    }
948
949
    public function issueAnnouncement($cid, $title, $content, $uid)
950
    {
951
        return DB::table("contest_clarification")->insertGetId([
952
            "cid"=>$cid,
953
            "type"=>0,
954
            "title"=>$title,
955
            "content"=>$content,
956
            "public"=>"1",
957
            "uid"=>$uid,
958
            "create_time"=>date("Y-m-d H:i:s")
959
        ]);
960
    }
961
962
    public function isContestEnded($cid)
963
    {
964
        return DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
965
    }
966
967
    public function isContestRunning($cid)
968
    {
969
        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();
970
    }
971
972
    public function formatSubmitTime($date)
973
    {
974
        $periods=["second", "minute", "hour", "day", "week", "month", "year", "decade"];
975
        $lengths=["60", "60", "24", "7", "4.35", "12", "10"];
976
977
        $now=time();
978
        $unix_date=strtotime($date);
979
980
        if (empty($unix_date)) {
981
            return "Bad date";
982
        }
983
984
        if ($now>$unix_date) {
985
            $difference=$now-$unix_date;
986
            $tense="ago";
987
        } else {
988
            $difference=$unix_date-$now;
989
            $tense="from now";
990
        }
991
992
        for ($j=0; $difference>=$lengths[$j] && $j<count($lengths)-1; $j++) {
993
            $difference/=$lengths[$j];
994
        }
995
996
        $difference=round($difference);
997
998
        if ($difference!=1) {
999
            $periods[$j].="s";
1000
        }
1001
1002
        return "$difference $periods[$j] {$tense}";
1003
    }
1004
1005
    public function formatAbsTime($sec)
1006
    {
1007
        $periods=["second", "minute", "hour", "day", "week", "month", "year", "decade"];
1008
        $lengths=["60", "60", "24", "7", "4.35", "12", "10"];
1009
1010
1011
        $difference=$sec;
1012
1013
        for ($j=0; $difference>=$lengths[$j] && $j<count($lengths)-1; $j++) {
1014
            $difference/=$lengths[$j];
1015
        }
1016
1017
        $difference=round($difference);
1018
1019
        if ($difference!=1) {
1020
            $periods[$j].="s";
1021
        }
1022
1023
        return "$difference $periods[$j]";
1024
    }
1025
1026
    public function frozenTime($cid)
1027
    {
1028
        $basicInfo=$this->basic($cid);
1029
        return $this->formatAbsTime($basicInfo["froze_length"]);
1030
    }
1031
1032
    public function getContestRecord($cid)
1033
    {
1034
        $basicInfo=$this->basic($cid);
1035
        $userInfo=DB::table('group_member')->where('gid',$basicInfo["gid"])->where('uid',Auth::user()->id)->get()->first();
1036
        $problemSet_temp=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
1037
            "cid"=>$cid
1038
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title", "points", "tot_score")->get()->all();
1039
        $problemSet=[];
1040
        foreach ($problemSet_temp as $p) {
1041
            $problemSet[(string) $p["pid"]]=["ncode"=>$p["ncode"], "points"=>$p["points"], "tot_score"=>$p["tot_score"]];
1042
        }
1043
1044
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
1045
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
1046
        $contestEnd=time()>$end_time;
1047
1048
        if($userInfo==null || $userInfo["role"]!=3){
1049
            if ($basicInfo["status_visibility"]==2) {
1050
                // View all
1051
                $paginator=DB::table("submission")->where([
1052
                    'cid'=>$cid
1053
                ])->where(
1054
                    "submission_date",
1055
                    "<",
1056
                    $end_time
1057
                )->join(
1058
                    "users",
1059
                    "users.id",
1060
                    "=",
1061
                    "submission.uid"
1062
                )->where(function ($query) use ($frozen_time) {
1063
                    $query->where(
1064
                        "submission_date",
1065
                        "<",
1066
                        $frozen_time
1067
                    )->orWhere(
1068
                        'uid',
1069
                        Auth::user()->id
1070
                    );
1071
                })->select(
1072
                    "sid",
1073
                    "uid",
1074
                    "pid",
1075
                    "name",
1076
                    "color",
1077
                    "verdict",
1078
                    "time",
1079
                    "memory",
1080
                    "language",
1081
                    "score",
1082
                    "submission_date",
1083
                    "share"
1084
                )->orderBy(
1085
                    'submission_date',
1086
                    'desc'
1087
                )->paginate(50);
1088
            } elseif ($basicInfo["status_visibility"]==1) {
1089
                $paginator=DB::table("submission")->where([
1090
                    'cid'=>$cid,
1091
                    'uid'=>Auth::user()->id
1092
                ])->where(
1093
                    "submission_date",
1094
                    "<",
1095
                    $end_time
1096
                )->join(
1097
                    "users",
1098
                    "users.id",
1099
                    "=",
1100
                    "submission.uid"
1101
                )->select(
1102
                    "sid",
1103
                    "uid",
1104
                    "pid",
1105
                    "name",
1106
                    "color",
1107
                    "verdict",
1108
                    "time",
1109
                    "memory",
1110
                    "language",
1111
                    "score",
1112
                    "submission_date",
1113
                    "share"
1114
                )->orderBy(
1115
                    'submission_date',
1116
                    'desc'
1117
                )->paginate(50);
1118
            } else {
1119
                return [
1120
                    "paginator"=>null,
1121
                    "records"=>[]
1122
                ];
1123
            }
1124
        }else{
1125
            if ($basicInfo["status_visibility"]==2) {
1126
                // View all
1127
                $paginator=DB::table("submission")->where([
1128
                    'cid'=>$cid
1129
                ])->where(
1130
                    "submission_date",
1131
                    "<",
1132
                    $end_time
1133
                )->join(
1134
                    "users",
1135
                    "users.id",
1136
                    "=",
1137
                    "submission.uid"
1138
                )->select(
1139
                    "sid",
1140
                    "uid",
1141
                    "pid",
1142
                    "name",
1143
                    "color",
1144
                    "verdict",
1145
                    "time",
1146
                    "memory",
1147
                    "language",
1148
                    "score",
1149
                    "submission_date",
1150
                    "share"
1151
                )->orderBy(
1152
                    'submission_date',
1153
                    'desc'
1154
                )->paginate(50);
1155
            } elseif ($basicInfo["status_visibility"]==1) {
1156
                $paginator=DB::table("submission")->where([
1157
                    'cid'=>$cid,
1158
                    'uid'=>Auth::user()->id
1159
                ])->where(
1160
                    "submission_date",
1161
                    "<",
1162
                    $end_time
1163
                )->join(
1164
                    "users",
1165
                    "users.id",
1166
                    "=",
1167
                    "submission.uid"
1168
                )->select(
1169
                    "sid",
1170
                    "uid",
1171
                    "pid",
1172
                    "name",
1173
                    "color",
1174
                    "verdict",
1175
                    "time",
1176
                    "memory",
1177
                    "language",
1178
                    "score",
1179
                    "submission_date",
1180
                    "share"
1181
                )->orderBy(
1182
                    'submission_date',
1183
                    'desc'
1184
                )->paginate(50);
1185
            } else {
1186
                return [
1187
                    "paginator"=>null,
1188
                    "records"=>[]
1189
                ];
1190
            }
1191
        }
1192
1193
        $records=$paginator->all();
1194
        foreach ($records as &$r) {
1195
            $r["submission_date_parsed"]=$this->formatSubmitTime(date('Y-m-d H:i:s', $r["submission_date"]));
1196
            $r["submission_date"]=date('Y-m-d H:i:s', $r["submission_date"]);
1197
            $r["nick_name"]="";
1198
            $r["ncode"]=$problemSet[(string) $r["pid"]]["ncode"];
1199
            if ($r["verdict"]=="Partially Accepted") {
1200
                $score_parsed=round($r["score"] / $problemSet[(string) $r["pid"]]["tot_score"] * $problemSet[(string) $r["pid"]]["points"], 1);
1201
                $r["verdict"].=" ($score_parsed)";
1202
            }
1203
            if (!$contestEnd) {
1204
                $r["share"]=0;
1205
            }
1206
        }
1207
        return [
1208
            "paginator"=>$paginator,
1209
            "records"=>$records
1210
        ];
1211
    }
1212
1213
    public function registration($cid, $uid=0)
1214
    {
1215
        if ($uid==0) {
1216
            return [];
1217
        }
1218
1219
1220
        return DB::table("contest_participant")->where([
1221
            "cid" => $cid,
1222
            "uid" => $uid,
1223
            "audit" => 1
1224
        ])->first();
1225
    }
1226
1227
    public function judgeClearance($cid, $uid=0)
1228
    {
1229
        /***************************
1230
         * 2 stands for participant*
1231
         * 3 stands for admin      *
1232
         ***************************/
1233
        if ($uid==0) {
1234
            return 0;
1235
        }
1236
        $groupModel = new GroupModel();
1237
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
1238
        $userInfo=DB::table('group_member')->where('gid',$contest_info["gid"])->where('uid',$uid)->get()->first();
1239
1240
        if(empty($contest_info)){
1241
            // contest not exist
1242
            return 0;
1243
        }
1244
1245
        if($uid == $contest_info['assign_uid'] || $groupModel->judgeClearance($contest_info['gid'],$uid) == 3){
1246
            return 3;
1247
        }
1248
1249
        $contest_started = strtotime($contest_info['begin_time']) < time();
1250
        $contest_ended = strtotime($contest_info['end_time']) < time();
1251
        if (!$contest_started) {
1252
            // not started or do not exist
1253
            return 0;
1254
        }
1255
1256
        if ($userInfo["role"]==3) {
1257
            return 3;
1258
        }
1259
1260
        if ($contest_info["public"]) {
1261
            //public
1262
            if ($contest_ended) {
1263
                return 1;
1264
            } else {
1265
                if ($contest_info["registration"]) {
1266
                    // check if uid in registration, temp return 3
1267
                    $isParticipant=DB::table("contest_participant")->where([
1268
                        "cid" => $cid,
1269
                        "uid" => $uid,
1270
                        "audit" => 1
1271
                    ])->count();
1272
                    if ($isParticipant) {
1273
                        return 2;
1274
                    } else {
1275
                        return 0;
1276
                    }
1277
                } else {
1278
                    return 2;
1279
                }
1280
            }
1281
        } else {
1282
            //private
1283
            $isMember=DB::table("group_member")->where([
1284
                "gid"=> $contest_info["gid"],
1285
                "uid"=> $uid
1286
            ])->where("role", ">", 0)->count();
1287
            if (!$isMember) {
1288
                return 0;
1289
            } else {
1290
                if ($contest_info["registration"]) {
1291
                    // check if uid in registration, temp return 3
1292
                    $isParticipant=DB::table("contest_participant")->where([
1293
                        "cid" => $cid,
1294
                        "uid" => $uid,
1295
                        "audit" => 1
1296
                    ])->count();
1297
                    if ($isParticipant) {
1298
                        return 2;
1299
                    } else {
1300
                        return 0;
1301
                    }
1302
                } else {
1303
                    return 2;
1304
                }
1305
            }
1306
        }
1307
    }
1308
1309
    public function judgeOutsideClearance($cid, $uid=0)
1310
    {
1311
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
1312
        if (empty($contest_info)) {
1313
            return 0;
1314
        }
1315
        if ($contest_info["public"]) {
1316
            return 1;
1317
        } else {
1318
            if ($uid==0) {
1319
                return 0;
1320
            }
1321
            return DB::table("group_member")->where([
1322
                "gid"=> $contest_info["gid"],
1323
                "uid"=> $uid
1324
            ])->where("role", ">", 0)->count() ? 1 : 0;
1325
        }
1326
    }
1327
1328
    public function contestName($cid)
1329
    {
1330
        return DB::table("contest")->where("cid", $cid)->select("name")->first()["name"];
1331
    }
1332
1333
    public function contestRule($cid)
1334
    {
1335
        return DB::table("contest")->where("cid", $cid)->select("rule")->first()["rule"];
1336
    }
1337
1338
    public function updateProfessionalRate($cid)
1339
    {
1340
        $basic=$this->basic($cid);
1341
        if($basic["rated"]&&!$basic["is_rated"]){
1342
            $ratingCalculator=new RatingCalculator($cid);
1343
            if($ratingCalculator->calculate()){
1344
                $ratingCalculator->storage();
1345
                return true;
1346
            }else{
1347
                return false;
1348
            }
1349
        } else {
1350
            return false;
1351
        }
1352
    }
1353
1354
    public function contestUpdate($cid,$data,$problems)
1355
    {
1356
        if($problems !== false){
1357
            $old_problmes = array_column(
1358
                DB::table('contest_problem')
1359
                ->where('cid',$cid)
1360
                ->get()->all(),
1361
                'pid'
1362
            );
1363
            DB::transaction(function () use ($cid, $data, $problems,$old_problmes) {
1364
                DB::table($this->tableName)
1365
                    ->where('cid',$cid)
1366
                    ->update($data);
1367
                DB::table('contest_problem')
1368
                    ->where('cid',$cid)
1369
                    ->delete();
1370
                $new_problems = [];
1371
                foreach ($problems as $p) {
1372
                    $pid=DB::table("problem")->where(["pcode"=>$p["pcode"]])->select("pid")->first()["pid"];
1373
                    array_push($new_problems,$pid);
1374
                    DB::table("contest_problem")->insert([
1375
                        "cid"=>$cid,
1376
                        "number"=>$p["number"],
1377
                        "ncode"=>$this->intToChr($p["number"]-1),
1378
                        "pid"=>$pid,
1379
                        "alias"=>"",
1380
                        "points"=>$p["points"]
1381
                    ]);
1382
                }
1383
                foreach($old_problmes as $op) {
1384
                    if(!in_array($op,$new_problems)){
1385
                        DB::table('submission')
1386
                            ->where('cid',$cid)
1387
                            ->where('pid',$op)
1388
                            ->delete();
1389
                    }
1390
                }
1391
            }, 5);
1392
            $contestRankRaw = $this->contestRankCache($cid);
1393
            Cache::tags(['contest', 'rank'])->put($cid, $contestRankRaw);
1394
            Cache::tags(['contest', 'rank'])->put("contestAdmin$cid", $contestRankRaw);
1395
        }else{
1396
            DB::table($this->tableName)
1397
                ->where('cid',$cid)
1398
                ->update($data);
1399
        }
1400
    }
1401
1402
    public function arrangeContest($gid, $config, $problems)
1403
    {
1404
        DB::transaction(function () use ($gid, $config, $problems) {
1405
            $cid=DB::table($this->tableName)->insertGetId([
1406
                "gid"=>$gid,
1407
                "name"=>$config["name"],
1408
                "assign_uid"=>$config["assign_uid"],
1409
                "verified"=>0, //todo
1410
                "rated"=>0,
1411
                "anticheated"=>0,
1412
                "practice"=>$config["practice"],
1413
                "featured"=>0,
1414
                "description"=>$config["description"],
1415
                "rule"=>1, //todo
1416
                "begin_time"=>$config["begin_time"],
1417
                "end_time"=>$config["end_time"],
1418
                "vcid"=>isset($config["vcid"])?$config["vcid"]:null,
1419
                "public"=>0, //todo
1420
                "registration"=>0, //todo
1421
                "registration_due"=>null, //todo
1422
                "registant_type"=>0, //todo
1423
                "froze_length"=>0, //todo
1424
                "status_visibility"=>2, //todo
1425
                "create_time"=>date("Y-m-d H:i:s"),
1426
                "audit_status"=>1                       //todo
1427
            ]);
1428
1429
            foreach ($problems as $p) {
1430
                $pid=DB::table("problem")->where(["pcode"=>$p["pcode"]])->select("pid")->first()["pid"];
1431
                DB::table("contest_problem")->insert([
1432
                    "cid"=>$cid,
1433
                    "number"=>$p["number"],
1434
                    "ncode"=>$this->intToChr($p["number"]-1),
1435
                    "pid"=>$pid,
1436
                    "alias"=>"",
1437
                    "points"=>$p["points"]
1438
                ]);
1439
            }
1440
        }, 5);
1441
    }
1442
1443
    public function updateContestRankTable($cid,$sub)
1444
    {
1445
        $lock = Cache::lock("contestrank$cid",10);
1446
        try{
1447
            if($lock->get()){
1448
                if(Cache::tags(['contest','rank'])->get($cid) != null){
1449
                    $chache = Cache::tags(['contest','data'])->get($cid);
1450
                    $ret = Cache::tags(['contest','rank'])->get($cid);
1451
1452
                    /**
1453
                     * Fix bugs caused by calling every 5 seconds(temporary)
1454
                     */
1455
                    if($chache['contest_info']['rule']==1){
1456
                        //ACM-ICPC Mode
1457
                        foreach($ret as $cr){
1458
                            if($cr["uid"]==$sub['uid']){
1459
                                foreach($cr["problem_detail"] as $crp){
1460
                                    if($crp["pid"]==$sub['pid'] && $crp["solved_time_parsed"]){
1461
                                        return ;
1462
                                    }
1463
                                }
1464
                            }
1465
                        }
1466
                    } elseif ($chache['contest_info']['rule']==2){
1467
                        //TODO: OI Mode
1468
                    }
1469
1470
                    $id = 0;
1471
1472
                    foreach($chache['problemSet'] as $key => $p){
1473
                        if ($p['pid'] == $sub['pid']){
1474
                            $chache['problemSet'][$key]['cpid'] = $key;
1475
                            $id = $key;
1476
                        }
1477
                    }
1478
1479
                    $ret = $this->updateContestRankDetail($chache['contest_info'],$chache['problemSet'][$id],$cid,$sub['uid'],$ret);
1480
                    $ret = $this->sortContestRankTable($chache['contest_info'],$cid,$ret);
1481
1482
                    if (time() < $chache['frozen_time']){
1483
                        Cache::tags(['contest', 'rank'])->put($cid, $ret);
1484
                    }
1485
                    Cache::tags(['contest', 'rank'])->put("contestAdmin$cid", $ret);
1486
                }
1487
                else{
1488
                    $ret=[];
1489
                    $chache=[];
1490
                    $chache['contest_info']=DB::table("contest")->where("cid", $cid)->first();
1491
                    $chache['problemSet']=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
1492
                        "cid"=>$cid
1493
                    ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
1494
                    $chache['frozen_time']=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
1495
                    $chache['end_time']=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
1496
1497
                    Cache::tags(['contest', 'data'])->put($cid, $chache);
1498
1499
                    if ($chache['contest_info']["registration"]) {
1500
                        $submissionUsers=DB::table("contest_participant")->where([
1501
                            "cid"=>$cid,
1502
                            "audit"=>1
1503
                        ])->select('uid')->get()->all();
1504
                    }else{
1505
                        $submissionUsers=DB::table("submission")->where([
1506
                            "cid"=>$cid
1507
                        ])->where(
1508
                            "submission_date",
1509
                            "<",
1510
                            $chache['frozen_time']
1511
                        )->select('uid')->groupBy('uid')->get()->all();
1512
                        $submissionUsersAdmin=DB::table("submission")->where([
1513
                            "cid"=>$cid
1514
                        ])->select('uid')->groupBy('uid')->get()->all();
1515
                    }
1516
1517
                    $chacheAdmin = $chache;
1518
1519
                    foreach ($submissionUsers as $s) {
1520
                        foreach ($chache['problemSet'] as $key => $p) {
1521
                            $p['cpid'] = $key;
1522
                            $ret = $this->updateContestRankDetail($chache['contest_info'],$p,$cid,$s['uid'],$ret);
1523
                        }
1524
                    }
1525
                    $ret = $this->sortContestRankTable($chache['contest_info'],$cid,$ret);
1526
                    Cache::tags(['contest', 'rank'])->put($cid, $ret);
1527
1528
                    $retAdmin=[];
1529
                    foreach ($submissionUsersAdmin as $s) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $submissionUsersAdmin does not seem to be defined for all execution paths leading up to this point.
Loading history...
1530
                        foreach ($chacheAdmin['problemSet'] as $key => $p) {
1531
                            $p['cpid'] = $key;
1532
                            $retAdmin = $this->updateContestRankDetail($chacheAdmin['contest_info'],$p,$cid,$s['uid'],$retAdmin);
1533
                        }
1534
                    }
1535
                    $retAdmin = $this->sortContestRankTable($chacheAdmin['contest_info'],$cid,$retAdmin);
1536
                    Cache::tags(['contest', 'rank'])->put("contestAdmin$cid", $retAdmin);
1537
                }
1538
            }
1539
        }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...
1540
            Log::warning("Contest Rank Lock Timed Out");
1541
        }finally{
1542
            optional($lock)->release();
1543
        }
1544
    }
1545
1546
    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

1546
    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...
1547
    {
1548
        if ($contest_info["rule"]==1){
1549
            usort($ret, function ($a, $b) {
1550
                if ($a["score"]==$b["score"]) {
1551
                    if ($a["penalty"]==$b["penalty"]) {
1552
                        return 0;
1553
                    } elseif (($a["penalty"]>$b["penalty"])) {
1554
                        return 1;
1555
                    } else {
1556
                        return -1;
1557
                    }
1558
                } elseif ($a["score"]>$b["score"]) {
1559
                    return -1;
1560
                } else {
1561
                    return 1;
1562
                }
1563
            });
1564
        }else if ($contest_info["rule"]==2){
1565
            usort($ret, function ($a, $b) {
1566
                if ($a["score"]==$b["score"]) {
1567
                    if ($a["solved"]==$b["solved"]) {
1568
                        return 0;
1569
                    } elseif (($a["solved"]<$b["solved"])) {
1570
                        return 1;
1571
                    } else {
1572
                        return -1;
1573
                    }
1574
                } elseif ($a["score"]>$b["score"]) {
1575
                    return -1;
1576
                } else {
1577
                    return 1;
1578
                }
1579
            });
1580
        }
1581
        return $ret;
1582
    }
1583
1584
    public function updateContestRankDetail($contest_info,$problem,$cid,$uid,$ret)
1585
    {
1586
        $id = count($ret);
1587
        foreach($ret as $key => $r){
1588
            if($r['uid'] == $uid)
1589
                $id = $key;
1590
        }
1591
        if ($contest_info["rule"]==1) {
1592
            // ACM/ICPC Mode
1593
            if($id == count($ret)){
1594
                $prob_detail = [];
1595
                $totPen = 0;
1596
                $totScore = 0;
1597
            }else{
1598
                $prob_detail = $ret[$id]['problem_detail'];
1599
                $totPen=$ret[$id]['penalty'];
1600
                $totScore=$ret[$id]['score'];
1601
            };
1602
1603
            $prob_stat=$this->contestProblemInfoACM($cid, $problem["pid"], $uid);
1604
1605
            $prob_detail[$problem['cpid']]=[
1606
                "ncode"=>$problem["ncode"],
1607
                "pid"=>$problem["pid"],
1608
                "color"=>$prob_stat["color"],
1609
                "wrong_doings"=>$prob_stat["wrong_doings"],
1610
                "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
1611
            ];
1612
            if ($prob_stat["solved"]) {
1613
                $totPen+=$prob_stat["wrong_doings"] * 20;
1614
                $totPen+=$prob_stat["solved_time"] / 60;
1615
                $totScore+=$prob_stat["solved"];
1616
            }
1617
1618
            $ret[$id]=[
1619
                "uid" => $uid,
1620
                "name" => DB::table("users")->where([
1621
                    "id"=>$uid
1622
                ])->first()["name"],
1623
                "nick_name" => DB::table("group_member")->where([
1624
                    "uid" => $uid,
1625
                    "gid" => $contest_info["gid"]
1626
                ])->where("role", ">", 0)->first()["nick_name"],
1627
                "score" => $totScore,
1628
                "penalty" => $totPen,
1629
                "problem_detail" => $prob_detail
1630
            ];
1631
        } elseif ($contest_info["rule"]==2) {
1632
            // OI Mode
1633
            if($id == count($ret)){
1634
                $prob_detail = [];
1635
                $totSolved = 0;
1636
                $totScore = 0;
1637
            }else{
1638
                $prob_detail = $ret[$id]['problem_detail'];
1639
                $totSolved=$ret[$id]['solved'];
1640
                $totScore=$ret[$id]['score'];
1641
            };
1642
1643
            $prob_stat=$this->contestProblemInfoOI($cid, $problem["pid"], $uid);
1644
            $prob_detail[$problem['cpid']]=[
1645
                "ncode"=>$problem["ncode"],
1646
                "pid"=>$problem["pid"],
1647
                "color"=>$prob_stat["color"],
1648
                "score"=>$prob_stat["score"],
1649
                "score_parsed"=>$prob_stat["score_parsed"]
1650
            ];
1651
            $totSolved+=$prob_stat["solved"];
1652
            $totScore+=intval($prob_stat["score_parsed"]);
1653
1654
            $ret[$id]=[
1655
                "uid" => $uid,
1656
                "name" => DB::table("users")->where([
1657
                    "id"=> $uid
1658
                ])->first()["name"],
1659
                "nick_name" => DB::table("group_member")->where([
1660
                    "uid" => $uid,
1661
                    "gid" => $contest_info["gid"]
1662
                ])->where("role", ">", 0)->first()["nick_name"],
1663
                "score" => $totScore,
1664
                "solved" => $totSolved,
1665
                "problem_detail" => $prob_detail
1666
            ];
1667
        }
1668
        return $ret;
1669
    }
1670
1671
    public function assignMember($cid,$uid){
1672
        return DB::table("contest")->where(["cid"=>$cid])->update([
1673
            "assign_uid"=>$uid
1674
        ]);
1675
    }
1676
1677
    public function replyClarification($ccid, $content)
1678
    {
1679
        return DB::table("contest_clarification")->where('ccid','=',$ccid)->update([
1680
            "reply"=>$content
1681
        ]);
1682
    }
1683
1684
    public function setClarificationPublic($ccid, $public)
1685
    {
1686
        if($public)
1687
        {
1688
            return DB::table("contest_clarification")->where('ccid','=',$ccid)->update([
1689
                "public"=>1
1690
            ]);
1691
        }
1692
        else
1693
        {
1694
            return DB::table("contest_clarification")->where('ccid','=',$ccid)->update([
1695
                "public"=>0
1696
            ]);
1697
        }
1698
    }
1699
1700
    public function getContestAccount($cid)
1701
    {
1702
        return Cache::tags(['contest', 'account'])->get($cid);
1703
    }
1704
1705
    public function praticeAnalysis($cid)
1706
    {
1707
        $gid = DB::table('contest')
1708
            ->where('cid',$cid)
1709
            ->first()['gid'];
1710
        $contestRank = $this->contestRank($cid,Auth::user()->id);
1711
        if(!empty($contestRank)){
1712
            $all_problems = DB::table('problem')
1713
            ->whereIn('pid',array_column($contestRank[0]['problem_detail'],'pid'))
1714
            ->select('pid','title')
1715
            ->get()->all();
1716
        }else{
1717
            $all_problems = [];
1718
        }
1719
        $tags = DB::table('group_problem_tag')
1720
            ->where('gid', $gid)
1721
            ->whereIn('pid', array_column($all_problems,'pid'))
1722
            ->get()->all();
1723
        $all_tags = array_unique(array_column($tags,'tag'));
1724
        $memberData = [];
1725
        foreach($contestRank as $member){
1726
            $m = [
1727
                'uid' => $member['uid'],
1728
                'name' => $member['name'],
1729
                'nick_name' => $member['nick_name'],
1730
            ];
1731
            $completion = [];
1732
            foreach ($all_tags as $tag){
1733
                $completion[$tag] = [];
1734
                foreach ($tags as $t) {
1735
                    if($t['tag'] == $tag){
1736
                        foreach ($member['problem_detail'] as $pd) {
1737
                            if($pd['pid'] == $t['pid']){
1738
                                $completion[$tag][$t['pid']] = $pd['solved_time_parsed'] == "" ? 0 : 1;
1739
                            }
1740
                        }
1741
                    }
1742
                }
1743
            }
1744
            $m['completion'] = $completion;
1745
            $memberData[] = $m;
1746
        }
1747
        return $memberData;
1748
    }
1749
1750
    public function storeContestRankInMySQL($cid, $data)
1751
    {
1752
        $contestRankJson = json_encode($data);
1753
        return DB::table('contest')->where('cid','=',$cid)->update([
1754
            'rank' => $contestRankJson
1755
        ]);
1756
    }
1757
1758
    public function getContestRankFromMySQL($cid)
1759
    {
1760
        $contestRankJson = DB::table('contest')->where('cid','=',$cid)->pluck('rank')->first();
1761
        $data = json_decode($contestRankJson, true);
1762
        return $data;
1763
    }
1764
1765
    public function isVerified($cid)
1766
    {
1767
        return DB::table('contest')->where('cid','=',$cid)->pluck('verified')->first();
1768
    }
1769
}
1770