1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use crate::{
  configuration::GraphConfiguration,
  link::Link,
  node::{Node, SharedNode},
  LinkType,
};
use mcai_types::Coordinates;
use std::collections::HashMap;

pub trait ToGraph {
  fn to_graph(&self, configuration: GraphConfiguration) -> Graph;
}

#[derive(Debug)]
pub struct Graph {
  nodes: HashMap<u32, SharedNode>,
  configuration: GraphConfiguration,
}

impl Graph {
  pub fn new(configuration: GraphConfiguration) -> Self {
    Self {
      nodes: HashMap::new(),
      configuration,
    }
  }

  pub fn nodes(&self) -> HashMap<u32, SharedNode> {
    self.nodes.clone()
  }

  pub fn add_node(&mut self, id: u32, coordinates: Coordinates) -> SharedNode {
    let dimensions = self.configuration.node_configuration().get_dimensions();
    let node = Node::new(id, coordinates, dimensions).into_rc();
    self.nodes.insert(id, node.clone());
    node
  }

  pub fn get_node(&self, id: u32) -> Option<SharedNode> {
    self.nodes.get(&id).cloned()
  }

  pub fn get_links(&self, link_type: LinkType) -> Vec<Link> {
    self
      .nodes
      .iter()
      .flat_map(|(_, node)| node.borrow().get_links(&link_type))
      .collect()
  }

  pub fn move_node(&mut self, id: u32, coordinates: Coordinates) {
    if let Some(node) = self.nodes.get_mut(&id) {
      let mut node = node.borrow_mut();
      node.set_coordinates(coordinates);
    }
  }

  pub fn connect(&mut self, src_id: u32, dst_id: u32, link_type: &LinkType) {
    if let Some(dst_node) = self.get_node(dst_id) {
      if let Some(src_node) = self.get_node(src_id) {
        match link_type {
          LinkType::Parentage => dst_node.borrow_mut().add_parent(src_node),
          LinkType::Requirement => dst_node.borrow_mut().add_required(src_node),
        }
      }
    }
  }

  pub fn disconnect(&mut self, src_id: u32, dst_id: u32, link_type: &LinkType) {
    if let Some(dst_node) = self.get_node(dst_id) {
      match link_type {
        LinkType::Parentage => dst_node.borrow_mut().remove_parent(src_id),
        LinkType::Requirement => dst_node.borrow_mut().remove_required(src_id),
      }
    }
  }
}