#[cfg(test)]
#[path = "../../../tests/unit/models/solution/actor_test.rs"]
mod actor_test;
use crate::models::problem::{Actor, Fleet};
use hashbrown::{HashMap, HashSet};
use rosomaxa::prelude::Random;
use std::sync::Arc;
pub struct Registry {
available: HashMap<usize, HashSet<Arc<Actor>>>,
index: HashMap<Arc<Actor>, usize>,
all: Vec<Arc<Actor>>,
random: Arc<dyn Random + Send + Sync>,
}
impl Registry {
pub fn new(fleet: &Fleet, random: Arc<dyn Random + Send + Sync>) -> Self {
let index = fleet
.groups
.iter()
.flat_map(|(group_id, actors)| actors.iter().map(|a| (a.clone(), *group_id)).collect::<Vec<_>>())
.collect();
Self { available: fleet.groups.clone(), index, all: fleet.actors.to_vec(), random }
}
pub fn use_actor(&mut self, actor: &Arc<Actor>) -> bool {
self.available.get_mut(self.index.get(actor).expect("unknown actor")).unwrap().remove(actor)
}
pub fn free_actor(&mut self, actor: &Arc<Actor>) -> bool {
self.available.get_mut(self.index.get(actor).expect("unknown actor")).unwrap().insert(actor.clone())
}
pub fn all(&'_ self) -> impl Iterator<Item = Arc<Actor>> + '_ {
self.all.iter().cloned()
}
pub fn available(&'_ self) -> impl Iterator<Item = Arc<Actor>> + '_ {
self.available.iter().flat_map(|(_, set)| set.iter().cloned())
}
pub fn next(&'_ self) -> impl Iterator<Item = Arc<Actor>> + '_ {
self.available.iter().flat_map(move |(_, set)| {
let skip_amount = if set.len() < 2 { 0 } else { self.random.uniform_int(0, set.len() as i32 - 1) as usize };
set.iter().skip(skip_amount).take(1).cloned()
})
}
pub fn deep_copy(&self) -> Self {
Self {
available: self.available.clone(),
index: self.index.clone(),
all: self.all.clone(),
random: self.random.clone(),
}
}
pub fn deep_slice(&self, filter: impl Fn(&Actor) -> bool) -> Self {
Self {
available: self
.available
.iter()
.map(|(idx, actors)| {
let actors = actors.iter().filter(|actor| filter(actor.as_ref())).cloned().collect::<HashSet<_>>();
(*idx, actors)
})
.collect(),
index: self
.index
.iter()
.filter(|(actor, _)| filter(actor.as_ref()))
.map(|(actor, idx)| (actor.clone(), *idx))
.collect(),
all: self.all.iter().filter(|actor| filter(actor.as_ref())).cloned().collect(),
random: self.random.clone(),
}
}
}