ED_LRR/rust/src/galaxy.rs

102 lines
3.1 KiB
Rust

//! 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<GalaxyBody>,
}
/// 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::<GalaxySystem>(&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(())
}