about summary refs log tree commit diff
path: root/src/command/leaderboard.rs
blob: 97971f59a8f2433d4823313ab82e4d7d3bb2febb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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()
		}
	}
}