Test Setup Failed
Push — master ( a5fc5d...50cd41 )
by John
04:33
created

ContestModel::detail()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 28
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 23
nc 2
nop 2
dl 0
loc 28
rs 9.552
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 contestProblemInfo($cid, $pid, $uid)
251
    {
252
        $ret=[
253
            "color"=>"",
254
            "solved"=>0,
255
            "solved_time"=>"",
256
            "solved_time_parsed"=>"",
257
            "wrong_doings"=>0,
258
            "color"=>"",
259
        ];
260
261
        $frozen_time = strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
262
263
        $ac_record = DB::table("submission")->where([
264
            "cid"=>$cid,
265
            "pid"=>$pid,
266
            "uid"=>$uid,
267
            "verdict"=>"Accepted"
268
        ])->where("submission_date", "<", $frozen_time)->orderBy('submission_date', 'asc')->first();
269
270
        if (!empty($ac_record)) {
271
            $ret["solved"]=1;
272
273
            $ret["solved_time"]=$ac_record["submission_date"] - strtotime(DB::table($this->tableName)->where([
274
                "cid"=>$cid
275
            ])->first()["begin_time"]);
276
277
            $ret["solved_time_parsed"]=$this->formatTime($ret["solved_time"]);
278
279
            $ret["wrong_doings"] = DB::table("submission")->where([
280
                "cid"=>$cid,
281
                "pid"=>$pid,
282
                "uid"=>$uid
283
            ])->whereIn('verdict', [
284
                'Runtime Error',
285
                'Wrong Answer',
286
                'Time Limit Exceed',
287
                'Real Time Limit Exceed',
288
                'Memory Limit Exceed',
289
                'Presentation Error',
290
                'Output Limit Exceeded'
291
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
292
293
            $others_first = DB::table("submission")->where([
294
                "cid"=>$cid,
295
                "pid"=>$pid,
296
                "verdict"=>"Accepted"
297
            ])->where("submission_date", "<", $ac_record["submission_date"])->count();
298
299
            $ret["color"]=$others_first?"wemd-green-text":"wemd-teal-text";
300
        } else {
301
            $ret["wrong_doings"] = DB::table("submission")->where([
302
                "cid"=>$cid,
303
                "pid"=>$pid,
304
                "uid"=>$uid
305
            ])->whereIn('verdict', [
306
                'Runtime Error',
307
                'Wrong Answer',
308
                'Time Limit Exceed',
309
                'Real Time Limit Exceed',
310
                'Memory Limit Exceed',
311
                'Presentation Error',
312
                'Output Limit Exceeded'
313
            ])->where("submission_date", "<", $frozen_time)->count();
314
        }
315
316
        return $ret;
317
    }
318
319
    public function contestRank($cid, $uid)
320
    {
321
        // [ToDo] If the current user's in the organizer group show nick name
322
        // [ToDo] The participants determination
323
        // [ToDo] Frozen Time
324
        // [ToDo] Performance Opt
325
        // [Todo] Ajaxization - Should have done in controller
326
        // [Todo] Authorization ( Public / Private ) - Should have done in controller
327
328
        $ret=[];
329
330
        $contest_info = DB::table("contest")->where("cid", $cid)->first();
331
        $user_in_group = !empty(DB::table("group_member")->where([
332
            "uid" => $uid,
333
            "gid" => $contest_info["gid"]
334
        ])->where("role",">",0)->first());
335
336
        $submissionUsers = DB::table("submission")->where([
337
            "cid"=>$cid
338
        ])->select('uid')->groupBy('uid')->get()->all();
339
340
        $problemSet = DB::table("contest_problem")->join("problem", "contest_problem.pid", "=", "problem.pid")->where([
341
            "cid"=>$cid
342
        ])->orderBy('ncode', 'asc')->select("ncode", "alias", "contest_problem.pid as pid", "title")->get()->all();
343
344
        foreach ($submissionUsers as $s) {
345
            $prob_detail=[];
346
            $totPen=0;
347
            $totScore=0;
348
            foreach ($problemSet as $p) {
349
                $prob_stat=$this->contestProblemInfo($cid, $p["pid"], $s["uid"]);
350
                $prob_detail[]=[
351
                    "ncode"=>$p["ncode"],
352
                    "pid"=>$p["pid"],
353
                    "color"=>$prob_stat["color"],
354
                    "wrong_doings"=>$prob_stat["wrong_doings"],
355
                    "solved_time_parsed"=>$prob_stat["solved_time_parsed"]
356
                ];
357
                if ($prob_stat["solved"]) {
358
                    $totPen+=$prob_stat["wrong_doings"]*20;
359
                    $totPen+=$prob_stat["solved_time"]/60;
360
                    $totScore+=$prob_stat["solved"];
361
                }
362
            }
363
            $ret[]=[
364
                "uid" => $s["uid"],
365
                "name" => DB::table("users")->where([
366
                    "id"=>$s["uid"]
367
                ])->first()["name"],
368
                "nick_name" => $user_in_group ? DB::table("group_member")->where([
369
                    "uid" => $s["uid"],
370
                    "gid" => $contest_info["gid"]
371
                ])->where("role",">",0)->first()["nick_name"] : "",
372
                "score" => $totScore,
373
                "penalty" => $totPen,
374
                "problem_detail" => $prob_detail
375
            ];
376
        }
377
378
        usort($ret, function ($a, $b) {
379
            if ($a["score"]==$b["score"]) {
380
                if ($a["penalty"]==$b["penalty"]) {
381
                    return 0;
382
                } elseif (($a["penalty"]>$b["penalty"])) {
383
                    return 1;
384
                } else {
385
                    return -1;
386
                }
387
            } elseif ($a["score"]>$b["score"]) {
388
                return -1;
389
            } else {
390
                return 1;
391
            }
392
        });
393
394
        return $ret;
395
    }
396
397
    public function getClarificationList($cid)
398
    {
399
        return DB::table("contest_clarification")->where([
400
            "cid"=>$cid,
401
            "public"=>1
402
        ])->orderBy('create_time', 'desc')->get()->all();
403
    }
404
405
    public function getClarificationDetail($ccid)
406
    {
407
        return DB::table("contest_clarification")->where([
408
            "ccid"=>$ccid,
409
            "public"=>1
410
        ])->first();
411
    }
412
413
    public function isContestEnded($cid)
414
    {
415
        return DB::table("contest")->where("cid", $cid)->where("end_time", "<", date("Y-m-d H:i:s"))->count();
416
    }
417
418
    public function judgeClearance($cid, $uid = 0)
419
    {
420
        if ($uid==0) {
421
            return 0;
422
        }
423
        $contest_started = DB::table("contest")->where("cid", $cid)->where("begin_time", "<", date("Y-m-d H:i:s"))->count();
424
        $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...
425
        if ($contest_started) {
426
            // judge if qualified
427
            // return 1 if view access, can only view
428
            // return 2 if participant access, can submit code
429
            // return 3 if admin access, can create announcements
430
            $contest_info = DB::table("contest")->where("cid", $cid)->first();
431
            if ($contest_info["registration"]) {
432
                // check if uid in registration, temp return 3
433
                return 2;
434
            } else {
435
                if ($contest_info["public"]) {
436
                    return 2;
437
                } else {
438
                    return DB::table("group_member")->where([
439
                        "gid"=> $contest_info["gid"],
440
                        "uid"=> $uid
441
                    ])->where("role", ">", 0)->count() ? 2 : 0;
442
                }
443
            }
444
        } else {
445
            // not started or do not exist
446
            return 0;
447
        }
448
    }
449
450
    public function judgeOutsideClearance($cid, $uid = 0)
451
    {
452
        $contest_info = DB::table("contest")->where("cid", $cid)->first();
453
        if (empty($contest_info)) {
454
            return 0;
455
        }
456
        if ($contest_info["public"]) {
457
            return 1;
458
        } else {
459
            if ($uid==0) {
460
                return 0;
461
            }
462
            return DB::table("group_member")->where([
463
                "gid"=> $contest_info["gid"],
464
                "uid"=> $uid
465
            ])->where("role", ">", 0)->count() ? 1 : 0;
466
        }
467
    }
468
469
    public function contestName($cid)
470
    {
471
        return DB::table("contest")->where("cid", $cid)->select("name")->first()["name"];
472
    }
473
474
    public function arrangeContest($gid, $config, $problems)
475
    {
476
        DB::transaction(function () use ($gid, $config, $problems) {
477
            $cid = DB::table($this->tableName)->insertGetId([
478
                "gid"=>$gid,
479
                "name"=>$config["name"],
480
                "verified"=>0,                          //todo
481
                "rated"=>0,
482
                "anticheated"=>0,
483
                "featured"=>0,
484
                "description"=>$config["description"],
485
                "rule"=>1,                              //todo
486
                "begin_time"=>$config["begin_time"],
487
                "end_time"=>$config["end_time"],
488
                "public"=>0,                            //todo
489
                "registration"=>0,                      //todo
490
                "registration_due"=>null,               //todo
491
                "registant_type"=>0,                    //todo
492
                "froze_length"=>0,                     //todo
493
                "status_visibility"=>3,                 //todo
494
                "create_time"=>date("Y-m-d H:i:s"),
495
                "audit_status"=>1                       //todo
496
            ]);
497
498
            foreach ($problems as $p) {
499
                $pid=DB::table("problem")->where(["pcode"=>$p["pcode"]])->select("pid")->first()["pid"];
500
                DB::table("contest_problem")->insert([
501
                    "cid"=>$cid,
502
                    "number"=>$p["number"],
503
                    "ncode"=>$this->intToChr($p["number"]-1),
504
                    "pid"=>$pid,
505
                    "alias"=>"",
506
                    "points"=>0
507
                ]);
508
            }
509
        }, 5);
510
    }
511
}
512