Passed
Push — master ( 19b4ee...35c8a3 )
by John
04:51
created

ContestModel::judgeOutsideClearance()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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

274
    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...
275
    {
276
        return DB::table("problem")->where([
277
            "cid"=>$cid
278
        ])->select("contest_problem.pid")->first()["pcode"];
279
    }
280
281
    public function getCustomInfo($cid)
282
    {
283
        $basic_info=DB::table($this->tableName)->where([
284
            "cid"=>$cid
285
        ])->select("verified", "custom_icon", "custom_title")->first();
286
        return $basic_info["verified"] ? ((is_null($basic_info["custom_icon"]) && is_null($basic_info["custom_title"])) ?null:$basic_info) : null;
287
    }
288
289
290
    public function formatTime($seconds)
291
    {
292
        if ($seconds>3600) {
293
            $hours=intval($seconds / 3600);
294
            $minutes=$seconds % 3600;
295
            $time=$hours.":".gmstrftime('%M:%S', $minutes);
296
        } else {
297
            $time=gmstrftime('%H:%M:%S', $seconds);
298
        }
299
        return $time;
300
    }
301
302
    public function contestProblemInfoOI($cid, $pid, $uid)
303
    {
304
        $ret=[
305
            "color"=>"",
306
            "score"=>null,
307
            "score_parsed"=>"",
308
            "solved"=>0,
309
            "points"=>DB::table("contest_problem")->where([
310
                "pid"=>$pid,
311
                "cid"=>$cid
312
            ])->first()["points"]
313
        ];
314
315
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
316
        $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...
317
318
        $highest_record=DB::table("submission")->where([
319
            "cid"=>$cid,
320
            "pid"=>$pid,
321
            "uid"=>$uid
322
        ])->where("submission_date", "<", $frozen_time)->orderBy('score', 'desc')->first();
323
324
        if (!empty($highest_record)) {
325
            $ret["score"]=$highest_record["score"];
326
327
            $tot_score=DB::table("problem")->where([
328
                "pid"=>$pid
329
            ])->first()["tot_score"];
330
331
            $ret["color"]=($ret["score"]==$tot_score) ? "wemd-teal-text" : "wemd-green-text";
332
            $ret["solved"]=($ret["score"]==$tot_score) ? 1 : 0;
333
            $ret["score_parsed"]=$ret["score"] / $tot_score * ($ret["points"]);
334
        }
335
        return $ret;
336
    }
337
338
    public function isFrozen($cid)
339
    {
340
        $frozen=DB::table("contest")->where(["cid"=>$cid])->select("froze_length", DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first();
341
        if (empty($frozen["froze_length"])) {
342
            return false;
343
        } else {
344
            return time()>$frozen["frozen_time"];
345
        }
346
    }
347
348
    public function contestProblemInfoACM($cid, $pid, $uid)
349
    {
350
        $ret=[
351
            "color"=>"",
352
            "solved"=>0,
353
            "solved_time"=>"",
354
            "solved_time_parsed"=>"",
355
            "wrong_doings"=>0,
356
            "color"=>"",
357
        ];
358
359
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
360
        $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...
361
362
        $ac_record=DB::table("submission")->where([
363
            "cid"=>$cid,
364
            "pid"=>$pid,
365
            "uid"=>$uid,
366
            "verdict"=>"Accepted"
367
        ])->where("submission_date", "<", $frozen_time)->orderBy('submission_date', 'asc')->first();
368
369
        if (!empty($ac_record)) {
370
            $ret["solved"]=1;
371
372
            $ret["solved_time"]=$ac_record["submission_date"]-strtotime(DB::table($this->tableName)->where([
373
                "cid"=>$cid
374
            ])->first()["begin_time"]);
375
376
            $ret["solved_time_parsed"]=$this->formatTime($ret["solved_time"]);
377
378
            $ret["wrong_doings"]=DB::table("submission")->where([
379
                "cid"=>$cid,
380
                "pid"=>$pid,
381
                "uid"=>$uid
382
            ])->whereIn('verdict', [
383
                'Runtime Error',
384
                'Wrong Answer',
385
                'Time Limit Exceed',
386
                'Real Time Limit Exceed',
387
                'Memory Limit Exceed',
388
                'Presentation Error',
389
                'Output Limit Exceeded'
390
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
391
392
            $others_first=DB::table("submission")->where([
393
                "cid"=>$cid,
394
                "pid"=>$pid,
395
                "verdict"=>"Accepted"
396
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
397
398
            $ret["color"]=$others_first ? "wemd-green-text" : "wemd-teal-text";
399
        } else {
400
            $ret["wrong_doings"]=DB::table("submission")->where([
401
                "cid"=>$cid,
402
                "pid"=>$pid,
403
                "uid"=>$uid
404
            ])->whereIn('verdict', [
405
                'Runtime Error',
406
                'Wrong Answer',
407
                'Time Limit Exceed',
408
                'Real Time Limit Exceed',
409
                'Memory Limit Exceed',
410
                'Presentation Error',
411
                'Output Limit Exceeded'
412
            ])->where("submission_date", "<", $frozen_time)->count();
413
        }
414
415
        return $ret;
416
    }
417
418
    public function contestRankCache($cid)
419
    {
420
        // if(Cache::tags(['contest','rank'])->get($cid)!=null) return Cache::tags(['contest','rank'])->get($cid);
421
        $ret=[];
422
423
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
424
425
        if ($contest_info["registration"]) {
426
            $submissionUsers=DB::table("contest_participant")->where([
427
                "cid"=>$cid,
428
                "audit"=>1
429
            ])->select('uid')->get()->all();
430
        } else {
431
            // Those who submitted are participants
432
            $submissionUsers=DB::table("submission")->where([
433
                "cid"=>$cid
434
            ])->select('uid')->groupBy('uid')->get()->all();
435
        }
436
437
        $problemSet=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
438
            "cid"=>$cid
439
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
440
441
        if ($contest_info["rule"]==1) {
442
            // ACM/ICPC Mode
443
            foreach ($submissionUsers as $s) {
444
                $prob_detail=[];
445
                $totPen=0;
446
                $totScore=0;
447
                foreach ($problemSet as $p) {
448
                    $prob_stat=$this->contestProblemInfoACM($cid, $p["pid"], $s["uid"]);
449
                    $prob_detail[]=[
450
                        "ncode"=>$p["ncode"],
451
                        "pid"=>$p["pid"],
452
                        "color"=>$prob_stat["color"],
453
                        "wrong_doings"=>$prob_stat["wrong_doings"],
454
                        "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
455
                    ];
456
                    if ($prob_stat["solved"]) {
457
                        $totPen+=$prob_stat["wrong_doings"] * 20;
458
                        $totPen+=$prob_stat["solved_time"] / 60;
459
                        $totScore+=$prob_stat["solved"];
460
                    }
461
                }
462
                $ret[]=[
463
                    "uid" => $s["uid"],
464
                    "name" => DB::table("users")->where([
465
                        "id"=>$s["uid"]
466
                    ])->first()["name"],
467
                    "nick_name" => DB::table("group_member")->where([
468
                        "uid" => $s["uid"],
469
                        "gid" => $contest_info["gid"]
470
                    ])->where("role", ">", 0)->first()["nick_name"],
471
                    "score" => $totScore,
472
                    "penalty" => $totPen,
473
                    "problem_detail" => $prob_detail
474
                ];
475
            }
476
            usort($ret, function ($a, $b) {
477
                if ($a["score"]==$b["score"]) {
478
                    if ($a["penalty"]==$b["penalty"]) {
479
                        return 0;
480
                    } elseif (($a["penalty"]>$b["penalty"])) {
481
                        return 1;
482
                    } else {
483
                        return -1;
484
                    }
485
                } elseif ($a["score"]>$b["score"]) {
486
                    return -1;
487
                } else {
488
                    return 1;
489
                }
490
            });
491
        } elseif ($contest_info["rule"]==2) {
492
            // OI Mode
493
            foreach ($submissionUsers as $s) {
494
                $prob_detail=[];
495
                $totScore=0;
496
                $totSolved=0;
497
                foreach ($problemSet as $p) {
498
                    $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $s["uid"]);
499
                    $prob_detail[]=[
500
                        "ncode"=>$p["ncode"],
501
                        "pid"=>$p["pid"],
502
                        "color"=>$prob_stat["color"],
503
                        "score"=>$prob_stat["score"],
504
                        "score_parsed"=>$prob_stat["score_parsed"]
505
                    ];
506
                    $totSolved+=$prob_stat["solved"];
507
                    $totScore+=intval($prob_stat["score_parsed"]);
508
                }
509
                $ret[]=[
510
                    "uid" => $s["uid"],
511
                    "name" => DB::table("users")->where([
512
                        "id"=>$s["uid"]
513
                    ])->first()["name"],
514
                    "nick_name" => DB::table("group_member")->where([
515
                        "uid" => $s["uid"],
516
                        "gid" => $contest_info["gid"]
517
                    ])->where("role", ">", 0)->first()["nick_name"],
518
                    "score" => $totScore,
519
                    "solved" => $totSolved,
520
                    "problem_detail" => $prob_detail
521
                ];
522
            }
523
            usort($ret, function ($a, $b) {
524
                if ($a["score"]==$b["score"]) {
525
                    if ($a["solved"]==$b["solved"]) {
526
                        return 0;
527
                    } elseif (($a["solved"]<$b["solved"])) {
528
                        return 1;
529
                    } else {
530
                        return -1;
531
                    }
532
                } elseif ($a["score"]>$b["score"]) {
533
                    return -1;
534
                } else {
535
                    return 1;
536
                }
537
            });
538
        }
539
540
        Cache::tags(['contest','rank'])->put($cid, $ret, 60);
541
542
        return $ret;
543
    }
544
545
    public function contestRank($cid, $uid)
546
    {
547
        // [ToDo] If the current user's in the organizer group show nick name
548
        // [ToDo] The participants determination
549
        // [ToDo] Frozen Time
550
        // [ToDo] Performance Opt
551
        // [Todo] Ajaxization - Should have done in controller
552
        // [Todo] Authorization ( Public / Private ) - Should have done in controller
553
554
        $ret=[];
0 ignored issues
show
Unused Code introduced by
The assignment to $ret is dead and can be removed.
Loading history...
555
556
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
557
558
        $user_in_group=!empty(DB::table("group_member")->where([
559
            "uid" => $uid,
560
            "gid" => $contest_info["gid"]
561
        ])->where("role", ">", 0)->first());
562
563
        $contestRankRaw=Cache::tags(['contest','rank'])->get($cid);
564
565
        if($contestRankRaw==null) $contestRankRaw=$this->contestRankCache($cid);
566
567
        $ret=$contestRankRaw;
568
569
        foreach($ret as $r){
570
            if(!$user_in_group) $r["nick_name"]='';
571
        }
572
573
        return $ret;
574
    }
575
576
    public function getRejudgeQueue($cid)
577
    {
578
        $problemModel=new ProblemModel();
579
        $submissionModel=new SubmissionModel();
0 ignored issues
show
Unused Code introduced by
The assignment to $submissionModel is dead and can be removed.
Loading history...
580
        $compilerModel=new CompilerModel();
581
582
        $tempQueue=DB::table("submission")->where([
583
            "cid"=>$cid
584
        ])->whereIn('verdict', [
585
            'Runtime Error',
586
            'Wrong Answer',
587
            'Time Limit Exceed',
588
            'Real Time Limit Exceed',
589
            'Memory Limit Exceed',
590
            'Presentation Error',
591
            'Output Limit Exceeded'
592
        ])->get()->all();
593
594
        foreach ($tempQueue as &$t) {
595
            $lang=$compilerModel->detail($t["coid"]);
596
            $probBasic=$problemModel->basic($t["pid"]);
597
            $t["oj"]=$problemModel->ocode($t["pid"]);
598
            $t["lang"]=$lang['lcode'];
599
            $t["cid"]=$probBasic["contest_id"];
600
            $t["iid"]=$probBasic["index_id"];
601
            $t["pcode"]=$probBasic["pcode"];
602
            $t["contest"]=$cid;
603
        }
604
605
        return $tempQueue;
606
    }
607
608
    public function getClarificationList($cid)
609
    {
610
        return DB::table("contest_clarification")->where([
611
            "cid"=>$cid
612
        ])->where(function ($query) {
613
            $query->where([
614
                "public"=>1
615
            ])->orWhere([
616
                "uid" => Auth::user()->id
617
            ]);
618
        })->orderBy('create_time', 'desc')->get()->all();
619
    }
620
621
    public function fetchClarification($cid)
622
    {
623
        return DB::table("contest_clarification")->where([
624
            "cid"=>$cid,
625
            "type"=>0,
626
            "public"=>1
627
        ])->whereBetween(
628
            'create_time', [
629
                date("Y-m-d H:i:s", time()-59),
630
                date("Y-m-d H:i:s")
631
            ]
632
        )->first();
633
    }
634
635
    public function getlatestClarification($cid)
636
    {
637
        return DB::table("contest_clarification")->where([
638
            "cid"=>$cid,
639
            "type"=>0,
640
            "public"=>1
641
        ])->orderBy('create_time', 'desc')->first();
642
    }
643
644
    public function getClarificationDetail($ccid)
645
    {
646
        return DB::table("contest_clarification")->where([
647
            "ccid"=>$ccid,
648
            "public"=>1
649
        ])->first();
650
    }
651
652
    public function requestClarification($cid, $title, $content, $uid)
653
    {
654
        return DB::table("contest_clarification")->insertGetId([
655
            "cid"=>$cid,
656
            "type"=>1,
657
            "title"=>$title,
658
            "content"=>$content,
659
            "public"=>"0",
660
            "uid"=>$uid,
661
            "create_time"=>date("Y-m-d H:i:s")
662
        ]);
663
    }
664
665
    public function isContestEnded($cid)
666
    {
667
        return DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
668
    }
669
670
    public function formatSubmitTime($date)
671
    {
672
        $periods=["second", "minute", "hour", "day", "week", "month", "year", "decade"];
673
        $lengths=["60", "60", "24", "7", "4.35", "12", "10"];
674
675
        $now=time();
676
        $unix_date=strtotime($date);
677
678
        if (empty($unix_date)) {
679
            return "Bad date";
680
        }
681
682
        if ($now>$unix_date) {
683
            $difference=$now-$unix_date;
684
            $tense="ago";
685
        } else {
686
            $difference=$unix_date-$now;
687
            $tense="from now";
688
        }
689
690
        for ($j=0; $difference>=$lengths[$j] && $j<count($lengths)-1; $j++) {
691
            $difference/=$lengths[$j];
692
        }
693
694
        $difference=round($difference);
695
696
        if ($difference!=1) {
697
            $periods[$j].="s";
698
        }
699
700
        return "$difference $periods[$j] {$tense}";
701
    }
702
703
    public function formatAbsTime($sec)
704
    {
705
        $periods=["second", "minute", "hour", "day", "week", "month", "year", "decade"];
706
        $lengths=["60", "60", "24", "7", "4.35", "12", "10"];
707
708
709
        $difference=$sec;
710
711
        for ($j=0; $difference>=$lengths[$j] && $j<count($lengths)-1; $j++) {
712
            $difference/=$lengths[$j];
713
        }
714
715
        $difference=round($difference);
716
717
        if ($difference!=1) {
718
            $periods[$j].="s";
719
        }
720
721
        return "$difference $periods[$j]";
722
    }
723
724
    public function frozenTime($cid)
725
    {
726
        $basicInfo=$this->basic($cid);
727
        return $this->formatAbsTime($basicInfo["froze_length"]);
728
    }
729
730
731
    public function getContestRecord($cid)
732
    {
733
        $basicInfo=$this->basic($cid);
734
        $problemSet_temp=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
735
            "cid"=>$cid
736
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title", "points", "tot_score")->get()->all();
737
        $problemSet=[];
738
        foreach ($problemSet_temp as $p) {
739
            $problemSet[(string) $p["pid"]]=["ncode"=>$p["ncode"], "points"=>$p["points"], "tot_score"=>$p["tot_score"]];
740
        }
741
742
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
743
        $end_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
744
745
        if ($basicInfo["status_visibility"]==2) {
746
            // View all
747
            $paginator=DB::table("submission")->where([
748
                'cid'=>$cid
749
            ])->where(
750
                "submission_date",
751
                "<",
752
                $end_time
753
            )->join(
754
                "users",
755
                "users.id",
756
                "=",
757
                "submission.uid"
758
            )->where(function ($query) use ($frozen_time) {
759
                $query->where(
760
                    "submission_date",
761
                    "<",
762
                    $frozen_time
763
                )->orWhere(
764
                    'uid',
765
                    Auth::user()->id
766
                );
767
            })->select(
768
                "sid",
769
                "uid",
770
                "pid",
771
                "name",
772
                "color",
773
                "verdict",
774
                "time",
775
                "memory",
776
                "language",
777
                "score",
778
                "submission_date"
779
            )->orderBy(
780
                'submission_date',
781
                'desc'
782
            )->paginate(50);
783
        } elseif ($basicInfo["status_visibility"]==1) {
784
            $paginator=DB::table("submission")->where([
785
                'cid'=>$cid,
786
                'uid'=>Auth::user()->id
787
            ])->where(
788
                "submission_date",
789
                "<",
790
                $end_time
791
            )->join(
792
                "users",
793
                "users.id",
794
                "=",
795
                "submission.uid"
796
            )->select(
797
                "sid",
798
                "uid",
799
                "pid",
800
                "name",
801
                "color",
802
                "verdict",
803
                "time",
804
                "memory",
805
                "language",
806
                "score",
807
                "submission_date"
808
            )->orderBy(
809
                'submission_date',
810
                'desc'
811
            )->paginate(50);
812
        } else {
813
            return [
814
                "paginator"=>null,
815
                "records"=>[]
816
            ];
817
        }
818
819
        $records=$paginator->all();
820
        foreach ($records as &$r) {
821
            $r["submission_date_parsed"]=$this->formatSubmitTime(date('Y-m-d H:i:s', $r["submission_date"]));
822
            $r["submission_date"]=date('Y-m-d H:i:s', $r["submission_date"]);
823
            $r["nick_name"]="";
824
            $r["ncode"]=$problemSet[(string) $r["pid"]]["ncode"];
825
            if ($r["verdict"]=="Partially Accepted") {
826
                $score_parsed=round($r["score"] / $problemSet[(string) $r["pid"]]["tot_score"] * $problemSet[(string) $r["pid"]]["points"], 1);
827
                $r["verdict"].=" ($score_parsed)";
828
            }
829
        }
830
        return [
831
            "paginator"=>$paginator,
832
            "records"=>$records
833
        ];
834
    }
835
836
    public function registration($cid, $uid=0)
837
    {
838
        if ($uid==0) {
839
            return [];
840
        }
841
842
843
        return DB::table("contest_participant")->where([
844
            "cid" => $cid,
845
            "uid" => $uid,
846
            "audit" => 1
847
        ])->first();
848
    }
849
850
    public function judgeClearance($cid, $uid=0)
851
    {
852
        if ($uid==0) {
853
            return 0;
854
        }
855
856
        $contest_started=DB::table("contest")->where("cid", $cid)->where("begin_time", "<", date("Y-m-d H:i:s"))->count();
857
        $contest_ended=DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
858
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
859
860
        if (!$contest_started) {
861
            // not started or do not exist
862
            return 0;
863
        }
864
865
        if ($contest_info["public"]) {
866
            //public
867
            if ($contest_ended) {
868
                return 1;
869
            } else {
870
                if ($contest_info["registration"]) {
871
                    // check if uid in registration, temp return 3
872
                    $isParticipant=DB::table("contest_participant")->where([
873
                        "cid" => $cid,
874
                        "uid" => $uid,
875
                        "audit" => 1
876
                    ])->count();
877
                    if ($isParticipant) {
878
                        return 2;
879
                    } else {
880
                        return 0;
881
                    }
882
                } else {
883
                    return 2;
884
                }
885
            }
886
        } else {
887
            //private
888
            $isMember=DB::table("group_member")->where([
889
                "gid"=> $contest_info["gid"],
890
                "uid"=> $uid
891
            ])->where("role", ">", 0)->count();
892
            if (!$isMember) {
893
                return 0;
894
            } else {
895
                if ($contest_info["registration"]) {
896
                    // check if uid in registration, temp return 3
897
                    $isParticipant=DB::table("contest_participant")->where([
898
                        "cid" => $cid,
899
                        "uid" => $uid,
900
                        "audit" => 1
901
                    ])->count();
902
                    if ($isParticipant) {
903
                        return 2;
904
                    } else {
905
                        return 0;
906
                    }
907
                } else {
908
                    return 2;
909
                }
910
            }
911
        }
912
    }
913
914
    public function judgeOutsideClearance($cid, $uid=0)
915
    {
916
        $contest_info=DB::table("contest")->where("cid", $cid)->first();
917
        if (empty($contest_info)) {
918
            return 0;
919
        }
920
        if ($contest_info["public"]) {
921
            return 1;
922
        } else {
923
            if ($uid==0) {
924
                return 0;
925
            }
926
            return DB::table("group_member")->where([
927
                "gid"=> $contest_info["gid"],
928
                "uid"=> $uid
929
            ])->where("role", ">", 0)->count() ? 1 : 0;
930
        }
931
    }
932
933
    public function contestName($cid)
934
    {
935
        return DB::table("contest")->where("cid", $cid)->select("name")->first()["name"];
936
    }
937
938
    public function contestRule($cid)
939
    {
940
        return DB::table("contest")->where("cid", $cid)->select("rule")->first()["rule"];
941
    }
942
943
    public function arrangeContest($gid, $config, $problems)
944
    {
945
        DB::transaction(function () use ($gid, $config, $problems) {
946
            $cid=DB::table($this->tableName)->insertGetId([
947
                "gid"=>$gid,
948
                "name"=>$config["name"],
949
                "verified"=>0, //todo
950
                "rated"=>0,
951
                "anticheated"=>0,
952
                "featured"=>0,
953
                "description"=>$config["description"],
954
                "rule"=>1, //todo
955
                "begin_time"=>$config["begin_time"],
956
                "end_time"=>$config["end_time"],
957
                "public"=>0, //todo
958
                "registration"=>0, //todo
959
                "registration_due"=>null, //todo
960
                "registant_type"=>0, //todo
961
                "froze_length"=>0, //todo
962
                "status_visibility"=>2, //todo
963
                "create_time"=>date("Y-m-d H:i:s"),
964
                "audit_status"=>1                       //todo
965
            ]);
966
967
            foreach ($problems as $p) {
968
                $pid=DB::table("problem")->where(["pcode"=>$p["pcode"]])->select("pid")->first()["pid"];
969
                DB::table("contest_problem")->insert([
970
                    "cid"=>$cid,
971
                    "number"=>$p["number"],
972
                    "ncode"=>$this->intToChr($p["number"]-1),
973
                    "pid"=>$pid,
974
                    "alias"=>"",
975
                    "points"=>$p["points"]
976
                ]);
977
            }
978
        }, 5);
979
    }
980
}
981