Changed segment container from Vec to HashMap.

This commit is contained in:
Patrick Marsee 2025-04-16 23:05:23 -04:00
parent 2db8b1f9e9
commit a7b3e4b745

View file

@ -3,8 +3,8 @@ use crate::rail_segment;
use crate::rail_segment::RailSegment; use crate::rail_segment::RailSegment;
use crate::rail_connector::RailConnector; use crate::rail_connector::RailConnector;
use crate::graph_coord::GraphCoord; use crate::graph_coord::GraphCoord;
//use std::collections::HashMap; use std::collections::HashMap;
use std::vec::Vec; //use std::vec::Vec;
//use std::string::String; //use std::string::String;
use std::error; use std::error;
use std::fmt; use std::fmt;
@ -27,7 +27,7 @@ impl fmt::Display for Error {
impl error::Error for Error {} impl error::Error for Error {}
pub struct RailGraph { pub struct RailGraph {
segments: Vec<Option<Box<dyn RailSegment>>>, segments: HashMap<usize, Box<dyn RailSegment>>,
// segment_names: HashMap<String, usize>, // segment_names: HashMap<String, usize>,
min_available_index: usize, min_available_index: usize,
@ -36,7 +36,7 @@ pub struct RailGraph {
impl RailGraph { impl RailGraph {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
segments: Vec::<Option::<Box::<dyn RailSegment>>>::new(), segments: HashMap::<usize, Box::<dyn RailSegment>>::new(),
//segment_names: {}, //segment_names: {},
min_available_index: 0, min_available_index: 0,
} }
@ -45,34 +45,26 @@ impl RailGraph {
// definition // definition
pub fn get_segment(&self, index: usize) -> Result<&Box<dyn RailSegment>, Error> { pub fn get_segment(&self, index: usize) -> Result<&Box<dyn RailSegment>, Error> {
match &self.segments.get(index) { match &self.segments.get(&index) {
Some(Some(ret)) => Ok(ret), Some(ret) => Ok(ret),
_ => Err(Error::IndexError(index)), _ => Err(Error::IndexError(index)),
} }
} }
pub fn add_segment(&mut self, segment: Box<dyn RailSegment>) -> usize { pub fn add_segment(&mut self, segment: Box<dyn RailSegment>) -> usize {
let ret = self.min_available_index; let ret = self.min_available_index;
if self.segments.len() == self.min_available_index { self.segments.insert(ret, segment);
self.segments.push(Some(segment)); self.min_available_index += 1;
self.min_available_index = self.segments.len();
} else {
self.segments[self.min_available_index] = Some(segment);
self.update_min_available_index();
}
ret ret
} }
pub fn remove_segment(&mut self, index: usize) -> Result<bool, Error> { pub fn remove_segment(&mut self, index: usize) -> Result<bool, Error> {
if index >= self.segments.len() { if !self.validate_index(index) {
return Err(Error::IndexError(index)); return Err(Error::IndexError(index));
} }
self.isolate_segment(index); self.isolate_segment(index);
self.segments[index] = Option::None; self.segments.remove(&index);
if index < self.min_available_index {
self.min_available_index = index;
}
Ok(true) Ok(true)
} }
@ -95,56 +87,47 @@ impl RailGraph {
let old_connection1 = self.get_connection_from_index(index1, endpoint1); let old_connection1 = self.get_connection_from_index(index1, endpoint1);
let old_connection2 = self.get_connection_from_index(index2, endpoint2); let old_connection2 = self.get_connection_from_index(index2, endpoint2);
if let Ok(old_connection) = old_connection1 { if let Ok(old_connection) = old_connection1 {
match &mut self.segments[old_connection.segment_index] { match self.segments.get_mut(&old_connection.segment_index) {
Some(old_segment) => { Some(old_segment) => {
if let Err(e) = old_segment.remove_connection(old_connection.endpoint_index) { if let Err(e) = old_segment.remove_connection(old_connection.endpoint_index) {
return Err(Error::SegmentError(e)); return Err(Error::SegmentError(e));
} }
}, },
None => { None => {
return Err(Error::IndexError(old_connection.segment_index)); return Err(Error::IndexError(old_connection.segment_index));
} },
} }
} }
if let Ok(old_connection) = old_connection2 { if let Ok(old_connection) = old_connection2 {
match &mut self.segments[old_connection.segment_index] { match self.segments.get_mut(&old_connection.segment_index) {
Some(old_segment) => { Some(old_segment) => {
if let Err(e) = old_segment.remove_connection(old_connection.endpoint_index) { if let Err(e) = old_segment.remove_connection(old_connection.endpoint_index) {
return Err(Error::SegmentError(e)); return Err(Error::SegmentError(e));
} }
}, },
None => { None => {
return Err(Error::IndexError(old_connection.segment_index)); return Err(Error::IndexError(old_connection.segment_index));
} },
} }
} }
// Connect them now // Connect them now
let segment1 = &mut self.segments[index1].as_mut().unwrap(); let segment1 = self.segments.get_mut(&index1).unwrap();
let _ = segment1.add_connection(endpoint1, connector1); let _ = segment1.add_connection(endpoint1, connector1);
let segment2 = &mut self.segments[index2].as_mut().unwrap(); let segment2 = self.segments.get_mut(&index2).unwrap();
let _ = segment2.add_connection(endpoint2, connector2); let _ = segment2.add_connection(endpoint2, connector2);
//if let Some(segment1) = &mut self.segments[index1] {
// if let Err(e) = segment1.add_connection(endpoint1, connector1) {
// return Err(Error::SegmentError(e));
// }
//}
//if let Some(segment2) = &mut self.segments[index2] {
// if let Err(e) = segment2.add_connection(endpoint2, connector2) {
// return Err(Error::SegmentError(e));
// }
//}
Ok(true) Ok(true)
} }
pub fn disconnect_endpoint(&mut self, index: usize, endpoint: usize) -> Result<bool, Error> { pub fn disconnect_endpoint(&mut self, index: usize, endpoint: usize) -> Result<bool, Error> {
if index >= self.segments.len() { if !self.validate_index(index) {
return Err(Error::IndexError(index)); return Err(Error::IndexError(index));
} else if !self.validate_endpoint(index, endpoint) {
return Err(Error::SegmentError(rail_segment::Error::EndpointError(endpoint)));
} }
match self.get_connection_from_index(index, endpoint) { match self.get_connection_from_index(index, endpoint) {
Ok(old_connection) => { Ok(old_connection) => {
match &mut self.segments[old_connection.segment_index] { match self.segments.get_mut(&old_connection.segment_index) {
Some(old_segment) => { Some(old_segment) => {
if let Err(e) = old_segment.remove_connection(old_connection.endpoint_index) { if let Err(e) = old_segment.remove_connection(old_connection.endpoint_index) {
return Err(Error::SegmentError(e)); return Err(Error::SegmentError(e));
@ -160,13 +143,10 @@ impl RailGraph {
}, },
} }
if let Some(segment) = &mut self.segments[index] { let segment = self.segments.get_mut(&index).unwrap();
match segment.remove_connection(endpoint) { match segment.remove_connection(endpoint) {
Ok(_) => Ok(true), Ok(_) => Ok(true),
Err(e) => Err(Error::SegmentError(e)), Err(e) => Err(Error::SegmentError(e)),
}
} else {
Err(Error::IndexError(index)) // should never happen since this is already tested in the big match block.
} }
} }
@ -224,21 +204,18 @@ impl RailGraph {
// private // private
fn validate_index(&self, index: usize) -> bool { fn validate_index(&self, index: usize) -> bool {
match &self.segments.get(index) { self.segments.contains_key(&index)
Some(Some(_)) => true,
_ => false,
}
} }
fn validate_endpoint(&self, index: usize, endpoint: usize) -> bool { fn validate_endpoint(&self, index: usize, endpoint: usize) -> bool {
match self.get_segment(index) { match &self.segments.get(&index) {
Ok(segment) => { Some(segment) => {
match segment.check_connection(endpoint) { match segment.check_connection(endpoint) {
Err(rail_segment::Error::EndpointError(_)) => false, Err(rail_segment::Error::EndpointError(_)) => false,
_ => true, _ => true,
} }
}, },
Err(_) => false, None => false,
} }
} }
@ -250,39 +227,29 @@ impl RailGraph {
} }
fn get_connection_from_index(&self, index: usize, endpoint: usize) -> Result<RailConnector, Error> { fn get_connection_from_index(&self, index: usize, endpoint: usize) -> Result<RailConnector, Error> {
match self.get_segment(index) { match &self.segments.get(&index) {
Ok(segment) => Self::get_connection_from_segment(segment, endpoint), Some(segment) => Self::get_connection_from_segment(segment, endpoint),
Err(e) => Err(e), None => Err(Error::IndexError(index)),
} }
} }
fn isolate_segment(&mut self, index: usize) { fn isolate_segment(&mut self, index: usize) {
// Get the old connections // Get the old connections
let mut connections = Vec::<RailConnector>::new(); let mut connections = Vec::<RailConnector>::new();
if let Some(segment) = &self.segments[index] { let segment = &self.segments[&index];
for connection in segment.connection_iter() { for connection in segment.connection_iter() {
connections.push(*connection); connections.push(*connection);
}
} }
// disconnect neighbors // disconnect neighbors
for connection in connections { for connection in connections {
if let Some(old_segment) = &mut self.segments[connection.segment_index] { let old_segment = self.segments.get_mut(&connection.segment_index).unwrap();
let _ = old_segment.remove_connection(connection.endpoint_index); let _ = old_segment.remove_connection(connection.endpoint_index);
}
} }
// reflect the same change in the original segment. // reflect the same change in the original segment.
if let Some(segment) = &mut self.segments[index] { let segment = self.segments.get_mut(&index).unwrap();
segment.remove_all_connections(); segment.remove_all_connections();
}
}
fn update_min_available_index(&mut self) {
// I should just replace this with a heap.
while let Some(_segment) = &self.segments[self.min_available_index] {
self.min_available_index += 1;
}
} }
// Difference from the public version: offset is relative to the segment. // Difference from the public version: offset is relative to the segment.
@ -440,8 +407,8 @@ mod tests {
// test successes // test successes
assert!(match test_graph.remove_segment(1) { Ok(true)=>true, _=>false, }, assert!(match test_graph.remove_segment(1) { Ok(true)=>true, _=>false, },
"Segment was not removed."); "Segment was not removed.");
assert_eq!(test_graph.segments.len(), 3, "Graph has incorrect number of segments."); assert_eq!(test_graph.segments.len(), 2, "Graph has incorrect number of segments.");
assert_eq!(test_graph.min_available_index, 1, "Incorrect min_available_index."); assert_eq!(test_graph.min_available_index, 3, "Incorrect min_available_index.");
let first_segment = test_graph.get_segment(0).unwrap(); let first_segment = test_graph.get_segment(0).unwrap();
assert!(!first_segment.check_connection(1).unwrap(), "Connection 1 wasn't broken."); assert!(!first_segment.check_connection(1).unwrap(), "Connection 1 wasn't broken.");
let second_segment = test_graph.get_segment(2).unwrap(); let second_segment = test_graph.get_segment(2).unwrap();