/// <summary> /// Check road map for some errors that may not have been caught by XSD schema. /// Throws ApplicationException with error descriptions if some errors were found. /// Otherwise returns nothing. /// </summary> /// <param name="roadMap">road map to check</param> private void CheckMapErrors(RoadMap roadMap) { string errors = string.Empty; if (roadMap == null) { errors += "No road map set\n"; } if (roadMap.Nodes.Where(n => n.Role == RoadNodeRole.Start && n.State != RoadNodeState.Crash).Count() != 1) { errors += "There is no exactly one start and not crashed node\n"; } if (roadMap.Nodes.Where(n => n.Role == RoadNodeRole.Finish && n.State != RoadNodeState.Crash).Count() != 1) { errors += "There is no exactly one finish and not crashed node\n"; } errors += CheckLinks(roadMap); if (!string.IsNullOrEmpty(errors)) { throw new ApplicationException("There are errors in the map: \n" + errors); } }
public PathFinder(RoadMap roadMap) { if (roadMap == null) { throw new ApplicationException("Roadmap is not set\n"); } this.roadMap = roadMap; }
static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine(String.Format("Usage: {0} <RoadMapFile.xml>", Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName))); Console.ReadLine(); return; } else { string roadMapFileName = args[0]; XmlDocument roadMapXmlDocument = new XmlDocument(); try { roadMapXmlDocument.Load(roadMapFileName); } catch (Exception) { Console.WriteLine(string.Format("Error: Unable to load XML file {0}. Check if file exists and contains correct XML", roadMapFileName)); Console.ReadLine(); return; } try { RoadMap roadMap = XmlRoadDataParser.ParseRoadMapXml(roadMapXmlDocument); if (roadMap == null) { Console.WriteLine("Error: Unable to parse road map XML"); Console.ReadLine(); return; } PathFinder pathFinder = new PathFinder(roadMap); List <RoadPath> paths = pathFinder.FindAllPaths().OrderBy(p => p.Length).ToList(); UIPrinter.PrintFoundPaths(paths); Console.ReadLine(); } catch (ApplicationException ex) { Console.WriteLine(string.Format("Error: {0}", ex.Message)); Console.ReadLine(); return; } catch (Exception ex) { Console.WriteLine(string.Format("Unknown error: {0}", ex.Message)); Console.ReadLine(); return; } } }
/// <summary> /// Parse source road map XML document /// </summary> /// <param name="sourceXml">road map XML document</param> /// <returns>parsed RoadMap object</returns> public static RoadMap ParseRoadMapXml(XmlDocument sourceXml) { if (sourceXml == null) { return(null); } RoadMap roadMap = new RoadMap(); if (ValidateSchema(sourceXml)) { XmlNode graph = sourceXml.SelectNodes("/graph").Item(0); XmlNodeList nodes = graph.SelectNodes("node"); foreach (XmlNode node in nodes) { RoadNodeRole nodeRole = RoadNodeRole.Normal; if (node.Attributes["role"] != null && node.Attributes["role"].Value == "start") { nodeRole = RoadNodeRole.Start; } else if (node.Attributes["role"] != null && node.Attributes["role"].Value == "finish") { nodeRole = RoadNodeRole.Finish; } RoadNodeState nodeState = RoadNodeState.Ok; if (node.Attributes["status"] != null && node.Attributes["status"].Value == "crash") { nodeState = RoadNodeState.Crash; } int nodeId = Convert.ToInt32(node.Attributes["id"].Value); RoadNode roadNode = new RoadNode(nodeId, nodeRole, nodeState); XmlNodeList links = node.SelectNodes("link"); foreach (XmlNode link in links) { int linkRef = Convert.ToInt32(link.Attributes["ref"].Value); int linkWeight = Convert.ToInt32(link.Attributes["weight"].Value); RoadLink roadLink = new RoadLink(linkWeight, linkRef); roadNode.Links.Add(roadLink); } roadMap.Nodes.Add(roadNode); } } return(roadMap); }
/// <summary> /// Parse source road map XML document /// </summary> /// <param name="sourceXml">road map XML document</param> /// <returns>parsed RoadMap object</returns> public static RoadMap ParseRoadMapXml(XmlDocument sourceXml) { if (sourceXml == null) return null; RoadMap roadMap = new RoadMap(); if (ValidateSchema(sourceXml)) { XmlNode graph = sourceXml.SelectNodes("/graph").Item(0); XmlNodeList nodes = graph.SelectNodes("node"); foreach (XmlNode node in nodes) { RoadNodeRole nodeRole = RoadNodeRole.Normal; if (node.Attributes["role"] != null && node.Attributes["role"].Value == "start") { nodeRole = RoadNodeRole.Start; } else if (node.Attributes["role"] != null &&node.Attributes["role"].Value == "finish") { nodeRole = RoadNodeRole.Finish; } RoadNodeState nodeState = RoadNodeState.Ok; if (node.Attributes["status"] != null && node.Attributes["status"].Value == "crash") { nodeState = RoadNodeState.Crash; } int nodeId = Convert.ToInt32(node.Attributes["id"].Value); RoadNode roadNode = new RoadNode(nodeId, nodeRole, nodeState); XmlNodeList links = node.SelectNodes("link"); foreach (XmlNode link in links) { int linkRef = Convert.ToInt32(link.Attributes["ref"].Value); int linkWeight = Convert.ToInt32(link.Attributes["weight"].Value); RoadLink roadLink = new RoadLink(linkWeight, linkRef); roadNode.Links.Add(roadLink); } roadMap.Nodes.Add(roadNode); } } return roadMap; }
/// <summary> /// Check if all links between nodes are correct. /// </summary> /// <param name="roadMap">road map to check</param> /// <returns>String with errors descriptions or empty string if no errors found</returns> private string CheckLinks(RoadMap roadMap) { string errors = string.Empty; foreach (var node in roadMap.Nodes) { foreach (var link in node.Links) { try { //check if exactly one node exists by link ref RoadNode neighbourByLink = roadMap.Nodes.Where(n => n.Id == link.RefNodeId).Single(); //check if exactly one back link exists and has the same weight as direct link RoadLink backLink = neighbourByLink.Links.Where(l => l.RefNodeId == node.Id && l.Weight == link.Weight).Single(); } catch (InvalidOperationException) { errors += string.Format("Node {0} has wrong link\n", node.Id); } } } return errors; }
/// <summary> /// Check if all links between nodes are correct. /// </summary> /// <param name="roadMap">road map to check</param> /// <returns>String with errors descriptions or empty string if no errors found</returns> private string CheckLinks(RoadMap roadMap) { string errors = string.Empty; foreach (var node in roadMap.Nodes) { foreach (var link in node.Links) { try { //check if exactly one node exists by link ref RoadNode neighbourByLink = roadMap.Nodes.Where(n => n.Id == link.RefNodeId).Single(); //check if exactly one back link exists and has the same weight as direct link RoadLink backLink = neighbourByLink.Links.Where(l => l.RefNodeId == node.Id && l.Weight == link.Weight).Single(); } catch (InvalidOperationException) { errors += string.Format("Node {0} has wrong link\n", node.Id); } } } return(errors); }
/// <summary> /// Check road map for some errors that may not have been caught by XSD schema. /// Throws ApplicationException with error descriptions if some errors were found. /// Otherwise returns nothing. /// </summary> /// <param name="roadMap">road map to check</param> private void CheckMapErrors(RoadMap roadMap) { string errors = string.Empty; if (roadMap == null) errors += "No road map set\n"; if (roadMap.Nodes.Where(n => n.Role == RoadNodeRole.Start && n.State != RoadNodeState.Crash).Count() != 1) { errors += "There is no exactly one start and not crashed node\n"; } if (roadMap.Nodes.Where(n => n.Role == RoadNodeRole.Finish && n.State != RoadNodeState.Crash).Count() != 1) { errors += "There is no exactly one finish and not crashed node\n"; } errors += CheckLinks(roadMap); if (!string.IsNullOrEmpty(errors)) { throw new ApplicationException("There are errors in the map: \n" + errors); } }