Passed
Pull Request — master (#192)
by Chenyi
04:34
created

ContestModel::updateCrawlStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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