use std::io::{BufRead, BufReader};
use flate2::bufread::GzDecoder;
use crate::{ArcInfo, Network};
#[derive(Clone, Debug)]
pub struct KnuthMilesNodeAttributes {
pub name: String,
pub position: (f64, f64),
pub population: f64,
}
#[must_use]
pub fn knuth_miles() -> Network<u16, KnuthMilesNodeAttributes, u16> {
let file_bytes = include_bytes!("../resources/knuth_miles.txt.gz");
let reader = BufReader::new(GzDecoder::new(&file_bytes[..]));
let mut network: Network<u16, KnuthMilesNodeAttributes, u16> = Network::new();
let mut i = 0;
let mut next_node_id = 0;
for line in reader.lines() {
let line = line.expect("The next line should be readable");
if let Some(first_char) = line.chars().next() {
if first_char == '*' {
continue;
}
if first_char.is_ascii_digit() {
let distances: Vec<u16> = line
.split_whitespace()
.map(|s| s.parse().expect("Distances should be integers"))
.collect();
for distance in distances {
network
.add_arc((
next_node_id - 1,
u16::try_from(network.n_nodes() - i - 1)
.expect("All values are u16 encodable"),
distance,
))
.expect("Nodes should be in network already");
i += 1;
}
} else {
i = 1;
let (name, rem) = line.split_once('[').expect("Should have [ delimiter");
let (coord, pop) = rem.split_once(']').expect("Should have ] delimiter");
let (x, y) = coord
.split_once(',')
.expect("Coords should be comma seperated values");
let x = x.parse().expect("x coordinate should be an integer");
let y = y.parse().expect("y coordinate should be an integer");
let population = pop.parse().expect("Population should be an integer");
network.add_node(
next_node_id,
KnuthMilesNodeAttributes {
name: name.to_string(),
position: (x, y),
population,
},
);
next_node_id += 1;
}
}
}
let backwards_arcs: Vec<_> = network
.arc_iter()
.map(|a| ArcInfo::new(a.head, a.tail, a.attributes))
.collect();
network
.add_arcs(backwards_arcs)
.expect("Head and Tail nodes are already inserted.");
network
}
#[cfg(test)]
mod tests {
use super::knuth_miles;
#[test]
fn load_knuth_miles() {
let network = knuth_miles();
assert_eq!(network.n_nodes(), 128);
for (&id, _) in network.iter_nodes() {
assert_eq!(network.forward_arcs(&id).count(), 127);
}
}
}