예제 #1
0
파일: main.py 프로젝트: aschenkuttel/dsbot
    async def fetch_bulk(self,
                         world,
                         iterable,
                         table=None,
                         *,
                         name=False,
                         dictionary=False):
        dsobj = utils.DSType(table or 0)
        base = f'SELECT * FROM {dsobj.table} WHERE world = $1'

        if not name:
            query = f'{base} AND id = ANY($2)'
        else:
            if dsobj.table == "village":
                iterable = [vil.replace("|", "") for vil in iterable]
                query = f'{base} AND CAST(x AS TEXT)||CAST(y as TEXT) = ANY($2)'

            else:
                iterable = [utils.converter(obj, True) for obj in iterable]
                if dsobj.table == "tribe":
                    query = f'{base} AND ARRAY[LOWER(name), LOWER(tag)] && $2'
                else:
                    query = f'{base} AND LOWER(name) = ANY($2)'

        async with self.pool.acquire() as conn:
            res = await conn.fetch(query, world, iterable)
            if dictionary:
                return {rec[1]: dsobj.Class(rec) for rec in res}
            else:
                return [dsobj.Class(rec) for rec in res]
예제 #2
0
파일: main.py 프로젝트: aschenkuttel/dsbot
    async def fetch_random(self, world, **kwargs):
        amount = kwargs.get('amount', 1)
        top = kwargs.get('top', 500)
        dsobj = utils.DSType(kwargs.get('tribe', 0))
        least = kwargs.get('least', False)

        statement = f'SELECT * FROM {dsobj.table} WHERE world = $1 AND rank <= $2'
        async with self.pool.acquire() as conn:
            data = await conn.fetch(statement, world, top)

        if len(data) < amount:
            if kwargs.get('max'):
                amount = len(data)
            else:
                return

        result = []
        while len(result) < amount:
            ds = random.choice(data)
            data.remove(ds)

            if not least:
                result.append(dsobj.Class(ds))
            elif ds['member'] > 3:
                result.append(dsobj.Class(ds))

        return result[0] if amount == 1 else result
예제 #3
0
파일: main.py 프로젝트: aschenkuttel/dsbot
    async def fetch_all(self, world, table=0, dictionary=False):
        dsobj = utils.DSType(table)

        async with self.pool.acquire() as conn:
            query = f'SELECT * FROM {dsobj.table} WHERE world = $1'
            cache = await conn.fetch(query, world)

            if dictionary:
                result = {rec['id']: dsobj.Class(rec) for rec in cache}
            else:
                result = [dsobj.Class(rec) for rec in cache]

            return result
예제 #4
0
파일: main.py 프로젝트: aschenkuttel/dsbot
    async def fetch_top(self, world, table=None, till=10, balanced=False):
        dsobj = utils.DSType(table or 0)
        till = 100 if balanced else till
        query = f'SELECT * FROM {dsobj.table} WHERE world = $1 AND rank <= $2 ORDER BY rank'

        async with self.pool.acquire() as conn:
            top10 = await conn.fetch(query, world, till)
            dsobj_list = [dsobj.Class(rec) for rec in top10]

        if not balanced:
            return dsobj_list

        else:
            cache = sorted(dsobj_list, key=lambda t: t.points, reverse=True)
            balenciaga = [
                ds for ds in cache if (cache[0].points / 12) < ds.points
            ]
            return balenciaga
예제 #5
0
    async def ingame_(self, ctx, *, username):
        ds_type = utils.DSType(ctx.invoked_with.lower())
        dsobj = await ds_type.fetch(ctx, username, name=True)

        queries = []
        for num in range(29):
            table = f"{ds_type.table}{num or ''}"
            base = f'SELECT * FROM {table} WHERE ' \
                   f'{table}.world = $1 AND {table}.id = $2'

            queries.append(base)

        query = " UNION ALL ".join(queries)
        async with self.bot.pool.acquire() as conn:
            records = await conn.fetch(query, ctx.server, dsobj.id)
            data = [ds_type.Class(rec) for rec in records]
            data.reverse()

        rows = [
            f"**{dsobj.name}** | {ctx.world.show(clean=True)} {ctx.world.icon}"
        ]

        urls = []
        for url_type in ["ingame", "guest", "twstats"]:
            url = getattr(dsobj, f"{url_type}_url")
            urls.append(f"[{url_type.capitalize()}]({url})")

        rows.append(" | ".join(urls))

        points = f"**Punkte:** `{utils.seperator(dsobj.points)}` | **Rang:** `{dsobj.rank}`"

        if hasattr(dsobj, 'tribe_id'):
            tribe = await self.bot.fetch_tribe(ctx.server, dsobj.tribe_id)
            desc = tribe.mention if tribe else "None"
            villages = f"**Stamm:** {desc}"
        else:
            villages = f"**Mitglieder:** `{dsobj.member}`"

        villages += f" | **Dörfer:** `{utils.seperator(dsobj.villages)}`"
        rows.extend(["", points, villages, "", "**Besiegte Gegner:**"])

        bash_rows = OrderedDict()
        for index, stat in enumerate(
            ['all_bash', 'att_bash', 'def_bash', 'sup_bash']):

            if index == 3 and isinstance(dsobj, utils.Tribe):
                value = await dsobj.fetch_supbash(ctx)
                rank_value = None
            else:
                value = getattr(dsobj, stat)
                rank_stat = f"{stat.split('_')[0]}_rank"
                rank_value = getattr(dsobj, rank_stat)

            stat_title = self.bot.msg['statTitle'][stat]
            represent = f"{stat_title}: `{sep(value)}`"

            if rank_value:
                represent += f" | Rang: `{rank_value}`"

            bash_rows[represent] = value

        clean = sorted(bash_rows.items(), key=lambda l: l[1], reverse=True)
        rows.extend([line[0] for line in clean])

        profile = discord.Embed(description="\n".join(rows))
        profile.colour = discord.Color.blue()

        image_url = await self.fetch_profile_picture(dsobj)
        if image_url is not None:
            profile.set_thumbnail(url=image_url)

        filled = [0] * (29 - len(data)) + [d.points for d in data]
        plot_data = pd.DataFrame({'x_coord': range(29), 'y_coord': filled})

        config = {
            'color':
            '#3498db',
            'linewidth':
            5,
            'path_effects':
            [patheffects.SimpleLineShadow(linewidth=8),
             patheffects.Normal()]
        }

        figure = self.create_figure()

        if not data:
            plt.ylim(top=50, bottom=-3)

        figure.plot('x_coord', 'y_coord', data=plot_data, **config)
        figure.grid(axis='y', zorder=1, alpha=0.3)

        buf = io.BytesIO()
        plt.savefig(buf, format='png', dpi=100, transparent=True)
        buf.seek(0)
        plt.close()

        file = discord.File(buf, "example.png")
        profile.set_image(url="attachment://example.png")
        await ctx.send(embed=profile, file=file)
예제 #6
0
    async def daily_(self, ctx, award_type):
        award = award_type.lower()
        award_data = self.bash_value.get(award)

        if award_data is None:
            raise MissingRequiredKey(self.bash_value)

        tribe = ctx.invoked_with.lower() == "aktueller"
        dstype = utils.DSType(int(tribe))
        negative = award in ["verlierer"]

        async with self.bot.pool.acquire() as conn:
            if tribe and award == "unterstützer":
                query = '(SELECT tribe_id, SUM(sup_bash) AS sup FROM player WHERE ' \
                        'world = $1 GROUP BY tribe_id ORDER BY sup DESC) ' \
                        'UNION ALL ' \
                        '(SELECT tribe_id, SUM(sup_bash) AS sup FROM player1 WHERE ' \
                        'world = $1 GROUP BY tribe_id ORDER BY sup DESC)'

                cache = await conn.fetch(query, ctx.server)
                all_values = {rec['tribe_id']: [] for rec in cache}
                all_values.pop(0)

                for record in cache:
                    arguments = list(record.values())
                    tribe_id = arguments[0]
                    points = arguments[1]
                    if tribe_id != 0:
                        all_values[tribe_id].append(points)

                value_list = [(k, v) for k, v in all_values.items()
                              if len(v) == 2]
                value_list.sort(key=lambda tup: tup[1][0] - tup[1][1],
                                reverse=True)

                tribe_ids = [tup[0] for tup in value_list[:5]]
                kwargs = {'table': 'tribe', 'dictionary': True}
                tribes = await self.bot.fetch_bulk(ctx.server, tribe_ids,
                                                   **kwargs)
                data = [tribes[idc] for idc in tribe_ids]

            else:
                base = 'SELECT * FROM {0} INNER JOIN {1} ON {0}.id = {1}.id ' \
                       'WHERE {0}.world = $1 AND {1}.world = $1 ' \
                       'ORDER BY ({0}.{2} - {1}.{2}) {3} LIMIT 5'

                switch = "ASC" if negative else "DESC"
                query = base.format(dstype.table, f"{dstype.table}1",
                                    award_data['value'], switch)
                data = await conn.fetch(query, ctx.server)

        ranking = []
        for record in data:
            if isinstance(record, utils.Tribe):
                values = all_values[record.id]
                cur_value, old_value = values
                dsobj = record

            else:
                records = utils.unpack_join(record)
                dsobj = dstype.Class(records[0])
                old_dsobj = dstype.Class(records[1])
                cur_value = getattr(dsobj, award_data['value'], 0)
                old_value = getattr(old_dsobj, award_data['value'], 0)

            if negative:
                value = old_value - cur_value
            else:
                value = cur_value - old_value

            if value < 1:
                continue

            item = award_data['item']
            if value == 1 and item == "Dörfer":
                item = "Dorf"

            line = f"`{sep(value)} {item}` | {dsobj.guest_mention}"
            ranking.append(line)

        if ranking:
            description = "\n".join(ranking)
            title = f"{award.capitalize()} des Tages ({ctx.world.show(True)})"
            footer = "Daten aufgrund von Inno nur stündlich aktualisiert"
            embed = discord.Embed(title=title, description=description)
            embed.colour = discord.Color.blue()
            embed.set_footer(text=footer)

        else:
            msg = "Aktuell liegen noch keine Daten vor"
            embed = discord.Embed(description=msg, color=discord.Color.red())

        await ctx.send(embed=embed)