151 lines
4.5 KiB
Rust
151 lines
4.5 KiB
Rust
use std::io::Write;
|
|
use anyhow::anyhow;
|
|
use simd_json::Node;
|
|
|
|
use edalyze::tapetool::{TapeCursor, TapeObject, Value};
|
|
use edalyze::bindata::{System, Point, Box};
|
|
|
|
|
|
|
|
fn star_typ(sub_type: &str) -> u8 {
|
|
use edalyze::bindata::{IS_FUEL, IS_WDRF, IS_NEUT};
|
|
if sub_type.starts_with("Wh") {
|
|
return IS_WDRF;
|
|
} else if sub_type.starts_with("N") {
|
|
return IS_NEUT;
|
|
} else {
|
|
let c2 = &sub_type.as_bytes()[..2];
|
|
if b"OBAFGKM".contains(&c2[0]) && c2[1] == b' ' {
|
|
return IS_FUEL;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn parse_coords(c: TapeObject) -> Result<Point, &'static str> {
|
|
let mut pt = Point::default();
|
|
|
|
for (k,v) in c {
|
|
let v = v.as_f64().ok_or("Coord value must be f64")? as f32;
|
|
let v = (v * 32.) as i32;
|
|
match k {
|
|
"x" => pt.0 = v,
|
|
"y" => pt.1 = v,
|
|
"z" => pt.2 = v,
|
|
_ => return Err("Unexpected coord field"),
|
|
}
|
|
}
|
|
Ok(pt)
|
|
}
|
|
|
|
fn parse_body(v: Value) -> Option<(f32, u8)> {
|
|
let mut distance = None;
|
|
let mut star_flags = 255;
|
|
let mut is_star = false;
|
|
for (k,v) in v.as_object()? {
|
|
match k {
|
|
"type" => {
|
|
is_star = v.as_str()? == "Star";
|
|
if !is_star {
|
|
return None;
|
|
}
|
|
}
|
|
"subType" => star_flags = star_typ(v.as_str()?),
|
|
"distanceToArrival" => distance = Some(v.as_f64()? as f32),
|
|
_ => continue,
|
|
}
|
|
if is_star && star_flags != 255 && distance.is_some() {
|
|
return Some((distance.unwrap(), star_flags));
|
|
}
|
|
}
|
|
return None
|
|
}
|
|
|
|
fn parse_system<'a>(tape: &'a [Node<'a>]) -> Result<System, &'static str> {
|
|
let mut system = System::default();
|
|
let mut csr = TapeCursor::new(tape);
|
|
|
|
let mut obj = csr.next()
|
|
.ok_or("Expected a JSON object")?
|
|
.as_object()
|
|
.ok_or("Expected a JSON object")?;
|
|
while let Some((k,v)) = obj.next() {
|
|
match k {
|
|
"name" => system.name = v.as_str().map(str::to_owned).ok_or("name must be str")?,
|
|
"coords" => system.coords = parse_coords(v.as_object().ok_or("coords must be object")?)?,
|
|
"bodies" => {
|
|
system.star_flags = v.as_array().ok_or("bodies should be array")?
|
|
.filter_map(parse_body)
|
|
.map(|x| x.1)
|
|
.fold(0, |x,y| x|y)
|
|
}
|
|
_ => (),
|
|
}
|
|
}
|
|
Ok(system)
|
|
}
|
|
|
|
fn id<T> (x:T) -> T { x }
|
|
|
|
fn processor_e(line: &mut [u8]) -> anyhow::Result<System> {
|
|
let tape = simd_json::to_tape(line)?;
|
|
parse_system(tape.as_slice())
|
|
.map_err(|err| anyhow!(err))
|
|
}
|
|
fn processor(line: &mut [u8]) -> Option<System> {
|
|
match processor_e(line) {
|
|
Ok(v) => Some(v),
|
|
Err(e) => {
|
|
let json = String::from_utf8_lossy(line).to_owned();
|
|
eprintln!("Error: {e}\nIn system: {}", json);
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
//static FILENAME: &str = "/space/data/ed-utils/spansh/galaxy_subset.json.zst";
|
|
static FILENAME: &str = "/space/data/ed-utils/spansh/galaxy.json.zst";
|
|
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
let f = edalyze::ioutil::Processor::open_file(FILENAME, processor)?;
|
|
|
|
// Small region
|
|
#[cfg(ignore)]
|
|
let region = Box::from_corners(
|
|
Point(11900*32, -3800*32, -11510*32),
|
|
Point(17400*32, 3800*32, -6500*32),
|
|
);
|
|
// Everything southeast of Haffner 18 LSS 27
|
|
let region = Box::from_corners(
|
|
Point(11900*32, -3800*32, -18510*32),
|
|
Point(64400*32, 3800*32, -6500*32),
|
|
);
|
|
|
|
let mut reg_name = std::io::BufWriter::new(std::fs::File::create("region.nam")?);
|
|
let mut reg_data = std::io::BufWriter::new(std::fs::File::create("region.dat")?);
|
|
let mut name_pos = 0;
|
|
|
|
for mut sys in f.filter_map(id).filter(|sys| region.contains(sys.coords)) {
|
|
sys.name_off = name_pos as usize;
|
|
let hdr = [sys.name.len().min(255) as u8];
|
|
if hdr[0] == 255 {
|
|
eprintln!("WARNING: Long system name {}", sys.name);
|
|
}
|
|
reg_name.write(&hdr[..])?;
|
|
reg_name.write(&sys.name.as_bytes()[..hdr[0] as usize])?;
|
|
name_pos += hdr[0] as u32 + 1;
|
|
|
|
reg_data.write(&sys.coords.0 .to_be_bytes()[..])?;
|
|
reg_data.write(&sys.coords.1 .to_be_bytes()[..])?;
|
|
reg_data.write(&sys.coords.2 .to_be_bytes()[..])?;
|
|
|
|
let rest = (sys.star_flags as u32) + (name_pos << 4);
|
|
reg_data.write(&rest.to_be_bytes()[..])?;
|
|
}
|
|
|
|
|
|
Ok(())
|
|
}
|