Passed
Pull Request — master (#206)
by
unknown
04:01
created

ContestModel::updateContestRankDetail()   C

Complexity

Conditions 12
Paths 27

Size

Total Lines 100
Code Lines 79

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
cc 12
eloc 79
c 3
b 2
f 0
nc 27
nop 5
dl 0
loc 100
rs 6.0315

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

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

1567
    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...
1568
    {
1569
        if ($contest_info["rule"]==1){
1570
            usort($ret, function ($a, $b) {
1571
                if ($a["score"]==$b["score"]) {
1572
                    if ($a["penalty"]==$b["penalty"]) {
1573
                        return 0;
1574
                    } elseif (($a["penalty"]>$b["penalty"])) {
1575
                        return 1;
1576
                    } else {
1577
                        return -1;
1578
                    }
1579
                } elseif ($a["score"]>$b["score"]) {
1580
                    return -1;
1581
                } else {
1582
                    return 1;
1583
                }
1584
            });
1585
        }else if ($contest_info["rule"]==2){
1586
            usort($ret, function ($a, $b) {
1587
                if ($a["score"]==$b["score"]) {
1588
                    if ($a["solved"]==$b["solved"]) {
1589
                        return 0;
1590
                    } elseif (($a["solved"]<$b["solved"])) {
1591
                        return 1;
1592
                    } else {
1593
                        return -1;
1594
                    }
1595
                } elseif ($a["score"]>$b["score"]) {
1596
                    return -1;
1597
                } else {
1598
                    return 1;
1599
                }
1600
            });
1601
        }
1602
        return $ret;
1603
    }
1604
1605
    public function updateContestRankDetail($contest_info,$problem,$cid,$uid,$ret)
1606
    {
1607
        $id = count($ret);
1608
        foreach($ret as $key => $r){
1609
            if($r['uid'] == $uid)
1610
                $id = $key;
1611
        }
1612
        if ($contest_info["rule"]==1) {
1613
            // ACM/ICPC Mode
1614
            if($id == count($ret)){
1615
                $prob_detail = [];
1616
                $totPen = 0;
1617
                $totScore = 0;
1618
            }else{
1619
                $prob_detail = $ret[$id]['problem_detail'];
1620
                $totPen=$ret[$id]['penalty'];
1621
                $totScore=$ret[$id]['score'];
1622
            };
1623
1624
            $ac_times=DB::table("submission")->where([
1625
                "cid"=>$cid,
1626
                "pid"=>$problem['pid'],
1627
                "uid"=>$uid,
1628
                "verdict"=>"Accepted"
1629
            ])->count();
1630
1631
            $last_record=DB::table("submission")->where([
1632
                "cid"=>$cid,
1633
                "pid"=>$problem['pid'],
1634
                "uid"=>$uid,
1635
            ])->orderBy('submission_date', 'desc')->first();
1636
    
1637
            if ($ac_times<=1 && $last_record->verdict!="Waiting" && $last_record->verdict!="Submission Error" && $last_record->verdict!="System Error"){
1638
                $prob_stat=$this->contestProblemInfoACM($cid, $problem["pid"], $uid);
1639
1640
                $prob_detail[$problem['cpid']]=[
1641
                    "ncode"=>$problem["ncode"],
1642
                    "pid"=>$problem["pid"],
1643
                    "color"=>$prob_stat["color"],
1644
                    "wrong_doings"=>$prob_stat["wrong_doings"],
1645
                    "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
1646
                ];
1647
                if ($prob_stat["solved"]) {
1648
                    $totPen+=$prob_stat["wrong_doings"] * 20;
1649
                    $totPen+=$prob_stat["solved_time"] / 60;
1650
                    $totScore+=$prob_stat["solved"];
1651
                }
1652
    
1653
                $ret[$id]=[
1654
                    "uid" => $uid,
1655
                    "name" => DB::table("users")->where([
1656
                        "id"=>$uid
1657
                    ])->first()["name"],
1658
                    "nick_name" => DB::table("group_member")->where([
1659
                        "uid" => $uid,
1660
                        "gid" => $contest_info["gid"]
1661
                    ])->where("role", ">", 0)->first()["nick_name"],
1662
                    "score" => $totScore,
1663
                    "penalty" => $totPen,
1664
                    "problem_detail" => $prob_detail
1665
                ];
1666
            }
1667
        } elseif ($contest_info["rule"]==2) {
1668
            // OI Mode
1669
            if($id == count($ret)){
1670
                $prob_detail = [];
1671
                $totSolved = 0;
1672
                $totScore = 0;
1673
            }else{
1674
                $prob_detail = $ret[$id]['problem_detail'];
1675
                $totSolved=$ret[$id]['solved'];
1676
                $totScore=$ret[$id]['score'];
1677
            };
1678
1679
            $prob_stat=$this->contestProblemInfoOI($cid, $problem["pid"], $uid);
1680
            $prob_detail[$problem['cpid']]=[
1681
                "ncode"=>$problem["ncode"],
1682
                "pid"=>$problem["pid"],
1683
                "color"=>$prob_stat["color"],
1684
                "score"=>$prob_stat["score"],
1685
                "score_parsed"=>$prob_stat["score_parsed"]
1686
            ];
1687
            $totSolved+=$prob_stat["solved"];
1688
            $totScore+=intval($prob_stat["score_parsed"]);
1689
1690
            $ret[$id]=[
1691
                "uid" => $uid,
1692
                "name" => DB::table("users")->where([
1693
                    "id"=> $uid
1694
                ])->first()["name"],
1695
                "nick_name" => DB::table("group_member")->where([
1696
                    "uid" => $uid,
1697
                    "gid" => $contest_info["gid"]
1698
                ])->where("role", ">", 0)->first()["nick_name"],
1699
                "score" => $totScore,
1700
                "solved" => $totSolved,
1701
                "problem_detail" => $prob_detail
1702
            ];
1703
        }
1704
        return $ret;
1705
    }
1706
1707
    public function assignMember($cid,$uid){
1708
        return DB::table("contest")->where(["cid"=>$cid])->update([
1709
            "assign_uid"=>$uid
1710
        ]);
1711
    }
1712
1713
    public function canUpdateContestTime($cid,$time = [])
1714
    {
1715
        $begin_time_new = $time['begin'] ?? null;
1716
        $end_time_new = $time['end'] ?? null;
1717
1718
        $hold_time = DB::table('contest')
1719
            ->where('cid',$cid)
1720
            ->select('begin_time','end_time')
1721
            ->first();
1722
        $begin_stamps = strtotime($hold_time['begin_time']);
1723
        $end_stamps = strtotime($hold_time['end_time']);
1724
        /*
1725
        -1 : have not begun
1726
         0 : ing
1727
         1 : end
1728
        */
1729
        $status = time() >= $end_stamps ? 1
1730
                : (time() <= $begin_stamps ? -1 : 0);
1731
        if($status === -1){
1732
            if(time() > $begin_time_new){
1733
                return false;
1734
            }
1735
            return true;
1736
        }else if($status === 0){
1737
            if($begin_time_new !== null){
1738
                return false;
1739
            }
1740
            if($end_time_new !== null){
1741
                if(strtotime($end_time_new) <= time()){
1742
                    return false;
1743
                }else{
1744
                    return true;
1745
                }
1746
            }
1747
        }else{
1748
            return false;
1749
        }
1750
1751
        return true;
1752
    }
1753
1754
    public function replyClarification($ccid, $content)
1755
    {
1756
        return DB::table("contest_clarification")->where('ccid','=',$ccid)->update([
1757
            "reply"=>$content
1758
        ]);
1759
    }
1760
1761
    public function setClarificationPublic($ccid, $public)
1762
    {
1763
        if($public)
1764
        {
1765
            return DB::table("contest_clarification")->where('ccid','=',$ccid)->update([
1766
                "public"=>1
1767
            ]);
1768
        }
1769
        else
1770
        {
1771
            return DB::table("contest_clarification")->where('ccid','=',$ccid)->update([
1772
                "public"=>0
1773
            ]);
1774
        }
1775
    }
1776
1777
    public function getContestAccount($cid)
1778
    {
1779
        return Cache::tags(['contest', 'account'])->get($cid);
1780
    }
1781
1782
    public function praticeAnalysis($cid){
1783
        $gid = DB::table('contest')
1784
            ->where('cid',$cid)
1785
            ->first()['gid'];
1786
        $contestRank = $this->contestRank($cid,Auth::user()->id);
1787
        if(!empty($contestRank)){
1788
            $all_problems = DB::table('problem')
1789
            ->whereIn('pid',array_column($contestRank[0]['problem_detail'],'pid'))
1790
            ->select('pid','title')
1791
            ->get()->all();
1792
        }else{
1793
            $all_problems = [];
1794
        }
1795
        $tags = DB::table('group_problem_tag')
1796
            ->where('gid', $gid)
1797
            ->whereIn('pid', array_column($all_problems,'pid'))
1798
            ->get()->all();
1799
        $all_tags = array_unique(array_column($tags,'tag'));
1800
        $memberData = [];
1801
        foreach($contestRank as $member){
1802
            $m = [
1803
                'uid' => $member['uid'],
1804
                'name' => $member['name'],
1805
                'nick_name' => $member['nick_name'],
1806
            ];
1807
            $completion = [];
1808
            foreach ($all_tags as $tag){
1809
                $completion[$tag] = [];
1810
                foreach ($tags as $t) {
1811
                    if($t['tag'] == $tag){
1812
                        foreach ($member['problem_detail'] as $pd) {
1813
                            if($pd['pid'] == $t['pid']){
1814
                                $completion[$tag][$t['pid']] = $pd['solved_time_parsed'] == "" ? 0 : 1;
1815
                            }
1816
                        }
1817
                    }
1818
                }
1819
            }
1820
            $m['completion'] = $completion;
1821
            $memberData[] = $m;
1822
        }
1823
        return $memberData;
1824
    }
1825
1826
    public function storeContestRankInMySQL($cid, $data)
1827
    {
1828
        $contestRankJson = json_encode($data);
1829
        return DB::table('contest')->where('cid','=',$cid)->update([
1830
            'rank' => $contestRankJson
1831
        ]);
1832
    }
1833
1834
    public function getContestRankFromMySQL($cid)
1835
    {
1836
        $contestRankJson = DB::table('contest')->where('cid','=',$cid)->pluck('rank')->first();
1837
        $data = json_decode($contestRankJson, true);
1838
        return $data;
1839
    }
1840
1841
    public function isVerified($cid)
1842
    {
1843
        return DB::table('contest')->where('cid','=',$cid)->pluck('verified')->first();
1844
    }
1845
}
1846