Passed
Pull Request — master (#220)
by
unknown
03:57
created

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