Passed
Branch BonHowi (7aa8f1)
by Bartosz
01:20
created

build.cogs.leaderboardcog   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 26
eloc 125
dl 0
loc 156
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A LeaderboardsCog.cog_unload() 0 2 1
A LeaderboardsCog.__init__() 0 5 1
A LeaderboardsCog.update_leaderboard() 0 14 1
A LeaderboardsCog.update_member_roles() 0 6 1
A LeaderboardsCog.update_leaderboards() 0 7 1
A LeaderboardsCog.update_role_ext() 0 10 4
A LeaderboardsCog.update_leaderboards_loop() 0 3 1
A LeaderboardsCog.update_event_leaderboards() 0 12 1
A LeaderboardsCog.update_roles() 0 16 5
A LeaderboardsCog.before_update_leaderboards_loop() 0 10 3
B LeaderboardsCog.print_leaderboard() 0 29 5
A LeaderboardsCog.reload_leaderboards() 0 7 1

1 Function

Rating   Name   Duplication   Size   Complexity  
A setup() 0 2 1
1
import discord
2
import pandas as pd
3
from discord.ext import commands, tasks
4
from discord.utils import get
5
from discord_slash import cog_ext, SlashContext
6
import cogs.cogbase as cogbase
7
from cogs.databasecog import DatabaseCog
8
from modules.utils import get_dominant_color
9
10
11
class LeaderboardsCog(cogbase.BaseCog):
12
    def __init__(self, base):
13
        super().__init__(base)
14
15
        self.common_total = 0
16
        self.update_leaderboards_loop.start()
17
18
    def cog_unload(self):
19
        self.update_leaderboards_loop.cancel()
20
21
    # Send leaderboards to specified channel
22
    async def update_leaderboard(self, channel: int, ch_type: str) -> None:
23
        top_ch = self.bot.get_channel(channel)
24
        spots_df = await DatabaseCog.db_get_spots_df()
25
        monsters_df = await DatabaseCog.db_get_monster_spots_df()
26
        # Hard coded because there is only one interesting monster
27
        event_monster_df = monsters_df.filter(["member_id", "Nightmare"], axis=1)
28
        spots_df = pd.merge(spots_df, event_monster_df, on=["member_id"])
29
        spots_df = spots_df.drop(spots_df[spots_df.member_id == self.bot.user.id].index)
30
        spots_df["total"] = spots_df["legendary"] * self.legend_multiplier + spots_df["rare"] + (spots_df["Nightmare"])
31
        spots_df_top = spots_df.sort_values(ch_type, ascending=False).head(15)
32
        spots_df_top = spots_df_top.reset_index(drop=True)
33
        await self.print_leaderboard(top_ch, spots_df_top, ch_type)
34
35
        self.create_log_msg(f"Leaderboards updated - {ch_type}")
36
37
    # TODO: get data from spot_temp table
38
    # TODO: create temp event db
39
    async def update_event_leaderboards(self, channel: int, event_monster: str) -> None:
40
        top_ch = self.bot.get_channel(channel)
41
        spots_df = await DatabaseCog.db_get_monster_spots_df()
42
        event_monster_df = spots_df.filter(["member_id", event_monster], axis=1)
43
        member_names_df = await DatabaseCog.db_get_member_names()
44
45
        event_df = pd.merge(event_monster_df, member_names_df, on=["member_id"])
46
        event_df = event_df.drop(event_df[event_df.member_id == self.bot.user.id].index)
47
        event_df = event_df.sort_values(event_monster, ascending=False).head(15)
48
        event_df = event_df.reset_index(drop=True)
49
        await self.print_leaderboard(top_ch, event_df, event_monster)
50
        self.create_log_msg('Leaderboards updated - event')
51
52
    async def print_leaderboard(self, leaderboard_ch, monster_df, monster_type):
53
        try:
54
            await leaderboard_ch.purge()
55
        except discord.errors.NotFound:
56
            pass
57
58
        top_print = []
59
        top_user_id = int(monster_df.at[0, 'member_id'])
60
        for index, row in monster_df.iterrows():
61
            if row[monster_type] == 0:
62
                member_stats = ""
63
            elif row['member_id'] == top_user_id:
64
                member_stats = [f"**[{index + 1}]  {row['display_name']} - {row[monster_type]}**"]
65
            else:
66
                member_stats = [f"**[{index + 1}]**  {row['display_name']} - {row[monster_type]}"]
67
            top_print.append(member_stats)
68
        top_print = ['\n'.join(sublist) for sublist in top_print]
69
        top_print = "\n".join(top_print)
70
        ch_type = ''.join(i for i in monster_type if not i.isdigit())
71
72
        top_user = get(self.bot.get_all_members(), id=top_user_id)
73
        top_user_color = get_dominant_color(top_user.avatar_url)
74
        embed_command = discord.Embed(title=f"TOP 15 {ch_type.upper()}", description=top_print,
75
                                      color=top_user_color)
76
        member = self.bot.get_user(monster_df['member_id'].iloc[0])
77
        embed_command.set_thumbnail(url=f'{member.avatar_url}')
78
        dt_string = self.bot.get_current_time()
79
        embed_command.set_footer(text=f"{dt_string}")
80
        await leaderboard_ch.send(embed=embed_command)
81
82
    # TODO: something wrong is going on here
83
    # Update member spotting role(total/common)
84
    async def update_roles(self, guild, spot_roles: dict, common: bool) -> None:
85
        roles_type = "common" if common else "total"
86
        spots_df = await DatabaseCog.db_get_spots_df()
87
88
        if not common:
89
            monsters_df = await DatabaseCog.db_get_monster_spots_df()
90
            event_monster_df = monsters_df.filter(["member_id", "Nightmare"], axis=1)
91
            spots_df = pd.merge(spots_df, event_monster_df, on=["member_id"])
92
            spots_df["total"] = spots_df["legendary"] * self.legend_multiplier \
93
                                + spots_df["rare"] + (spots_df["Nightmare"])
94
        for guild_member in guild.members:
95
            member_data = spots_df.loc[spots_df["member_id"] == guild_member.id]
96
            member_score = member_data[roles_type].iloc[0]
97
            roles_list = [key for (key, value) in spot_roles.items() if member_score >= value]
98
            if roles_list:
99
                await self.update_role_ext(guild, roles_list, guild_member)
100
        # except KeyError as e:
101
        #     print(e)
102
103
    async def update_role_ext(self, guild, roles_list: list, guild_member) -> None:
104
        await self.create_new_role(guild, roles_list[-1])
105
        role_new = get(guild.roles, name=roles_list[-1])
106
        if role_new not in guild_member.roles:
107
            await guild_member.add_roles(role_new)
108
        if len(roles_list) > 1:
109
            await self.create_new_role(guild, roles_list[-2])
110
            role_old = get(guild.roles, name=roles_list[-2])
111
            if role_old in guild_member.roles:
112
                await guild_member.remove_roles(role_old)
113
114
    # Update members' spotting roles
115
    async def update_member_roles(self) -> None:
116
        guild = self.bot.get_guild(self.bot.guild[0])
117
        spot_roles_total = self.bot.config["total_milestones"][0]
118
        spot_roles_common = self.bot.config["common_milestones"][0]
119
        await self.update_roles(guild, spot_roles_total, False)
120
        await self.update_roles(guild, spot_roles_common, True)
121
122
    async def update_leaderboards(self) -> None:
123
        await self.update_leaderboard(self.bot.ch_leaderboards, "total")
124
        await self.update_leaderboard(self.bot.ch_leaderboards_common, "common")
125
        # await self.update_event_leaderboards(self.bot.ch_leaderboards_event, "Nightmare")
126
        self.create_log_msg('All leaderboards updated')
127
        await self.update_member_roles()
128
        self.create_log_msg('All member roles updated')
129
130
    @tasks.loop(minutes=30)
131
    async def update_leaderboards_loop(self) -> None:
132
        await self.update_leaderboards()
133
134
    @update_leaderboards_loop.before_loop
135
    async def before_update_leaderboards_loop(self) -> None:
136
        self.create_log_msg('Waiting until Bot is ready')
137
        common_ch = self.bot.get_channel(self.bot.ch_common)
138
        try:
139
            async for _ in common_ch.history(limit=None, oldest_first=True):
140
                self.common_total += 1
141
        except AttributeError:
142
            pass
143
        await self.bot.wait_until_ready()
144
145
    @cog_ext.cog_slash(name="reloadLeaderboards", guild_ids=cogbase.GUILD_IDS,
146
                       description="Reload leaderboards",
147
                       default_permission=False,
148
                       permissions=cogbase.PERMISSION_MODS)
149
    async def reload_leaderboards(self, ctx: SlashContext) -> None:
150
        await ctx.send('Leaderboards reloaded', hidden=True)
151
        await self.update_leaderboards()
152
153
154
def setup(bot: commands.Bot) -> None:
155
    bot.add_cog(LeaderboardsCog(bot))
156