Test Setup Failed
Push — master ( eb21ec...2ac834 )
by John
04:36
created

ContestModel::getCustomInfo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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

229
    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...
230
    {
231
        return DB::table("problem")->where([
232
            "cid"=>$cid
233
        ])->select("contest_problem.pid")->first()["pcode"];
234
    }
235
236
    public function getCustomInfo($cid)
237
    {
238
        $basic_info = DB::table($this->tableName)->where([
239
            "cid"=>$cid
240
        ])->select("verified", "gid")->first();
241
        return $basic_info["verified"] ? DB::table("group")->where([
242
            "gid"=>$basic_info["gid"]
243
        ])->select("custom_icon", "custom_title", "gcode")->first() : null;
244
    }
245
246
247
    public function formatTime($seconds)
248
    {
249
        if ($seconds >3600) {
250
            $hours =intval($seconds/3600);
251
            $minutes = $seconds % 3600;
252
            $time = $hours.":".gmstrftime('%M:%S', $minutes);
253
        } else {
254
            $time = gmstrftime('%H:%M:%S', $seconds);
255
        }
256
        return $time;
257
    }
258
259
    public function contestProblemInfoOI($cid, $pid, $uid)
260
    {
261
        $ret=[
262
            "color"=>"",
263
            "score"=>null,
264
            "score_parsed"=>"",
265
            "points"=>DB::table("contest_problem")->where([
266
                "pid"=>$pid,
267
                "cid"=>$cid
268
            ])->first()["points"]
269
        ];
270
271
        $frozen_time = strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
272
273
        $highest_record = DB::table("submission")->where([
274
            "cid"=>$cid,
275
            "pid"=>$pid,
276
            "uid"=>$uid
277
        ])->where("submission_date", "<", $frozen_time)->orderBy('score', 'desc')->first();
278
279
        if (!empty($highest_record)) {
280
            $ret["score"]=$highest_record["score"];
281
282
            $tot_score=DB::table("problem")->where([
283
                "pid"=>$pid
284
            ])->first()["tot_score"];
285
286
            $ret["color"]=($ret["score"]==$tot_score)?"wemd-teal-text":"wemd-green-text";
287
            $ret["score_parsed"]=$ret["score"]/$tot_score*($ret["points"]);
288
        }
289
        return $ret;
290
    }
291
292
    public function contestProblemInfoACM($cid, $pid, $uid)
293
    {
294
        $ret=[
295
            "color"=>"",
296
            "solved"=>0,
297
            "solved_time"=>"",
298
            "solved_time_parsed"=>"",
299
            "wrong_doings"=>0,
300
            "color"=>"",
301
        ];
302
303
        $frozen_time = strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
304
305
        $ac_record = DB::table("submission")->where([
306
            "cid"=>$cid,
307
            "pid"=>$pid,
308
            "uid"=>$uid,
309
            "verdict"=>"Accepted"
310
        ])->where("submission_date", "<", $frozen_time)->orderBy('submission_date', 'asc')->first();
311
312
        if (!empty($ac_record)) {
313
            $ret["solved"]=1;
314
315
            $ret["solved_time"]=$ac_record["submission_date"] - strtotime(DB::table($this->tableName)->where([
316
                "cid"=>$cid
317
            ])->first()["begin_time"]);
318
319
            $ret["solved_time_parsed"]=$this->formatTime($ret["solved_time"]);
320
321
            $ret["wrong_doings"] = DB::table("submission")->where([
322
                "cid"=>$cid,
323
                "pid"=>$pid,
324
                "uid"=>$uid
325
            ])->whereIn('verdict', [
326
                'Runtime Error',
327
                'Wrong Answer',
328
                'Time Limit Exceed',
329
                'Real Time Limit Exceed',
330
                'Memory Limit Exceed',
331
                'Presentation Error',
332
                'Output Limit Exceeded'
333
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
334
335
            $others_first = DB::table("submission")->where([
336
                "cid"=>$cid,
337
                "pid"=>$pid,
338
                "verdict"=>"Accepted"
339
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
340
341
            $ret["color"]=$others_first?"wemd-green-text":"wemd-teal-text";
342
        } else {
343
            $ret["wrong_doings"] = DB::table("submission")->where([
344
                "cid"=>$cid,
345
                "pid"=>$pid,
346
                "uid"=>$uid
347
            ])->whereIn('verdict', [
348
                'Runtime Error',
349
                'Wrong Answer',
350
                'Time Limit Exceed',
351
                'Real Time Limit Exceed',
352
                'Memory Limit Exceed',
353
                'Presentation Error',
354
                'Output Limit Exceeded'
355
            ])->where("submission_date", "<", $frozen_time)->count();
356
        }
357
358
        return $ret;
359
    }
360
361
    public function contestRank($cid, $uid)
362
    {
363
        // [ToDo] If the current user's in the organizer group show nick name
364
        // [ToDo] The participants determination
365
        // [ToDo] Frozen Time
366
        // [ToDo] Performance Opt
367
        // [Todo] Ajaxization - Should have done in controller
368
        // [Todo] Authorization ( Public / Private ) - Should have done in controller
369
370
        $ret=[];
371
372
        $contest_info = DB::table("contest")->where("cid", $cid)->first();
373
374
        $user_in_group = !empty(DB::table("group_member")->where([
375
            "uid" => $uid,
376
            "gid" => $contest_info["gid"]
377
        ])->where("role",">",0)->first());
378
379
        if ($contest_info["registration"]) {
380
            $submissionUsers = DB::table("contest_participant")->where([
381
                "cid"=>$cid,
382
                "audit"=>1
383
            ])->select('uid')->get()->all();
384
        } else {
385
            // Those who submitted are participants
386
            $submissionUsers = DB::table("submission")->where([
387
                "cid"=>$cid
388
            ])->select('uid')->groupBy('uid')->get()->all();
389
        }
390
391
        $problemSet = DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
392
            "cid"=>$cid
393
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
394
395
        if ($contest_info["rule"]==1) {
396
            // ACM/ICPC Mode
397
            foreach ($submissionUsers as $s) {
398
                $prob_detail=[];
399
                $totPen=0;
400
                $totScore=0;
401
                foreach ($problemSet as $p) {
402
                    $prob_stat=$this->contestProblemInfoACM($cid, $p["pid"], $s["uid"]);
403
                    $prob_detail[]=[
404
                        "ncode"=>$p["ncode"],
405
                        "pid"=>$p["pid"],
406
                        "color"=>$prob_stat["color"],
407
                        "wrong_doings"=>$prob_stat["wrong_doings"],
408
                        "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
409
                    ];
410
                    if ($prob_stat["solved"]) {
411
                        $totPen+=$prob_stat["wrong_doings"]*20;
412
                        $totPen+=$prob_stat["solved_time"]/60;
413
                        $totScore+=$prob_stat["solved"];
414
                    }
415
                }
416
                $ret[]=[
417
                    "uid" => $s["uid"],
418
                    "name" => DB::table("users")->where([
419
                        "id"=>$s["uid"]
420
                    ])->first()["name"],
421
                    "nick_name" => $user_in_group ? DB::table("group_member")->where([
422
                        "uid" => $s["uid"],
423
                        "gid" => $contest_info["gid"]
424
                    ])->where("role", ">", 0)->first()["nick_name"] : "",
425
                    "score" => $totScore,
426
                    "penalty" => $totPen,
427
                    "problem_detail" => $prob_detail
428
                ];
429
            }
430
        } else if ($contest_info["rule"]==2) {
431
            // OI Mode
432
            foreach ($submissionUsers as $s) {
433
                $prob_detail=[];
434
                $totScore=0;
435
                foreach ($problemSet as $p) {
436
                    $prob_stat=$this->contestProblemInfoOI($cid, $p["pid"], $s["uid"]);
437
                    $prob_detail[]=[
438
                        "ncode"=>$p["ncode"],
439
                        "pid"=>$p["pid"],
440
                        "color"=>$prob_stat["color"],
441
                        "score"=>$prob_stat["score"],
442
                        "score_parsed"=>$prob_stat["score_parsed"]
443
                    ];
444
                    $totScore+=intval($prob_stat["score_parsed"]);
445
                }
446
                $ret[]=[
447
                    "uid" => $s["uid"],
448
                    "name" => DB::table("users")->where([
449
                        "id"=>$s["uid"]
450
                    ])->first()["name"],
451
                    "nick_name" => $user_in_group ? DB::table("group_member")->where([
452
                        "uid" => $s["uid"],
453
                        "gid" => $contest_info["gid"]
454
                    ])->where("role", ">", 0)->first()["nick_name"] : "",
455
                    "score" => $totScore,
456
                    "penalty" => 0,
457
                    "problem_detail" => $prob_detail
458
                ];
459
            }
460
        }
461
462
        usort($ret, function ($a, $b) {
463
            if ($a["score"]==$b["score"]) {
464
                if ($a["penalty"]==$b["penalty"]) {
465
                    return 0;
466
                } elseif (($a["penalty"]>$b["penalty"])) {
467
                    return 1;
468
                } else {
469
                    return -1;
470
                }
471
            } elseif ($a["score"]>$b["score"]) {
472
                return -1;
473
            } else {
474
                return 1;
475
            }
476
        });
477
478
        return $ret;
479
    }
480
481
    public function getClarificationList($cid)
482
    {
483
        return DB::table("contest_clarification")->where([
484
            "cid"=>$cid,
485
            "public"=>1
486
        ])->orderBy('create_time', 'desc')->get()->all();
487
    }
488
489
    public function getClarificationDetail($ccid)
490
    {
491
        return DB::table("contest_clarification")->where([
492
            "ccid"=>$ccid,
493
            "public"=>1
494
        ])->first();
495
    }
496
497
    public function isContestEnded($cid)
498
    {
499
        return DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
500
    }
501
502
    public function judgeClearance($cid, $uid = 0)
503
    {
504
        if ($uid==0) {
505
            return 0;
506
        }
507
        $contest_started = DB::table("contest")->where("cid", $cid)->where("begin_time", "<", date("Y-m-d H:i:s"))->count();
508
        $contest_ended = DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
0 ignored issues
show
Unused Code introduced by
The assignment to $contest_ended is dead and can be removed.
Loading history...
509
        if ($contest_started) {
510
            // judge if qualified
511
            // return 1 if view access, can only view
512
            // return 2 if participant access, can submit code
513
            // return 3 if admin access, can create announcements
514
            $contest_info = DB::table("contest")->where("cid", $cid)->first();
515
            if ($contest_info["registration"]) {
516
                // check if uid in registration, temp return 3
517
                return 2;
518
            } else {
519
                if ($contest_info["public"]) {
520
                    return 2;
521
                } else {
522
                    return DB::table("group_member")->where([
523
                        "gid"=> $contest_info["gid"],
524
                        "uid"=> $uid
525
                    ])->where("role", ">", 0)->count() ? 2 : 0;
526
                }
527
            }
528
        } else {
529
            // not started or do not exist
530
            return 0;
531
        }
532
    }
533
534
    public function judgeOutsideClearance($cid, $uid = 0)
535
    {
536
        $contest_info = DB::table("contest")->where("cid", $cid)->first();
537
        if (empty($contest_info)) {
538
            return 0;
539
        }
540
        if ($contest_info["public"]) {
541
            return 1;
542
        } else {
543
            if ($uid==0) {
544
                return 0;
545
            }
546
            return DB::table("group_member")->where([
547
                "gid"=> $contest_info["gid"],
548
                "uid"=> $uid
549
            ])->where("role", ">", 0)->count() ? 1 : 0;
550
        }
551
    }
552
553
    public function contestName($cid)
554
    {
555
        return DB::table("contest")->where("cid", $cid)->select("name")->first()["name"];
556
    }
557
558
    public function contestRule($cid)
559
    {
560
        return DB::table("contest")->where("cid", $cid)->select("rule")->first()["rule"];
561
    }
562
563
    public function arrangeContest($gid, $config, $problems)
564
    {
565
        DB::transaction(function () use ($gid, $config, $problems) {
566
            $cid = DB::table($this->tableName)->insertGetId([
567
                "gid"=>$gid,
568
                "name"=>$config["name"],
569
                "verified"=>0,                          //todo
570
                "rated"=>0,
571
                "anticheated"=>0,
572
                "featured"=>0,
573
                "description"=>$config["description"],
574
                "rule"=>1,                              //todo
575
                "begin_time"=>$config["begin_time"],
576
                "end_time"=>$config["end_time"],
577
                "public"=>0,                            //todo
578
                "registration"=>0,                      //todo
579
                "registration_due"=>null,               //todo
580
                "registant_type"=>0,                    //todo
581
                "froze_length"=>0,                      //todo
582
                "status_visibility"=>3,                 //todo
583
                "create_time"=>date("Y-m-d H:i:s"),
584
                "audit_status"=>1                       //todo
585
            ]);
586
587
            foreach ($problems as $p) {
588
                $pid=DB::table("problem")->where(["pcode"=>$p["pcode"]])->select("pid")->first()["pid"];
589
                DB::table("contest_problem")->insert([
590
                    "cid"=>$cid,
591
                    "number"=>$p["number"],
592
                    "ncode"=>$this->intToChr($p["number"]-1),
593
                    "pid"=>$pid,
594
                    "alias"=>"",
595
                    "points"=>0
596
                ]);
597
            }
598
        }, 5);
599
    }
600
}
601