# Leaderboard

> How to create a leaderboard message

In this tutorial, you'll learn how to make a slash command that displays a leaderboard!

> This tutorial assumes you know the basics of inventor.bot- we recommend doing the [Ping Command](https://inventor.bot/docs/tutorials/ping-command) tutorial if you haven't already.

We'll assume you already have a database you want to make a leaderboard for. It could be xp, points, economy, etc., as long as it has a number column (make sure it's the `number` type!) and a column with a user ID!

![leaderboard 1 db setup](https://docs.inventorassets.com/3c91513e-82bb-4d65-b6c3-96e74dfd9f27.png)

Add a local variable called `content`. You can access the local variable menu from the three-dot menu by the component's name.

![leaderboard 2 local vars](https://docs.inventorassets.com/fd4545b5-3ef0-4490-8199-3b85ccd7b76f.png)

Add a **Database Lookup (Iterator)** block.  Give it a limit of 10 (or anything else as long as you don't hit the message character limit!). Sort by the number column, (`points`, `xp`, `money`, etc.)

![leaderboard 3 iterator](https://docs.inventorassets.com/9dde6bcb-562c-4314-909a-bca4c78dc60b.png)

**Iteration Number** starts starts at 0, so we need to add 1 to it.

![leaderboard 4 math](https://docs.inventorassets.com/a6ab8988-09d6-4ea3-a94c-7eccb029fccd.png)

Add an **Update Local Variable** block to the iterator and add variables to compose what each row will look like. In this case, rows will look like "1. @user - 12345"

![leaderboard 5 append](https://docs.inventorassets.com/2aa230e9-1130-4180-b5f7-7f0208b04e2e.png)

The `content` local variable now contains the leaderboard! You can send it however you'd like. In this example, we'll send it as an ephemeral reply to the user.

![leaderboard 6 send](https://docs.inventorassets.com/ed0c3d4a-01c6-468a-b8c2-a36db9955cc1.png)

Make sure the command is published, then test it out!

![basic leaderboard result](https://docs.inventorassets.com/08f34558-0c99-4c8e-b15b-8dc23b7e2bcb.png)

You now have a basic leaderboard system. Here are some ideas for improvements you could make!

* You could change it to a public leaderboard that automatically updates
  * Change the trigger to Schedule and swap to a **Send or Edit Text Message** block.
  * Wait for it to trigger once and send the message, then copy the message ID and put it into the **Edit Message ID** field.
* Try using an Embed Message or Advanced Message for a fancier message!
* Let the user control the **Offset** input of the Database Lookup (Iterator) block with a slash command option!
  * If you do this, make sure to handle cases where the user's offset returns no rows!
* Add nicer number formatting with the **Format Number** block

### Adding Pagination

If you want paginated leaderboard messages, you can follow this guide instead:

Since we need to reuse logic in two components, we'll make a custom block. It'll need an `offset` input.

![paginated leaderboard 01](https://docs.inventorassets.com/b9453c95-2c14-4fe8-9ec9-b622feddf541.png)

Now lets add a **Database Lookup (Iterator)** block with a **Sort By** and the **Offset** from the trigger. We'll also set the **Limit** to the number of rows you want per page **plus one**.

![paginated leaderboard 02](https://docs.inventorassets.com/e132d3f3-628d-4390-8e2c-e67d3cca93c5.png)

We need to add a few local variables- `content` and `hasNext`. Both should have a blank default value.

![paginated leaderboard 03](https://docs.inventorassets.com/1f4d16c9-6f56-4b71-8f4e-89ee12c969da.png)
We'll add an **If Statement** that checks if this is the extra row that we don't need.
![paginated leaderboard 04](https://docs.inventorassets.com/9cf72413-c6d1-4a8f-95aa-166e13271343.png)

If it is that extra row, we'll use **Update Local Variable** to set `hasNext` to true.

> ##### Why do we track `hasNext`?
>
> We want to disable the Next button if there aren't any more rows, so even though we only display 10 rows, we ask the database for 11. If it returns 11, we know that there's at least one more row that we can display on the next page, so we can enable the Next button. If it returns 10 or less, we leave it disabled since there aren't any more rows.

![paginated leaderboard 05](https://docs.inventorassets.com/7de9c78f-bfe3-456c-baef-71b45aa0b021.png)

If it's not the last row, we need to figure out what place this row is in. We'll add the offset and the current **Iteration Number**.

![paginated leaderboard 06](https://docs.inventorassets.com/dccbe0aa-e6e5-4dc7-884f-bf6cb18ccafb.png)

We also need to add one more, since **Iteration Number** starts counting at `0` (but we want the leaderboard to start at `1`!)

![paginated leaderboard 07](https://docs.inventorassets.com/69b0e912-3877-4c5b-b8a1-3c7f5a6798d8.png)

Now we'll update the `content` variable to add the row. Make sure to use the variable from the last **Math Operations** block!

![paginated leaderboard 08](https://docs.inventorassets.com/76d6d1d9-007a-40f3-b944-f08a01ce8907.png)

Great, that's the leaderboard content finished! Let's add a **Respond to Interaction with Advanced Message** block. **Update Original Message** and **Ephemeral** should both be true!

![paginated leaderboard 09](https://docs.inventorassets.com/e9a6227c-6f0d-48ba-84e9-302f0ea53338.png)

We'll add a **Message Container**, then **Text** inside of it. That'll be our `content` variable.

![paginated leaderboard 10](https://docs.inventorassets.com/9edeff3b-ef93-4565-94d8-a582b315c786.png)

Now we'll add an **Action Row** with an **If Statement** inside. We'll check if the offset doesn't equal `0`.

![paginated leaderboard 11](https://docs.inventorassets.com/14ab5e11-c225-4709-a5f5-78eee8118e9e.png)

In **If True**, we'll subtract the number of rows per page from the current offset to figure out the offset of the previous page.

![paginated leaderboard 12](https://docs.inventorassets.com/ec18388b-a1a3-4209-b3ea-4dcfeb13c288.png)

Now add the button:

![paginated leaderboard 13](https://docs.inventorassets.com/2b83d083-8366-4f4b-9f72-c1992f4dcb1c.png)

Now we'll add the disabled button. It still needs an ID, so we'll put in something random. Make sure to mark it as **Disabled**! If you want the buttons to disappear when they're disabled, you can skip this.

![paginated leaderboard 14](https://docs.inventorassets.com/19029e18-def4-4375-b1c9-d08f2aa8dcc7.png)

Now we'll do something similar for the Next button. Add another **If Statement**, this time checking if `hasNext` is true.

![paginated leaderboard 15](https://docs.inventorassets.com/50b6c71b-a966-4e6f-a1be-8789eee5ba22.png)

**If True**, we'll find the next page's offset by adding 10 to the current offset.

![paginated leaderboard 16](https://docs.inventorassets.com/247a4407-a076-49e5-98de-954feac33f29.png)

Now add the button:

![paginated leaderboard 17](https://docs.inventorassets.com/399503fa-af57-4152-8c27-a758e80195dd.png)

Now we'll add the disabled button. It still needs an ID, so we'll put in something random. Make sure to mark it as **Disabled**! If you want the buttons to disappear when they're disabled, you can skip this.

![paginated leaderboard 18](https://docs.inventorassets.com/ebb83a5e-1b5f-4535-a3ea-2be3187eb84c.png)

Save and publish that custom block, we're done with it!

Now let's use the block in two components. This first component will be a slash command that triggers the leaderboard. Add **Call Custom Block** and select the one we just made. Set offset to `0`

![paginated leaderboard 19](https://docs.inventorassets.com/5b19b25c-ad41-4b3a-8722-09ad36e4407c.png)

Now we'll make a **Button Click** flow. The **Custom ID** will be `leaderboard_*`

![paginated leaderboard 20](https://docs.inventorassets.com/f5531135-5ed5-43f6-b326-2513337c281b.png)

And now we'll call the custom block. The offset is the **Wildcard Value** output from the trigger.

![paginated leaderboard 21](https://docs.inventorassets.com/a2c71614-1146-4a90-bed2-f46535e728ea.png)

That's it! Make sure both of the new flows are published, then give it a go! You should be able to flip through all the pages (and not go out of bounds!)

![paginated leaderboard result](https://docs.inventorassets.com/9b0e884c-78ac-4767-9b58-e8285ad997b2.png)
