Changed segment container from Vec to HashMap.
This commit is contained in:
parent
2db8b1f9e9
commit
a7b3e4b745
1 changed files with 43 additions and 76 deletions
|
@ -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();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue