/// <summary> /// This is the algorithm we use the run scenarios through our rail system. We take a supplied list of routes and traverse all possible scenarios with the specific starting point. /// </summary> /// <param name="routes">List if routes in the train system</param> /// <param name="container">A reference object that we store the scenario data in</param> /// <param name="outerLoop">A boolean that helps us determine what layer of the method we are in</param> private void TraverseRouteScenarios(List <RouteDomainItem> routes, ref RouteScenarioContainer container, bool outerLoop) { foreach (var route in routes) { //if we are in the outer loop and the starting point provided matches the starting point of the route then we need to create a new passenger instance if (outerLoop && route.StartingLocation.CompareTo(container.StartingLocation) == 0) { RoutePassenger passenger = new RoutePassenger() { TravelingToward = route.Destination, DistanceTraveled = route.Distance, Stops = new LinkedList <char>(), RouteMap = new LinkedList <char>(), }; //we use the route map to keep track of everywhere the passenger has been passenger.RouteMap.AddLast(route.StartingLocation); passenger.RouteMap.AddLast(route.Destination); //we use the stops to map everywhere the passenger has arrived passenger.Stops.AddLast(route.Destination); //we create a hash to have an easy way to identify this passenger passenger.SetHash(); container.Passengers.Add(passenger); //We created our passenger, now lets recursively determine how many places he can possibly go in the specified distance TraverseRouteScenarios(routes, ref container, false); }//If we are in a inner loop we can examine our passengers and see if they have divergent options else { for (var i = 0; i < container.Passengers.Count(); i++) { //if the upcoming route is where this passenger is traveling to if (container.Passengers[i].TravelingToward.CompareTo(route.StartingLocation) == 0) { //since we need to preserve scenario data we clone our passenger inorder to create a new instance for tracking purposes var clone = container.Passengers[i].Clone(); clone.Stops.AddLast(route.Destination); clone.RouteMap.AddLast(route.Destination); //since this passenger is divergent from the passenger that may have stopped we will create a new unique identifier clone.SetHash(); clone.DistanceTraveled += route.Distance; clone.TravelingToward = route.Destination; //if we dont have a max distance traveled this passenger would travel forever and probably starve to death //also we need to make sure this clone does not already exist in this universe otherwise we end up with duplicate data //this is why we generated unique identifier with the hash function if (clone.DistanceTraveled < container.MaxDistance && !container.Passengers.Any(m => string.Compare(m.Hash, clone.Hash, true) == 0)) { container.Passengers.Add(clone); //lets traverse all the new possibilities with this new clone TraverseRouteScenarios(routes, ref container, false); } } } } } }
/// <summary> /// We have to do some funky stuff to clone the passenger with new in memory data points to prevent issues with referenced datapoints /// </summary> /// <returns></returns> public RoutePassenger Clone() { var clone = new RoutePassenger() { DistanceTraveled = DistanceTraveled, TravelingToward = TravelingToward, }; clone.Stops = new LinkedList <char>(); foreach (var stop in Stops) { clone.Stops.AddLast(stop); } clone.RouteMap = new LinkedList <char>(); foreach (var stop in RouteMap) { clone.RouteMap.AddLast(stop); } return(clone); }