diff options
Diffstat (limited to 'src/command/leaderboard.rs')
-rw-r--r-- | src/command/leaderboard.rs | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/command/leaderboard.rs b/src/command/leaderboard.rs new file mode 100644 index 0000000..97971f5 --- /dev/null +++ b/src/command/leaderboard.rs @@ -0,0 +1,91 @@ +use std::sync::Arc; + +use twilight_model::{ + application::interaction::application_command::{CommandData, CommandOptionValue}, + http::interaction::InteractionResponseData, + id::{Id, marker::GuildMarker}, +}; +use twilight_util::builder::{InteractionResponseDataBuilder, embed::EmbedBuilder}; + +use crate::{brain::Brain, database::Error as DbError, fail, util}; + +enum Style { + TiesEqual, + TiesBroken, +} + +pub fn 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.") + } + Err(DbError::UserNotExist) => unreachable!(), + Ok(data) => { + let placed = util::tiebreak_shared_positions(data); + + 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, placement.row.user_id, placement.row.points + ) + }) + .collect::<Vec<String>>() + .join("\n"), + }; + + let embed = EmbedBuilder::new().description(str).build(); + InteractionResponseDataBuilder::new() + .embeds([embed]) + .build() + } + } +} |