about summary refs log tree commit diff
path: root/src/types/entity_map.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/types/entity_map.rs')
-rw-r--r--src/types/entity_map.rs430
1 files changed, 0 insertions, 430 deletions
diff --git a/src/types/entity_map.rs b/src/types/entity_map.rs
deleted file mode 100644
index 202d8b593e15..000000000000
--- a/src/types/entity_map.rs
+++ /dev/null
@@ -1,430 +0,0 @@
-use crate::entities::entity::Identified;
-use crate::entities::EntityID;
-use crate::types::Neighbors;
-use crate::types::Position;
-use crate::types::Positioned;
-use crate::types::PositionedMut;
-use alga::general::{
-    AbstractMagma, AbstractMonoid, AbstractSemigroup, Additive, Identity,
-};
-use std::collections::{hash_map, BTreeMap, HashMap};
-use std::iter::FromIterator;
-
-#[derive(Debug, Clone, Default)]
-pub struct EntityMap<A> {
-    by_position: BTreeMap<Position, Vec<EntityID>>,
-    by_id: HashMap<EntityID, A>,
-    last_id: EntityID,
-}
-
-impl<A: PartialEq> PartialEq for EntityMap<A> {
-    fn eq(&self, other: &Self) -> bool {
-        self.by_position == other.by_position && self.by_id == other.by_id
-    }
-}
-impl<A: Eq> Eq for EntityMap<A> {}
-
-const BY_POS_INVARIANT: &str =
-    "Invariant: All references in EntityMap.by_position should point to existent references in by_id";
-
-impl<A> EntityMap<A> {
-    pub fn new() -> EntityMap<A> {
-        EntityMap {
-            by_position: BTreeMap::new(),
-            by_id: HashMap::new(),
-            last_id: 0,
-        }
-    }
-
-    pub fn len(&self) -> usize {
-        self.by_id.len()
-    }
-
-    /// Returns a list of all entities at the given position
-    pub fn at<'a>(&'a self, pos: Position) -> Vec<&'a A> {
-        self.by_position
-            .get(&pos)
-            .iter()
-            .flat_map(|eids| {
-                eids.iter()
-                    .map(|eid| self.by_id.get(eid).expect(BY_POS_INVARIANT))
-            })
-            .collect()
-    }
-
-    /// Remove all entities at the given position
-    pub fn remove_all_at(&mut self, pos: Position) {
-        if let Some(eids) = self.by_position.remove(&pos) {
-            for eid in eids {
-                self.by_id.remove(&eid).expect(BY_POS_INVARIANT);
-            }
-        }
-    }
-
-    pub fn get(&self, id: EntityID) -> Option<&A> {
-        self.by_id.get(&id)
-    }
-
-    pub fn get_mut(&mut self, id: EntityID) -> Option<&mut A> {
-        self.by_id.get_mut(&id)
-    }
-
-    pub fn entities(&self) -> impl Iterator<Item = &A> {
-        self.by_id.values()
-    }
-
-    pub fn entities_mut(&mut self) -> impl Iterator<Item = &mut A> {
-        self.by_id.values_mut()
-    }
-
-    pub fn ids(&self) -> hash_map::Keys<'_, EntityID, A> {
-        self.by_id.keys()
-    }
-
-    pub fn drain(&mut self) -> Drain<'_, A> {
-        let ids = self.ids().copied().collect::<Vec<_>>();
-        Drain {
-            map: self,
-            ids_iter: Box::new(ids.into_iter()),
-        }
-    }
-
-    fn next_id(&mut self) -> EntityID {
-        self.last_id += 1;
-        self.last_id
-    }
-}
-
-impl<A: Positioned + Identified<EntityID>> EntityMap<A> {
-    pub fn insert(&mut self, mut entity: A) -> EntityID {
-        let pos = entity.position();
-        let entity_id = self.next_id();
-        entity.set_id(entity_id);
-        self.by_id.entry(entity_id).or_insert(entity);
-        self.by_position
-            .entry(pos)
-            .or_insert_with(Vec::new)
-            .push(entity_id);
-        entity_id
-    }
-
-    /// Remove the entity with the given ID
-    pub fn remove(&mut self, id: EntityID) -> Option<A> {
-        self.by_id.remove(&id).map(|e| {
-            let mut empty = false;
-            let position = e.position();
-
-            if let Some(es) = self.by_position.get_mut(&position) {
-                es.retain(|e| *e != id);
-                if es.is_empty() {
-                    empty = true;
-                }
-            }
-
-            if empty {
-                self.by_position.remove(&position);
-            }
-            e
-        })
-    }
-
-    /// Moves all elements from `other` into `Self`, leathing `other` empty.
-    pub fn append(&mut self, other: &mut Self) {
-        // TODO there's probably some perf opportunities here by calling
-        // reserve() on stuff
-        for (_, entity) in other.drain() {
-            self.insert(entity);
-        }
-    }
-
-    /// Gets all 8 neighbors of the given position.
-    pub fn neighbors<'a>(
-        &'a self,
-        position: Position,
-    ) -> Neighbors<Vec<(EntityID, &'a A)>> {
-        Neighbors::of_position(position)
-            .map(|pos| self.at(*pos))
-            .mapmap(&|e| (e.id(), *e))
-    }
-
-    pub fn neighbor_entities<'a>(
-        &'a self,
-        position: Position,
-    ) -> Neighbors<Vec<&'a A>> {
-        self.neighbors(position).mapmap(&|(_eid, ent)| *ent)
-    }
-
-    pub fn check_invariants(&self) {
-        for (id, ent) in &self.by_id {
-            assert_eq!(*id, ent.id());
-        }
-
-        for (pos, ents) in &self.by_position {
-            for eid in ents {
-                let ent = self.by_id.get(eid).unwrap();
-                assert_eq!(*pos, ent.position())
-            }
-        }
-    }
-}
-
-impl<'a, A: Positioned + Identified<EntityID>> IntoIterator
-    for &'a EntityMap<A>
-{
-    type Item = (&'a EntityID, &'a A);
-    type IntoIter = std::collections::hash_map::Iter<'a, EntityID, A>;
-    fn into_iter(self) -> Self::IntoIter {
-        (&self.by_id).iter()
-    }
-}
-
-impl<A: Positioned + Identified<EntityID>> IntoIterator for EntityMap<A> {
-    type Item = (EntityID, A);
-    type IntoIter = std::collections::hash_map::IntoIter<EntityID, A>;
-    fn into_iter(self) -> Self::IntoIter {
-        self.by_id.into_iter()
-    }
-}
-
-impl<A: Positioned + Identified<EntityID>> FromIterator<A> for EntityMap<A> {
-    fn from_iter<I: IntoIterator<Item = A>>(iter: I) -> Self {
-        let mut em = EntityMap::new();
-        for ent in iter {
-            em.insert(ent);
-        }
-        em
-    }
-}
-
-impl<A: Positioned + Identified<EntityID> + Eq + Clone> AbstractMagma<Additive>
-    for EntityMap<A>
-{
-    fn operate(&self, right: &Self) -> Self {
-        let mut by_position = self.by_position.clone();
-        by_position.append(&mut right.by_position.clone());
-
-        let mut by_id = self.by_id.clone();
-        for (k, v) in right.by_id.clone() {
-            by_id.insert(k, v);
-        }
-
-        EntityMap {
-            by_position,
-            by_id,
-            last_id: self.last_id.max(right.last_id),
-        }
-    }
-}
-
-impl<A: Positioned + Identified<EntityID> + Eq + Clone>
-    AbstractSemigroup<Additive> for EntityMap<A>
-{
-}
-
-impl<A: Positioned + Identified<EntityID> + Eq> Identity<Additive>
-    for EntityMap<A>
-{
-    fn identity() -> Self {
-        EntityMap::new()
-    }
-}
-
-impl<A: Positioned + Identified<EntityID> + Eq + Clone> AbstractMonoid<Additive>
-    for EntityMap<A>
-{
-}
-
-impl<A: PositionedMut> EntityMap<A> {
-    pub fn update_position(
-        &mut self,
-        entity_id: EntityID,
-        new_position: Position,
-    ) {
-        let mut old_pos = None;
-        if let Some(entity) = self.by_id.get_mut(&entity_id) {
-            if entity.position() == new_position {
-                return;
-            }
-            old_pos = Some(entity.position());
-            entity.set_position(new_position);
-        }
-
-        if let Some(p) = old_pos {
-            if let Some(es) = self.by_position.get_mut(&p) {
-                es.retain(|e| *e != entity_id);
-            }
-
-            self.by_position
-                .entry(new_position)
-                .or_insert_with(Vec::new)
-                .push(entity_id);
-        }
-    }
-}
-
-pub struct Drain<'a, A> {
-    map: &'a mut EntityMap<A>,
-    ids_iter: Box<dyn Iterator<Item = EntityID> + 'a>,
-}
-
-impl<A: Positioned + Identified<EntityID>> Iterator for Drain<'_, A> {
-    type Item = (EntityID, A);
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.ids_iter
-            .next()
-            .map(|eid| (eid, self.map.remove(eid).expect(BY_POS_INVARIANT)))
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::types::PositionedMut;
-    use proptest::prelude::*;
-    use proptest_derive::Arbitrary;
-
-    #[derive(Debug, Arbitrary, PartialEq, Eq, Clone)]
-    struct TestEntity {
-        _id: Option<EntityID>,
-        position: Position,
-        name: String,
-    }
-
-    impl Positioned for TestEntity {
-        fn position(&self) -> Position {
-            self.position
-        }
-    }
-
-    impl PositionedMut for TestEntity {
-        fn set_position(&mut self, pos: Position) {
-            self.position = pos
-        }
-    }
-
-    impl Identified<EntityID> for TestEntity {
-        fn opt_id(&self) -> Option<EntityID> {
-            self._id
-        }
-
-        fn set_id(&mut self, id: EntityID) {
-            self._id = Some(id);
-        }
-    }
-
-    fn gen_entity_map() -> BoxedStrategy<EntityMap<TestEntity>> {
-        any::<Vec<TestEntity>>()
-            .prop_map(|ents| {
-                ents.iter().cloned().collect::<EntityMap<TestEntity>>()
-            })
-            .boxed()
-    }
-
-    proptest! {
-        #![proptest_config(ProptestConfig::with_cases(10))]
-
-        #[test]
-        fn test_entity_map_len(items: Vec<TestEntity>) {
-            let mut map = EntityMap::new();
-            assert_eq!(map.len(), 0);
-            for ent in &items {
-                map.insert(ent.clone());
-            }
-            assert_eq!(map.len(), items.len());
-        }
-
-        #[test]
-        fn test_entity_map_getset(
-            mut em in gen_entity_map(),
-            ent: TestEntity
-        ) {
-            em.insert(ent.clone());
-            assert!(em.at(ent.position).iter().any(|e| e.name == ent.name))
-        }
-
-        #[test]
-        fn test_entity_map_set_iter_contains(
-            mut em in gen_entity_map(),
-            ent: TestEntity
-        ) {
-            em.insert(ent.clone());
-            assert!(em.entities().any(|e| e.name == ent.name))
-        }
-
-        #[test]
-        fn test_update_position(
-            mut em in gen_entity_map(),
-            ent: TestEntity,
-            new_position: Position,
-        ) {
-            let original_position = ent.position();
-            let entity_id = em.insert(ent.clone());
-            em.update_position(entity_id, new_position);
-
-            if new_position != original_position {
-                assert!(em.at(original_position).iter().all(|e| e.name != ent.name));
-            }
-            assert_eq!(
-                em.get(entity_id).map(|e| e.position()),
-                Some(new_position)
-            );
-            assert!(
-                em.at(new_position).iter().map(
-                    |e| e.name.clone()).any(|en| en == ent.name),
-            )
-        }
-
-        #[test]
-        fn test_remove_all_at(
-            mut em in gen_entity_map(),
-            pos: Position,
-        ) {
-            em.remove_all_at(pos);
-            assert_eq!(em.at(pos).len(), 0);
-        }
-
-        #[test]
-        fn test_entity_map_semigroup_laws(
-            em1 in gen_entity_map(),
-            em2 in gen_entity_map(),
-            em3 in gen_entity_map(),
-        ) {
-            assert!(AbstractSemigroup::prop_is_associative((em1, em2, em3)));
-        }
-
-        fn test_entity_map_monoid_laws(
-            em in gen_entity_map(),
-        ) {
-            assert!(
-                AbstractMonoid::prop_operating_identity_element_is_noop((em,))
-            );
-        }
-
-        #[test]
-        fn test_entity_map_append(
-            mut target in gen_entity_map(),
-            mut source in gen_entity_map(),
-        ) {
-            let orig_target = target.clone();
-            let orig_source = source.clone();
-
-            target.append(&mut source);
-            target.check_invariants();
-
-            assert_eq!(source, EntityMap::new());
-
-            for ent in orig_source.entities() {
-                assert!(
-                    target.at(ent.position()).iter().any(|e| e.name == ent.name)
-                );
-            }
-
-            for ent in orig_target.entities() {
-                assert!(
-                    target.at(ent.position()).iter().any(|e| e.name == ent.name)
-                );
-            }
-        }
-    }
-}