|
|
|
@ -16,14 +16,21 @@ use std::{io::prelude::*, fs::File, collections::HashMap, mem};
|
|
|
|
use nalgebra_glm::Vec2;
|
|
|
|
use nalgebra_glm::Vec2;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
// MapObject
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
pub enum MapCell
|
|
|
|
pub enum MapObject
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Empty,
|
|
|
|
Empty,
|
|
|
|
Freq(u8),
|
|
|
|
Freq(u8),
|
|
|
|
|
|
|
|
Antinode(Antinode),
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
// PointIdx
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
pub struct PointIdx
|
|
|
|
pub struct PointIdx
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -50,21 +57,116 @@ impl PointIdx
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
// Antinode
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
pub struct Antinode
|
|
|
|
pub struct Antinode
|
|
|
|
{
|
|
|
|
{
|
|
|
|
location: PointIdx,
|
|
|
|
location: PointIdx,
|
|
|
|
freq: u8,
|
|
|
|
freq: u8,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl PartialEq for Antinode
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
fn eq(&self, other: &Antinode) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
self.location.i == other.location.i &&
|
|
|
|
|
|
|
|
self.location.j == other.location.j
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Antinode
|
|
|
|
impl Antinode
|
|
|
|
{
|
|
|
|
{
|
|
|
|
pub fn new(location: PointIdx, freq: u8) -> Antinode
|
|
|
|
pub fn new(location: PointIdx, freq: u8) -> Antinode
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Antinode { location, freq }
|
|
|
|
Antinode { location, freq }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn new_empty() -> Antinode
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Antinode { location: PointIdx::new(0, 0), freq: 0 }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
// MapCell
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
|
|
|
pub struct MapCell
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
contents: Vec<MapObject>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl MapCell
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
pub fn new(contents: Vec<MapObject>) -> MapCell
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
MapCell { contents }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn has_antenna(self: &MapCell) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for mo in &self.contents
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if mem::discriminant(mo) == mem::discriminant(&MapObject::Freq(0))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn has_antinode(self: &MapCell) -> bool
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for mo in &self.contents
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if mem::discriminant(mo) == mem::discriminant(&MapObject::Antinode(Antinode::new_empty()))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn get_antenna_freq(self: &MapCell) -> Option<u8>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for mo in &self.contents
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match *mo
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
MapObject::Empty => (),
|
|
|
|
|
|
|
|
MapObject::Antinode(_) => (),
|
|
|
|
|
|
|
|
MapObject::Freq(freq) => return Some(freq),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn get_antinode_freq(self: &MapCell) -> Option<u8>
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for mo in &self.contents
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
match *mo
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
MapObject::Empty => (),
|
|
|
|
|
|
|
|
MapObject::Freq(_) => (),
|
|
|
|
|
|
|
|
MapObject::Antinode(anode) => return Some(anode.freq),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
// Map
|
|
|
|
|
|
|
|
//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct Map
|
|
|
|
pub struct Map
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -102,10 +204,10 @@ impl Map
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match *c
|
|
|
|
match *c
|
|
|
|
{
|
|
|
|
{
|
|
|
|
b'.' => parsed_row.push(MapCell::Empty),
|
|
|
|
b'.' => parsed_row.push(MapCell::new(vec![MapObject::Empty])),
|
|
|
|
b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' =>
|
|
|
|
b'0'..=b'9' | b'a'..=b'z' | b'A'..=b'Z' =>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
parsed_row.push(MapCell::Freq(*c));
|
|
|
|
parsed_row.push(MapCell::new(vec![MapObject::Freq(*c)]));
|
|
|
|
|
|
|
|
|
|
|
|
if !antenna_locations.contains_key(c)
|
|
|
|
if !antenna_locations.contains_key(c)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -142,18 +244,22 @@ impl Map
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (j, c) in row.iter().enumerate()
|
|
|
|
for (j, c) in row.iter().enumerate()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if mem::discriminant(c) == mem::discriminant(&MapCell::Freq(0))
|
|
|
|
for o in &c.contents
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if let MapCell::Freq(f) = c
|
|
|
|
if mem::discriminant(o) == mem::discriminant(&MapObject::Freq(0))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if !self.antenna_locations[f].contains(&PointIdx::new(i, j))
|
|
|
|
if let MapObject::Freq(f) = o
|
|
|
|
{
|
|
|
|
{
|
|
|
|
println!("ERROR: Incorrect Antenna Location! Actual: ({}, {}), Locations for this frequency ({}): {:#?}",
|
|
|
|
if !self.antenna_locations[f].contains(&PointIdx::new(i, j))
|
|
|
|
i, j, *f as char, self.antenna_locations);
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
println!("ERROR: Incorrect Antenna Location! Actual: ({}, {}), Locations for this frequency ({}): {:#?}",
|
|
|
|
|
|
|
|
i, j, *f as char, self.antenna_locations);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -164,7 +270,7 @@ impl Map
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if include_antinodes
|
|
|
|
if include_antinodes
|
|
|
|
{
|
|
|
|
{
|
|
|
|
print!("MAP (w/ antinodes):")
|
|
|
|
print!("MAP (w/ antinodes, * = antinode that covers an antenna):")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -175,14 +281,37 @@ impl Map
|
|
|
|
print!("\n\t");
|
|
|
|
print!("\n\t");
|
|
|
|
for (_j, c) in row.iter().enumerate()
|
|
|
|
for (_j, c) in row.iter().enumerate()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
match c
|
|
|
|
let has_antenna = c.has_antenna();
|
|
|
|
|
|
|
|
let mut has_antinode = c.has_antinode();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !include_antinodes
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
has_antinode = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if has_antenna && has_antinode
|
|
|
|
{
|
|
|
|
{
|
|
|
|
MapCell::Empty => print!("."),
|
|
|
|
print!("*");
|
|
|
|
MapCell::Freq(f) =>
|
|
|
|
}
|
|
|
|
|
|
|
|
else if has_antenna
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if let Some(freq) = c.get_antenna_freq()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
print!("{}", *f as char);
|
|
|
|
print!("{}", freq as char);
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
panic!("MapCell says it has an antenna but won't give it's freq!");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if has_antinode
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
print!("#");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
print!(".");
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
println!();
|
|
|
|
println!();
|
|
|
|
@ -195,36 +324,58 @@ impl Map
|
|
|
|
|
|
|
|
|
|
|
|
pub fn dump_map_data_by_freq(self: &Map, filename: &str)
|
|
|
|
pub fn dump_map_data_by_freq(self: &Map, filename: &str)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
let mut file = File::create("foo.txt").expect(&format!("Failed to create file {}", filename));
|
|
|
|
let mut file = File::create(filename).expect(&format!("Failed to create file {}", filename));
|
|
|
|
for (freq, _locations) in &self.antenna_locations
|
|
|
|
println!("DUMPING MAP FILE FOR EACH FREQUENCY");
|
|
|
|
{
|
|
|
|
|
|
|
|
file.write_all(&format!("\nMap for freq: {}", *freq as char).as_bytes()).expect("Failed to write to file!");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (_i, row) in self.map.iter().enumerate()
|
|
|
|
for (freq, _) in &self.antenna_locations
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
println!("Dumping freq: {}", *freq as char);
|
|
|
|
|
|
|
|
file.write_all(&format!("\nMap for freq: {}\n", *freq as char).as_bytes()).expect("Failed to write to dump file [6]");
|
|
|
|
|
|
|
|
for row in &self.map
|
|
|
|
{
|
|
|
|
{
|
|
|
|
file.write_all(b"\n\t").expect("Failed to write to file again");
|
|
|
|
for c in row
|
|
|
|
for (_j, c) in row.iter().enumerate()
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
let mut has_antenna = c.has_antenna();
|
|
|
|
|
|
|
|
|
|
|
|
match c
|
|
|
|
if let Some(ant_freq) = c.get_antenna_freq()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
MapCell::Empty => file.write_all(b".").expect("Failed to write to file (in match statement)"),
|
|
|
|
if ant_freq != *freq
|
|
|
|
MapCell::Freq(f) =>
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if *freq == *f
|
|
|
|
has_antenna = false;
|
|
|
|
{
|
|
|
|
}
|
|
|
|
file.write_all(&format!("{}", *f as char).as_bytes()).expect("Failed to write to file (in match statement 2)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
let mut has_antinode = c.has_antinode();
|
|
|
|
{
|
|
|
|
|
|
|
|
file.write_all(b".").expect("Failed to write to file (in match statement 3)");
|
|
|
|
if let Some(anode_freq) = c.get_antinode_freq()
|
|
|
|
}
|
|
|
|
{
|
|
|
|
},
|
|
|
|
if anode_freq != *freq
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
has_antinode = false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if has_antenna && has_antinode
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file.write_all(b"*").expect("Failed to write to dump file [1]");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if has_antenna
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file.write_all(&format!("{}", *freq as char).as_bytes()).expect("Failed to write to dump file [2]")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if has_antinode
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file.write_all(b"#").expect("Failed to write to dump file [3]");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
file.write_all(b".").expect("Failed to write to dump file [4]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
file.write_all(b"\n").expect("Failed to write to dump file [5]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// an antinode occurs at any point that is perfectly in line with two antennas of the same
|
|
|
|
// an antinode occurs at any point that is perfectly in line with two antennas of the same
|
|
|
|
@ -289,6 +440,7 @@ impl Map
|
|
|
|
|
|
|
|
|
|
|
|
if !antinodes.contains(&antinode)
|
|
|
|
if !antinodes.contains(&antinode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
self.map[antinode.location.i][antinode.location.j].contents.push(MapObject::Antinode(antinode));
|
|
|
|
antinodes.push(antinode);
|
|
|
|
antinodes.push(antinode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|