Improve cf live commands

This commit is contained in:
Natsu Kagami 2021-02-10 16:32:28 +09:00 committed by Natsu Kagami
parent 537e396140
commit e0c11a09fb
2 changed files with 39 additions and 53 deletions

View file

@ -4,7 +4,7 @@ use serenity::{
macros::{command, group}, macros::{command, group},
Args, CommandResult, Args, CommandResult,
}, },
model::channel::Message, model::{channel::Message, guild::Member},
utils::MessageBuilder, utils::MessageBuilder,
}; };
use std::{collections::HashMap, sync::Arc, time::Duration}; use std::{collections::HashMap, sync::Arc, time::Duration};
@ -293,18 +293,43 @@ pub async fn contestranks(ctx: &Context, m: &Message, mut args: Args) -> Command
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
contest_rank_table(ctx, m, contest, problems, ranks).await?;
Ok(())
}
#[command]
#[description = "Watch a contest and announce any change on the members of the server assigned to the contest."]
#[usage = "[the contest id]"]
#[num_args(1)]
#[required_permissions(MANAGE_CHANNELS)]
#[only_in(guilds)]
pub async fn watch(ctx: &Context, m: &Message, mut args: Args) -> CommandResult {
let contest_id: u64 = args.single()?;
live::watch_contest(ctx, m.guild_id.unwrap(), m.channel_id, contest_id).await?;
Ok(())
}
pub(crate) async fn contest_rank_table(
ctx: &Context,
reply_to: &Message,
contest: Contest,
problems: Vec<codeforces::Problem>,
ranks: Vec<(Member, String, codeforces::RanklistRow)>,
) -> Result<()> {
const ITEMS_PER_PAGE: usize = 10;
let total_pages = (ranks.len() + ITEMS_PER_PAGE - 1) / ITEMS_PER_PAGE;
if ranks.is_empty() { if ranks.is_empty() {
m.reply(&ctx, "No one in this server participated in the contest...") reply_to
.reply(&ctx, "No one in this server participated in the contest...")
.await?; .await?;
return Ok(()); return Ok(());
} }
let ranks = Arc::new(ranks); let ranks = Arc::new(ranks);
const ITEMS_PER_PAGE: usize = 10;
let total_pages = (ranks.len() + ITEMS_PER_PAGE - 1) / ITEMS_PER_PAGE;
paginate_reply_fn( paginate_reply_fn(
move |page, ctx, msg| { move |page, ctx, msg| {
let contest = contest.clone(); let contest = contest.clone();
@ -395,23 +420,8 @@ pub async fn contestranks(ctx: &Context, m: &Message, mut args: Args) -> Command
}) })
}, },
ctx, ctx,
m, reply_to,
Duration::from_secs(60), Duration::from_secs(60),
) )
.await?; .await
Ok(())
}
#[command]
#[description = "Watch a contest and announce any change on the members of the server assigned to the contest."]
#[usage = "[the contest id]"]
#[num_args(1)]
#[required_permissions(MANAGE_CHANNELS)]
#[only_in(guilds)]
pub async fn watch(ctx: &Context, m: &Message, mut args: Args) -> CommandResult {
let contest_id: u64 = args.single()?;
live::watch_contest(ctx, m.guild_id.unwrap(), m.channel_id, contest_id).await?;
Ok(())
} }

View file

@ -56,7 +56,7 @@ pub async fn watch_contest(
.await; .await;
let http = data.get::<CFClient>().unwrap(); let http = data.get::<CFClient>().unwrap();
let (mut contest, _, _) = let (mut contest, problems, _) =
Contest::standings(&*http.borrow().await?, contest_id, |f| f.limit(1, 1)).await?; Contest::standings(&*http.borrow().await?, contest_id, |f| f.limit(1, 1)).await?;
msg.edit(&ctx, |e| { msg.edit(&ctx, |e| {
@ -76,6 +76,7 @@ pub async fn watch_contest(
)) ))
}) })
.await?; .await?;
msg.pin(ctx).await.ok();
loop { loop {
if let Ok(messages) = if let Ok(messages) =
@ -103,38 +104,13 @@ pub async fn watch_contest(
.filter_map(|(_, m)| { .filter_map(|(_, m)| {
let member = m.member; let member = m.member;
let handle = m.handle; let handle = m.handle;
m.row.map(|row| ((handle, member), row)) m.row.map(|row| (member, handle, row))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
ranks.sort_by(|(_, a), (_, b)| a.rank.cmp(&b.rank)); ranks.sort_by(|(_, _, a), (_, _, b)| a.rank.cmp(&b.rank));
if ranks.is_empty() {
channel
.send_message(&ctx, |e| {
e.content(format!(
"**{}** has ended, but I can't find anyone in this server on the scoreboard...",
contest.name
))
})
.await?;
return Ok(());
}
channel.send_message(
&ctx, |e|
e.content(format!(
"**{}** has ended, and the rankings in the server is:\n{}", contest.name,
ranks.into_iter().map(|((handle, mem), row)| format!(
"- **#{}**: {} (**{}**) with **{:.0}** points [{}] and ({} succeeded, {} failed) hacks!",
row.rank,
mem.mention(),
handle,
row.points,
row.problem_results.iter().map(|p| format!("{:.0}", p.points)).collect::<Vec<_>>().join("/"),
row.successful_hack_count,
row.unsuccessful_hack_count,
)).collect::<Vec<_>>().join("\n")))).await?;
msg.unpin(ctx).await.ok();
crate::contest_rank_table(&ctx, &msg, contest, problems, ranks).await?;
Ok(()) Ok(())
} }