use rand::rngs::StdRng;
use rand::SeedableRng;
use rustsim_core::interaction::{PositionedAgent, SpaceInteraction};
use rustsim_core::prelude::*;
use rustsim_spaces::graph::{GraphPos, GraphSpace, GraphSpaceError, NeighborType};
#[derive(Debug, Clone)]
struct GraphBot {
id: AgentId,
pos: GraphPos,
}
impl Agent for GraphBot {
fn id(&self) -> AgentId {
self.id
}
}
impl PositionedAgent for GraphBot {
type Position = GraphPos;
fn position(&self) -> &GraphPos {
&self.pos
}
fn set_position(&mut self, p: GraphPos) {
self.pos = p;
}
}
#[test]
fn create_graph_add_edges() {
let mut g = GraphSpace::new(5);
assert_eq!(g.num_vertices(), 5);
assert_eq!(g.num_edges(), 0);
g.add_edge(0, 1);
g.add_edge(1, 2);
g.add_edge(2, 3);
g.add_edge(3, 4);
assert_eq!(g.num_edges(), 4);
assert_eq!(g.neighbors_out(1), &[0, 2]); }
#[test]
fn directed_graph() {
let mut g = GraphSpace::new_directed(3, true);
g.add_edge(0, 1);
g.add_edge(1, 2);
assert_eq!(g.num_edges(), 2);
assert_eq!(g.neighbors_out(0), &[1]);
assert!(g.neighbors_out(1).contains(&2));
assert_eq!(g.neighbors_in(2), &[1]);
assert!(g.neighbors_in(0).is_empty());
}
#[test]
fn add_remove_vertex() {
let mut g = GraphSpace::new(3);
g.add_edge(0, 1);
g.add_edge(1, 2);
let new_v = g.add_vertex();
assert_eq!(new_v, 3);
assert_eq!(g.num_vertices(), 4);
g.add_edge(2, 3);
assert_eq!(g.num_edges(), 3);
g.rem_vertex(1);
assert_eq!(g.num_vertices(), 3);
}
#[test]
fn add_remove_edge() {
let mut g = GraphSpace::new(4);
g.add_edge(0, 1);
g.add_edge(1, 2);
g.add_edge(2, 3);
assert_eq!(g.num_edges(), 3);
g.rem_edge(1, 2);
assert_eq!(g.num_edges(), 2);
assert!(!g.add_edge(0, 1));
}
#[test]
fn agents_on_graph() {
let mut g = GraphSpace::new(4);
g.add_edge(0, 1);
g.add_edge(1, 2);
g.add_edge(2, 3);
let a = GraphBot { id: 1, pos: 0 };
let b = GraphBot { id: 2, pos: 1 };
let c = GraphBot { id: 3, pos: 3 };
SpaceInteraction::<GraphBot>::add_agent(&mut g, &a).unwrap();
SpaceInteraction::<GraphBot>::add_agent(&mut g, &b).unwrap();
SpaceInteraction::<GraphBot>::add_agent(&mut g, &c).unwrap();
assert_eq!(g.ids_in_position(0), &[1]);
assert_eq!(g.ids_in_position(1), &[2]);
assert_eq!(g.ids_in_position(3), &[3]);
let near = g.nearby_agent_ids(1, 1, NeighborType::Out);
assert!(near.contains(&1)); assert!(near.contains(&2)); assert!(!near.contains(&3));
let near2 = g.nearby_agent_ids(1, 2, NeighborType::Out);
assert!(near2.contains(&3));
}
#[test]
fn remove_agent_from_graph() {
let mut g = GraphSpace::new(2);
g.add_edge(0, 1);
let a = GraphBot { id: 1, pos: 0 };
SpaceInteraction::<GraphBot>::add_agent(&mut g, &a).unwrap();
assert_eq!(g.ids_in_position(0).len(), 1);
SpaceInteraction::<GraphBot>::remove_agent(&mut g, &a).unwrap();
assert!(g.ids_in_position(0).is_empty());
}
#[test]
fn nearby_positions_bfs() {
let mut g = GraphSpace::new(5);
for i in 0..4 {
g.add_edge(i, i + 1);
}
let r1 = g.nearby_positions(2, 1, NeighborType::Out);
assert!(r1.contains(&1));
assert!(r1.contains(&3));
assert!(!r1.contains(&0));
assert!(!r1.contains(&4));
assert!(!r1.contains(&2));
let r2 = g.nearby_positions(2, 2, NeighborType::Out);
assert!(r2.contains(&0));
assert!(r2.contains(&4));
}
#[test]
fn multi_floor_building() {
let mut g = GraphSpace::new(7);
g.add_edge(0, 1); g.add_edge(1, 2);
g.add_edge(1, 3); g.add_edge(3, 5);
g.add_edge(4, 5); g.add_edge(5, 6);
assert_eq!(g.num_vertices(), 7);
assert_eq!(g.num_edges(), 6);
let agents = vec![
GraphBot { id: 1, pos: 0 }, GraphBot { id: 2, pos: 2 }, GraphBot { id: 3, pos: 4 }, GraphBot { id: 4, pos: 6 }, ];
for a in &agents {
SpaceInteraction::<GraphBot>::add_agent(&mut g, a).unwrap();
}
let near_corridor1 = g.nearby_positions(1, 1, NeighborType::Out);
assert!(near_corridor1.contains(&0));
assert!(near_corridor1.contains(&2));
assert!(near_corridor1.contains(&3));
assert!(!near_corridor1.contains(&5));
let near_corridor1_r2 = g.nearby_positions(1, 2, NeighborType::Out);
assert!(near_corridor1_r2.contains(&5));
let near_room1a = g.nearby_agent_ids(0, 2, NeighborType::Out);
assert!(near_room1a.contains(&1)); assert!(near_room1a.contains(&2));
assert!(!near_room1a.contains(&3));
assert!(!near_room1a.contains(&4));
let near_room1a_r4 = g.nearby_agent_ids(0, 4, NeighborType::Out);
assert!(near_room1a_r4.contains(&3)); assert!(near_room1a_r4.contains(&4)); }
#[test]
fn random_position_in_graph() {
let g = GraphSpace::new(10);
let mut rng = StdRng::seed_from_u64(7);
for _ in 0..100 {
let pos = SpaceInteraction::<GraphBot>::random_position(&g, &mut rng);
assert!(pos < 10);
}
}
#[test]
fn invalid_node_returns_error() {
let mut g = GraphSpace::new(3);
let a = GraphBot { id: 1, pos: 99 };
let result = SpaceInteraction::<GraphBot>::add_agent(&mut g, &a);
assert!(matches!(result, Err(GraphSpaceError::InvalidNode(99))));
}