Passed
Push — master ( a37d29...809c90 )
by John
04:10
created

ProblemModel::solutionList()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 37
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 33
nc 4
nop 2
dl 0
loc 37
rs 9.392
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 ProblemModel extends Model
10
{
11
    protected $table='problem';
12
    protected $primaryKey = 'pid';
13
    const UPDATED_AT = "update_date";
14
15
    public function detail($pcode, $cid=null)
16
    {
17
        $prob_detail=DB::table($this->table)->where("pcode", $pcode)->first();
18
        // [Depreciated] Joint Query was depreciated here for code maintenance reasons
19
        if (!is_null($prob_detail)) {
20
            if($prob_detail["force_raw"]) {
21
                $prob_detail["parsed"]=[
22
                    "description"=>$prob_detail["description"],
23
                    "input"=>$prob_detail["input"],
24
                    "output"=>$prob_detail["output"],
25
                    "note"=>$prob_detail["note"]
26
                ];
27
            } elseif ($prob_detail["markdown"]) {
28
                $prob_detail["parsed"]=[
29
                    "description"=>clean(Markdown::convertToHtml($prob_detail["description"])),
30
                    "input"=>clean(Markdown::convertToHtml($prob_detail["input"])),
31
                    "output"=>clean(Markdown::convertToHtml($prob_detail["output"])),
32
                    "note"=>clean(Markdown::convertToHtml($prob_detail["note"]))
33
                ];
34
            } else {
35
                $prob_detail["parsed"]=[
36
                    "description"=>$prob_detail["description"],
37
                    "input"=>$prob_detail["input"],
38
                    "output"=>$prob_detail["output"],
39
                    "note"=>$prob_detail["note"]
40
                ];
41
            }
42
            $prob_detail["update_date"]=date_format(date_create($prob_detail["update_date"]), 'm/d/Y H:i:s');
43
            $prob_detail["oj_detail"]=DB::table("oj")->where("oid", $prob_detail["OJ"])->first();
44
            $prob_detail["samples"]=DB::table("problem_sample")->where("pid", $prob_detail["pid"])->get()->all();
45
            $prob_detail["tags"]=DB::table("problem_tag")->where("pid", $prob_detail["pid"])->get()->all();
46
            if ($cid) {
47
                $frozen_time=strtotime(DB::table("contest")->where(["cid"=>$cid])->select("end_time")->first()["end_time"]);
48
                $prob_stat=DB::table("submission")->select(
49
                    DB::raw("count(sid) as submission_count"),
50
                    DB::raw("sum(verdict='accepted') as passed_count"),
51
                    DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
52
                )->where([
53
                    "pid"=>$prob_detail["pid"],
54
                    "cid"=>$cid,
55
                ])->where("submission_date", "<", $frozen_time)->first();
56
                $prob_detail["points"]=DB::table("contest_problem")->where(["cid"=>$cid, "pid"=>$prob_detail["pid"]])->select("points")->first()["points"];
57
            } else {
58
                $prob_stat=DB::table("submission")->select(
59
                    DB::raw("count(sid) as submission_count"),
60
                    DB::raw("sum(verdict='accepted') as passed_count"),
61
                    DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
62
                )->where(["pid"=>$prob_detail["pid"]])->first();
63
                $prob_detail["points"]=0;
64
            }
65
            if ($prob_stat["submission_count"]==0) {
66
                $prob_detail["submission_count"]=0;
67
                $prob_detail["passed_count"]=0;
68
                $prob_detail["ac_rate"]=0;
69
            } else {
70
                $prob_detail["submission_count"]=$prob_stat["submission_count"];
71
                $prob_detail["passed_count"]=$prob_stat["passed_count"];
72
                $prob_detail["ac_rate"]=round($prob_stat["ac_rate"], 2);
73
            }
74
        }
75
        return $prob_detail;
76
    }
77
78
    public function basic($pid)
79
    {
80
        return DB::table($this->table)->where("pid", $pid)->first();
81
    }
82
83
    public function tags()
84
    {
85
        return DB::table("problem_tag")->groupBy('tag')->select("tag", DB::raw('count(*) as tag_count'))->orderBy('tag_count', 'desc')->limit(12)->get()->all();
86
    }
87
88
    public function ojs()
89
    {
90
        return DB::table("oj")->orderBy('oid', 'asc')->limit(12)->get()->all();
91
    }
92
93
    public function ojdetail($oid)
94
    {
95
        return DB::table("oj")->where('oid', $oid)->first();
96
    }
97
98
    public function solutionList($pid,$uid=null)
99
    {
100
        if(is_null($uid)) {
101
            $details=DB::table("problem_solution")->join("users","id","=","problem_solution.uid")->where(['problem_solution.pid'=>$pid,'problem_solution.audit'=>1])->first();
102
        } else {
103
            $details=DB::table("problem_solution")->join(
104
                "users",
105
                "id",
106
                "=",
107
                "problem_solution.uid"
108
            )->leftjoin(
109
                "problem_solution_vote",
110
                "problem_solution.psoid",
111
                "=",
112
                "problem_solution_vote.psoid"
113
            )->where([
114
                'problem_solution.pid'=>$pid,
115
                'problem_solution.audit'=>1,
116
                'problem_solution.uid'=>$uid
117
            ])->select([
118
                "problem_solution.psoid as psoid",
119
                "problem_solution.uid as uid",
120
                "problem_solution.pid as pid",
121
                "problem_solution.content as content",
122
                "problem_solution.audit as audit",
123
                "problem_solution.votes as votes",
124
                "problem_solution.created_at as created_at",
125
                "problem_solution.updated_at as updated_at",
126
                "avatar",
127
                "name",
128
                "type"
129
            ])->get()->all();
130
        }
131
        foreach($details as &$d){
132
            $d["content_parsed"]=clean(Markdown::convertToHtml($d["content"]));
133
        }
134
        return $details;
135
    }
136
137
    public function solution($pid,$uid)
138
    {
139
        $details=DB::table("problem_solution")->join("users","id","=","uid")->where(['pid'=>$pid,'uid'=>$uid])->first();
140
        return $details;
141
    }
142
143
    public function addSolution($pid,$uid,$content)
144
    {
145
        $details=DB::table("problem_solution")->where(['pid'=>$pid,'uid'=>$uid])->first();
146
        if(empty($details)){
147
            DB::table("problem_solution")->insert([
148
                "uid"=>$uid,
149
                "pid"=>$pid,
150
                "content"=>$content,
151
                "votes"=>0,
152
                "created_at"=>date("Y-m-d H:i:s"),
153
                "updated_at"=>date("Y-m-d H:i:s"),
154
            ]);
155
            return true;
156
        }
157
        return false;
158
    }
159
160
    public function voteSolution($psoid,$uid,$type)
161
    {
162
        $val=$type?1:-1;
163
        $details=DB::table("problem_solution")->where(['psoid'=>$psoid])->first();
164
        if(empty($details)) return ["ret"=>false];
165
166
        $userVote=DB::table("problem_solution_vote")->where(['uid'=>$uid,"psoid"=>$psoid])->first();
167
168
        if(!empty($userVote)){
169
            DB::table("problem_solution_vote")->where(['uid'=>$uid,"psoid"=>$psoid])->delete();
170
            if($userVote["type"]==$type){
171
                DB::table("problem_solution")->where([
172
                    'psoid'=>$psoid
173
                ])->update([
174
                    "votes"=>$details["votes"]+($userVote["type"]==1?-1:1),
175
                ]);
176
                return ["ret"=>true,"votes"=>$details["votes"]+($userVote["type"]==1?-1:1),"select"=>-1]; //disvote
177
            }elseif($userVote["type"]==1){
178
                $val--;
179
            }else{
180
                $val++;
181
            }
182
        }
183
184
        DB::table("problem_solution")->where([
185
            'psoid'=>$psoid
186
        ])->update([
187
            "votes"=>$details["votes"]+$val,
188
        ]);
189
190
        DB::table("problem_solution_vote")->insert([
191
            "uid"=>$uid,
192
            "psoid"=>$psoid,
193
            "type"=>$type,
194
        ]);
195
196
        return ["ret"=>true,"votes"=>$details["votes"]+$val,"select"=>$type];
197
    }
198
199
    public function removeSolution($psoid,$uid)
200
    {
201
        if(empty(DB::table("problem_solution")->where(['psoid'=>$psoid,'uid'=>$uid])->first())) return false;
202
        DB::table("problem_solution")->where(['psoid'=>$psoid,'uid'=>$uid])->delete();
203
        return true;
204
    }
205
206
    public function updateSolution($psoid,$uid,$content)
207
    {
208
        if(empty(DB::table("problem_solution")->where(['psoid'=>$psoid,'uid'=>$uid])->first())) return false;
209
        DB::table("problem_solution")->where(['psoid'=>$psoid,'uid'=>$uid])->update([
210
            "content"=>$content,
211
            "audit"=>0,
212
            "updated_at"=>date("Y-m-d H:i:s"),
213
        ]);
214
        return true;
215
    }
216
217
    public function isBlocked($pid, $cid=null)
218
    {
219
        $conflictContests=DB::table("contest")
220
                            ->join("contest_problem", "contest.cid", "=", "contest_problem.cid")
221
                            ->where("end_time", ">", date("Y-m-d H:i:s"))
222
                            ->where(["verified"=>1, "pid"=>$pid])
223
                            ->select(["contest_problem.cid as cid"])
224
                            ->get()
225
                            ->all();
226
        if (empty($conflictContests)) {
227
            return false;
228
        }
229
        foreach ($conflictContests as $c) {
230
            if ($cid==$c["cid"]) {
231
                return false;
232
            }
233
        }
234
        // header("HTTP/1.1 403 Forbidden");
235
        // exit();
236
        return true;
237
    }
238
239
    public function list($filter)
240
    {
241
        // $prob_list = DB::table($this->table)->select("pid","pcode","title")->get()->all(); // return a array
242
        $preQuery=DB::table($this->table);
243
        if ($filter['oj']) {
244
            $preQuery=$preQuery->where(["OJ"=>$filter['oj']]);
245
        }
246
        if ($filter['tag']) {
247
            $preQuery=$preQuery->join("problem_tag", "problem.pid", "=", "problem_tag.pid")->where(["tag"=>$filter['tag']]);
248
        }
249
        $paginator=$preQuery->select("problem.pid as pid", "pcode", "title")->orderBy(
250
            "OJ",
251
            "ASC"
252
        )->orderBy(
253
            DB::raw("length(contest_id)"),
254
            "ASC"
255
        )->orderBy(
256
            "contest_id",
257
            "ASC"
258
        )->orderBy(
259
            DB::raw("length(index_id)"),
260
            "ASC"
261
        )->orderBy(
262
            "index_id",
263
            "ASC"
264
        )->orderBy(
265
            "pcode",
266
            "ASC"
267
        )->paginate(20);
268
        $prob_list=$paginator->all();
269
270
        if (empty($prob_list)) {
271
            return null;
272
        }
273
        foreach ($prob_list as &$p) {
274
            $prob_stat=DB::table("submission")->select(
275
                DB::raw("count(sid) as submission_count"),
276
                DB::raw("sum(verdict='accepted') as passed_count"),
277
                DB::raw("sum(verdict='accepted')/count(sid)*100 as ac_rate")
278
            )->where(["pid"=>$p["pid"]])->first();
279
            if ($prob_stat["submission_count"]==0) {
280
                $p["submission_count"]=0;
281
                $p["passed_count"]=0;
282
                $p["ac_rate"]=0;
283
            } else {
284
                $p["submission_count"]=$prob_stat["submission_count"];
285
                $p["passed_count"]=$prob_stat["passed_count"];
286
                $p["ac_rate"]=round($prob_stat["ac_rate"], 2);
287
            }
288
        }
289
        return [
290
            'paginator' => $paginator,
291
            'problems' => $prob_list,
292
        ];
293
    }
294
295
    public function existPCode($pcode)
296
    {
297
        $temp=DB::table($this->table)->where(["pcode"=>$pcode])->select("pcode")->first();
298
        return empty($temp) ? null : $temp["pcode"];
299
    }
300
301
    public function pid($pcode)
302
    {
303
        $temp=DB::table($this->table)->where(["pcode"=>$pcode])->select("pid")->first();
304
        return empty($temp) ? 0 : $temp["pid"];
305
    }
306
307
    public function pcode($pid)
308
    {
309
        $temp=DB::table($this->table)->where(["pid"=>$pid])->select("pcode")->first();
310
        return empty($temp) ? 0 : $temp["pcode"];
311
    }
312
313
    public function ocode($pid)
314
    {
315
        $temp=DB::table($this->table)->where(["pid"=>$pid])->select("OJ as oid")->first();
316
        return empty($temp) ? null : DB::table("oj")->where(["oid"=>$temp["oid"]])->select("ocode")->first()["ocode"];
317
    }
318
319
    public function oid($pid)
320
    {
321
        return DB::table($this->table)->where(["pid"=>$pid])->select("OJ as oid")->first()["oid"];
322
    }
323
324
    public function clearTags($pid)
325
    {
326
        DB::table("problem_tag")->where(["pid"=>$pid])->delete();
327
        return true;
328
    }
329
330
    public function addTags($pid, $tag)
331
    {
332
        DB::table("problem_tag")->insert(["pid"=>$pid, "tag"=>$tag]);
333
        return true;
334
    }
335
336
    public function getSolvedCount($oid)
337
    {
338
        return DB::table($this->table)->select("pid", "solved_count")->where(["OJ"=>$oid])->get()->all();
339
    }
340
341
    public function updateDifficulty($pid, $diff_level)
342
    {
343
        DB::table("problem_tag")->where(["pid"=>$pid])->update(["difficulty"=>$diff_level]);
344
        return true;
345
    }
346
347
    public function insertProblem($data)
348
    {
349
        $pid=DB::table($this->table)->insertGetId([
350
            'difficulty'=>-1,
351
            'file'=>$data['file'],
352
            'title'=>$data['title'],
353
            'time_limit'=>$data['time_limit'],
354
            'memory_limit'=>$data['memory_limit'],
355
            'OJ'=>$data['OJ'],
356
            'description'=>$data['description'],
357
            'input'=>$data['input'],
358
            'output'=>$data['output'],
359
            'note'=>$data['note'],
360
            'input_type'=>$data['input_type'],
361
            'output_type'=>$data['output_type'],
362
            'pcode'=>$data['pcode'],
363
            'contest_id'=>$data['contest_id'],
364
            'index_id'=>$data['index_id'],
365
            'origin'=>$data['origin'],
366
            'source'=>$data['source'],
367
            'solved_count'=>$data['solved_count'],
368
            'update_date'=>date("Y-m-d H:i:s"),
369
            'tot_score'=>$data['tot_score'],
370
            'partial'=>$data['partial'],
371
            'markdown'=>$data['markdown'],
372
            'special_compiler'=>$data['special_compiler'],
373
        ]);
374
375
        if (!empty($data["sample"])) {
376
            foreach ($data["sample"] as $d) {
377
                DB::table("problem_sample")->insert([
378
                    'pid'=>$pid,
379
                    'sample_input'=>$d['sample_input'],
380
                    'sample_output'=>$d['sample_output'],
381
                ]);
382
            }
383
        }
384
385
        return $pid;
386
    }
387
388
    public function updateProblem($data)
389
    {
390
        DB::table($this->table)->where(["pcode"=>$data['pcode']])->update([
391
            'difficulty'=>-1,
392
            'file'=>$data['file'],
393
            'title'=>$data['title'],
394
            'time_limit'=>$data['time_limit'],
395
            'memory_limit'=>$data['memory_limit'],
396
            'OJ'=>$data['OJ'],
397
            'description'=>$data['description'],
398
            'input'=>$data['input'],
399
            'output'=>$data['output'],
400
            'note'=>$data['note'],
401
            'input_type'=>$data['input_type'],
402
            'output_type'=>$data['output_type'],
403
            'contest_id'=>$data['contest_id'],
404
            'index_id'=>$data['index_id'],
405
            'origin'=>$data['origin'],
406
            'source'=>$data['source'],
407
            'solved_count'=>$data['solved_count'],
408
            'update_date'=>date("Y-m-d H:i:s"),
409
            'tot_score'=>$data['tot_score'],
410
            'partial'=>$data['partial'],
411
            'markdown'=>$data['markdown'],
412
            'special_compiler'=>$data['special_compiler'],
413
        ]);
414
415
        $pid=$this->pid($data['pcode']);
416
417
        DB::table("problem_sample")->where(["pid"=>$pid])->delete();
418
419
        if (!empty($data["sample"])) {
420
            foreach ($data["sample"] as $d) {
421
                DB::table("problem_sample")->insert([
422
                    'pid'=>$pid,
423
                    'sample_input'=>$d['sample_input'],
424
                    'sample_output'=>$d['sample_output'],
425
                ]);
426
            }
427
        }
428
429
        return $pid;
430
    }
431
}
432