Passed
Pull Request — master (#182)
by John
04:01
created

GroupModel::judgeClearance()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Models;
4
5
use App\Models\Rating\GroupRatingCalculator;
6
use GrahamCampbell\Markdown\Facades\Markdown;
7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Facades\DB;
9
use Cache;
10
11
class GroupModel extends Model
12
{
13
    protected $tableName='group';
14
    protected $table='group';
15
    protected $primaryKey='gid';
16
    const DELETED_AT=null;
17
    const UPDATED_AT=null;
18
    const CREATED_AT=null;
19
20
    /*
21
        join_policy:
22
            1:a user can join this group only by invitation
23
            2:a user can join this group only by application
24
            3:a user can join this group by both invitation and application
25
    */
26
    public $role=[
27
        "-3"=>"None",
28
        "-1"=>"Invited",
29
        "0"=>"Pending",
30
        "1"=>"Member",
31
        "2"=>"Manager",
32
        "3"=>"Leader"
33
    ];
34
    public $role_color=[
35
        "-3"=>"wemd-black",
36
        "-1"=>"wemd-deep-purple",
37
        "0"=>"wemd-red",
38
        "1"=>"wemd-grey",
39
        "2"=>"wemd-light-blue",
40
        "3"=>"wemd-amber"
41
    ];
42
43
    public function trendingGroups()
44
    {
45
        return Cache::tags(['group'])->get('trending');
46
    }
47
48
    public function gid($gcode)
49
    {
50
        return DB::table($this->tableName)->where(["gcode"=>$gcode])->first()["gid"];
51
    }
52
53
    public function cacheTrendingGroups()
54
    {
55
        $trending_groups=DB::table($this->tableName)->where(["public"=>1])->orderBy('create_time', 'desc')->select("gid", "gcode", "img", "name", "verified")->get()->all();
56
        foreach ($trending_groups as &$t) {
57
            $t["members"]=$this->countGroupMembers($t["gid"]);
58
        }
59
        usort($trending_groups, function ($a, $b) {
60
            return $b["members"]<=>$a["members"];
61
        });
62
        Cache::tags(['group'])->put('trending', array_slice($trending_groups,0,12), 3600*24);
63
    }
64
65
    public function userGroups($uid)
66
    {
67
        $user_groups=DB::table("group_member")->join("group", "group_member.gid", "=", "group.gid")->where(["uid"=>$uid])->select("group.gid as gid", "gcode", "img", "name", "verified")->limit(12)->get()->all();
68
        foreach ($user_groups as &$m) {
69
            $m["members"]=$this->countGroupMembers($m["gid"]);
70
        }
71
        return $user_groups;
72
    }
73
74
    public function countGroupMembers($gid)
75
    {
76
        return DB::table("group_member")->where(["gid"=>$gid])->count();
77
    }
78
79
    public function getGroupTags($gid)
80
    {
81
        return DB::table("group_tag")->where(["gid"=>$gid])->select("tag")->get()->all();
82
    }
83
84
    public function countGroupContest($gid)
85
    {
86
        return [
87
            "contest_ahead" => DB::table("contest")->where(["gid"=>$gid])->where("begin_time", ">", DB::raw("now()"))->count(),
88
            "contest_going" => DB::table("contest")->where(["gid"=>$gid])->where("begin_time", "<=", DB::raw("now()"))->where("end_time", ">=", DB::raw("now()"))->count(),
89
            "contest_end" => DB::table("contest")->where(["gid"=>$gid])->where("end_time", "<", DB::raw("now()"))->count()
90
        ];
91
    }
92
93
    public function changeNickName($gid, $uid, $nickName)
94
    {
95
        return DB::table("group_member")->where(["gid"=>$gid, "uid"=>$uid])->update([
96
            "nick_name"=>$nickName
97
        ]);
98
    }
99
100
    public function changeGroupName($gid, $GroupName)
101
    {
102
        return DB::table("group")->where('gid',$gid)->update([
103
            "name"=>$GroupName
104
        ]);
105
    }
106
107
    public function changeJoinPolicy($gid, $JoinPolicy){
108
        return DB::table("group")->where('gid',$gid)->update([
109
            "join_policy"=>$JoinPolicy
110
        ]);
111
    }
112
113
    public function details($gcode)
114
    {
115
        $basic_info=DB::table($this->tableName)->where(["gcode"=>$gcode])->first();
116
        if(empty($basic_info)) return [];
117
        $basic_info["members"]=$this->countGroupMembers($basic_info["gid"]);
118
        $basic_info["tags"]=$this->getGroupTags($basic_info["gid"]);
119
        $basic_info["create_time_foramt"]=date_format(date_create($basic_info["create_time"]), 'M jS, Y');
120
        $basic_info["contest_stat"]=$this->countGroupContest($basic_info["gid"]);
121
        return $basic_info;
122
    }
123
124
    public function joinPolicy($gid)
125
    {
126
        $ret=DB::table($this->tableName)->where(["gid"=>$gid])->first();
127
        return empty($ret) ? null : $ret["join_policy"];
128
    }
129
130
    public function userProfile($uid, $gid)
131
    {
132
        $info=DB::table("group_member")
133
        ->join('users','users.id','=','group_member.uid')
134
        ->where(["gid"=>$gid, "uid"=>$uid])
135
        ->where("role", ">", 0)
136
        ->select('avatar','describes','email','gid','uid','name','nick_name','professional_rate','role','sub_group')
137
        ->first();
138
        if (!empty($info)) {
139
            $info["role_parsed"]=$this->role[$info["role"]];
140
            $info["role_color"]=$this->role_color[$info["role"]];
141
        }
142
        return $info;
143
    }
144
145
    public function userList($gid)
146
    {
147
        $user_list=DB::table("group_member")->join(
148
            "users",
149
            "users.id",
150
            "=",
151
            "group_member.uid"
152
        )->where(["gid"=>$gid])->orderBy('role', 'desc')->select(
153
            "role",
154
            "uid",
155
            "name",
156
            "nick_name",
157
            "avatar",
158
            "sub_group",
159
            "ranking"
160
        )->get()->all();
161
        foreach ($user_list as &$u) {
162
            $u["role_parsed"]=$this->role[$u["role"]];
163
            $u["role_color"]=$this->role_color[$u["role"]];
164
            if(is_null($u["sub_group"])) $u["sub_group"]="None";
165
        }
166
        return $user_list;
167
    }
168
169
    public function groupNotice($gid)
170
    {
171
        $notice_item=DB::table("group_notice")->where(["gid"=>$gid])->first();
172
        if (empty($notice_item)) {
173
            return [];
174
        }
175
        $notice_author=DB::table("users")->where(["id"=>$notice_item["uid"]])->first();
176
        $notice_item["name"]=$notice_author["name"];
177
        $notice_item["avatar"]=$notice_author["avatar"];
178
        $notice_item["post_date_parsed"]=$this->formatPostTime($notice_item["post_date"]);
179
        $notice_item["content_parsed"]=clean(Markdown::convertToHtml($notice_item["content"]));
180
        return $notice_item;
181
    }
182
183
    public function judgeClearance($gid, $uid)
184
    {
185
        $ret=DB::table("group_member")->where(["gid"=>$gid, "uid"=>$uid])->first();
186
        return empty($ret) ? -3 : $ret["role"];
187
    }
188
189
    public function changeClearance($uid, $gid, $clearance)
190
    {
191
        return DB::table("group_member")->where([
192
            "uid"=>$uid,
193
            "gid"=>$gid
194
        ])->update([
195
            "role"=>$clearance
196
        ]);
197
    }
198
199
    public function removeClearance($uid, $gid)
200
    {
201
        return DB::table("group_member")->where([
202
            "uid"=>$uid,
203
            "gid"=>$gid
204
        ])->delete();
205
    }
206
207
    public function addClearance($uid, $gid, $clearance)
208
    {
209
        return DB::table("group_member")->insert([
210
            "uid"=>$uid,
211
            "gid"=>$gid,
212
            "role"=>$clearance,
213
            "join_time"=>date("Y-m-d H:i:s")
214
        ]);
215
    }
216
217
    public function isMember($gid, $uid)
218
    {
219
        return DB::table("group_member")->where([
220
            "gid"=> $gid,
221
            "uid"=> $uid
222
        ])->where("role", ">", 0)->count();
223
    }
224
225
    public function problemTags($gid,$pid = -1)
226
    {
227
        if($pid == -1){
228
            $tags =  DB::table('group_problem_tag')
229
            ->select('tag')
230
            ->where('gid',$gid)
231
            ->distinct()
232
            ->get()->all();
233
        }else{
234
            $tags =  DB::table('group_problem_tag')
235
            ->select('tag')
236
            ->where('gid', $gid)
237
            ->where('pid', $pid)
238
            ->distinct()
239
            ->get()->all();
240
        }
241
242
        $tags_arr = [];
243
        if(!empty($tags)){
244
            foreach ($tags as $value) {
245
                array_push($tags_arr,$value['tag']);
246
            }
247
        }
248
        return $tags_arr;
249
    }
250
251
    public function problems($gid)
252
    {
253
        $problems = DB::table('contest_problem')
254
        ->join('contest','contest_problem.cid', '=', 'contest.cid')
255
        ->join('problem','contest_problem.pid', '=', 'problem.pid' )
256
        ->select('problem.pid as pid', 'pcode', 'title')
257
        ->where('contest.gid',$gid)
258
        ->where('contest.practice',1)
259
        ->distinct()
260
        ->get()->all();
261
        foreach($problems as &$value){
262
            $value['tags'] = $this->problemTags($gid,$value['pid']);
263
        }
264
        return $problems;
265
    }
266
267
    public function problemAddTag($gid,$pid,$tag)
268
    {
269
        return DB::table("group_problem_tag")->insert([
270
            "gid"=>$gid,
271
            "pid"=>$pid,
272
            "tag"=>$tag,
273
        ]);
274
    }
275
276
    public function problemRemoveTag($gid,$pid,$tag)
277
    {
278
        return DB::table("group_problem_tag")->where([
279
            "gid"=>$gid,
280
            "pid"=>$pid,
281
            "tag"=>$tag
282
        ])->delete();
283
    }
284
285
    public function formatPostTime($date)
286
    {
287
        $periods=["second", "minute", "hour", "day", "week", "month", "year", "decade"];
288
        $lengths=["60", "60", "24", "7", "4.35", "12", "10"];
289
290
        $now=time();
291
        $unix_date=strtotime($date);
292
293
        if (empty($unix_date)) {
294
            return "Bad date";
295
        }
296
297
        if ($now>$unix_date) {
298
            $difference=$now-$unix_date;
299
            $tense="ago";
300
        } else {
301
            $difference=$unix_date-$now;
302
            $tense="from now";
303
        }
304
305
        for ($j=0; $difference>=$lengths[$j] && $j<count($lengths)-1; $j++) {
306
            $difference/=$lengths[$j];
307
        }
308
309
        $difference=round($difference);
310
311
        if ($difference!=1) {
312
            $periods[$j].="s";
313
        }
314
315
        return "$difference $periods[$j] {$tense}";
316
    }
317
318
    public function judgeEmailClearance($gid, $email)
319
    {
320
        $user=DB::table("users")->where(["email"=>$email])->first();
321
        if(empty($user)) return -4;
322
        $ret=DB::table("group_member")->where([
323
            "gid"=>$gid,
324
            "uid"=>$user["id"],
325
        ])->first();
326
        return empty($ret) ? -3 : $ret["role"];
327
    }
328
329
    public function inviteMember($gid, $email)
330
    {
331
        $uid=DB::table("users")->where(["email"=>$email])->first();
332
        return DB::table("group_member")->insert([
333
            "uid"=>$uid["id"],
334
            "gid"=>$gid,
335
            "role"=>-1,
336
            "join_time"=>date("Y-m-d H:i:s")
337
        ]);
338
    }
339
340
    public function isUser($email)
341
    {
342
        return DB::table("users")->where([
343
            "email"=>$email
344
        ])->count();
345
    }
346
347
    public function isGroup($gcode)
348
    {
349
        return DB::table("group")->where([
350
            "gcode"=>$gcode,
351
        ])->count();
352
    }
353
354
    public function createGroup($uid, $gcode, $img, $name, $public, $description, $join_policy)
355
    {
356
        $gid=DB::table("group")->insertGetId([
357
            "gcode"=>$gcode,
358
            "img"=>$img,
359
            "name"=>$name,
360
            "public"=>$public,
361
            "verified"=>0,
362
            "description"=>$description,
363
            "join_policy"=>$join_policy,
364
            "custom_icon"=>null,
365
            "custom_title"=>null,
366
            "create_time"=>date("Y-m-d H:i:s")
367
        ]);
368
        return DB::table("group_member")->insert([
369
            "uid"=>$uid,
370
            "gid"=>$gid,
371
            "role"=>3,
372
            "join_time"=>date("Y-m-d H:i:s")
373
        ]);
374
    }
375
376
    public function detailNotice($gcode)
377
    {
378
        $group=DB::table("group")->where([
379
            "gcode"=>$gcode,
380
        ])->first();
381
        return $group_notice=DB::table("group_notice")->where([
0 ignored issues
show
Unused Code introduced by
The assignment to $group_notice is dead and can be removed.
Loading history...
382
            "gid"=>$group["gid"],
383
        ])->first();
384
    }
385
386
    public function createNotice($gid, $uid, $title, $content)
387
    {
388
        return DB::table("group_notice")->updateOrInsert(
389
            [
390
                "gid"=>$gid
391
            ],
392
            [
393
                "uid"=>$uid,
394
                "title"=>$title,
395
                "content"=>$content,
396
                "post_date"=>date("Y-m-d H:i:s"),
397
            ]);
398
    }
399
400
    public function groupMemberPracticeContestStat($gid)
401
    {
402
        $contestModel = new ContestModel();
403
404
        $this->rankingUpdate($gid);
405
406
        $allPracticeContest = DB::table('contest')
407
            ->where([
408
                'gid' => $gid,
409
                'practice' => 1,
410
            ])
411
            ->select('cid','name')
412
            ->get()->all();
413
        $user_list = $this->userList($gid);
414
415
        $memberData = [];
416
        foreach ($user_list as $u) {
417
            $memberData[$u['uid']] = [
418
                'name' => $u['name'],
419
                'nick_name' => $u['nick_name'],
420
                'elo' => $u['ranking'],
421
                'solved_all' => 0,
422
                'problem_all' => 0,
423
                'penalty' => 0,
424
                'contest_detial' => []
425
            ];
426
427
        }
428
        foreach ($allPracticeContest as $c) {
429
            $contestRank = $contestModel->contestRank($c['cid'],0);
430
            $problemsCount = DB::table('contest_problem')
431
                ->where('cid',$c['cid'])
432
                ->count();
433
            $rank = 0;
434
            foreach ($contestRank as $cr) {
435
                $rank++;
436
                if(in_array($cr['uid'],array_keys($memberData))) {
437
                    $memberData[$cr['uid']]['solved_all'] += $cr['solved'];
438
                    $memberData[$cr['uid']]['problem_all'] += $problemsCount;
439
                    $memberData[$cr['uid']]['penalty'] += $cr['penalty'];
440
                    $memberData[$cr['uid']]['contest_detial'][$c['cid']] = [
441
                        'rank' => $rank,
442
                        'solved' => $cr['solved'],
443
                        'problems' => $problemsCount,
444
                        'penalty' => $cr['penalty']
445
                    ];
446
                }
447
            }
448
        }
449
        $new_memberData = [];
450
        foreach ($memberData as $uid => $data) {
451
            $contest_count = 0;
452
            $rank_sum = 0;
453
            foreach ($data['contest_detial'] as $cid => $c) {
454
                $rank_sum += $c['rank'];
455
                $contest_count += 1;
456
            }
457
            $temp = $data;
458
            $temp['uid'] = $uid;
459
            if($contest_count != 0){
460
                $temp['rank_ave'] = $rank_sum/$contest_count;
461
            }
462
            array_push($new_memberData,$temp);
463
        }
464
        $ret = [
465
            'contest_list' => $allPracticeContest,
466
            'member_data' => $new_memberData
467
        ];
468
        return $ret;
469
    }
470
471
    public function groupMemberPracticeTagStat($gid)
472
    {
473
        $tags = $this->problemTags($gid);
474
        $tag_problems = [];
475
476
        $user_list = $this->userList($gid);
477
        foreach ($tags as $tag) {
478
            $tag_problems[$tag] = DB::table('problem')
479
                ->join('group_problem_tag','problem.pid','=','group_problem_tag.pid')
480
                ->where([
481
                    'group_problem_tag.gid' => $gid,
482
                    'tag' => $tag
483
                ])
484
                ->select('group_problem_tag.pid as pid','pcode','title')
485
                ->get()->all();
486
        }
487
        $all_problems = [];
488
        foreach ($tag_problems as &$tag_problem_set) {
489
            foreach ($tag_problem_set as $problem) {
490
                $all_problems[$problem['pid']] = $problem;
491
            }
492
            $tag_problem_set = array_column($tag_problem_set,'pid');
493
        }
494
        $submission_data =  DB::table('submission')
495
            ->whereIn('pid',array_keys($all_problems))
496
            ->whereIn('uid',array_column($user_list,'uid'))
497
            ->where('verdict','Accepted')
498
            ->select('pid','uid')
499
            ->get()->all();
500
501
        $memberData = [];
502
        foreach ($user_list as $member) {
503
            $completion = [];
504
            foreach($tag_problems as $tag => $problems) {
505
                $completion[$tag] = [];
506
                foreach ($problems as $problem) {
507
                    $is_accepted = 0;
508
                    foreach ($submission_data as $sd) {
509
                        if($sd['pid'] == $problem && $sd['uid'] == $member['uid']){
510
                            $is_accepted = 1;
511
                            break;
512
                        }
513
                    }
514
                    $completion[$tag][$problem] = $is_accepted;
515
                }
516
            }
517
            array_push($memberData,[
518
                'uid' => $member['uid'],
519
                'name' => $member['name'],
520
                'nick_name' => $member['nick_name'],
521
                'completion' => $completion,
522
            ]);
523
        }
524
        $ret = [
525
            'all_problems' => $all_problems,
526
            'tag_problems' => $tag_problems,
527
            'member_data' => $memberData
528
        ];
529
        return $ret;
530
    }
531
532
    public function rankingUpdate($gid)
533
    {
534
        $contests = DB::table('contest')
535
            ->leftJoin('group_rated_change_log','contest.cid','=','group_rated_change_log.cid')
536
            ->where([
537
                'contest.gid' => $gid,
538
                'practice' => 1
539
            ])->where('end_time','<',date('Y-m-d H:i:s'))
540
            ->select('contest.cid as cid','group_rated_change_log.cid as cid_rated')
541
            ->whereNull('group_rated_change_log.cid')
542
            ->orderBy('end_time')
543
            ->get()->all();
544
545
        if(empty($contests)){
546
            return true;
547
        }
548
549
        foreach ($contests as $contest) {
550
            $calc = new GroupRatingCalculator($contest['cid']);
551
            $calc->calculate();
552
            $calc->storage();
553
        }
554
555
        return true;
556
    }
557
}
558