use std::fs::File;
use std::io::{BufReader, Write};
use std::path::Path;
use serde_json::Value;
fn fix_points(points: &mut Vec<(f64, f64)>) {
let mut s = 0.0;
for i in 0..points.len() {
let (px, py) = points[i];
let (qx, qy) = points[(i + 1) % points.len()];
s += (qx - px) * (qy + py);
}
if s < 0.0 {
points.reverse();
}
}
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {} <input_file> [--output <output_file>]", args[0]);
std::process::exit(1);
}
let in_name = &args[1];
let out_name = match args.get(2) {
Some(arg) if arg == "--output" => {
if args.len() < 4 {
eprintln!("No output file provided.");
std::process::exit(1);
}
args[3].clone()
}
_ => Path::new(in_name).with_extension("txt").to_string_lossy().to_string(),
};
let in_file = File::open(in_name).expect("Failed to open input file.");
let reader = BufReader::new(in_file);
let j: Value = serde_json::from_reader(reader).expect("Failed to parse JSON.");
let mut out_file = File::create(&out_name).expect("Failed to create output file.");
if let Some(layers) = j["layers"].as_array() {
for l in layers {
if let Some(name) = l["name"].as_str() {
if name == "walls" {
if let Some(objects) = l["objects"].as_array() {
for o in objects {
if let (Some(x), Some(y), Some(polygon)) = (o["x"].as_f64(), o["y"].as_f64(), o["polygon"].as_array()) {
let mut points = Vec::new();
for p in polygon {
if let (Some(px), Some(py)) = (p["x"].as_f64(), p["y"].as_f64()) {
points.push((x + px, y + py));
}
}
fix_points(&mut points);
let s = points.iter().map(|(x, y)| format!("({} {})", x, y)).collect::<Vec<_>>().join(" ");
out_file.write_all(format!("wall [{}]\n", s).as_bytes()).expect("Failed to write to output file.");
}
}
}
} else if name == "objects" {
if let Some(objects) = l["objects"].as_array() {
for o in objects {
if let (Some(name), Some(x), Some(y)) = (o["name"].as_str(), o["x"].as_f64(), o["y"].as_f64()) {
out_file.write_all(format!("{} ({} {})\n", name, x, y).as_bytes()).expect("Failed to write to output file.");
}
}
}
}
}
}
}
}