diff --git a/rust/src/common.rs b/rust/src/common.rs index 33b8132..b8fa857 100644 --- a/rust/src/common.rs +++ b/rust/src/common.rs @@ -28,7 +28,6 @@ impl SystemSerde { } } - #[derive(Debug, Clone, Deserialize, Serialize)] pub struct System { pub id: u32, @@ -42,13 +41,12 @@ pub struct System { impl Ord for System { fn cmp(&self, other: &Self) -> Ordering { - return self.id.cmp(&other.id); + self.id.cmp(&other.id) } } impl PartialOrd for System { fn partial_cmp(&self, other: &Self) -> Option { - return Some(self.cmp(other)); + Some(self.cmp(other)) } } - diff --git a/rust/src/lib.rs b/rust/src/lib.rs index ee39dd4..9b82f91 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -2,38 +2,40 @@ extern crate strsim; mod common; mod preprocess; mod route; -use std::collections::HashMap; +use common::{System, SystemSerde}; use pyo3::exceptions::*; use pyo3::prelude::*; use pyo3::types::{PyDict, PyList}; +use std::collections::HashMap; use std::path::PathBuf; -use common::{System,SystemSerde}; -fn find_matches(path:&PathBuf,names:Vec) -> Result)>,String> { - let mut best: HashMap)> = HashMap::new(); +fn find_matches( + path: &PathBuf, + names: Vec, +) -> Result)>, String> { + let mut best: HashMap)> = HashMap::new(); for name in &names { - best.insert(name.to_string(),(0.0,None)); - }; + best.insert(name.to_string(), (0.0, None)); + } let mut reader = match csv::ReaderBuilder::new().from_path(path) { - Ok(rdr) => rdr, - Err(e) => { - return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e).to_string()); - } - }; - let systems=reader - .deserialize::(); - for sys in systems { - let sys=sys.unwrap(); - for name in &names { - best.entry(name.clone()).and_modify(|ent| { - let d1=strsim::normalized_levenshtein(&sys.system,&name); - if d1>ent.0 { - *ent=(d1,Some(sys.build())) - } - }); - } + Ok(rdr) => rdr, + Err(e) => { + return Err(format!("Error opening {}: {}", path.to_str().unwrap(), e).to_string()); } - return Ok(best); + }; + let systems = reader.deserialize::(); + for sys in systems { + let sys = sys.unwrap(); + for name in &names { + best.entry(name.clone()).and_modify(|ent| { + let d1 = strsim::normalized_levenshtein(&sys.system, &name); + if d1 > ent.0 { + *ent = (d1, Some(sys.build())) + } + }); + } + } + Ok(best) } #[pymodule] @@ -67,7 +69,7 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { &PathBuf::from(infile_bodies), &PathBuf::from(infile_systems), &PathBuf::from(outfile), - Box::new(callback_wrapped), + &callback_wrapped, ) .unwrap(); Ok(state.to_object(py)) @@ -75,17 +77,17 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { ///find_sys(sys_names,sys_list) /// -- - /// + /// /// Find system by name #[pyfn(m, "find_sys")] - fn find_sys(py:Python,sys_names:Vec,sys_list:String) -> PyResult { - let path=PathBuf::from(sys_list); - match find_matches(&path,sys_names) { + fn find_sys(py: Python, sys_names: Vec, sys_list: String) -> PyResult { + let path = PathBuf::from(sys_list); + match find_matches(&path, sys_names) { Ok(vals) => { - let ret=PyDict::new(py); - for (key,(diff,sys)) in vals { - let ret_dict=PyDict::new(py); - if let Some(val)= sys { + let ret = PyDict::new(py); + for (key, (diff, sys)) in vals { + let ret_dict = PyDict::new(py); + if let Some(val) = sys { let pos = PyList::new(py, val.pos.iter()); ret_dict.set_item("star_type", val.star_type.clone())?; ret_dict.set_item("system", val.system.clone())?; @@ -93,13 +95,13 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { ret_dict.set_item("distance", val.distance)?; ret_dict.set_item("pos", pos)?; ret_dict.set_item("id", val.id)?; - ret.set_item(key,(diff,ret_dict).to_object(py))?; + ret.set_item(key, (diff, ret_dict).to_object(py))?; } } - return Ok(ret.to_object(py)); - }, + Ok(ret.to_object(py)) + } Err(e) => { - return Err(PyErr::new::(e)); + Err(PyErr::new::(e)) } } } @@ -147,11 +149,11 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { state_dict.set_item("prc_seen", state.prc_seen)?; callback.call(py, (state_dict,), None) }; - let mut systems=Vec::new(); + let mut systems = Vec::new(); for sys in hops { systems.push(route::SysEntry::parse(&sys)) } - println!("SYSTEMS: {:?}",systems); + println!("SYSTEMS: {:?}", systems); let opts = RouteOpts { systems, range: Some(range), @@ -165,7 +167,7 @@ pub fn _ed_lrr(_py: Python, m: &PyModule) -> PyResult<()> { keep_first, keep_last, primary, - radius_mult + radius_mult, }; let none = ().to_object(py); match route(opts) { diff --git a/rust/src/preprocess.rs b/rust/src/preprocess.rs index 53a8e95..5474244 100644 --- a/rust/src/preprocess.rs +++ b/rust/src/preprocess.rs @@ -1,14 +1,14 @@ use crate::common::SystemSerde; use fnv::FnvHashMap; +use pyo3::prelude::*; use serde::Deserialize; use serde_json::Result; use std::fs::File; use std::io::Seek; use std::io::{BufRead, BufReader, BufWriter, SeekFrom}; use std::path::PathBuf; -use std::time::Instant; use std::str; -use pyo3::prelude::*; +use std::time::Instant; #[derive(Debug, Deserialize)] #[allow(non_snake_case)] @@ -48,7 +48,6 @@ pub struct PreprocessState { pub count: usize, } - fn get_mult(star_type: &str) -> f32 { if star_type.contains("White Dwarf") { return 1.5; @@ -59,18 +58,22 @@ fn get_mult(star_type: &str) -> f32 { 1.0 } -fn process(path: &PathBuf, func: &mut dyn for<'r> FnMut(&'r str) -> (),callback: &Box PyResult>) -> std::io::Result<()> { +fn process( + path: &PathBuf, + func: &mut dyn for<'r> FnMut(&'r str) -> (), + callback: &dyn Fn(&PreprocessState) -> PyResult, +) -> std::io::Result<()> { let mut buffer = String::new(); let fh = File::open(path)?; - let total_size= fh.metadata()?.len(); - let mut t_last=Instant::now(); + let total_size = fh.metadata()?.len(); + let mut t_last = Instant::now(); let mut reader = BufReader::new(fh); - let mut state=PreprocessState { + let mut state = PreprocessState { file: path.to_str().unwrap().to_owned(), total: total_size, done: 0, - count: 0 , - message: format!("Processing {} ...", path.to_str().unwrap()) + count: 0, + message: format!("Processing {} ...", path.to_str().unwrap()), }; println!("Loading {} ...", path.to_str().unwrap()); while let Ok(n) = reader.read_line(&mut buffer) { @@ -81,28 +84,35 @@ fn process(path: &PathBuf, func: &mut dyn for<'r> FnMut(&'r str) -> (),callback: if !buffer.is_empty() { func(&buffer); } - let pos=reader.seek(SeekFrom::Current(0)).unwrap(); - state.done=pos; + let pos = reader.seek(SeekFrom::Current(0)).unwrap(); + state.done = pos; state.count += 1; - if t_last.elapsed().as_millis()>100 { + if t_last.elapsed().as_millis() > 100 { callback(&state)?; - t_last=Instant::now(); + t_last = Instant::now(); } buffer.clear(); } Ok(()) } -fn process_systems(path: &PathBuf,callback: &Box PyResult> ) -> FnvHashMap { +fn process_systems( + path: &PathBuf, + callback: &dyn Fn(&PreprocessState) -> PyResult, +) -> FnvHashMap { let mut ret = FnvHashMap::default(); - process(path, &mut |line| { - let sys_res: Result = serde_json::from_str(&line); - if let Ok(sys) = sys_res { - ret.insert(sys.id, sys); - } else { - eprintln!("\nError parsing: {}\n\t{:?}\n", line, sys_res.unwrap_err()); - } - },callback) + process( + path, + &mut |line| { + let sys_res: Result = serde_json::from_str(&line); + if let Ok(sys) = sys_res { + ret.insert(sys.id, sys); + } else { + eprintln!("\nError parsing: {}\n\t{:?}\n", line, sys_res.unwrap_err()); + } + }, + callback, + ) .unwrap(); ret } @@ -125,7 +135,7 @@ fn process_bodies( path: &PathBuf, out_path: &PathBuf, systems: &mut FnvHashMap, - callback: &Box PyResult>, + callback: &dyn Fn(&PreprocessState) -> PyResult, ) -> std::io::Result<()> { println!( "Processing {} into {} ...", @@ -134,47 +144,56 @@ fn process_bodies( ); let mut n: u32 = 0; let mut wtr = csv::Writer::from_path(out_path)?; - process(path, &mut |line| { - if !line.contains("Star") { - return; - } - let body_res: Result = serde_json::from_str(&line); - if let Ok(body) = body_res { - if !body.body_type.contains("Star") { + process( + path, + &mut |line| { + if !line.contains("Star") { return; } - if let Some(sys) = systems.get(&body.systemId) { - let sub_type = body.subType; - let mult = get_mult(&sub_type); - let sys_name = sys.name.clone(); - let rec = SystemSerde { - id: n, - star_type: sub_type, - system: sys_name, - body: body.name, - mult, - distance: body.distance, - x: sys.coords.x, - y: sys.coords.y, - z: sys.coords.z, + let body_res: Result = serde_json::from_str(&line); + if let Ok(body) = body_res { + if !body.body_type.contains("Star") { + return; + } + if let Some(sys) = systems.get(&body.systemId) { + let sub_type = body.subType; + let mult = get_mult(&sub_type); + let sys_name = sys.name.clone(); + let rec = SystemSerde { + id: n, + star_type: sub_type, + system: sys_name, + body: body.name, + mult, + distance: body.distance, + x: sys.coords.x, + y: sys.coords.y, + z: sys.coords.z, + }; + wtr.serialize(rec).unwrap(); + n += 1; }; - wtr.serialize(rec).unwrap(); - n += 1; - }; - } else { - eprintln!("\nError parsing: {}\n\t{:?}\n", line, body_res.unwrap_err()); - } - },callback) + } else { + eprintln!("\nError parsing: {}\n\t{:?}\n", line, body_res.unwrap_err()); + } + }, + callback, + ) .unwrap(); println!("Total Systems: {}", n); systems.clear(); Ok(()) } -pub fn preprocess_files(bodies: &PathBuf,systems:&PathBuf,out_path:&PathBuf,callback: Box PyResult>) -> std::io::Result<()> { +pub fn preprocess_files( + bodies: &PathBuf, + systems: &PathBuf, + out_path: &PathBuf, + callback: &dyn Fn(&PreprocessState) -> PyResult, +) -> std::io::Result<()> { if !out_path.exists() { - let mut systems = process_systems(systems,&callback); - process_bodies(bodies, out_path, &mut systems,&callback)?; + let mut systems = process_systems(systems, &callback); + process_bodies(bodies, out_path, &mut systems, &callback)?; } else { println!( "File '{}' exists, not overwriting it", diff --git a/rust/src/route.rs b/rust/src/route.rs index 5d58c40..3a7878f 100644 --- a/rust/src/route.rs +++ b/rust/src/route.rs @@ -104,6 +104,7 @@ impl System { pub fn dist2(&self, p: &[f32; 3]) -> f32 { dist2(&self.pos, p) } + pub fn distp(&self, p: &System) -> f32 { dist(&self.pos, &p.pos) } @@ -320,12 +321,12 @@ impl Router { return scoopable; } let df = src.distp(dst); - return (sys.distp(src) + sys.distp(dst)) < (df * (1.0 + self.radius_mult)); + (sys.distp(src) + sys.distp(dst)) < (df * (1.0 + self.radius_mult)) } pub fn best_multiroute( &self, - waypoints: &Vec, + waypoints: &[System], range: f32, keep: (bool, bool), mode: Mode, @@ -367,14 +368,14 @@ impl Router { pub fn multiroute( &self, - waypoints: &Vec, + waypoints: &[System], range: f32, mode: Mode, factor: f32, ) -> Result, String> { let mut route: Vec = Vec::new(); for pair in waypoints.windows(2) { - match pair.clone() { + match pair { [src, dst] => { let block = match mode { Mode::BFS => self.route_bfs(&src, &dst, range)?, @@ -423,13 +424,13 @@ impl Router { for ent in systems { match ent { SysEntry::ID(i) => match sys_by_id.get(i) { - Some(sys) => ret.push(sys.clone().clone()), + Some(sys) => ret.push((*sys).clone()), None => { return Err(format!("System: {:?} not found", ent)); } }, SysEntry::Name(n) => match sys_by_name.get(n) { - Some(sys) => ret.push(sys.clone().clone()), + Some(sys) => ret.push((*sys).clone()), None => { return Err(format!("System: {:?} not found", ent)); } @@ -509,9 +510,9 @@ impl Router { .filter(|&nb| seen.insert(nb.id)) .map(|nb| { prev.insert(nb.id, sys); - let d_g=nb.distp(goal_sys); - if d_g Result>, String> { }; let systems: Vec = router .resolve_systems(&opts.systems)? - .iter() - .map(|sys| sys.clone()) - .collect(); + .to_vec(); if opts.precompute { for sys in systems { router.route_tree = None;