Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leaderboard #156

Merged
merged 8 commits into from
Jun 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions assets/emoji-maps/leaderboardEmojis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const leaderboardEmojis = {
1: "<:1:1169034779379896361>",
2: "<:2:1169034779933540375>",
3: "<:3:1169034781665788004>",
4: "<:4:1169034782471114862>",
5: "<:5:1169034783263838219>",
6: "<:6:1169034784069124180>",
7: "<:7:1169034785373560852>",
8: "<:8:1169034934195863562>",
9: "<:9:1169034935789699082>",
10: "<:10:1169034786875130008>"
}

export default leaderboardEmojis;
130 changes: 130 additions & 0 deletions lame-bot/commands/leaderboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { CommandInteraction, GuildMember, SlashCommandBuilder } from "discord.js";
import leaderboardEmojis from "../../assets/emoji-maps/leaderboardEmojis";
import { getDefaultGameGuild, getLeaderboard } from "../../src/database/db";
import { formatNumber, getCleanName } from "../../src/utils";
import { getGuild } from "../src/client";
import { getRemarkEmoji } from "../../src/emoji-renderer";

export const data = new SlashCommandBuilder()
.setName("leaderboard")
.setDescription("View the Word Bomb Mini leaderboard!")
.addIntegerOption((option) =>
option
.setName("page")
// no page should be treated as the users page but whats a good way to convey that?
.setDescription(
"The page of the leaderboard to view (default is Your Page)"
)
// leaderboard is ever changing so we cant know a exact value
// should default to last page if index is out of bounds
.setMaxValue(9999)
.setMinValue(1)
.setRequired(false)
);

export const cooldown = 5 * 1000;
export const broadcastable = true;

async function getDisplayName(userID: string) {
return await (await getDefaultGameGuild()).members
.fetch(userID)
.then((member: GuildMember) => {
return getCleanName(member.displayName ?? member.user.displayName);
})
.catch(() => {
return "Lame Guest";
});
}

async function buildLeaderboardMessage(page: any[], startNum: number, cmdUserID: string) {
let message = `### ${getRemarkEmoji("bomb")} All-Time Score`;
let names = await Promise.all(
page.map(async (page) => {
return await getDisplayName(page.user);
})
);

for (let i = 0; i < page.length; i++) {
let user = page[i];
let name = names[i];
let placement = startNum + i;

if (cmdUserID === user.user) {
name = `<@${cmdUserID}>`;
}

if (placement <= 10) {
message += `\n${leaderboardEmojis[placement]} ${name} • **${formatNumber(user.score)} points**`;
} else {
message += `\n${placement}. ${name} • **${formatNumber(user.score)} points**`;
}
}

return message;
}

export async function execute(interaction: CommandInteraction, preferBroadcast: boolean) {
let page = interaction.options.get("page");
let message;
let leaderboard = await getLeaderboard(null);

if (!page) {
let user = interaction.user.id;
// im hoping this isnt Mega Slow but honestly its probably fine
let userIndex = leaderboard.findIndex((page) => page.user === user);

// Rust would make this So Much Cooler
if (userIndex === -1) {
message = await buildLeaderboardMessage(
leaderboard.slice(0, 10),
1,
interaction.user.id
);
return;
} else {
let startnum = userIndex - 5;
if (userIndex + 1 >= leaderboard.length - 10) {
startnum = leaderboard.length - 10;
}

// Old code for showing the full Page the user is on
// pagenum = Math.floor(userIndex / 10) + 1;
// message = await buildLeaderboardMessage(leaderboard.slice((pagenum - 1) * 10, pagenum * 10), (pagenum - 1) * 10)

// show the placement of the user, but keep them in the middle of the page
// (its 10 so it cant be exactly in the middle, overscores said this works fine)
message = await buildLeaderboardMessage(
leaderboard.slice(startnum, startnum + 10),
startnum + 1,
interaction.user.id
);
}
} else {
let pagenum: number = page.value as number;
let totalNumOfPages = Math.ceil(leaderboard.length / 10);
let startnum: number;

if (pagenum >= totalNumOfPages) {
let itemsOnLastPage = leaderboard.length % 10;
let itemsNeeded = 10 - itemsOnLastPage;
startnum = Math.max(
leaderboard.length - itemsOnLastPage - itemsNeeded,
0
);
} else {
startnum = (pagenum - 1) * 10;
}

let endnum = Math.min(startnum + 10, leaderboard.length);
message = await buildLeaderboardMessage(
leaderboard.slice(startnum, endnum),
startnum + 1,
interaction.user.id
);
}

await interaction.reply({
content: message,
ephemeral: !preferBroadcast
});
}
14 changes: 1 addition & 13 deletions lame-bot/src/word-bomb-mini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
} from "../../src/dictionary/dictionary";
import { getRemarkEmoji, getStreakNumbers } from "../../src/emoji-renderer";
import { convertTextToHighlights, escapeRegExp, getPromptRegexDisplayText, getPromptRepeatableText } from "../../src/regex";
import { createEnglishList, escapeDiscordMarkdown, formatNumber, formatPercentage, formatPlacement } from "../../src/utils";
import { createEnglishList, escapeDiscordMarkdown, formatNumber, formatPercentage, formatPlacement, getCleanName } from "../../src/utils";
import { getChannel, getGuild, lameBotClient, sendMessage, sendMessageAsReply } from "./client";

let guild;
Expand Down Expand Up @@ -163,18 +163,6 @@ async function startRound() {
await startRound();
})();

function getCleanName(name) {
let cleanName = escapeDiscordMarkdown(name.replace(/﷽𒐫𒈙⸻꧅ဪ௵௸/g, ""));
if (cleanName === "") {
if (name.length === 0) {
return "Lame Member";
} else {
return "\\" + name[0];
}
}
return cleanName;
}

async function getDisplayName(userID) {
return await guild.members
.fetch(userID)
Expand Down
4 changes: 4 additions & 0 deletions src/command-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,10 @@ export async function replyToInteraction(interaction: CommandInteraction, header
* @param broadcast Whether or not this interaction is being broadcasted.
*/
export async function editInteractionReply(interaction: CommandInteraction, header: string, response: string, broadcast: boolean) {
if (!interaction.replied) {
return;
}

await interaction.editReply({
content: getInteractionContent(interaction, header, response, broadcast),
});
Expand Down
29 changes: 29 additions & 0 deletions src/database/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,32 @@ export async function getCurrentRoundInfo() {

return { lastWinner, streak };
}

// export async function getLeaderboardSection(id, startIndex: number, endIndex: number) {
// let leaderboardID = id ?? await getAllTimeLeaderboardID();

// let limit = endIndex ? endIndex - startIndex : 0;

// let leaderboard = await client
// .db(dbName)
// .collection("rankings")
// .find({ leaderboardID })
// .sort({ score: -1 })
// .skip(startIndex)
// .limit(limit)
// .toArray();

// return leaderboard;
// }

export async function getLeaderboard(id) {
let leaderboardID = id ?? await getAllTimeLeaderboardID();

let leaderboard = await client
.db(dbName)
.collection("rankings")
.find({ leaderboardID })
.sort({ score: -1 })
.toArray();
return leaderboard;
}
2 changes: 1 addition & 1 deletion src/regex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function trimArrows(string: string): string {
return string.replace(/^<|>$/g, "");
}

const invalidPromptSearchRegex = /[^A-Z0-9'\-@.? ]/;
const invalidPromptSearchRegex = /[^A-Z0-9'\-@.? ]/i;

/**
* A regular expression used to determine if a search is regex or not.
Expand Down
13 changes: 13 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ export function escapeDiscordMarkdown(string: string): string {
.replace(/[\\_~\*\|:#@><-]/g, "\\$&");
}

// TODO: write documentation for this
export function getCleanName(name: string) {
let cleanName = escapeDiscordMarkdown(name.replace(/﷽𒐫𒈙⸻꧅ဪ௵௸/g, ""));
if (cleanName === "") {
if (name.length === 0) {
return "Lame Member";
} else {
return "\\" + name[0];
}
}
return cleanName;
}

/**
* A collection of sorting functions for strings.
*/
Expand Down