GroupModel::userProfile()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 2
dl 0
loc 13
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace App\Models;
4
5
use App\Models\Rating\GroupRatingCalculator;
6
use Illuminate\Database\Eloquent\Model;
7
use Illuminate\Support\Facades\DB;
8
use Cache;
9
use Auth;
10
use App\Models\ContestModel;
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
            0:a user can join this group by both invitation and application // old version default value
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('created_at', '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")->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 basic($gid)
116
    {
117
        $basic_info=DB::table($this->tableName)->where(["gid"=>$gid])->first();
118
        return $basic_info;
119
    }
120
121
    public function details($gcode)
122
    {
123
        $basic_info=DB::table($this->tableName)->where(["gcode"=>$gcode])->first();
124
        if (empty($basic_info)) {
125
            return [];
126
        }
127
        $basic_info["members"]=$this->countGroupMembers($basic_info["gid"]);
128
        $basic_info["tags"]=$this->getGroupTags($basic_info["gid"]);
129
        $basic_info["create_time_foramt"]=date_format(date_create($basic_info["created_at"]), 'M jS, Y');
130
        $basic_info["contest_stat"]=$this->countGroupContest($basic_info["gid"]);
131
        return $basic_info;
132
    }
133
134
    public function joinPolicy($gid)
135
    {
136
        $ret=DB::table($this->tableName)->where(["gid"=>$gid])->first();
137
        return empty($ret) ? null : $ret["join_policy"];
138
    }
139
140
    public function userProfile($uid, $gid)
141
    {
142
        $info=DB::table("group_member")
143
        ->join('users', 'users.id', '=', 'group_member.uid')
144
        ->where(["gid"=>$gid, "uid"=>$uid])
145
        ->where("role", ">", 0)
146
        ->select('avatar', 'describes', 'email', 'gid', 'uid', 'name', 'nick_name', 'professional_rate', 'role', 'sub_group')
147
        ->first();
148
        if (!empty($info)) {
149
            $info["role_parsed"]=$this->role[$info["role"]];
150
            $info["role_color"]=$this->role_color[$info["role"]];
151
        }
152
        return $info;
153
    }
154
155
    public function userList($gid)
156
    {
157
        $user_list=DB::table("group_member")->join(
158
            "users",
159
            "users.id",
160
            "=",
161
            "group_member.uid"
162
        )->where(["gid"=>$gid])->orderBy('role', 'desc')->select(
163
            "role",
164
            "uid",
165
            "name",
166
            "nick_name",
167
            "avatar",
168
            "sub_group",
169
            "ranking"
170
        )->get()->all();
171
        foreach ($user_list as &$u) {
172
            $u["role_parsed"]=$this->role[$u["role"]];
173
            $u["role_color"]=$this->role_color[$u["role"]];
174
            if (is_null($u["sub_group"])) {
175
                $u["sub_group"]="None";
176
            }
177
        }
178
        return $user_list;
179
    }
180
181
    public function groupNotice($gid)
182
    {
183
        $notice_item=DB::table("group_notice")->where(["gid"=>$gid])->first();
184
        if (empty($notice_item)) {
185
            return [];
186
        }
187
        $notice_author=DB::table("users")->where(["id"=>$notice_item["uid"]])->first();
188
        $notice_item["name"]=$notice_author["name"];
189
        $notice_item["avatar"]=$notice_author["avatar"];
190
        $notice_item["post_date_parsed"]=formatHumanReadableTime($notice_item["created_at"]);
191
        $notice_item["content_parsed"]=clean(convertMarkdownToHtml($notice_item["content"]));
192
        return $notice_item;
193
    }
194
195
    public function judgeClearance($gid, $uid)
196
    {
197
        $ret=DB::table("group_member")->where(["gid"=>$gid, "uid"=>$uid])->first();
198
        return empty($ret) ? -3 : $ret["role"];
199
    }
200
201
    public function changeClearance($uid, $gid, $clearance)
202
    {
203
        return DB::table("group_member")->where([
204
            "uid"=>$uid,
205
            "gid"=>$gid
206
        ])->update([
207
            "role"=>$clearance
208
        ]);
209
    }
210
211
    public function removeClearance($uid, $gid)
212
    {
213
        return DB::table("group_member")->where([
214
            "uid"=>$uid,
215
            "gid"=>$gid
216
        ])->delete();
217
    }
218
219
    public function addClearance($uid, $gid, $clearance)
220
    {
221
        return DB::table("group_member")->insert([
222
            "uid"=>$uid,
223
            "gid"=>$gid,
224
            "role"=>$clearance,
225
            "created_at"=>date("Y-m-d H:i:s")
226
        ]);
227
    }
228
229
    public function isMember($gid, $uid)
230
    {
231
        return DB::table("group_member")->where([
232
            "gid"=> $gid,
233
            "uid"=> $uid
234
        ])->where("role", ">", 0)->count();
235
    }
236
237
    public function problemTags($gid, $pid=-1)
238
    {
239
        if ($pid==-1) {
240
            $tags=DB::table('group_problem_tag')
241
            ->select('tag')
242
            ->where('gid', $gid)
243
            ->distinct()
244
            ->get()->all();
245
        } else {
246
            $tags=DB::table('group_problem_tag')
247
            ->select('tag')
248
            ->where('gid', $gid)
249
            ->where('pid', $pid)
250
            ->distinct()
251
            ->get()->all();
252
        }
253
254
        $tags_arr=[];
255
        if (!empty($tags)) {
256
            foreach ($tags as $value) {
257
                array_push($tags_arr, $value['tag']);
258
            }
259
        }
260
        return $tags_arr;
261
    }
262
263
    public function problems($gid)
264
    {
265
        $contestModel=new ContestModel();
266
        $problems=DB::table('contest_problem')
267
        ->join('contest', 'contest_problem.cid', '=', 'contest.cid')
268
        ->join('problem', 'contest_problem.pid', '=', 'problem.pid')
269
        ->select('contest_problem.cid as cid', 'problem.pid as pid', 'pcode', 'title')
270
        ->where('contest.gid', $gid)
271
        ->where('contest.practice', 1)
272
        ->orderBy('contest.created_at', 'desc')
273
        ->distinct()
274
        ->get()->all();
275
        $user_id=Auth::user()->id;
0 ignored issues
show
Bug introduced by
Accessing id on the interface Illuminate\Contracts\Auth\Authenticatable suggest that you code against a concrete implementation. How about adding an instanceof check?
Loading history...
276
        foreach ($problems as $key => $value) {
277
            if ($contestModel->judgeClearance($value['cid'], $user_id)!=3) {
278
                unset($problems[$key]);
279
            } else {
280
                $problems[$key]['tags']=$this->problemTags($gid, $value['pid']);
281
            }
282
        }
283
        return $problems;
284
    }
285
286
    public function problemAddTag($gid, $pid, $tag)
287
    {
288
        return DB::table("group_problem_tag")->insert([
289
            "gid"=>$gid,
290
            "pid"=>$pid,
291
            "tag"=>$tag,
292
        ]);
293
    }
294
295
    public function problemRemoveTag($gid, $pid, $tag)
296
    {
297
        return DB::table("group_problem_tag")->where([
298
            "gid"=>$gid,
299
            "pid"=>$pid,
300
            "tag"=>$tag
301
        ])->delete();
302
    }
303
304
    public function judgeEmailClearance($gid, $email)
305
    {
306
        $user=DB::table("users")->where(["email"=>$email])->first();
307
        if (empty($user)) {
308
            return -4;
309
        }
310
        $ret=DB::table("group_member")->where([
311
            "gid"=>$gid,
312
            "uid"=>$user["id"],
313
        ])->first();
314
        return empty($ret) ? -3 : $ret["role"];
315
    }
316
317
    public function inviteMember($gid, $email)
318
    {
319
        $uid=DB::table("users")->where(["email"=>$email])->first();
320
        return DB::table("group_member")->insert([
321
            "uid"=>$uid["id"],
322
            "gid"=>$gid,
323
            "role"=>-1,
324
            "created_at"=>date("Y-m-d H:i:s")
325
        ]);
326
    }
327
328
    public function changeGroup($uid, $gid, $sub)
329
    {
330
        return DB::table("group_member")->where([
331
            "uid"=>$uid,
332
            "gid"=>$gid
333
        ])->update([
334
            "sub_group"=>$sub
335
        ]);
336
    }
337
338
    public function isUser($email)
339
    {
340
        return DB::table("users")->where([
341
            "email"=>$email
342
        ])->count();
343
    }
344
345
    public function isGroup($gcode)
346
    {
347
        return DB::table("group")->where([
348
            "gcode"=>$gcode,
349
        ])->count();
350
    }
351
352
    public function createGroup($uid, $gcode, $img, $name, $public, $description, $join_policy)
353
    {
354
        $gid=DB::table("group")->insertGetId([
355
            "gcode"=>$gcode,
356
            "img"=>$img,
357
            "name"=>$name,
358
            "public"=>$public,
359
            "verified"=>0,
360
            "description"=>$description,
361
            "join_policy"=>$join_policy,
362
            "custom_icon"=>null,
363
            "custom_title"=>null,
364
            "created_at"=>date("Y-m-d H:i:s")
365
        ]);
366
        return DB::table("group_member")->insert([
367
            "uid"=>$uid,
368
            "gid"=>$gid,
369
            "role"=>3,
370
            "created_at"=>date("Y-m-d H:i:s")
371
        ]);
372
    }
373
374
    public function detailNotice($gcode)
375
    {
376
        $group=DB::table("group")->where([
377
            "gcode"=>$gcode,
378
        ])->first();
379
        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...
380
            "gid"=>$group["gid"],
381
        ])->first();
382
    }
383
384
    public function createNotice($gid, $uid, $title, $content)
385
    {
386
        return DB::table("group_notice")->updateOrInsert(
387
            [
388
                "gid"=>$gid
389
            ],
390
            [
391
                "uid"=>$uid,
392
                "title"=>$title,
393
                "content"=>$content,
394
                "created_at"=>date("Y-m-d H:i:s"),
395
            ]);
396
    }
397
398
    public function groupMemberPracticeContestStat($gid)
399
    {
400
        $contestModel=new ContestModel();
401
402
        $allPracticeContest=DB::table('contest')
403
            ->where([
404
                'gid' => $gid,
405
                'practice' => 1,
406
            ])
407
            ->select('cid', 'name')
408
            ->get()->all();
409
        $user_list=$this->userList($gid);
410
411
        $memberData=[];
412
        foreach ($user_list as $u) {
413
            $memberData[$u['uid']]=[
414
                'name' => $u['name'],
415
                'nick_name' => $u['nick_name'],
416
                'elo' => $u['ranking'],
417
                'solved_all' => 0,
418
                'problem_all' => 0,
419
                'penalty' => 0,
420
                'contest_detial' => []
421
            ];
422
        }
423
        foreach ($allPracticeContest as $c) {
424
            $contestRankRaw=$contestModel->contestRank($c['cid']);
425
            foreach ($contestRankRaw as $key => $contestRank) {
426
                if (isset($contestRank['remote']) && $contestRank['remote']) {
427
                    unset($contestRankRaw[$key]);
428
                }
429
            }
430
            $contestRank=array_values($contestRankRaw);
431
            $problemsCount=DB::table('contest_problem')
432
                ->where('cid', $c['cid'])
433
                ->count();
434
            $index=1;
435
            $rank=1;
436
            $last_cr=[];
437
            $last_rank=1;
438
            foreach ($contestRank as $cr) {
439
                $last_rank=$index;
440
                if (!empty($last_cr)) {
441
                    if ($cr['solved']==$last_cr['solved'] && $cr['penalty']==$last_cr['penalty']) {
442
                        $rank=$last_rank;
443
                    } else {
444
                        $rank=$index;
445
                        $last_rank=$rank;
0 ignored issues
show
Unused Code introduced by
The assignment to $last_rank is dead and can be removed.
Loading history...
446
                    }
447
                }
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
                $last_cr=$cr;
460
                $index++;
461
            }
462
        }
463
        $new_memberData=[];
464
        foreach ($memberData as $uid => $data) {
465
            $contest_count=0;
466
            $rank_sum=0;
467
            foreach ($data['contest_detial'] as $cid => $c) {
468
                $rank_sum+=$c['rank'];
469
                $contest_count+=1;
470
            }
471
            $temp=$data;
472
            $temp['uid']=$uid;
473
            if ($contest_count!=0) {
474
                $temp['rank_ave']=$rank_sum / $contest_count;
475
            }
476
            array_push($new_memberData, $temp);
477
        }
478
        $ret=[
479
            'contest_list' => $allPracticeContest,
480
            'member_data' => $new_memberData
481
        ];
482
        return $ret;
483
    }
484
485
    public function groupMemberPracticeTagStat($gid)
486
    {
487
        $tags=$this->problemTags($gid);
488
        $tag_problems=[];
489
490
        $user_list=$this->userList($gid);
491
        foreach ($tags as $tag) {
492
            $tag_problems[$tag]=DB::table('problem')
493
                ->join('group_problem_tag', 'problem.pid', '=', 'group_problem_tag.pid')
494
                ->where([
495
                    'group_problem_tag.gid' => $gid,
496
                    'tag' => $tag
497
                ])
498
                ->select('group_problem_tag.pid as pid', 'pcode', 'title')
499
                ->get()->all();
500
        }
501
        $all_problems=[];
502
        foreach ($tag_problems as &$tag_problem_set) {
503
            foreach ($tag_problem_set as $problem) {
504
                $all_problems[$problem['pid']]=$problem;
505
            }
506
            $tag_problem_set=array_column($tag_problem_set, 'pid');
507
        }
508
        $submission_data=DB::table('submission')
509
            ->whereIn('pid', array_keys($all_problems))
510
            ->whereIn('uid', array_column($user_list, 'uid'))
511
            ->where('verdict', 'Accepted')
512
            ->select('pid', 'uid')
513
            ->get()->all();
514
515
        $memberData=[];
516
        foreach ($user_list as $member) {
517
            $completion=[];
518
            foreach ($tag_problems as $tag => $problems) {
519
                $completion[$tag]=[];
520
                foreach ($problems as $problem) {
521
                    $is_accepted=0;
522
                    foreach ($submission_data as $sd) {
523
                        if ($sd['pid']==$problem && $sd['uid']==$member['uid']) {
524
                            $is_accepted=1;
525
                            break;
526
                        }
527
                    }
528
                    $completion[$tag][$problem]=$is_accepted;
529
                }
530
            }
531
            array_push($memberData, [
532
                'uid' => $member['uid'],
533
                'name' => $member['name'],
534
                'nick_name' => $member['nick_name'],
535
                'completion' => $completion,
536
            ]);
537
        }
538
        $ret=[
539
            'all_problems' => $all_problems,
540
            'tag_problems' => $tag_problems,
541
            'member_data' => $memberData
542
        ];
543
        return $ret;
544
    }
545
546
    public function refreshAllElo()
547
    {
548
        $result=[];
549
        $gids=DB::table('group')->select('gid', 'name')->get()->all();
550
        foreach ($gids as $gid) {
551
            $result[$gid['gid']]=[
552
                'name' => $gid['name'],
553
                'result' => $this->refreshElo($gid['gid']),
554
            ];
555
        }
556
        return $result;
557
    }
558
559
    public function refreshElo($gid)
560
    {
561
        DB::table('group_rated_change_log')
562
            ->where('gid', $gid)
563
            ->delete();
564
        DB::table('group_member')
565
            ->where('gid', $gid)
566
            ->update([
567
                'ranking' => 1500
568
            ]);
569
        $contests=DB::table('contest')
570
            ->where([
571
                'gid' => $gid,
572
                'practice' => 1
573
            ])
574
            ->where('end_time', '<', date("Y-m-d H:i:s"))
575
            ->select('cid', 'name')
576
            ->orderBy('end_time')
577
            ->get()->all();
578
579
        if (empty($contests)) {
580
            return [];
581
        }
582
        $result=[];
583
        $contestModel=new ContestModel();
584
        foreach ($contests as $contest) {
585
            $judge_status=$contestModel->judgeOver($contest['cid']);
586
            if ($judge_status['result']==true) {
587
                $calc=new GroupRatingCalculator($contest['cid']);
588
                $calc->calculate();
589
                $calc->storage();
590
                $result[]=[
591
                    'ret' => 'success',
592
                    'cid' => $contest['cid'],
593
                    'name' => $contest['name']
594
                ];
595
            } else {
596
                $result[]=[
597
                    'ret' => 'judging',
598
                    'cid' => $contest['cid'],
599
                    'name' => $contest['name'],
600
                    'submissions' => $judge_status['sid']
601
                ];
602
            }
603
        }
604
605
        return $result;
606
    }
607
608
    public function getEloChangeLog($gid, $uid)
609
    {
610
        $ret=DB::table('group_rated_change_log')
611
            ->join('contest', 'group_rated_change_log.cid', '=', 'contest.cid')
612
            ->where([
613
                'group_rated_change_log.gid' => $gid,
614
                'group_rated_change_log.uid' => $uid
615
            ])->select('group_rated_change_log.cid as cid', 'contest.name as name', 'ranking', 'end_time')
616
            ->orderBy('contest.end_time')
617
            ->get()->all();
618
        $begin=[
619
            'cid' => -1,
620
            'name' => '',
621
            'ranking' => '1500',
622
            'end_time' => date("Y-m-d H:i:s", (strtotime($ret[0]['end_time'] ?? time())-3600 * 24)),
623
        ];
624
        array_unshift($ret, $begin);
625
        return $ret;
626
    }
627
}
628