/// <summary> /// Gets the medium speed of the given loc on the given route. /// </summary> public static int GetMediumSpeed(this ILocState loc, IRouteState route) { var speed = loc.MediumSpeed; var routeSpeed = route.Speed / 100.0; return(Math.Max((int)(speed * routeSpeed), loc.SlowSpeed)); }
private void SelectNextState(IRouteState route) { if (lastSensor != null) { lastSensor.Active.Actual = false; } if (state == States.Initial) { var sensor = route.Sensors.FirstOrDefault(x => route.IsEnteringDestinationSensor(x, loc)); if (sensor != null) { sensor.Active.Actual = true; lastSensor = sensor; state = States.Enter; return; } } // Activate reached sensor { var sensor = route.Sensors.FirstOrDefault(x => route.IsReachedDestinationSensor(x, loc)); if (sensor != null) { sensor.Active.Actual = true; lastSensor = sensor; state = States.Initial; } } }
/// <summary> /// Can the given route be taken by the given loc? /// </summary> /// <param name="route">The route being investigated</param> /// <param name="loc">The loc a route should be choosen for</param> /// <param name="locDirection">The direction the loc is facing in the From block of the given <see cref="route"/>.</param> /// <param name="avoidDirectionChanges">If true, the route is considered not available if a direction change is needed.</param> /// <param name="generationDelta">If larger than 0, look this number of generation less far in the future.</param> /// <returns>True if the route can be locked and no sensor in the route is active (outside current route).</returns> public override IRouteOption IsAvailableFor(IRouteState route, ILocState loc, Model.BlockSide locDirection, bool avoidDirectionChanges, int generationDelta) { // Perform standard testing first var result = base.IsAvailableFor(route, loc, locDirection, avoidDirectionChanges, generationDelta); if (!result.IsPossible) { return(result); } // If last resort, we're ok when critical section is empty. if (generationDelta > 0) { if (route.CriticalSection.IsEmpty) { return(result); } } // Now test future possibilities of the entire railway to detect possible deadlocks. var genSet = new FutureAlternativeSet(this, route, loc); if (!genSet.Test(generationDelta)) { // Not Ok return(new RouteOption(route, RouteImpossibleReason.DeadLock)); } return(result); }
/// <summary> /// Default ctor /// </summary> public RouteOption(IRouteState route, bool isPossible, RouteImpossibleReason reason, string extra) { this.route = route; this.isPossible = isPossible; this.reason = reason; this.extra = extra; }
/// <summary> /// Find the route that is the reverse of the given route. /// </summary> /// <returns>Null if not found</returns> public static IRouteState GetReverse(this IRouteState route) { var from = route.To; var to = route.From; var railway = route.RailwayState; if ((from == null) || (to == null) || (railway == null)) { return(null); } var reverseRoutes = railway.RouteStates.Where(x => (x.From == from) && (x.To == to)); foreach (var iterator in reverseRoutes) { // From side should match if (route.FromBlockSide != iterator.ToBlockSide) { // No match continue; } // To side should match if (route.ToBlockSide != iterator.FromBlockSide) { // No match continue; } // We found it return(iterator); } // Not found return(null); }
/// <summary> /// Default ctor /// </summary> public FutureAlternativeSet(LiveRouteAvailabilityTester live, IRouteState route, ILocState loc) { this.testLoc = loc; minGenerations = live.railwayState.BlockStates.Count; var tester = new FutureRouteAvailabilityTester(live.railwayState); tester.TakeRoute(route, loc); alternatives.Add(new FutureAlternative(tester, 0)); autoLocs = live.railwayState.LocStates.Where(x => x.ControlledAutomatically.Actual && (x.CurrentBlock.Actual != null)).ToList(); }
/// <summary> /// Add the given route to the end of this sequence. /// </summary> public void Add(IRouteState route) { if (sequence.Count > 0) { // Route must start from destination of last route if (sequence[sequence.Count - 1].To != route.From) { throw new ArgumentException("Route does not connect to existing sequence."); } } sequence.Add(route); }
/// <summary> /// Default ctor /// </summary> internal RouteStateForLoc(ILocState loc, IRouteState route) { this.loc = loc; this.route = route; foreach (var @event in route.Events) { var behavior = @event.Behaviors.FirstOrDefault(x => x.AppliesTo(loc)); if (behavior != null) { behaviors[@event.Sensor] = behavior; } } }
/// <summary> /// Is any of the sensors of the given route active? /// Sensors that are also in the current route of the given loc are ignored. /// </summary> protected virtual bool IsAnySensorActive(IRouteState route, ILocState loc) { var activeSensors = route.Sensors.Where(x => x.Active.Actual); var currentRoute = loc.CurrentRoute.Actual; if (currentRoute == null) { // There must be no active sensor return(activeSensors.Any()); } // The loc has a current route. // There must not be any active sensor that is not listed in the current route. return(activeSensors.Any(x => !currentRoute.Route.Contains(x))); }
/// <summary> /// Is the position of this block matching the direction of the route. /// </summary> private bool IsPositionMatchingRoute(IRouteState route) { var block = Block; if (block == route.From) { if (Type == BlockSignalType.Entry) { return(false); } return(Position == route.FromBlockSide); } if (block == route.To) { if (Type == BlockSignalType.Exit) { return(Position == route.ToBlockSide.Invert()); } return(Position == route.ToBlockSide); } // Unknown return(false); }
/// <summary> /// Is there are traffic in the opposite direction of the given route (not including the given loc). /// </summary> protected bool HasTrafficInOppositeDirection(IRouteState route, ILocState currentLoc, int stepsRemaining, out IBlockState blockContainingTraffic) { if (stepsRemaining <= 0) { // We've taken to long to find opposing traffic blockContainingTraffic = null; return(false); } var toBlock = route.To; if (HasTrafficInOppositeDirection(toBlock, route.ToBlockSide, currentLoc)) { blockContainingTraffic = toBlock; return(true); } // Check next routes var nextRoutes = railwayState.GetAllPossibleNonClosedRoutesFromBlock(toBlock).ToList(); //var nextRoutes = railwayState.GetAllPossibleNonClosedRoutesFromBlock(toBlock, locDirection).ToList(); if (nextRoutes.Count == 0) { // No next routes at all, we do no longer care about opposing traffic blockContainingTraffic = null; return(false); } if (nextRoutes.Count > 1) { // Multiple next routes, we stop now blockContainingTraffic = null; return(false); } // Only one route possible, check that for opposing traffic return(HasTrafficInOppositeDirection(nextRoutes[0], currentLoc, stepsRemaining - 1, out blockContainingTraffic)); }
/// <summary> /// Create an 1 length sequence. /// </summary> public RouteSequence(IRouteState first) { sequence = new List <IRouteState> { first }; }
/// <summary> /// Default ctor /// </summary> public CriticalSectionBuilder(IRouteState route, IRailwayState railway) { this.route = route; this.railway = railway; }
/// <summary> /// Default ctor /// </summary> public BlockAndSide(IRouteState route) { block = route.To; enterSide = route.ToBlockSide; }
/// <summary> /// Can the given route be locked for the given loc? /// </summary> protected override bool CanLock(IRouteState route, ILocState loc, out ILocState lockedBy) { lockedBy = GetLockedBy(route.To); return((lockedBy == null) || (lockedBy == loc)); }
/// <summary> /// Let the given loc take the given route. /// </summary> public void TakeRoute(IRouteState route, ILocState loc) { locStates[loc].ChangeTo(route.To, route.ToBlockSide); }
/// <summary> /// Is any of the sensors of the given route active? /// Sensors that are also in the current route of the given loc are ignored. /// </summary> protected override bool IsAnySensorActive(IRouteState route, ILocState loc) { return(false); }
/// <summary> /// Is the critical section for the given route free for the given loc? /// </summary> protected override bool IsCriticalSectionFree(IRouteState route, ILocState loc) { return(true); }
/// <summary> /// Is the critical section for the given route free for the given loc? /// </summary> protected virtual bool IsCriticalSectionFree(IRouteState route, ILocState loc) { return(route.CriticalSection.AllFree(loc)); }
/// <summary> /// Can the given route be taken by the given loc? /// </summary> /// <param name="route">The route being investigated</param> /// <param name="loc">The loc a route should be choosen for</param> /// <param name="locDirection">The direction the loc is facing in the From block of the given <see cref="route"/>.</param> /// <param name="avoidDirectionChanges">If true, the route is considered not available if a direction change is needed.</param> /// <param name="generationDelta">If larger than 0, look this number of generation less far in the future.</param> /// <returns>True if the route can be locked and no sensor in the route is active (outside current route).</returns> public virtual IRouteOption IsAvailableFor(IRouteState route, ILocState loc, BlockSide locDirection, bool avoidDirectionChanges, int generationDelta) { ILocState lockedBy; if (!CanLock(route, loc, out lockedBy)) { // Cannot lock return(new RouteOption(route, RouteImpossibleReason.Locked, (lockedBy != null) ? lockedBy.Description : "?")); } // Route closed? if (route.Closed) { // Route closed return(new RouteOption(route, RouteImpossibleReason.Closed)); } // Target blocked closed? if (route.To.Closed.Actual || route.To.Closed.Requested) { // Destination closed. return(new RouteOption(route, RouteImpossibleReason.DestinationClosed)); } // Check opposite traffic IBlockState blockContainingTraffic; var maxSteps = Math.Max(1, railwayState.BlockStates.Count - generationDelta); if (HasTrafficInOppositeDirection(route, loc, maxSteps, out blockContainingTraffic)) { // Traffic in opposite direction found return(new RouteOption(route, RouteImpossibleReason.OpposingTraffic, blockContainingTraffic.Description)); } // Check critical section of route if (!IsCriticalSectionFree(route, loc)) { // Some route in critical section not free return(new RouteOption(route, RouteImpossibleReason.CriticalSectionOccupied)); } // Check direction if (route.IsDirectionChangeNeeded(locDirection)) { if (avoidDirectionChanges) { // Do not take this route because a direction change would be needed. return(new RouteOption(route, RouteImpossibleReason.DirectionChangeNeeded)); } if (loc.ChangeDirection != ChangeDirection.Allow) { // Loc does not allow direction changes if (!route.From.IsDeadEnd) { return(new RouteOption(route, RouteImpossibleReason.DirectionChangeNeeded)); } // Loc will reverse out of a dead end } if (route.From.ChangeDirection != ChangeDirection.Allow) { // From block does not allowed direction changes return(new RouteOption(route, RouteImpossibleReason.DirectionChangeNeeded)); } } // Check permissions if (!route.Permissions.Evaluate(loc)) { // Loc not allowed by permissions return(new RouteOption(route, RouteImpossibleReason.NoPermission)); } // Check sensor states if (IsAnySensorActive(route, loc)) { // Route is not available return(new RouteOption(route, RouteImpossibleReason.SensorActive)); } // Route is available return(new RouteOption(route, true, RouteImpossibleReason.None)); }
/// <summary> /// Default ctor /// </summary> public RouteOption(IRouteState route, bool isPossible, RouteImpossibleReason reason) : this(route, isPossible, reason, null) { }
/// <summary> /// Default ctor /// </summary> public RouteOption(IRouteState route, RouteImpossibleReason reason) : this(route, false, reason, null) { }
/// <summary> /// Default ctor /// </summary> public RouteOption(IRouteState route, RouteImpossibleReason reason, string extra) : this(route, false, reason, extra) { }
/// <summary> /// Is is needed for a loc facing in the given direction (in the From block of the given route) /// to chance direction when taking this route? /// </summary> /// <param name="route">The route being investigated</param> /// <param name="locDirection">The direction the loc is facing in the From block of the given <see cref="route"/>.</param> internal static bool IsDirectionChangeNeeded(this IRouteState route, BlockSide locDirection) { var fromSide = route.FromBlockSide; return(fromSide != locDirection); }
/// <summary> /// Can the given route be locked for the given loc? /// </summary> protected virtual bool CanLock(IRouteState route, ILocState loc, out ILocState lockedBy) { return(route.CanLock(loc, out lockedBy)); }