use std::sync::Arc;
use std::time::Duration;
use tokio::sync::RwLock;
use tokio::time::timeout;
use crate::bot::Bot;
use crate::bot::account::BotAccount;
use crate::bot::transmitter::{BotPackage, NullPackage};
use crate::swarm::{SharedSwarm, Swarm, SwarmObject};
use crate::utils::time::sleep;
pub mod bot;
pub mod swarm;
pub mod utils;
pub mod export;
pub fn create_bot(username: &str) -> Bot<NullPackage> {
let account = BotAccount::new(username);
Bot::create(account)
}
pub fn create_bot_with_package<P: BotPackage>(username: &str) -> Bot<P> {
let account = BotAccount::new(username);
Bot::create(account)
}
pub fn create_swarm(objects: Vec<SwarmObject>) -> Swarm<NullPackage> {
let mut swarm = Swarm::create();
for object in objects {
swarm.add_object(object);
}
swarm
}
pub fn create_swarm_with_package<P: BotPackage>(objects: Vec<SwarmObject>) -> Swarm<P> {
let mut swarm = Swarm::create();
for object in objects {
swarm.add_object(object);
}
swarm
}
pub fn create_shared_swarm(objects: Vec<SwarmObject>) -> SharedSwarm<NullPackage> {
Arc::new(RwLock::new(create_swarm(objects)))
}
pub fn create_shared_swarm_with_package<P: BotPackage>(objects: Vec<SwarmObject>) -> SharedSwarm<P> {
Arc::new(RwLock::new(create_swarm_with_package(objects)))
}
pub fn launch_shared_swarm<P: BotPackage>(swarm: SharedSwarm<P>, server_host: impl Into<String>, server_port: u16, join_delay: u64) {
let host = server_host.into();
tokio::spawn(async move {
let bots = std::mem::take(&mut swarm.write().await.bots);
let mut handles = Vec::new();
for bot in bots {
let handle = bot.spawn(&host, server_port);
handles.push(handle);
if join_delay > 0 {
sleep(join_delay).await;
}
}
{
let mut swarm_guard = swarm.write().await;
swarm_guard.handles.extend(handles);
}
});
}
pub async fn destroy_shared_swarm<P: BotPackage>(swarm: SharedSwarm<P>) -> std::io::Result<()> {
match timeout(Duration::from_secs(5), swarm.write()).await {
Ok(mut guard) => {
guard.destroy().await;
Ok(())
}
Err(_) => match timeout(Duration::from_millis(100), swarm.write()).await {
Ok(mut guard) => {
guard.force_destroy();
Ok(())
}
Err(_) => Err(std::io::Error::new(std::io::ErrorKind::TimedOut, "Failed to acquire write lock for swarm destruction")),
},
}
}