1use crate::deadlock::{WaitForGraph, WaitingFor};
4use std::collections::{HashMap, HashSet};
5use waremax_core::{EdgeId, NodeId, RobotId};
6
7pub struct TrafficManager {
9 edge_occupancy: HashMap<EdgeId, HashSet<RobotId>>,
10 node_occupancy: HashMap<NodeId, HashSet<RobotId>>,
11 edge_capacity: HashMap<EdgeId, u32>,
12 node_capacity: HashMap<NodeId, u32>,
13 default_edge_capacity: u32,
14 default_node_capacity: u32,
15 pub wait_graph: WaitForGraph,
17 pub deadlock_detection_enabled: bool,
19}
20
21impl TrafficManager {
22 pub fn new(default_edge_capacity: u32, default_node_capacity: u32) -> Self {
23 Self {
24 edge_occupancy: HashMap::new(),
25 node_occupancy: HashMap::new(),
26 edge_capacity: HashMap::new(),
27 node_capacity: HashMap::new(),
28 default_edge_capacity,
29 default_node_capacity,
30 wait_graph: WaitForGraph::new(),
31 deadlock_detection_enabled: false,
32 }
33 }
34
35 pub fn set_deadlock_detection(&mut self, enabled: bool) {
37 self.deadlock_detection_enabled = enabled;
38 }
39
40 pub fn set_edge_capacity(&mut self, edge: EdgeId, capacity: u32) {
41 self.edge_capacity.insert(edge, capacity);
42 }
43
44 pub fn set_node_capacity(&mut self, node: NodeId, capacity: u32) {
45 self.node_capacity.insert(node, capacity);
46 }
47
48 pub fn can_enter_edge(&self, edge: EdgeId, robot: RobotId) -> bool {
49 let capacity = self
50 .edge_capacity
51 .get(&edge)
52 .copied()
53 .unwrap_or(self.default_edge_capacity);
54 let occupants = self.edge_occupancy.get(&edge);
55
56 if let Some(set) = occupants {
57 if set.contains(&robot) {
58 return true;
59 }
60 (set.len() as u32) < capacity
61 } else {
62 capacity > 0
63 }
64 }
65
66 pub fn can_enter_node(&self, node: NodeId, robot: RobotId) -> bool {
67 let capacity = self
68 .node_capacity
69 .get(&node)
70 .copied()
71 .unwrap_or(self.default_node_capacity);
72 let occupants = self.node_occupancy.get(&node);
73
74 if let Some(set) = occupants {
75 if set.contains(&robot) {
76 return true;
77 }
78 (set.len() as u32) < capacity
79 } else {
80 capacity > 0
81 }
82 }
83
84 pub fn enter_edge(&mut self, edge: EdgeId, robot: RobotId) {
85 self.edge_occupancy.entry(edge).or_default().insert(robot);
86 }
87
88 pub fn leave_edge(&mut self, edge: EdgeId, robot: RobotId) {
89 if let Some(set) = self.edge_occupancy.get_mut(&edge) {
90 set.remove(&robot);
91 }
92 }
93
94 pub fn enter_node(&mut self, node: NodeId, robot: RobotId) {
95 self.node_occupancy.entry(node).or_default().insert(robot);
96 }
97
98 pub fn leave_node(&mut self, node: NodeId, robot: RobotId) {
99 if let Some(set) = self.node_occupancy.get_mut(&node) {
100 set.remove(&robot);
101 }
102 }
103
104 pub fn get_edge_occupancy(&self, edge: EdgeId) -> usize {
105 self.edge_occupancy.get(&edge).map_or(0, |s| s.len())
106 }
107
108 pub fn get_node_occupancy(&self, node: NodeId) -> usize {
109 self.node_occupancy.get(&node).map_or(0, |s| s.len())
110 }
111
112 pub fn robots_on_edge(&self, edge: EdgeId) -> impl Iterator<Item = RobotId> + '_ {
113 self.edge_occupancy
114 .get(&edge)
115 .into_iter()
116 .flat_map(|s| s.iter().copied())
117 }
118
119 pub fn robots_at_node(&self, node: NodeId) -> impl Iterator<Item = RobotId> + '_ {
120 self.node_occupancy
121 .get(&node)
122 .into_iter()
123 .flat_map(|s| s.iter().copied())
124 }
125
126 pub fn record_edge_wait(&mut self, robot: RobotId, edge: EdgeId) {
132 if !self.deadlock_detection_enabled {
133 return;
134 }
135
136 let blockers: Vec<RobotId> = self.robots_on_edge(edge).filter(|&r| r != robot).collect();
137
138 self.wait_graph.add_wait(
139 robot,
140 WaitingFor::Edge {
141 edge_id: edge,
142 blocked_by: blockers,
143 },
144 );
145 }
146
147 pub fn record_node_wait(&mut self, robot: RobotId, node: NodeId) {
151 if !self.deadlock_detection_enabled {
152 return;
153 }
154
155 let blockers: Vec<RobotId> = self.robots_at_node(node).filter(|&r| r != robot).collect();
156
157 self.wait_graph.add_wait(
158 robot,
159 WaitingFor::Node {
160 node_id: node,
161 blocked_by: blockers,
162 },
163 );
164 }
165
166 pub fn clear_wait(&mut self, robot: RobotId) {
168 self.wait_graph.remove_wait(robot);
169 }
170
171 pub fn is_waiting(&self, robot: RobotId) -> bool {
173 self.wait_graph.is_waiting(robot)
174 }
175
176 pub fn check_deadlock(&self) -> Option<Vec<RobotId>> {
180 if !self.deadlock_detection_enabled {
181 return None;
182 }
183 self.wait_graph.detect_cycle()
184 }
185
186 pub fn waiting_count(&self) -> usize {
188 self.wait_graph.waiting_count()
189 }
190}