Passed
Push — master ( 06835c...2f48f9 )
by John
04:01
created

ContestModel::contestName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
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()
143
    {
144
        $paginator=DB::table($this->tableName)->where([
145
            "public"=>1,
146
            "audit_status"=>1
147
        ])->orderBy('begin_time', 'desc')->paginate(10);
148
149
        $contest_list=$paginator->all();
150
        foreach ($contest_list as &$c) {
151
            $c["rule_parsed"]=$this->rule[$c["rule"]];
152
            $c["date_parsed"]=[
153
                "date"=>date_format(date_create($c["begin_time"]), 'j'),
154
                "month_year"=>date_format(date_create($c["begin_time"]), 'M, Y'),
155
            ];
156
            $c["length"]=$this->calcLength($c["begin_time"], $c["end_time"]);
157
        }
158
        return [
159
            'contents' => $contest_list,
160
            'paginator' => $paginator
161
        ];
162
    }
163
164
    public function featured()
165
    {
166
        $featured=DB::table($this->tableName)->where([
167
            "public"=>1,
168
            "audit_status"=>1,
169
            "featured"=>1
170
        ])->orderBy('begin_time', 'desc')->first();
171
172
        if (!empty($featured)) {
173
            $featured["rule_parsed"]=$this->rule[$featured["rule"]];
174
            $featured["date_parsed"]=[
175
                "date"=>date_format(date_create($featured["begin_time"]), 'j'),
176
                "month_year"=>date_format(date_create($featured["begin_time"]), 'M, Y'),
177
            ];
178
            $featured["length"]=$this->calcLength($featured["begin_time"], $featured["end_time"]);
179
            return $featured;
180
        } else {
181
            return null;
182
        }
183
    }
184
185
    public function remainingTime($cid)
186
    {
187
        $end_time=DB::table($this->tableName)->where([
188
            "cid"=>$cid
189
        ])->select("end_time")->first()["end_time"];
190
        $end_time=strtotime($end_time);
191
        $cur_time=time();
192
        return $end_time-$cur_time;
193
    }
194
195
    public function intToChr($index, $start=65)
196
    {
197
        $str='';
198
        if (floor($index / 26)>0) {
199
            $str.=$this->intToChr(floor($index / 26)-1);
200
        }
201
        return $str.chr($index % 26+$start);
202
    }
203
204
    public function contestProblems($cid, $uid)
205
    {
206
        $submissionModel=new SubmissionModel();
207
208
        $contest_rule=$this->contestRule($cid);
209
210
        $problemSet=DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
211
            "cid"=>$cid
212
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
213
214
        $frozen_time=DB::table("contest")->where(["cid"=>$cid])->select(DB::raw("UNIX_TIMESTAMP(end_time)-froze_length as frozen_time"))->first()["frozen_time"];
215
        $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...
216
217
        foreach ($problemSet as &$p) {
218
            if ($contest_rule==1) {
219
                $prob_stat=DB::table("submission")->select(
220
                    DB::raw("count(sid) as submission_count"),
221
                    DB::raw("sum(verdict='accepted') as passed_count"),
222
                    DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
223
                )->where([
224
                    "pid"=>$p["pid"],
225
                    "cid"=>$cid
226
                ])->where("submission_date", "<", $frozen_time)->first();
227
228
                if ($prob_stat["submission_count"]==0) {
229
                    $p["submission_count"]=0;
230
                    $p["passed_count"]=0;
231
                    $p["ac_rate"]=0;
232
                } else {
233
                    $p["submission_count"]=$prob_stat["submission_count"];
234
                    $p["passed_count"]=$prob_stat["passed_count"];
235
                    $p["ac_rate"]=round($prob_stat["ac_rate"], 2);
236
                }
237
            } else {
238
                $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $uid);
239
                $p["points"]=$prob_stat["points"];
240
                $p["score"]=empty($prob_stat["score_parsed"]) ? 0 : $prob_stat["score_parsed"];
241
            }
242
            $prob_status=$submissionModel->getProblemStatus($p["pid"], $uid, $cid);
243
            if (empty($prob_status)) {
244
                $p["prob_status"]=[
245
                    "icon"=>"checkbox-blank-circle-outline",
246
                    "color"=>"wemd-grey-text"
247
                ];
248
            } else {
249
                $p["prob_status"]=[
250
                    "icon"=>$prob_status["verdict"]=="Accepted" ? "checkbox-blank-circle" : "cisco-webex",
251
                    "color"=>$prob_status["color"]
252
                ];
253
            }
254
        }
255
256
        return $problemSet;
257
    }
258
259
    public function getPid($cid, $ncode)
260
    {
261
        return DB::table("contest_problem")->where([
262
            "cid"=>$cid,
263
            "ncode"=>$ncode
264
        ])->select("contest_problem.pid")->first()["pid"];
265
    }
266
267
    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

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