Completed
Push — master ( 9cf369...804d92 )
by John
15s queued 10s
created

GroupModel::judgeEmailClearance()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 9
rs 10
c 3
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
        }
434
        foreach ($allPracticeContest as $c) {
435
            $contestRank = $contestModel->contestRank($c['cid'],0);
436
            $problemsCount = DB::table('contest_problem')
437
                ->where('cid',$c['cid'])
438
                ->count();
439
            $rank = 0;
440
            foreach ($contestRank as $cr) {
441
                $rank++;
442
                if(in_array($cr['uid'],array_keys($memberData))) {
443
                    $memberData[$cr['uid']]['solved_all'] += $cr['solved'];
444
                    $memberData[$cr['uid']]['problem_all'] += $problemsCount;
445
                    $memberData[$cr['uid']]['penalty'] += $cr['penalty'];
446
                    $memberData[$cr['uid']]['contest_detial'][$c['cid']] = [
447
                        'rank' => $rank,
448
                        'solved' => $cr['solved'],
449
                        'problems' => $problemsCount,
450
                        'penalty' => $cr['penalty']
451
                    ];
452
                }
453
            }
454
        }
455
        $new_memberData = [];
456
        foreach ($memberData as $uid => $data) {
457
            $contest_count = 0;
458
            $rank_sum = 0;
459
            foreach ($data['contest_detial'] as $cid => $c) {
460
                $rank_sum += $c['rank'];
461
                $contest_count += 1;
462
            }
463
            $temp = $data;
464
            $temp['uid'] = $uid;
465
            if($contest_count != 0){
466
                $temp['rank_ave'] = $rank_sum/$contest_count;
467
            }
468
            array_push($new_memberData,$temp);
469
        }
470
        $ret = [
471
            'contest_list' => $allPracticeContest,
472
            'member_data' => $new_memberData
473
        ];
474
        return $ret;
475
    }
476
477
    public function groupMemberPracticeTagStat($gid)
478
    {
479
        $tags = $this->problemTags($gid);
480
        $tag_problems = [];
481
482
        $user_list = $this->userList($gid);
483
        foreach ($tags as $tag) {
484
            $tag_problems[$tag] = DB::table('problem')
485
                ->join('group_problem_tag','problem.pid','=','group_problem_tag.pid')
486
                ->where([
487
                    'group_problem_tag.gid' => $gid,
488
                    'tag' => $tag
489
                ])
490
                ->select('group_problem_tag.pid as pid','pcode','title')
491
                ->get()->all();
492
        }
493
        $all_problems = [];
494
        foreach ($tag_problems as &$tag_problem_set) {
495
            foreach ($tag_problem_set as $problem) {
496
                $all_problems[$problem['pid']] = $problem;
497
            }
498
            $tag_problem_set = array_column($tag_problem_set,'pid');
499
        }
500
        $submission_data =  DB::table('submission')
501
            ->whereIn('pid',array_keys($all_problems))
502
            ->whereIn('uid',array_column($user_list,'uid'))
503
            ->where('verdict','Accepted')
504
            ->select('pid','uid')
505
            ->get()->all();
506
507
        $memberData = [];
508
        foreach ($user_list as $member) {
509
            $completion = [];
510
            foreach($tag_problems as $tag => $problems) {
511
                $completion[$tag] = [];
512
                foreach ($problems as $problem) {
513
                    $is_accepted = 0;
514
                    foreach ($submission_data as $sd) {
515
                        if($sd['pid'] == $problem && $sd['uid'] == $member['uid']){
516
                            $is_accepted = 1;
517
                            break;
518
                        }
519
                    }
520
                    $completion[$tag][$problem] = $is_accepted;
521
                }
522
            }
523
            array_push($memberData,[
524
                'uid' => $member['uid'],
525
                'name' => $member['name'],
526
                'nick_name' => $member['nick_name'],
527
                'completion' => $completion,
528
            ]);
529
        }
530
        $ret = [
531
            'all_problems' => $all_problems,
532
            'tag_problems' => $tag_problems,
533
            'member_data' => $memberData
534
        ];
535
        return $ret;
536
    }
537
538
    public function refreshElo($gid)
539
    {
540
        DB::table('group_rated_change_log')
541
            ->where('gid',$gid)
542
            ->delete();
543
        DB::table('group_member')
544
            ->where('gid',$gid)
545
            ->update([
546
                'ranking' => 1500
547
            ]);
548
        $contests = DB::table('contest')
549
            ->where([
550
                'gid' => $gid,
551
                'practice' => 1
552
            ])
553
            ->whereNull('contest.vcid')
554
            ->whereNull('vcid')
555
            ->select('cid')
556
            ->orderBy('end_time')
557
            ->get()->all();
558
559
        if(empty($contests)) {
560
            return true;
561
        }
562
563
        foreach ($contests as $contest) {
564
            $calc = new GroupRatingCalculator($contest['cid']);
565
            $calc->calculate();
566
            $calc->storage();
567
        }
568
569
        return true;
570
    }
571
}
572