//! Spansh galaxy.json to csv converter use crate::common::{get_mult, System}; use eyre::Result; use flate2::bufread::GzDecoder; use log::*; use serde::Deserialize; use std::fs::File; use std::io::{BufRead, BufReader, BufWriter, Seek}; use std::path::Path; use std::str; #[derive(Debug, Deserialize, Clone)] struct GalaxyCoords { x: f32, y: f32, z: f32, } #[derive(Debug, Deserialize, Clone)] struct GalaxyBody { name: String, #[serde(rename = "type")] body_type: String, #[serde(rename = "subType")] sub_type: String, #[serde(rename = "distanceToArrival")] distance: f32, } #[derive(Debug, Deserialize, Clone)] struct GalaxySystem { coords: GalaxyCoords, name: String, bodies: Vec, } /// Load compressed galaxy.json from `path` and write `stars.csv` to `out_path` pub fn process_galaxy_dump(path: &Path, out_path: &Path) -> Result<()> { let out_path = out_path.with_extension("csv"); let mut wtr = csv::WriterBuilder::new() .has_headers(false) .from_writer(BufWriter::new(File::create(out_path)?)); let mut buffer = String::new(); let rdr = BufReader::new(File::open(path)?); let mut reader = BufReader::new(GzDecoder::new(rdr)); let mut count: usize = 0; let mut total: usize = 0; let mut errors: usize = 0; let mut bodies: usize = 0; let mut systems = 0; let max_len = File::metadata(reader.get_ref().get_ref().get_ref())?.len(); while let Ok(n) = reader.read_line(&mut buffer) { if n == 0 { break; } buffer = buffer .trim_end_matches(|c: char| c == ',' || c.is_whitespace()) .to_string(); total += 1; if let Ok(sys) = serde_json::from_str::(&buffer) { let mut sys_rec = System { id: systems, mult: 1.0, name: sys.name, num_bodies: 0, pos: [sys.coords.x, sys.coords.y, sys.coords.z], has_scoopable: false, }; for b in sys.bodies.iter().filter(|b| b.body_type == "Star").cloned() { sys_rec.mult = sys_rec.mult.max(get_mult(&b.sub_type)); sys_rec.num_bodies += 1; for c in "KGBFOAM".chars() { if b.sub_type.starts_with(c) { sys_rec.has_scoopable |= true; break; } } } bodies += sys_rec.num_bodies as usize; systems += 1; count += 1; wtr.serialize(sys_rec)?; if count % 100_000 == 0 { let cur_pos = reader.get_ref().get_ref().get_ref().stream_position()?; let prc: f64 = ((cur_pos as f64) / (max_len as f64)) * 100.0; info!("[{:.2} %] {} systems written", prc, count); } } else { errors += 1; } buffer.clear(); } info!("Total: {}", total); info!("Bodies: {}", bodies); info!("Systems: {}", systems); info!("Processed: {}", count); info!("Errors: {}", errors); Ok(()) }