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]
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
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
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
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)
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)