use std::path::Path;
use crate::string::{file_as_string, str_as_f64, str_as_u8};
#[derive(Debug)]
pub struct Map {
pub layers: Vec<MapLayer>,
}
#[derive(Debug)]
pub struct MapLayer {
pub id: usize,
pub labels: Vec<MapLabel>,
pub lines: Vec<MapLine>,
}
#[derive(Debug, PartialEq)]
pub struct MapLabel {
pub x: f64,
pub y: f64,
pub z: f64,
pub r: f32,
pub g: f32,
pub b: f32,
size: u8,
text: String,
}
#[derive(Debug, PartialEq)]
pub struct MapLine {
pub x1: f64,
pub y1: f64,
pub z1: f64,
pub x2: f64,
pub y2: f64,
pub z2: f64,
pub r: f32,
pub g: f32,
pub b: f32,
}
impl Map {
pub fn default() -> Self {
Self { layers: Vec::new() }
}
pub fn from_file(filename: &str) -> Self {
let mut map = Self::default();
map.read_layer(0, filename);
for i in 1..=3 {
let layerfile = Self::build_layer_filename(i, filename);
map.read_layer(i as usize, &layerfile);
}
map
}
fn build_layer_filename(layer_id: u8, filename: &str) -> String {
let path = Path::new(filename).canonicalize().unwrap();
let parent = path.parent().unwrap();
let basename = path.file_stem().unwrap();
let tmp = parent.join(basename);
let tmp = tmp.to_str().unwrap();
format!("{}_{}.txt", tmp, layer_id)
}
fn read_layer(&mut self, layer_id: usize, filename: &str) {
let mut layer = MapLayer::default();
layer.id = layer_id;
if let Some(s) = file_as_string(filename) {
for line in s.lines() {
layer.parse_row(line);
}
println!(
"Read map layer {} from {} with {} bytes",
layer_id,
filename,
s.len()
);
self.layers.push(layer);
}
}
}
impl MapLayer {
pub fn default() -> Self {
Self {
id: 0,
labels: Vec::new(),
lines: Vec::new(),
}
}
fn parse_row(&mut self, s: &str) {
if let Some(c) = s.get(0..2) {
match c {
"P " => {
if let Some(label) = parse_eqmap_label(&s[2..]) {
self.labels.push(label);
} else {
println!("XXX invalid LABEL: {}", s);
}
}
"L " => {
if let Some(line) = parse_eqmap_line(&s[2..]) {
self.lines.push(line);
} else {
println!("XXX invalid LINE: {}", s);
}
}
_ => println!("XXX unhandled map format: {} {}", c, s),
}
}
}
}
fn parse_eqmap_label(s: &str) -> Option<MapLabel> {
let parts: Vec<&str> = s.splitn(8, ',').collect();
if parts.len() != 8 {
return None;
}
Some(MapLabel {
x: str_as_f64(parts[0]),
y: str_as_f64(parts[1]),
z: str_as_f64(parts[2]),
r: f32::from(str_as_u8(parts[3])) / 255.,
g: f32::from(str_as_u8(parts[4])) / 255.,
b: f32::from(str_as_u8(parts[5])) / 255.,
size: str_as_u8(parts[6]),
text: parts[7].trim().to_owned(),
})
}
fn parse_eqmap_line(s: &str) -> Option<MapLine> {
let parts: Vec<&str> = s.splitn(9, ',').collect();
if parts.len() != 9 {
return None;
}
Some(MapLine {
x1: str_as_f64(parts[0]),
y1: str_as_f64(parts[1]),
z1: str_as_f64(parts[2]),
x2: str_as_f64(parts[3]),
y2: str_as_f64(parts[4]),
z2: str_as_f64(parts[5]),
r: f32::from(str_as_u8(parts[6])) / 255.,
g: f32::from(str_as_u8(parts[7])) / 255.,
b: f32::from(str_as_u8(parts[8])) / 255.,
})
}
#[test]
fn test_parse_eqmap_label() {
assert_eq!(
MapLabel {
x: 5531.2642,
y: -168.7061,
z: -299.5485,
r: 0.5019607843137255,
g: 1.,
b: 0.,
size: 2,
text: "Gargoyle_Island".to_owned()
},
parse_eqmap_label("5531.2642, -168.7061, -299.5485, 128, 255, 0, 2, Gargoyle_Island").unwrap()
);
assert_eq!(
MapLabel {
x: -3710.0198,
y: -1594.5485,
z: -192.5240,
r: 0.5019607843137255,
g: 1.,
b: 0.,
size: 2,
text: "Gull_Skytalon_(Named,Roam)".to_owned()
},
parse_eqmap_label("-3710.0198, -1594.5485, -192.5240, 128, 255, 0, 2, Gull_Skytalon_(Named,Roam)").unwrap()
);
}
#[test]
fn test_parse_eqmap_line() {
assert_eq!(
MapLine {
x1: 2881.0,
y1: -2022.0,
z1: -295.0,
x2: 2885.0,
y2: -2027.0,
z2: -295.0,
r: 0.5019607843137255,
g: 1.0,
b: 0.0
},
parse_eqmap_line("2881.0, -2022.0, -295.0, 2885.0, -2027.0, -295.0, 128, 255, 0").unwrap()
);
}