about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2025-08-03 21:28:27 -0500
committergennyble <gen@nyble.dev>2025-08-03 21:28:27 -0500
commit61927e384d5fc07c7094d0cdf77b8c246d456a63 (patch)
treee46142748b2f8a548043c1c1019ef7a439932b12
parent53e34df1ba9ff24708339ae1253ca86ab910771a (diff)
downloadleaberblord-61927e384d5fc07c7094d0cdf77b8c246d456a63.tar.gz
leaberblord-61927e384d5fc07c7094d0cdf77b8c246d456a63.zip
allow changing leaderboard display style
-rw-r--r--src/import/mod.rs2
-rw-r--r--src/main.rs84
2 files changed, 67 insertions, 19 deletions
diff --git a/src/import/mod.rs b/src/import/mod.rs
index fb14319..f1f2406 100644
--- a/src/import/mod.rs
+++ b/src/import/mod.rs
@@ -108,7 +108,7 @@ pub mod emboard_direct {
 				let body: String = resp.body_mut().read_to_string().unwrap();
 				super::import(&brain.db, body);
 
-				let embed = crate::get_leaderboard(brain.clone(), guild_id)
+				let embed = crate::get_leaderboard(brain.clone(), guild_id, None)
 					.embeds
 					.unwrap()[0]
 					.clone();
diff --git a/src/main.rs b/src/main.rs
index 73007e3..e7de9d5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,4 @@
-use std::{env, error::Error, path::PathBuf, sync::Arc};
+use std::{env, error::Error, ops::Deref, path::PathBuf, sync::Arc};
 
 use brain::Brain;
 use confindent::Confindent;
@@ -35,7 +35,7 @@ mod util;
 const PROD_APP_ID: u64 = 1363055126264283136;
 #[allow(dead_code)]
 const DEV_APP_ID: u64 = 1363494986699771984;
-const APP_ID: u64 = PROD_APP_ID;
+const APP_ID: u64 = DEV_APP_ID;
 
 macro_rules! bail {
 	($msg:expr) => {
@@ -198,6 +198,10 @@ async fn commands() -> Vec<Command> {
 		"View the server leaderboard",
 		CommandType::ChatInput,
 	)
+	.option(
+		StringBuilder::new("style", "style of leaderboard to display")
+			.choices([("Ties Equal", "equal"), ("Ties Broken", "broken")]),
+	)
 	.build();
 
 	let points = CommandBuilder::new("points", "Add and remove points!", CommandType::ChatInput)
@@ -244,7 +248,7 @@ async fn command_handler(
 	// Handle the command and create our interaction response data
 	let data = match command {
 		Commands::About => about(brain.clone(), guild),
-		Commands::Leaderboard => get_leaderboard(brain.clone(), guild),
+		Commands::Leaderboard => get_leaderboard(brain.clone(), guild, Some(command_data)),
 		Commands::Points => add_points(brain.clone(), guild, create, command_data).await,
 		Commands::Permission => permission(brain.clone(), guild, create, command_data).await,
 		Commands::Import => {
@@ -271,9 +275,39 @@ fn about(_brain: Arc<Brain>, _guild: Id<GuildMarker>) -> InteractionResponseData
 		.build()
 }
 
-fn get_leaderboard(brain: Arc<Brain>, guild: Id<GuildMarker>) -> InteractionResponseData {
+enum Style {
+	TiesEqual,
+	TiesBroken,
+}
+
+fn get_leaderboard(
+	brain: Arc<Brain>,
+	guild: Id<GuildMarker>,
+	data: Option<&CommandData>,
+) -> InteractionResponseData {
 	let board = brain.db.get_leaderboard(guild.get());
 
+	let mut style = Style::TiesBroken;
+	if let Some(data) = data {
+		for opt in &data.options {
+			match opt.name.as_str() {
+				"style" => match &opt.value {
+					CommandOptionValue::String(raw) => match raw.as_str() {
+						"equal" => style = Style::TiesEqual,
+						"broken" => style = Style::TiesBroken,
+						_ => {
+							return fail!(format!(
+								"{raw} is not a valid style option. Try 'equal' or 'broken'"
+							));
+						}
+					},
+					_ => unreachable!(),
+				},
+				_ => unreachable!(),
+			}
+		}
+	}
+
 	match board {
 		Err(DbError::TableNotExist) => {
 			fail!("No leaderboard exists for this server! Create one by giving someone points.")
@@ -282,23 +316,37 @@ fn get_leaderboard(brain: Arc<Brain>, guild: Id<GuildMarker>) -> InteractionResp
 		Ok(data) => {
 			let placed = util::tiebreak_shared_positions(data);
 
-			let str = placed
-				.into_iter()
-				.map(|placement| {
-					if placement.placement_first_of_tie {
+			let str = match style {
+				Style::TiesEqual => placed
+					.into_iter()
+					.map(|placement| {
+						if placement.placement_first_of_tie {
+							format!(
+								"`{:>2}` <@{}>: {}",
+								placement.placement_tie,
+								placement.row.user_id,
+								placement.row.points
+							)
+						} else {
+							format!(
+								"`  ` <@{}>: {}",
+								placement.row.user_id, placement.row.points
+							)
+						}
+					})
+					.collect::<Vec<String>>()
+					.join("\n"),
+				Style::TiesBroken => placed
+					.into_iter()
+					.map(|placement| {
 						format!(
 							"`{:>2}` <@{}>: {}",
-							placement.placement_tie, placement.row.user_id, placement.row.points
+							placement.placement, placement.row.user_id, placement.row.points
 						)
-					} else {
-						format!(
-							"`  ` <@{}>: {}",
-							placement.row.user_id, placement.row.points
-						)
-					}
-				})
-				.collect::<Vec<String>>()
-				.join("\n");
+					})
+					.collect::<Vec<String>>()
+					.join("\n"),
+			};
 
 			let embed = EmbedBuilder::new().description(str).build();
 			InteractionResponseDataBuilder::new()