use rand::Rng;
pub type JoinDelayFn = dyn Fn(u64, u64) -> u64 + Send + Sync;
pub struct JoinDelay(Box<JoinDelayFn>);
impl JoinDelay {
pub fn activate(&self, current: usize, total: usize) -> u64 {
self.0(current as u64, total as u64)
}
pub fn fixed(delay: u64) -> Self {
Self(Box::new(move |_current, _total| delay))
}
pub fn progressive(delay: u64, max_delay: u64, multiplier: u64) -> Self {
Self(Box::new(move |current, _total| {
let result = delay * ((current + 1) * multiplier);
if result > max_delay { max_delay } else { result }
}))
}
pub fn progressive_linear(delay: u64, max_delay: u64) -> Self {
Self(Box::new(move |current, _total| {
let result = delay * (current + 1);
if result > max_delay { max_delay } else { result }
}))
}
pub fn regressive(delay: u64, min_delay: u64, multiplier: u64) -> Self {
Self(Box::new(move |current, _total| {
let result = delay / ((current + 1) * multiplier);
if result < min_delay { min_delay } else { result }
}))
}
pub fn regressive_linear(delay: u64, min_delay: u64) -> Self {
Self(Box::new(move |current, _total| {
let result = delay / (current + 1);
if result < min_delay { min_delay } else { result }
}))
}
pub fn custom(func: Box<JoinDelayFn>) -> Self {
Self(func)
}
pub fn random(min_delay: u64, max_delay: u64) -> Self {
Self(Box::new(move |_current, _total| {
let mut rng = rand::thread_rng();
rng.gen_range(min_delay..=max_delay)
}))
}
pub fn intermediate(group_size: u64, delay: u64, intermediate_delay: u64) -> Self {
Self(Box::new(move |current, _total| {
if (current + 1) % group_size == 0 { intermediate_delay } else { delay }
}))
}
}
#[cfg(test)]
mod tests {
use std::io;
use std::time::Duration;
use crate::bot::Bot;
use crate::swarm::{JoinDelay, Swarm};
#[tokio::test]
async fn test_fixed_delay() -> io::Result<()> {
let mut swarm = Swarm::create_with_capacity(10).with_join_delay(JoinDelay::fixed(500)).bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(2)).await;
swarm.shutdown().await?;
Ok(())
}
#[tokio::test]
async fn test_progressive_linear_delay() -> io::Result<()> {
let mut swarm = Swarm::create_with_capacity(10)
.with_join_delay(JoinDelay::progressive_linear(500, 5000))
.bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(2)).await;
swarm.shutdown().await?;
Ok(())
}
#[tokio::test]
async fn test_progressive_delay() -> io::Result<()> {
let mut swarm = Swarm::create_with_capacity(10)
.with_join_delay(JoinDelay::progressive(10, 3000, 5))
.bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(2)).await;
swarm.shutdown().await?;
Ok(())
}
#[tokio::test]
async fn test_regressive_delay() -> io::Result<()> {
let mut swarm = Swarm::create_with_capacity(10).with_join_delay(JoinDelay::regressive(5000, 10, 5)).bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(2)).await;
swarm.shutdown().await?;
Ok(())
}
#[tokio::test]
async fn test_regressive_linear_delay() -> io::Result<()> {
let mut swarm = Swarm::create_with_capacity(10)
.with_join_delay(JoinDelay::regressive_linear(5000, 500))
.bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(2)).await;
swarm.shutdown().await?;
Ok(())
}
#[tokio::test]
async fn test_random_delay() -> io::Result<()> {
let mut swarm = Swarm::create_with_capacity(10).with_join_delay(JoinDelay::random(100, 3000)).bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(2)).await;
swarm.shutdown().await?;
Ok(())
}
#[tokio::test]
async fn test_custom_delay() -> io::Result<()> {
let join_delay_fn = |current, total| (500 + total) * current;
let mut swarm = Swarm::create_with_capacity(10)
.with_join_delay(JoinDelay::custom(Box::new(join_delay_fn)))
.bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(2)).await;
swarm.shutdown().await?;
Ok(())
}
#[tokio::test]
async fn test_intermediate_delay() -> io::Result<()> {
let mut swarm = Swarm::create_with_capacity(10)
.with_join_delay(JoinDelay::intermediate(2, 100, 2000))
.bind("localhost", 25565);
for i in 0..10 {
swarm.add_bot(Bot::create(format!("nurtex_{}", i)));
}
swarm.launch().await;
tokio::time::sleep(Duration::from_secs(3)).await;
swarm.shutdown().await?;
Ok(())
}
}