Test Setup Failed
Push — master ( 066fb0...ef01f5 )
by John
05:19
created

ContestModel::intToChr()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 7
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
        $problemSet = DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
172
            "cid"=>$cid
173
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
174
175
        foreach ($problemSet as &$p) {
176
            $frozen_time = strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
177
            $prob_stat = DB::table("submission")->select(
178
                DB::raw("count(sid) as submission_count"),
179
                DB::raw("sum(verdict='accepted') as passed_count"),
180
                DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
181
            )->where([
182
                "pid"=>$p["pid"],
183
                "cid"=>$cid
184
            ])->where("submission_date", "<", $frozen_time)->first();
185
186
            if ($prob_stat["submission_count"]==0) {
187
                $p["submission_count"]=0;
188
                $p["passed_count"]=0;
189
                $p["ac_rate"]=0;
190
            } else {
191
                $p["submission_count"]=$prob_stat["submission_count"];
192
                $p["passed_count"]=$prob_stat["passed_count"];
193
                $p["ac_rate"]=round($prob_stat["ac_rate"], 2);
194
            }
195
            $prob_status=$submissionModel->getProblemStatus($p["pid"], $uid, $cid);
196
            if (empty($prob_status)) {
197
                $p["prob_status"]=[
198
                    "icon"=>"checkbox-blank-circle-outline",
199
                    "color"=>"wemd-grey-text"
200
                ];
201
            } else {
202
                $p["prob_status"]=[
203
                    "icon"=>$prob_status["verdict"]=="Accepted" ? "checkbox-blank-circle" : "cisco-webex",
204
                    "color"=>$prob_status["color"]
205
                ];
206
            }
207
        }
208
209
        return $problemSet;
210
    }
211
212
    public function getPid($cid, $ncode)
213
    {
214
        return DB::table("contest_problem")->where([
215
            "cid"=>$cid,
216
            "ncode"=>$ncode
217
        ])->select("contest_problem.pid")->first()["pid"];
218
    }
219
220
    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

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