How to make data to be shown in tabular form in discord.py?

Viewed 7351

Hi I am creating a bot that makes points table/leaderboard , below is the code which works really nice.

def check(ctx):
    return lambda m: m.author == ctx.author and m.channel == ctx.channel


async def get_input_of_type(func, ctx):
    while True:
        try:
            msg = await bot.wait_for('message', check=check(ctx))
            return func(msg.content)
        except ValueError:
            continue

@bot.command()
async def start(ctx):
    await ctx.send("How many total teams are there?")
    t = await get_input_of_type(int, ctx)
    embed = discord.Embed(title=f"__**{ctx.guild.name} Results:**__", color=0x03f8fc,timestamp= ctx.message.created_at)
    
    lst = []
    
    for i in range(t):
        await ctx.send(f"Enter team {i+1} name :")
        teamname = await get_input_of_type(str, ctx)
        await ctx.send("How many kills did they get?")
        firstnum = await get_input_of_type(int, ctx)
        await ctx.send("How much Position points did they score?")
        secondnum = await get_input_of_type(int, ctx)
        lst.append((teamname, firstnum, secondnum))  # append 
        
    lstSorted = sorted(lst, key = lambda x: int(x[1]) + int(x[2],),reverse=True) # sort   
    for teamname, firstnum, secondnum in lstSorted:  # process embed
        embed.add_field(name=f'**{teamname}**', value=f'Kills: {firstnum}\nPosition Pt: {secondnum}\nTotal Pt: {firstnum+secondnum}',inline=True)

    await ctx.send(embed=embed)  

The result looks something like this:

enter image description here

But I want to know, can I do something to get the result in tabular form like The Team Name , positions points , total pts, kill pts written in a row and the results printed below them (I really don't if that made you understand what I am trying to say.)

Below image will help you understand ,

enter image description here

So I want the result to be in following format. I can't think of a way doing it , if you can answer this please do so, That would be a very great help! Thanks.

3 Answers

This is probably the closest you will get:

embed.add_field(name=f'**{teamname}**', value=f'> Kills: {firstnum}\n> Position Pt: {secondnum}\n> Total Pt: {firstnum+secondnum}',inline=False)

The code will output something like this:

image

I've set inline to False and added the > character to each of statistics.

With table2ascii, you can easily generate ascii tables and put them in codeblocks on Discord.

You may also choose to use it in an Embed.

from table2ascii import table2ascii as t2a, PresetStyle

# In your command:
output = t2a(
    header=["Rank", "Team", "Kills", "Position Pts", "Total"],
    body=[[1, 'Team A', 2, 4, 6], [2, 'Team B', 3, 3, 6], [3, 'Team C', 4, 2, 6]],
    style=PresetStyle.thin_compact
)

await ctx.send(f"```\n{output}\n```")

table 1

You can choose from many alternate styles.

from table2ascii import table2ascii as t2a, PresetStyle

# In your command:
output = t2a(
    header=["Rank", "Team", "Kills", "Position Pts", "Total"],
    body=[[1, 'Team A', 2, 4, 6], [2, 'Team B', 3, 3, 6], [3, 'Team C', 4, 2, 6]],
    first_col_heading=True
)

await ctx.send(f"```\n{output}\n```")

enter image description here

Ok, there is a way to do that, however, you won't be able to use the name of the field as a team name! This image shows how it will look like!

@bot.command(name = 'test')
async def test(context: commands.Context):
    # Example dataset here! 
    DATASET = (
        # Rank, team, kills, positions, totals ... 
        (1, 'A', 2, 4, 6),
        (2, 'B', 3, 3, 6),
        (3, 'C', 4, 2, 6)
    ) # Assumes we have sorted this! 
    s = ['Rank     Team   Kills   PosPts.  Total']
    # This needs to be adjusted based on expected range of values or   calculated dynamically
    for data in DATASET:
        s.append('   '.join([str(item).center(5, ' ') for item in data]))
        # Joining up scores into a line
    d = '```'+'\n'.join(s) + '```'
    # Joining all lines togethor! 
    embed = discord.Embed(title = 'Quotient Results', description = d)
    await context.send(embed = embed)

That should do as expected.

Related