From bac5907f1509a910ba613c5a6d829ef60719051d Mon Sep 17 00:00:00 2001 From: Daniel Seiller Date: Sun, 30 Jun 2019 02:01:14 +0200 Subject: [PATCH] Update main.rs Accelerate search for multiple systems by id/name by doing a single pass and returning a map --- src/main.rs | 122 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 20 deletions(-) diff --git a/src/main.rs b/src/main.rs index 460666b..e40dd31 100644 --- a/src/main.rs +++ b/src/main.rs @@ -272,7 +272,7 @@ impl Router { return ret; } - pub fn from_file(filename: &PathBuf) -> Self { + pub fn from_file(filename: &PathBuf) -> (PathBuf, Self) { let t_load = Instant::now(); let mut reader = BufReader::new(File::open(&filename).unwrap()); println!("Loading {}", filename.to_str().unwrap()); @@ -288,9 +288,16 @@ impl Router { if hash_file(&path) != file_hash { panic!("File hash mismatch!") } - let mut rtr = Self::new(&path, range, primary); - rtr.route_tree = Some(route_tree); - return rtr; + return ( + path, + Self { + tree: RTree::default(), + scoopable: FnvHashSet::default(), + route_tree: Some(route_tree), + range, + primary_only: primary, + }, + ); } fn closest(&self, point: &[f32; 3]) -> &System { @@ -636,13 +643,91 @@ impl Router { self.route_tree = Some(prev); } - pub fn route_to(&mut self, dst: &str) -> Vec { - let mut id_map: FnvHashMap = FnvHashMap::default(); - let mut id_set: FnvHashSet = FnvHashSet::default(); + fn get_systems_by_ids(path: &PathBuf, ids: &Vec) -> FnvHashMap { + 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::() + .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) -> FnvHashMap { + 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::() + .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::() + .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 { let prev = self.route_tree.as_ref().unwrap(); - let mut dst = self.name_to_systems(dst); - dst.sort_by_key(|&p| (p.mult * 10.0) as u8); - let dst: System = dst.last().cloned().unwrap().clone(); + let dst = Self::get_system_by_name(&systems_path, dst); if !prev.contains_key(&dst.id) { eprintln!("System-ID {} not found", dst.id); std::process::exit(1); @@ -652,7 +737,6 @@ impl Router { let mut curr_sys: u32 = dst.id; loop { v_ids.push(curr_sys); - id_set.insert(curr_sys); match prev.get(&curr_sys) { Some(sys_id) => curr_sys = *sys_id, None => { @@ -661,13 +745,9 @@ impl Router { } } v_ids.reverse(); - for sys in &self.tree { - if id_set.contains(&sys.id) { - id_map.insert(sys.id, &sys); - } - } + let id_map = Self::get_systems_by_ids(&systems_path, &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()) } return v; @@ -769,9 +849,11 @@ fn main() { } 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() { - Router::from_file(&opts.precomp_file.unwrap()) + let ret = Router::from_file(&opts.precomp_file.clone().unwrap()); + path = ret.0; + ret.1 } else { Router::new(&path, opts.range.unwrap(), opts.primary) }; @@ -801,7 +883,7 @@ fn main() { } let t_route = Instant::now(); let route = if router.route_tree.is_some() { - router.route_to(opts.systems.first().unwrap()) + router.route_to(opts.systems.first().unwrap(), &path) } else { if opts.permute || opts.full_permute { router.best_name_multiroute(