Passed
Pull Request — master (#220)
by
unknown
04:42
created

GroupModel::cacheTrendingGroups()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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