mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-18 16:28:55 +00:00
osu: Implement map length on server ranks
This commit is contained in:
parent
a50f44ad90
commit
11f32ccf04
12 changed files with 229 additions and 71 deletions
|
@ -15,6 +15,15 @@ All PRs welcome.
|
||||||
- `youmubot-core`: Core commands: admin, fun, community
|
- `youmubot-core`: Core commands: admin, fun, community
|
||||||
- `youmubot-osu`: osu!-related commands.
|
- `youmubot-osu`: osu!-related commands.
|
||||||
|
|
||||||
|
## Working with `sqlx`
|
||||||
|
|
||||||
|
### Regenerate compiler information
|
||||||
|
|
||||||
|
From within `./youmubot-db-sql` run
|
||||||
|
```bash
|
||||||
|
cargo sqlx prepare --database-url "sqlite:$(realpath ..)/youmubot.db"
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Basically MIT.
|
Basically MIT.
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "INSERT\n INTO osu_users(user_id, username, id, last_update, pp_std, pp_taiko, pp_mania, pp_catch, failures)\n VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (user_id) WHERE id = ? DO UPDATE\n SET\n last_update = excluded.last_update,\n username = excluded.username,\n pp_std = excluded.pp_std,\n pp_taiko = excluded.pp_taiko,\n pp_mania = excluded.pp_mania,\n pp_catch = excluded.pp_catch,\n failures = excluded.failures\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 10
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "26a910506c0613936be169df13320dfd7f9d3df62a35ba63c61efc5de70e750d"
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"db_name": "SQLite",
|
||||||
"query": "SELECT\n user_id as \"user_id: i64\",\n username,\n id as \"id: i64\",\n last_update as \"last_update: DateTime\",\n pp_std, pp_taiko, pp_mania, pp_catch,\n failures as \"failures: u8\"\n FROM osu_users",
|
"query": "SELECT\n user_id as \"user_id: i64\",\n username,\n id as \"id: i64\",\n last_update as \"last_update: DateTime\",\n pp_std, pp_taiko, pp_mania, pp_catch,\n failures as \"failures: u8\",\n std_weighted_map_length\n FROM osu_users",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,11 @@
|
||||||
"name": "failures: u8",
|
"name": "failures: u8",
|
||||||
"ordinal": 8,
|
"ordinal": 8,
|
||||||
"type_info": "Int64"
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "std_weighted_map_length",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Float"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -61,8 +66,9 @@
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false
|
false,
|
||||||
|
true
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "5753fe315c9a55154d2d80e6d293dc8abffcf426b845624a42cd0bfefc75fb74"
|
"hash": "6ef67ca385287a4cef9fdd47bf4258ec9de4802d90dbb2ab48de32c1a4ada601"
|
||||||
}
|
}
|
12
youmubot-db-sql/.sqlx/query-a06efa1b12c2c7c9cf5b83bff796c0e59d61596cb609c4bb952edc2d64cec868.json
generated
Normal file
12
youmubot-db-sql/.sqlx/query-a06efa1b12c2c7c9cf5b83bff796c0e59d61596cb609c4bb952edc2d64cec868.json
generated
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "INSERT\n INTO osu_users(user_id, username, id, last_update, pp_std, pp_taiko, pp_mania, pp_catch, failures, std_weighted_map_length)\n VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (user_id) WHERE id = ? DO UPDATE\n SET\n last_update = excluded.last_update,\n username = excluded.username,\n pp_std = excluded.pp_std,\n pp_taiko = excluded.pp_taiko,\n pp_mania = excluded.pp_mania,\n pp_catch = excluded.pp_catch,\n failures = excluded.failures,\n std_weighted_map_length = excluded.std_weighted_map_length\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 11
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "a06efa1b12c2c7c9cf5b83bff796c0e59d61596cb609c4bb952edc2d64cec868"
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"db_name": "SQLite",
|
||||||
"query": "SELECT\n user_id as \"user_id: i64\",\n username,\n id as \"id: i64\",\n last_update as \"last_update: DateTime\",\n pp_std, pp_taiko, pp_mania, pp_catch,\n failures as \"failures: u8\"\n FROM osu_users WHERE id = ?",
|
"query": "SELECT\n user_id as \"user_id: i64\",\n username,\n id as \"id: i64\",\n last_update as \"last_update: DateTime\",\n pp_std, pp_taiko, pp_mania, pp_catch,\n failures as \"failures: u8\",\n std_weighted_map_length\n FROM osu_users WHERE id = ?",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,11 @@
|
||||||
"name": "failures: u8",
|
"name": "failures: u8",
|
||||||
"ordinal": 8,
|
"ordinal": 8,
|
||||||
"type_info": "Int64"
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "std_weighted_map_length",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Float"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -61,8 +66,9 @@
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false
|
false,
|
||||||
|
true
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "08f2568a69a14ae240a24264238d4abc7aea5eee67d6062d049f0d37031e4d7a"
|
"hash": "b098282e73cc6fd435330f6ecd446b1a1cd2aeb89517b7ee09e7e6f8d6e0cd79"
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"db_name": "SQLite",
|
||||||
"query": "SELECT\n user_id as \"user_id: i64\",\n username,\n id as \"id: i64\",\n last_update as \"last_update: DateTime\",\n pp_std, pp_taiko, pp_mania, pp_catch,\n failures as \"failures: u8\"\n FROM osu_users WHERE user_id = ?",
|
"query": "SELECT\n user_id as \"user_id: i64\",\n username,\n id as \"id: i64\",\n last_update as \"last_update: DateTime\",\n pp_std, pp_taiko, pp_mania, pp_catch,\n failures as \"failures: u8\",\n std_weighted_map_length\n FROM osu_users WHERE user_id = ?",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
|
@ -47,6 +47,11 @@
|
||||||
"name": "failures: u8",
|
"name": "failures: u8",
|
||||||
"ordinal": 8,
|
"ordinal": 8,
|
||||||
"type_info": "Int64"
|
"type_info": "Int64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "std_weighted_map_length",
|
||||||
|
"ordinal": 9,
|
||||||
|
"type_info": "Float"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"parameters": {
|
"parameters": {
|
||||||
|
@ -61,8 +66,9 @@
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
false
|
false,
|
||||||
|
true
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "700ec95294d9a4f21e3d7ff53f15f5dc739bffe8fedc19e35cbb576b6dd2e948"
|
"hash": "df0aa5065268e59c68990ab46ab4a90ec3137398e83b3d0c626209306804399a"
|
||||||
}
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- Add migration script here
|
||||||
|
|
||||||
|
ALTER TABLE osu_users
|
||||||
|
ADD COLUMN std_weighted_map_length DOUBLE NULL DEFAULT NULL;
|
||||||
|
|
|
@ -14,6 +14,8 @@ pub struct OsuUser {
|
||||||
pub pp_catch: Option<f64>,
|
pub pp_catch: Option<f64>,
|
||||||
/// Number of consecutive update failures
|
/// Number of consecutive update failures
|
||||||
pub failures: u8,
|
pub failures: u8,
|
||||||
|
|
||||||
|
pub std_weighted_map_length: Option<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OsuUser {
|
impl OsuUser {
|
||||||
|
@ -30,7 +32,8 @@ impl OsuUser {
|
||||||
id as "id: i64",
|
id as "id: i64",
|
||||||
last_update as "last_update: DateTime",
|
last_update as "last_update: DateTime",
|
||||||
pp_std, pp_taiko, pp_mania, pp_catch,
|
pp_std, pp_taiko, pp_mania, pp_catch,
|
||||||
failures as "failures: u8"
|
failures as "failures: u8",
|
||||||
|
std_weighted_map_length
|
||||||
FROM osu_users WHERE user_id = ?"#,
|
FROM osu_users WHERE user_id = ?"#,
|
||||||
user_id
|
user_id
|
||||||
)
|
)
|
||||||
|
@ -52,7 +55,8 @@ impl OsuUser {
|
||||||
id as "id: i64",
|
id as "id: i64",
|
||||||
last_update as "last_update: DateTime",
|
last_update as "last_update: DateTime",
|
||||||
pp_std, pp_taiko, pp_mania, pp_catch,
|
pp_std, pp_taiko, pp_mania, pp_catch,
|
||||||
failures as "failures: u8"
|
failures as "failures: u8",
|
||||||
|
std_weighted_map_length
|
||||||
FROM osu_users WHERE id = ?"#,
|
FROM osu_users WHERE id = ?"#,
|
||||||
osu_id
|
osu_id
|
||||||
)
|
)
|
||||||
|
@ -74,7 +78,8 @@ impl OsuUser {
|
||||||
id as "id: i64",
|
id as "id: i64",
|
||||||
last_update as "last_update: DateTime",
|
last_update as "last_update: DateTime",
|
||||||
pp_std, pp_taiko, pp_mania, pp_catch,
|
pp_std, pp_taiko, pp_mania, pp_catch,
|
||||||
failures as "failures: u8"
|
failures as "failures: u8",
|
||||||
|
std_weighted_map_length
|
||||||
FROM osu_users"#,
|
FROM osu_users"#,
|
||||||
)
|
)
|
||||||
.fetch_many(conn)
|
.fetch_many(conn)
|
||||||
|
@ -90,8 +95,8 @@ impl OsuUser {
|
||||||
{
|
{
|
||||||
query!(
|
query!(
|
||||||
r#"INSERT
|
r#"INSERT
|
||||||
INTO osu_users(user_id, username, id, last_update, pp_std, pp_taiko, pp_mania, pp_catch, failures)
|
INTO osu_users(user_id, username, id, last_update, pp_std, pp_taiko, pp_mania, pp_catch, failures, std_weighted_map_length)
|
||||||
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
ON CONFLICT (user_id) WHERE id = ? DO UPDATE
|
ON CONFLICT (user_id) WHERE id = ? DO UPDATE
|
||||||
SET
|
SET
|
||||||
last_update = excluded.last_update,
|
last_update = excluded.last_update,
|
||||||
|
@ -100,7 +105,8 @@ impl OsuUser {
|
||||||
pp_taiko = excluded.pp_taiko,
|
pp_taiko = excluded.pp_taiko,
|
||||||
pp_mania = excluded.pp_mania,
|
pp_mania = excluded.pp_mania,
|
||||||
pp_catch = excluded.pp_catch,
|
pp_catch = excluded.pp_catch,
|
||||||
failures = excluded.failures
|
failures = excluded.failures,
|
||||||
|
std_weighted_map_length = excluded.std_weighted_map_length
|
||||||
"#,
|
"#,
|
||||||
self.user_id,
|
self.user_id,
|
||||||
self.username,
|
self.username,
|
||||||
|
@ -111,7 +117,10 @@ impl OsuUser {
|
||||||
self.pp_mania,
|
self.pp_mania,
|
||||||
self.pp_catch,
|
self.pp_catch,
|
||||||
self.failures,
|
self.failures,
|
||||||
self.user_id).execute(conn).await?;
|
self.std_weighted_map_length,
|
||||||
|
|
||||||
|
self.user_id,
|
||||||
|
).execute(conn).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use super::db::{OsuSavedUsers, OsuUser};
|
use super::db::{OsuSavedUsers, OsuUser};
|
||||||
|
use super::OsuClient;
|
||||||
use super::{embeds::score_embed, BeatmapWithMode};
|
use super::{embeds::score_embed, BeatmapWithMode};
|
||||||
use crate::{
|
use crate::{
|
||||||
discord::beatmap_cache::BeatmapMetaCache,
|
discord::beatmap_cache::BeatmapMetaCache,
|
||||||
|
@ -19,6 +20,7 @@ use serenity::{
|
||||||
};
|
};
|
||||||
use std::{convert::TryInto, sync::Arc};
|
use std::{convert::TryInto, sync::Arc};
|
||||||
use youmubot_prelude::announcer::CacheAndHttp;
|
use youmubot_prelude::announcer::CacheAndHttp;
|
||||||
|
use youmubot_prelude::stream::{FuturesUnordered, TryStreamExt};
|
||||||
use youmubot_prelude::*;
|
use youmubot_prelude::*;
|
||||||
|
|
||||||
/// osu! announcer's unique announcer key.
|
/// osu! announcer's unique announcer key.
|
||||||
|
@ -83,7 +85,12 @@ impl youmubot_prelude::Announcer for Announcer {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
osu_user.username = v.into_iter().next().unwrap().username.into();
|
osu_user.username = v.into_iter().next().unwrap().username.into();
|
||||||
osu_user.last_update = now;
|
osu_user.last_update = now;
|
||||||
|
osu_user.std_weighted_map_length =
|
||||||
|
Self::std_weighted_map_length(&ctx, &osu_user)
|
||||||
|
.await
|
||||||
|
.pls_ok();
|
||||||
let id = osu_user.id;
|
let id = osu_user.id;
|
||||||
|
println!("{:?}", osu_user);
|
||||||
ctx.data
|
ctx.data
|
||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
|
@ -185,6 +192,31 @@ impl Announcer {
|
||||||
.collect();
|
.collect();
|
||||||
Ok(scores)
|
Ok(scores)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn std_weighted_map_length(ctx: &Context, u: &OsuUser) -> Result<f64> {
|
||||||
|
let data = ctx.data.read().await;
|
||||||
|
let client = data.get::<OsuClient>().unwrap().clone();
|
||||||
|
let cache = data.get::<BeatmapMetaCache>().unwrap();
|
||||||
|
let scores = client
|
||||||
|
.user_best(UserID::ID(u.id), |f| f.mode(Mode::Std).limit(100))
|
||||||
|
.await?;
|
||||||
|
scores
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, s)| async move {
|
||||||
|
let beatmap = cache.get_beatmap_default(s.beatmap_id).await?;
|
||||||
|
const SCALING_FACTOR: f64 = 0.975;
|
||||||
|
Ok(beatmap
|
||||||
|
.difficulty
|
||||||
|
.apply_mods(s.mods, 0.0 /* dont care */)
|
||||||
|
.drain_length
|
||||||
|
.as_secs_f64()
|
||||||
|
* (SCALING_FACTOR.powi(i as i32)))
|
||||||
|
})
|
||||||
|
.collect::<FuturesUnordered<_>>()
|
||||||
|
.try_fold(0.0, |a, b| future::ready(Ok(a + b)))
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -145,6 +145,7 @@ pub struct OsuUser {
|
||||||
pub id: u64,
|
pub id: u64,
|
||||||
pub last_update: DateTime<Utc>,
|
pub last_update: DateTime<Utc>,
|
||||||
pub pp: [Option<f64>; 4],
|
pub pp: [Option<f64>; 4],
|
||||||
|
pub std_weighted_map_length: Option<f64>,
|
||||||
/// More than 5 failures => gone
|
/// More than 5 failures => gone
|
||||||
pub failures: u8,
|
pub failures: u8,
|
||||||
}
|
}
|
||||||
|
@ -160,6 +161,7 @@ impl From<OsuUser> for model::OsuUser {
|
||||||
pp_taiko: u.pp[Mode::Taiko as usize],
|
pp_taiko: u.pp[Mode::Taiko as usize],
|
||||||
pp_catch: u.pp[Mode::Catch as usize],
|
pp_catch: u.pp[Mode::Catch as usize],
|
||||||
pp_mania: u.pp[Mode::Mania as usize],
|
pp_mania: u.pp[Mode::Mania as usize],
|
||||||
|
std_weighted_map_length: u.std_weighted_map_length,
|
||||||
failures: u.failures,
|
failures: u.failures,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,6 +180,7 @@ impl From<model::OsuUser> for OsuUser {
|
||||||
Mode::Catch => u.pp_catch,
|
Mode::Catch => u.pp_catch,
|
||||||
Mode::Mania => u.pp_mania,
|
Mode::Mania => u.pp_mania,
|
||||||
}),
|
}),
|
||||||
|
std_weighted_map_length: u.std_weighted_map_length,
|
||||||
failures: u.failures,
|
failures: u.failures,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -326,6 +326,7 @@ async fn add_user(
|
||||||
failures: 0,
|
failures: 0,
|
||||||
last_update: chrono::Utc::now(),
|
last_update: chrono::Utc::now(),
|
||||||
pp: [None, None, None, None],
|
pp: [None, None, None, None],
|
||||||
|
std_weighted_map_length: None,
|
||||||
};
|
};
|
||||||
data.get::<OsuSavedUsers>().unwrap().new_user(u).await?;
|
data.get::<OsuSavedUsers>().unwrap().new_user(u).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -36,6 +36,75 @@ impl FromStr for ModeOrTotal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
enum Align {
|
||||||
|
Left,
|
||||||
|
Middle,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Align {
|
||||||
|
fn pad(self, input: &str, len: usize) -> String {
|
||||||
|
match self {
|
||||||
|
Align::Left => format!("{:<len$}", input),
|
||||||
|
Align::Middle => format!("{:^len$}", input),
|
||||||
|
Align::Right => format!("{:>len$}", input),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn table_formatting<const N: usize, S: AsRef<str> + std::fmt::Debug, Ts: AsRef<[[S; N]]>>(
|
||||||
|
headers: &[&'static str; N],
|
||||||
|
padding: &[Align; N],
|
||||||
|
table: Ts,
|
||||||
|
) -> String {
|
||||||
|
let table = table.as_ref();
|
||||||
|
// get length for each column
|
||||||
|
let lens = headers
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, header)| {
|
||||||
|
table
|
||||||
|
.iter()
|
||||||
|
.map(|r| r.as_ref()[i].as_ref().len())
|
||||||
|
.max()
|
||||||
|
.unwrap_or(0)
|
||||||
|
.max(header.len())
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
// paint with message builder
|
||||||
|
let mut m = MessageBuilder::new();
|
||||||
|
m.push_line("```");
|
||||||
|
// headers first
|
||||||
|
for (i, header) in headers.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
m.push(" | ");
|
||||||
|
}
|
||||||
|
m.push(padding[i].pad(header, lens[i]));
|
||||||
|
}
|
||||||
|
m.push_line("");
|
||||||
|
// separator
|
||||||
|
m.push_line(format!(
|
||||||
|
"{:-<total$}",
|
||||||
|
"",
|
||||||
|
total = lens.iter().sum::<usize>() + (lens.len() - 1) * 3
|
||||||
|
));
|
||||||
|
// table itself
|
||||||
|
for row in table {
|
||||||
|
let row = row.as_ref();
|
||||||
|
for (i, cell) in row.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
m.push(" | ");
|
||||||
|
}
|
||||||
|
let cell = cell.as_ref();
|
||||||
|
m.push(padding[i].pad(cell, lens[i]));
|
||||||
|
}
|
||||||
|
m.push_line("");
|
||||||
|
}
|
||||||
|
m.push_line("```");
|
||||||
|
m.build()
|
||||||
|
}
|
||||||
|
|
||||||
#[command("ranks")]
|
#[command("ranks")]
|
||||||
#[description = "See the server's ranks"]
|
#[description = "See the server's ranks"]
|
||||||
#[usage = "[mode (Std, Taiko, Catch, Mania) = Std]"]
|
#[usage = "[mode (Std, Taiko, Catch, Mania) = Std]"]
|
||||||
|
@ -89,6 +158,7 @@ pub async fn server_rank(ctx: &Context, m: &Message, mut args: Args) -> CommandR
|
||||||
let last_update = last_update.unwrap();
|
let last_update = last_update.unwrap();
|
||||||
paginate_reply_fn(
|
paginate_reply_fn(
|
||||||
move |page: u8, ctx: &Context, m: &mut Message| {
|
move |page: u8, ctx: &Context, m: &mut Message| {
|
||||||
|
use Align::*;
|
||||||
const ITEMS_PER_PAGE: usize = 10;
|
const ITEMS_PER_PAGE: usize = 10;
|
||||||
let users = users.clone();
|
let users = users.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
@ -99,51 +169,62 @@ pub async fn server_rank(ctx: &Context, m: &Message, mut args: Args) -> CommandR
|
||||||
}
|
}
|
||||||
let total_len = users.len();
|
let total_len = users.len();
|
||||||
let users = &users[start..end];
|
let users = &users[start..end];
|
||||||
let username_len = users
|
let table = if matches!(mode, ModeOrTotal::Mode(Mode::Std)) {
|
||||||
.iter()
|
const HEADERS: [&'static str; 5] =
|
||||||
.map(|(_, (_, u))| u.username.len())
|
["#", "pp", "Map length", "Username", "Member"];
|
||||||
.max()
|
const ALIGNS: [Align; 5] = [Right, Right, Right, Left, Left];
|
||||||
.unwrap_or(8)
|
|
||||||
.max(8);
|
let table = users
|
||||||
let member_len = users
|
.iter()
|
||||||
.iter()
|
.enumerate()
|
||||||
.map(|(_, (mem, _))| mem.len())
|
.map(|(i, (pp, (mem, ou)))| {
|
||||||
.max()
|
let map_length = match ou.std_weighted_map_length {
|
||||||
.unwrap_or(8)
|
Some(len) => {
|
||||||
.max(8);
|
let trunc_secs = len.floor() as u64;
|
||||||
let mut content = MessageBuilder::new();
|
let minutes = trunc_secs / 60;
|
||||||
content
|
let seconds = len - (60 * minutes) as f64;
|
||||||
.push_line("```")
|
format!("{}m{:02.2}s", minutes, seconds)
|
||||||
|
}
|
||||||
|
None => "unknown".to_owned(),
|
||||||
|
};
|
||||||
|
[
|
||||||
|
format!("{}", 1 + i + start),
|
||||||
|
format!("{:.2}", pp),
|
||||||
|
map_length,
|
||||||
|
ou.username.clone().into_owned(),
|
||||||
|
mem.clone(),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
table_formatting(&HEADERS, &ALIGNS, table)
|
||||||
|
} else {
|
||||||
|
const HEADERS: [&'static str; 4] = ["#", "pp", "Username", "Member"];
|
||||||
|
const ALIGNS: [Align; 4] = [Right, Right, Left, Left];
|
||||||
|
|
||||||
|
let table = users
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, (pp, (mem, ou)))| {
|
||||||
|
[
|
||||||
|
format!("{}", 1 + i + start),
|
||||||
|
format!("{:.2}", pp),
|
||||||
|
ou.username.clone().into_owned(),
|
||||||
|
mem.clone(),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
table_formatting(&HEADERS, &ALIGNS, table)
|
||||||
|
};
|
||||||
|
let content = MessageBuilder::new()
|
||||||
|
.push_line(table)
|
||||||
.push_line(format!(
|
.push_line(format!(
|
||||||
"Rank | pp | {:uw$} | Member",
|
"Page **{}**/**{}**. Last updated: {}",
|
||||||
"Username",
|
page + 1,
|
||||||
uw = username_len
|
(total_len + ITEMS_PER_PAGE - 1) / ITEMS_PER_PAGE,
|
||||||
|
last_update.format("<t:%s:R>"),
|
||||||
))
|
))
|
||||||
.push_line(format!(
|
.build();
|
||||||
"------------------{:-<uw$}---{:-<mw$}",
|
m.edit(ctx, EditMessage::new().content(content)).await?;
|
||||||
"",
|
|
||||||
"",
|
|
||||||
uw = username_len,
|
|
||||||
mw = member_len
|
|
||||||
));
|
|
||||||
for (id, (pp, (member, u))) in users.iter().enumerate() {
|
|
||||||
content.push_line(format!(
|
|
||||||
"{:>4} | {:>8.2} | {:uw$} | {}",
|
|
||||||
format!("#{}", 1 + id + start),
|
|
||||||
pp,
|
|
||||||
u.username,
|
|
||||||
member,
|
|
||||||
uw = username_len
|
|
||||||
));
|
|
||||||
}
|
|
||||||
content.push_line("```").push_line(format!(
|
|
||||||
"Page **{}**/**{}**. Last updated: {}",
|
|
||||||
page + 1,
|
|
||||||
(total_len + ITEMS_PER_PAGE - 1) / ITEMS_PER_PAGE,
|
|
||||||
last_update.format("<t:%s:R>"),
|
|
||||||
));
|
|
||||||
m.edit(ctx, EditMessage::new().content(content.to_string()))
|
|
||||||
.await?;
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue