use serde::{Deserialize, Serialize}; use std::fs::File; use std::io::{BufRead, BufReader, BufWriter}; use std::str; #[derive(Debug, Clone, Serialize)] pub struct SystemSerde { pub id: u32, pub star_type: String, pub system: String, pub body: String, pub mult: f32, pub distance: f32, pub x: f32, pub y: f32, pub z: f32, } fn get_mult(star_type: &str) -> f32 { if star_type.contains("White Dwarf") { return 1.5; } if star_type.contains("Neutron") { return 4.0; } 1.0 } #[derive(Debug, Deserialize)] struct Coords { x: f32, y: f32, z: f32, } #[derive(Debug, Deserialize)] struct Body { name: String, #[serde(rename = "type")] body_type: String, #[serde(rename = "subType")] sub_type: String, #[serde(rename = "distanceToArrival")] distance: f32, } #[derive(Debug, Deserialize)] struct System { coords: Coords, name: String, bodies: Vec, } pub fn process_galaxy_dump(path: &str) -> std::io::Result<()> { let fh = File::create("stars.csv")?; let mut wtr = csv::Writer::from_writer(BufWriter::new(fh)); let mut buffer = String::new(); let mut bz2_reader = std::process::Command::new("7z") .args(&["x", "-so", path]) .stdout(std::process::Stdio::piped()) .spawn() .unwrap_or_else(|err| { eprintln!("Failed to run 7z: {}", err); eprintln!("Falling back to bzip2"); std::process::Command::new("bzip2") .args(&["-d", "-c", path]) .stdout(std::process::Stdio::piped()) .spawn() .expect("Failed to execute bzip2!") }); let mut reader = BufReader::new( bz2_reader .stdout .as_mut() .expect("Failed to open stdout of child process"), ); let mut count = 0; while let Ok(n) = reader.read_line(&mut buffer) { if n == 0 { break; } buffer = buffer .trim() .trim_end_matches(|c| c == ',') .trim() .to_string(); if !buffer.contains("Star") { continue; }; if let Ok(sys) = serde_json::from_str::(&buffer) { for b in &sys.bodies { if b.body_type == "Star" { let s = SystemSerde { id: count, star_type: b.sub_type.clone(), distance: b.distance, mult: get_mult(&b.sub_type), body: b.name.clone(), system: sys.name.clone(), x: sys.coords.x, y: sys.coords.y, z: sys.coords.z, }; wtr.serialize(s)?; count += 1; } } } buffer.clear(); } println!("Total: {}", count); Ok(()) }