Completed
Push — master ( a4261d...fc5e52 )
by John
14s
created

ContestModel::getContestRecord()   C

Complexity

Conditions 11
Paths 44

Size

Total Lines 178
Code Lines 161

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 161
nc 44
nop 1
dl 0
loc 178
rs 5.8533
c 1
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

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