/// <summary>
        /// Route ploan for downstream exits
        /// </summary>
        /// <param name="downstreamPoints"></param>
        /// <param name="goal"></param>
        private void DetermineDownstreamPointRouteTimes(List<DownstreamPointOfInterest> downstreamPoints, INavigableNode goal, ArbiterWay aw)
        {
            // so, for each exit downstream we need to plan from the end of each interconnect to the goal
            foreach (DownstreamPointOfInterest dpoi in downstreamPoints)
            {
                // check if exit
                if (dpoi.IsExit)
                {
                    // current best time
                    double bestCurrent = Double.MaxValue;
                    List<INavigableNode> bestRoute = null;
                    ArbiterInterconnect bestInterconnect = null;

                    // fake node
                    FakeExitNode fen = new FakeExitNode(dpoi.PointOfInterest);

                    // init fields
                    double timeCost;
                    List<INavigableNode> routeNodes;

                    // plan
                    this.Plan(fen, goal, out routeNodes, out timeCost);

                    bestCurrent = timeCost;
                    bestRoute = routeNodes;
                    bestInterconnect = routeNodes.Count > 1 ? fen.GetEdge(routeNodes[1]) : null;

                    // plan from each interconnect to find the best time from exit
                    /*foreach (ArbiterInterconnect ai in dpoi.PointOfInterest.Exits)
                    {
                        // init fields
                        double timeCost;
                        List<INavigableNode> routeNodes;

                        // plan
                        this.Plan(ai.End, goal, out routeNodes, out timeCost);

                        // check
                        if (timeCost < bestCurrent)
                        {
                            bestCurrent = timeCost;
                            bestRoute = routeNodes;
                            bestInterconnect = ai;
                        }
                    }*/

                    // set best
                    dpoi.RouteTime = bestCurrent;
                    dpoi.BestRoute = bestRoute;
                    dpoi.BestExit = bestInterconnect;
                }
            }
        }
        /// <summary>
        /// Route ploan for downstream exits
        /// </summary>
        /// <param name="downstreamPoints"></param>
        /// <param name="goal"></param>
        private void RouteTimes(List<DownstreamPointOfInterest> downstreamPoints, INavigableNode goal)
        {
            // check if we are planning over the correct goal
            if (this.currentTimes.Key != CoreCommon.Mission.MissionCheckpoints.Peek().CheckpointNumber
                || this.currentTimes.Value == null)
            {
                // create new lookup
                this.currentTimes = new KeyValuePair<int, Dictionary<ArbiterWaypointId, DownstreamPointOfInterest>>(
                    CoreCommon.Mission.MissionCheckpoints.Peek().CheckpointNumber, new Dictionary<ArbiterWaypointId, DownstreamPointOfInterest>());
            }

            // so, for each exit downstream we need to plan from the end of each interconnect to the goal
            foreach (DownstreamPointOfInterest dpoi in downstreamPoints)
            {
                // container flag
                bool contains = this.currentTimes.Value.ContainsKey(dpoi.PointOfInterest.WaypointId);

                // check if exit
                if (dpoi.IsExit && !contains)
                {
                    // fake node
                    FakeExitNode fen = new FakeExitNode(dpoi.PointOfInterest);

                    // init fields
                    double timeCost;
                    List<INavigableNode> routeNodes;

                    // plan
                    this.Plan(fen, goal, out routeNodes, out timeCost);

                    // set best
                    dpoi.RouteTime = timeCost;
                    dpoi.BestRoute = routeNodes;
                    dpoi.BestExit = routeNodes.Count > 1 ? fen.GetEdge(routeNodes[1]) : null;

                    // add to keepers
                    this.currentTimes.Value.Add(dpoi.PointOfInterest.WaypointId, dpoi.Clone());
                }
                else if (dpoi.IsExit && contains)
                {
                    DownstreamPointOfInterest tmp = this.currentTimes.Value[dpoi.PointOfInterest.WaypointId];

                    if (tmp.BestExit == null)
                    {
                        ArbiterOutput.Output("NAV RouteTimes: Removing exit with no valid route: " + dpoi.PointOfInterest.WaypointId.ToString());

                        // remove
                        this.currentTimes.Value.Remove(dpoi.PointOfInterest.WaypointId);
                        dpoi.PointOfInterest = (ArbiterWaypoint)CoreCommon.RoadNetwork.ArbiterWaypoints[dpoi.PointOfInterest.WaypointId];

                        // fake node
                        FakeExitNode fen = new FakeExitNode(dpoi.PointOfInterest);

                        // init fields
                        double timeCost;
                        List<INavigableNode> routeNodes;

                        // plan
                        this.Plan(fen, goal, out routeNodes, out timeCost);

                        // set best
                        dpoi.RouteTime = timeCost;
                        dpoi.BestRoute = routeNodes;
                        dpoi.BestExit = routeNodes.Count > 1 ? fen.GetEdge(routeNodes[1]) : null;

                        // add to keepers
                        this.currentTimes.Value.Add(dpoi.PointOfInterest.WaypointId, dpoi);
                    }
                    else
                    {
                        dpoi.RouteTime = tmp.RouteTime;
                        dpoi.BestRoute = tmp.BestRoute;
                        dpoi.BestExit = tmp.BestExit;
                    }
                }
            }
        }