use std::thread;
use crate::traits::{Environment, Agent};
pub fn generate_default_env<A: 'static + Agent>(pop_size: u64) -> Result<Box<dyn Environment>, &'static str> {
let mut pop: Vec<Box<dyn Agent>> = vec!();
for _ in 0..pop_size {
let agent: Box<dyn Agent> = A::generate()?;
pop.push(agent);
}
let env: Box<DefaultEnvironment> = DefaultEnvironment::generate(pop)?;
Ok(env)
}
pub fn tick(mut environment: Box<dyn Environment>) -> Result<Box<dyn Environment>, &'static str> {
(*environment).tick()?;
Ok(environment)
}
pub fn tick_collect(mut environment: Box<dyn Environment>) -> Result<Box<dyn Environment>, &'static str> {
(*environment).tick()?;
(*environment).collect()?;
Ok(environment)
}
pub fn collect(environment: Box<dyn Environment>) -> Result<Box<dyn Environment>, &'static str> {
(*environment).collect()?;
Ok(environment)
}
pub fn generate_default_tick_collect<A: 'static + Agent>(pop_size: u64, ticks: u64, runs: u64) -> Result<(), &'static str> {
let cpu_count: u64 = num_cpus::get() as u64;
for _ in 0..(runs / cpu_count + 1) {
let mut v = vec!();
for _ in 0..cpu_count {
v.push(thread::spawn(move || -> Result<(), &'static str> {
let mut env = generate_default_env::<A>(pop_size)?;
for _ in 0..ticks {
env = tick(env)?;
}
collect(env)?;
Ok(())
}));
}
for handle in v {
handle.join().unwrap().unwrap();
}
}
Ok(())
}
pub fn generate_env<E:'static + Environment, A: 'static + Agent>(pop_size: u64) -> Result<Box<dyn Environment>, &'static str> {
let mut pop: Vec<Box<dyn Agent>> = vec!();
for _ in 0..pop_size {
let agent: Box<dyn Agent> = A::generate()?;
pop.push(agent);
}
let env: Box<E> = E::generate(pop)?;
Ok(env)
}
pub fn generate_tick_collect<E: 'static + Environment, A: 'static + Agent>(pop_size: u64, ticks: u64, runs: u64) -> Result<(), &'static str> {
let cpu_count: u64 = num_cpus::get() as u64;
for _ in 0..(runs / cpu_count + 1) {
let mut v = vec!();
for _ in 0..cpu_count {
v.push(thread::spawn(move || -> Result<(), &'static str> {
let mut env = generate_env::<E, A>(pop_size)?;
for _ in 0..ticks {
env = tick(env)?;
}
collect(env)?;
Ok(())
}));
}
for handle in v {
handle.join().unwrap().unwrap();
}
}
Ok(())
}
struct DefaultEnvironment {
population: Vec<Box<dyn Agent>>
}
impl Environment for DefaultEnvironment {
fn generate(population: Vec<Box<dyn Agent>>) -> Result<Box<Self>, &'static str> {
Ok(Box::new(Self {population}))
}
fn collect(&self) -> Result<(), &'static str> {
for agent in &self.population {
(*agent).collect()?;
}
Ok(())
}
fn tick(&mut self) -> Result<(), &'static str> {
let mut pop: Vec<Box<dyn Agent>> = vec!();
for _ in 0..self.population.len() {
let mut agent: Box<dyn Agent> = self.population.pop().unwrap();
agent.tick()?;
pop.push(agent);
}
self.population = pop;
Ok(())
}
fn add_agent(&mut self, agent: Box<dyn Agent>) -> Result<(), &'static str> {
self.population.push(agent);
Ok(())
}
fn add_agents(&mut self, agents: Vec<Box<dyn Agent>>) -> Result<() , &'static str> {
for agent in agents {
self.population.push(agent);
}
Ok(())
}
}