added different format for high repeat counts

This commit is contained in:
Lilith Schier 2026-08-20 19:21:38 +02:00
parent 3db5d719d2
commit 0843c77473
2 changed files with 53 additions and 44 deletions

View file

@ -1,4 +1,4 @@
pub const MAX_DICE_COUNT_PER_ROLL: usize = 20_000;
pub const RESULT_CULL_CHARACTER_THRESHOLD: usize = 3000;
pub const MAX_DISPLAYED_DICE_PER_MESSAGE: usize = 100;
pub const MAX_ROLL_REPEATS: usize = 35;
pub const MAX_ROLL_REPEATS: usize = 100;

View file

@ -1,3 +1,4 @@
use std::fmt::Write as FmtWrite;
mod dice;
mod limits;
mod parsing;
@ -12,7 +13,8 @@ use serenity::all::{
FullEvent, Interaction, InteractionContext, MessageFlags, ResolvedOption, ResolvedValue,
};
use serenity::builder::{
CreateCommand, CreateContainer, CreateContainerComponent, CreateInteractionResponse, CreateInteractionResponseMessage, CreateTextDisplay,
CreateCommand, CreateContainer, CreateContainerComponent, CreateInteractionResponse,
CreateInteractionResponseMessage, CreateTextDisplay,
};
use serenity::{async_trait, prelude::*};
use std::sync::Arc;
@ -135,7 +137,8 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
}
})
.unwrap_or(1)
.min(MAX_ROLL_REPEATS as i64);
.min(MAX_ROLL_REPEATS as i64)
.max(1) as usize;
let private = options
.iter()
.find(|option| option.name == "private")
@ -177,46 +180,59 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
let average = expression.average(&mut rng)?;
let ev = (average * 10.0).round() / 10.0;
let mut pre_paragraphs = Vec::new();
if let Some(description) = description {
pre_paragraphs.insert(0, format!(">>> {description}\n"));
}
let mut post_paragraphs = Vec::new();
if fixed_seed.is_some() {
post_paragraphs.push("***⚠️ This is not a fair roll. The result was generated based on a fixed seed and is thus fully reproducible.***".to_string());
}
post_paragraphs.push(format!("-# Expected value: {ev} | Seed: {seed}"));
let surrounding_par_count = pre_paragraphs.len() + post_paragraphs.len();
let paragraphs = if repeat <= 40 - surrounding_par_count {
let discord_md = Arc::new(std::sync::RwLock::new(DiscordMd {
buffers: vec![],
buffers: Vec::with_capacity(repeat),
dice_written: 0,
}));
if let Some(description) = description {
discord_md
.write()
.unwrap()
.buffers
.push(format!(">>> {description}\n"));
}
for _ in 0..repeat {
let mut witness = DiscordMd::create_witness(&discord_md);
let result = expression.evaluate(&mut rng, &mut witness, i64::MAX)?;
witness.witness_total_result(result)?;
witness.end();
}
if fixed_seed.is_some() {
discord_md
.write()
.unwrap()
.buffers
.push("***⚠️ This is not a fair roll. The result was generated based on a fixed seed and is thus fully reproducible.***".to_string());
let discord_md = Arc::into_inner(discord_md).unwrap().into_inner()?;
discord_md.buffers
} else {
let mut par = String::new();
for i in 0..repeat {
if i > 0 {
write!(par, ", ")?;
}
discord_md
.write()
.unwrap()
.buffers
.push(format!("-# Expected value: {ev} | Seed: {seed}"));
write!(
par,
"**{}**",
expression.evaluate(&mut rng, &mut std::io::sink(), i64::MAX)?
)?;
}
vec![par]
};
let discord_md = Arc::into_inner(discord_md)
.unwrap()
.into_inner()?;
pre_paragraphs.extend(paragraphs);
pre_paragraphs.extend(post_paragraphs);
let paragraphs = pre_paragraphs;
if discord_md.character_count() > 4000 {
if paragraphs.iter().map(|s| s.chars().count()).sum::<usize>() > 4000
|| paragraphs.len() > 40
{
bail!("Resulting message was too long, please roll fewer dice!");
}
};
let text_components = discord_md
.buffers
let text_components = paragraphs
.into_iter()
.map(|text| CreateContainerComponent::TextDisplay(CreateTextDisplay::new(text)))
.collect::<Vec<_>>();
@ -227,20 +243,13 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
text_components,
))])
// flags needs to be called before ephemeral for correct ordering
.flags(
MessageFlags::IS_COMPONENTS_V2 | MessageFlags::SUPPRESS_NOTIFICATIONS,
)
.flags(MessageFlags::IS_COMPONENTS_V2 | MessageFlags::SUPPRESS_NOTIFICATIONS)
.ephemeral(private),
);
debug!("Returning response: {response:#?}");
command
.create_response(
&ctx.http,
response,
)
.await?;
command.create_response(&ctx.http, response).await?;
Ok(())
}