Update main.rs

Accelerate search for multiple systems by id/name by doing a single pass and returning a map
This commit is contained in:
Daniel S. 2019-06-30 02:01:14 +02:00
parent 273e5c74c3
commit bac5907f15

View file

@ -272,7 +272,7 @@ impl Router {
return ret; return ret;
} }
pub fn from_file(filename: &PathBuf) -> Self { pub fn from_file(filename: &PathBuf) -> (PathBuf, Self) {
let t_load = Instant::now(); let t_load = Instant::now();
let mut reader = BufReader::new(File::open(&filename).unwrap()); let mut reader = BufReader::new(File::open(&filename).unwrap());
println!("Loading {}", filename.to_str().unwrap()); println!("Loading {}", filename.to_str().unwrap());
@ -288,9 +288,16 @@ impl Router {
if hash_file(&path) != file_hash { if hash_file(&path) != file_hash {
panic!("File hash mismatch!") panic!("File hash mismatch!")
} }
let mut rtr = Self::new(&path, range, primary); return (
rtr.route_tree = Some(route_tree); path,
return rtr; Self {
tree: RTree::default(),
scoopable: FnvHashSet::default(),
route_tree: Some(route_tree),
range,
primary_only: primary,
},
);
} }
fn closest(&self, point: &[f32; 3]) -> &System { fn closest(&self, point: &[f32; 3]) -> &System {
@ -636,13 +643,91 @@ impl Router {
self.route_tree = Some(prev); self.route_tree = Some(prev);
} }
pub fn route_to(&mut self, dst: &str) -> Vec<System> { fn get_systems_by_ids(path: &PathBuf, ids: &Vec<u32>) -> FnvHashMap<u32, System> {
let mut id_map: FnvHashMap<u32, &System> = FnvHashMap::default(); let mut ret = FnvHashMap::default();
let mut id_set: FnvHashSet<u32> = FnvHashSet::default(); let mut reader = csv::ReaderBuilder::new()
.from_path(path)
.unwrap_or_else(|e| {
println!("Error opening {}: {}", path.to_str().unwrap(), e);
std::process::exit(1);
});
reader
.deserialize::<SystemSerde>()
.map(|res| res.unwrap())
.filter(|sys| ids.contains(&sys.id))
.map(|sys| {
ret.insert(
sys.id,
System {
id: sys.id,
star_type: sys.star_type,
name: sys.name,
mult: sys.mult,
distance: sys.distance,
pos: [sys.x, sys.y, sys.z],
},
);
})
.last()
.expect(&format!("No systems matching {:?} found!", ids));
return ret;
}
fn get_systems_by_names(path: &PathBuf, names: &Vec<String>) -> FnvHashMap<String, System> {
let mut ret = FnvHashMap::default();
let mut reader = csv::ReaderBuilder::new()
.from_path(path)
.unwrap_or_else(|e| {
println!("Error opening {}: {}", path.to_str().unwrap(), e);
std::process::exit(1);
});
reader
.deserialize::<SystemSerde>()
.map(|res| res.unwrap())
.filter(|sys| names.contains(&sys.name))
.map(|sys| {
ret.insert(
sys.name.clone(),
System {
id: sys.id,
star_type: sys.star_type,
name: sys.name,
mult: sys.mult,
distance: sys.distance,
pos: [sys.x, sys.y, sys.z],
},
);
})
.last()
.expect(&format!("No systems matching {:?} found!", names));
return ret;
}
fn get_system_by_name(path: &PathBuf, name: &str) -> System {
let mut reader = csv::ReaderBuilder::new()
.from_path(path)
.unwrap_or_else(|e| {
println!("Error opening {}: {}", path.to_str().unwrap(), e);
std::process::exit(1);
});
let sys = reader
.deserialize::<SystemSerde>()
.map(|res| res.unwrap())
.find(|sys| sys.name == name)
.expect(&format!("System '{}' not found!", name));
return System {
id: sys.id,
star_type: sys.star_type,
name: sys.name,
mult: sys.mult,
distance: sys.distance,
pos: [sys.x, sys.y, sys.z],
};
}
pub fn route_to(&mut self, dst: &str, systems_path: &PathBuf) -> Vec<System> {
let prev = self.route_tree.as_ref().unwrap(); let prev = self.route_tree.as_ref().unwrap();
let mut dst = self.name_to_systems(dst); let dst = Self::get_system_by_name(&systems_path, dst);
dst.sort_by_key(|&p| (p.mult * 10.0) as u8);
let dst: System = dst.last().cloned().unwrap().clone();
if !prev.contains_key(&dst.id) { if !prev.contains_key(&dst.id) {
eprintln!("System-ID {} not found", dst.id); eprintln!("System-ID {} not found", dst.id);
std::process::exit(1); std::process::exit(1);
@ -652,7 +737,6 @@ impl Router {
let mut curr_sys: u32 = dst.id; let mut curr_sys: u32 = dst.id;
loop { loop {
v_ids.push(curr_sys); v_ids.push(curr_sys);
id_set.insert(curr_sys);
match prev.get(&curr_sys) { match prev.get(&curr_sys) {
Some(sys_id) => curr_sys = *sys_id, Some(sys_id) => curr_sys = *sys_id,
None => { None => {
@ -661,13 +745,9 @@ impl Router {
} }
} }
v_ids.reverse(); v_ids.reverse();
for sys in &self.tree { let id_map = Self::get_systems_by_ids(&systems_path, &v_ids);
if id_set.contains(&sys.id) {
id_map.insert(sys.id, &sys);
}
}
for sys_id in v_ids { for sys_id in v_ids {
let sys = *(id_map.get(&sys_id).unwrap()); let sys = id_map.get(&sys_id).unwrap();
v.push(sys.clone()) v.push(sys.clone())
} }
return v; return v;
@ -769,9 +849,11 @@ fn main() {
} }
std::process::exit(1); std::process::exit(1);
} }
let path = opts.file_path; let mut path = opts.file_path;
let mut router: Router = if opts.precomp_file.is_some() { let mut router: Router = if opts.precomp_file.is_some() {
Router::from_file(&opts.precomp_file.unwrap()) let ret = Router::from_file(&opts.precomp_file.clone().unwrap());
path = ret.0;
ret.1
} else { } else {
Router::new(&path, opts.range.unwrap(), opts.primary) Router::new(&path, opts.range.unwrap(), opts.primary)
}; };
@ -801,7 +883,7 @@ fn main() {
} }
let t_route = Instant::now(); let t_route = Instant::now();
let route = if router.route_tree.is_some() { let route = if router.route_tree.is_some() {
router.route_to(opts.systems.first().unwrap()) router.route_to(opts.systems.first().unwrap(), &path)
} else { } else {
if opts.permute || opts.full_permute { if opts.permute || opts.full_permute {
router.best_name_multiroute( router.best_name_multiroute(