pathfinder/map/
network.rs1use super::*;
6use std::io::{self, Error, ErrorKind};
7
8struct WNodes {
12 nodes: Vec<Node>,
13 weight: u32,
14}
15
16pub fn path<'a>(
27 network: &'a Network<Node>,
28 a: &str,
29 b: &str,
30 algorithm: &Fn(&Network<Node>, Node, Node) -> io::Result<Vec<Node>>,
31) -> io::Result<Vec<Node>> {
32 let opt_goal = network.get(b);
33 let opt_start = network.get(a);
34 if opt_goal.is_none() || opt_start.is_none() {
35 Err(Error::new(
36 ErrorKind::Other,
37 "Start or Goal path does not exist in Network",
38 ))
39 } else {
40 algorithm(&network, opt_start.unwrap(), opt_goal.unwrap())
41 }
42}
43
44pub fn get(network: &Network<Node>, element: &str) -> Option<Node> {
48 let hash = node!(element, 0, 0).hash;
49 for (i, elem) in network.hash_map.iter().enumerate() {
50 if elem.is_some() && i == hash as usize % consts::NETWORK_REM {
51 return network.hash_map[i];
52 }
53 }
54
55 None
56}
57
58pub fn path_shortest_leg<'a>(
70 network: &'a Network<Node>,
71 start: Node,
72 goal: Node,
73) -> io::Result<Vec<Node>> {
74 let format = |mut nodes: Vec<Node>, link: &HL, acc: u32| -> WNodes {
76 let node = network.hash_map[link.t as usize % consts::NETWORK_REM].unwrap();
77 let weight = acc + coordinate::distance(nodes.first().unwrap().geo, node.geo);
78 nodes.insert(0, node);
79 WNodes { weight, nodes }
80 };
81
82 let mut queue: Vec<WNodes> = start
84 .links()
85 .iter()
86 .filter(|x| x.is_connected())
87 .map(|x| format(vec![start], x, 0))
88 .collect::<Vec<_>>();
89
90 while !queue.is_empty() {
91 queue.sort_by_key(|wn| wn.weight);
93
94 let wnodes = queue.remove(0);
96
97 let current = wnodes.nodes.first().unwrap();
99
100 if current.hash == goal.hash {
102 return Ok(wnodes.nodes);
103 }
104
105 let _ = current
107 .links()
108 .iter()
109 .filter(|x| x.is_connected())
110 .map(|x| queue.push(format(wnodes.nodes.clone(), x, wnodes.weight)))
111 .collect::<Vec<_>>();
112 }
113
114 Err(Error::new(ErrorKind::Other, "not a valid path"))
117}
118
119#[cfg(test)]
120mod tests {
121
122 use super::*;
123
124 fn nodes() -> Vec<Node> {
126 let nodes = Node::from_list(&[(0, 0), (10, 10), (20, 20), (30, 30)]);
127 Node::linked_list(nodes)
128 }
129
130 fn network() -> Network<Node> {
132 Network::new(nodes())
133 }
134
135 #[test]
136 fn simple_network_shortest_leg() {
137 let network = network();
138 let path = path(&network, "D", "A", &path_shortest_leg).unwrap();
139 assert_eq!(path.len(), 4);
140 }
141
142 #[test]
143 fn simple_network() {
144 let path = network().path("A", "D").unwrap();
145 assert_eq!(path.len(), 4);
146 }
147
148 #[test]
149 fn simple_network_start_in_the_middle() {
150 let path = network().path("C", "D").unwrap();
151 assert_eq!(path.len(), 2);
152 }
153
154 #[test]
155 fn simple_network_end_in_the_middle() {
156 let path = network().path("C", "D").unwrap();
157 assert_eq!(path.len(), 2);
158 }
159
160 #[test]
161 fn simple_networks_have_same_path() {
162 let net = network();
163 let mut path_sl = path(&net, "D", "A", &path_shortest_leg).unwrap();
164 let path = net.path("A", "D").unwrap();
165 path_sl.reverse();
166
167 let f = |&p: &Node| p.geo;
168 let v1 = path.iter().map(f).collect::<Vec<_>>();
169 let v2 = path_sl.iter().map(f).collect::<Vec<_>>();
170
171 assert_eq!(v1, v2);
172 }
173
174 #[test]
175 fn valid_gets() {
176 let network = network();
177 for l in ["A", "B", "C", "D"].iter() {
178 assert!(get(&network, l).is_some());
179 }
180 }
181
182 #[test]
183 fn invalid_gets() {
184 let network = network();
185 for l in ["", "<>", "Test", "E", "AA", "EE", "f", "a"].iter() {
186 assert!(get(&network, l).is_none());
187 }
188 }
189
190 #[test]
191 fn invalid_network_1() {
192 assert!(network().path("B", "E").is_err());
193 }
194
195 #[test]
196 fn invalid_network_2() {
197 assert!(network().path("Testing", "One, two, Three.").is_err());
198 }
199
200 #[test]
201 fn invalid_network_3() {
202 assert!(network().path("", "<").is_err());
203 }
204
205 #[test]
206 fn invalid_network_4() {
207 assert!(network().path("<html>", "{json:test}").is_err());
208 }
209
210}