Пример #1
0
 /// <summary>
 /// Called when the loc has reached the given to-block of the current route.
 /// </summary>
 public void BlockReached(ILocState loc, IBlockState block)
 {
     if (block == targetBlock)
     {
         TargetReached(loc);
     }
 }
            /// <summary>
            /// Try to move the given loc to a new block.
            /// </summary>
            /// <returns>True if the loc has moved, false if there are no routes available.</returns>
            private bool MoveLoc(FutureAlternativeSet genSet, ILocState loc)
            {
                // Get possible routes
                var currentBlock          = state.GetCurrentBlock(loc);
                var currentBlockEnterSide = state.GetCurrentBlockEnterSide(loc);
                var locDirection          = currentBlockEnterSide.Invert();
                var avoidDirectionChanges = (loc.ChangeDirection == ChangeDirection.Avoid);
                var routeFromFromBlock    = state.RailwayState.GetAllPossibleNonClosedRoutesFromBlock(currentBlock);
                var routeOptions          = routeFromFromBlock.Select(x => state.IsAvailableFor(x, loc, locDirection, avoidDirectionChanges, 0)).ToList();
                var possibleRoutes        = routeOptions.Where(x => x.IsPossible).Select(x => x.Route).ToList();

                // If no routes, then return
                if (!possibleRoutes.Any())
                {
                    return(false);
                }
                if (possibleRoutes.Count > 1)
                {
                    // Create alternate generations
                    foreach (var route in possibleRoutes.Skip(1))
                    {
                        var alternateState = new FutureRouteAvailabilityTester(state);
                        alternateState.TakeRoute(route, loc);
                        genSet.Add(new FutureAlternative(alternateState, generation));
                    }
                }
                // Take the first route
                var firstRoute = possibleRoutes[0];

                state.TakeRoute(firstRoute, loc);
                return(true);
            }
Пример #3
0
 /// <summary>
 /// Select the given loc.
 /// </summary>
 public void SelectLoc(ILocState loc)
 {
     if (selectLoc != null)
     {
         selectLoc(loc);
     }
 }
        /// <summary>
        /// Execute this action on the given loc.
        /// </summary>
        protected override void Execute(ILocState loc, IActionContext context)
        {
            IStateProperty <bool> property;

            switch (Entity.Function)
            {
            case LocFunction.Light:
                property = loc.F0;
                break;

            default:
                if (!loc.TryGetFunctionState(Entity.Function, out property))
                {
                    return;
                }
                break;
            }

            switch (Entity.Command)
            {
            case LocFunctionCommand.On:
                property.Requested = true;
                break;

            case LocFunctionCommand.Off:
                property.Requested = false;
                break;

            case LocFunctionCommand.Toggle:
                property.Requested = !property.Requested;
                break;
            }
        }
Пример #5
0
        /// <summary>
        /// Is the given loc allowed to leave its current block?
        /// </summary>
        internal static bool CanLeaveCurrentBlock(this ILocState loc)
        {
            var currentBlock      = loc.CurrentBlock.Actual;
            var currentBlockGroup = (currentBlock != null) ? currentBlock.BlockGroup : null;

            return((currentBlockGroup == null) || (currentBlockGroup.FirstLocCanLeave));
        }
Пример #6
0
 public bool AllFree(ILocState allowedLoc)
 {
     // Check routes
     if (routes.Any(x => x.IsLocked()))
     {
         return(false);
     }
     // Check blocks in the routes
     foreach (var route in routes)
     {
         var toBlock = route.To;
         var loc     = toBlock.LockedBy;
         if ((loc != null) && (loc != allowedLoc) && (loc.CurrentBlockEnterSide.Actual == route.ToBlockSide))
         {
             // If the loc occupying the blokc cannot change direction, we may not enter this critical section.
             if (loc.ChangeDirection == ChangeDirection.Avoid)
             {
                 return(false);
             }
             // If changing direction in the blockis not allowed, we may not enter this critical section.
             if (toBlock.ChangeDirection == ChangeDirection.Avoid)
             {
                 return(false);
             }
         }
     }
     return(true);
 }
        /// <summary>
        /// The given loc has waited at it's destination.
        /// Let's assign a new route.
        /// </summary>
        /// <returns>The timespan before this method wants to be called again.</returns>
        private TimeSpan OnWaitingForDestinationGroupMinimum(ILocState loc, int generationDelta)
        {
            // Check state
            var state = loc.AutomaticState.Actual;

            if (state != AutoLocState.WaitingForDestinationGroupMinimum)
            {
                log.Warn("Loc {0} in valid state ({1}) at destination timeout.", loc, loc.AutomaticState);
                return(TimeSpan.MaxValue);
            }

            // Log state
            log.Trace("OnWaitingForDestinationGroupMinimum {0}", loc);

            // Do we still control this loc?
            if (!ShouldControlAutomatically(loc))
            {
                RemoveLocFromAutomaticControl(loc);
                return(TimeSpan.MaxValue);
            }

            // Timeout reached?
            if (loc.CanLeaveCurrentBlock() || overrideLeaveCurrentBlock(generationDelta))
            {
                // Yes, let's assign a new route
                loc.AutomaticState.Actual = AutoLocState.AssignRoute;
                return(TimeSpan.Zero);
            }

            // Nothing changed
            return(TimeSpan.MaxValue);
        }
Пример #8
0
        /// <summary>
        /// Select one of the given possible routes.
        /// Returns null if no route should be taken.
        /// </summary>
        /// <param name="possibleRoutes">A list of routes to choose from</param>
        /// <param name="loc">The loc to choose for</param>
        /// <param name="fromBlock">The block from which the next route will leave</param>
        /// <param name="locDirection">The direction the loc is facing in the <see cref="fromBlock"/>.</param>
        public IRouteState SelectRoute(IList <IRouteState> possibleRoutes, ILocState loc, IBlockState fromBlock, BlockSide locDirection)
        {
            // Look for a direct match
            var directRoutes = possibleRoutes.Where(x => x.To == targetBlock).ToList();

            if (directRoutes.Any())
            {
                return(new DefaultRouteSelector().SelectRoute(directRoutes, loc, fromBlock, locDirection));
            }

            // Look for routes that get us closer to the target block.
            var sequences = FindRouteSequences(fromBlock, locDirection.Invert(), targetBlock).ToList();

            // Filter sequences to start with possible routes
            var possibleSequences = sequences.Where(x => possibleRoutes.Contains(x.First)).OrderBy(x => x.Length).ToList();

            // Any sequences left?
            if (possibleSequences.Count == 0)
            {
                return(null);
            }

            // Take the first possible sequence.
            return(possibleSequences[0].First);
        }
        /// <summary>
        /// Check that the designated route is ready and if so, start the loc.
        /// </summary>
        /// <returns>The timespan before this method wants to be called again.</returns>
        private TimeSpan OnWaitingForRouteReady(ILocState loc)
        {
            // Check state
            if (loc.AutomaticState.Actual != AutoLocState.WaitingForAssignedRouteReady)
            {
                log.Warn("Cannot start running loc {0} in {1} state.", loc, loc.AutomaticState);
                return(TimeSpan.MaxValue);
            }

            // Log state
            log.Trace("OnWaitingForRouteReady{0}", loc);

            // If the route ready?
            var route = loc.CurrentRoute.Actual;

            if (!route.Route.IsPrepared)
            {
                // Make sure we stop
                loc.Speed.Requested = 0;
                // We're not ready yet
                return(TimeSpan.FromMinutes(1));
            }

            // Set to max speed
            loc.Speed.Requested = loc.GetMaximumSpeed(route.Route);

            // Update state
            loc.AutomaticState.Actual = AutoLocState.Running;

            // Already look for a next route
            ChooseNextRoute(loc);

            return(TimeSpan.MaxValue);
        }
 /// <summary>
 /// Should the given loc be controlled automatically?
 /// </summary>
 private bool ShouldControlAutomatically(ILocState loc)
 {
     return
         (loc.ControlledAutomatically.Requested &&
          !Stopping &&
          !disposing);
 }
        /// <summary>
        /// Choose an available route from the given block.
        /// </summary>
        /// <param name="loc">The loc a route should be choosen for</param>
        /// <param name="fromBlock">The starting block of the route</param>
        /// <param name="locDirection">The direction the loc is facing in the <see cref="fromBlock"/>.</param>
        /// <param name="avoidDirectionChanges">If true, routes requiring a direction change will not be considered, unless there is no alternative.</param>
        /// <returns>Null if not route is available.</returns>
        private IRouteState ChooseRoute(ILocState loc, IBlockState fromBlock, BlockSide locDirection, bool avoidDirectionChanges, int generationDelta)
        {
            // Gather possible routes.
            var routeFromFromBlock = railwayState.GetAllPossibleNonClosedRoutesFromBlock(fromBlock).ToList();
            var routeOptions       = routeFromFromBlock.Select(x => routeAvailabilityTester.IsAvailableFor(x, loc, locDirection, avoidDirectionChanges, generationDelta)).ToList();
            var possibleRoutes     = routeOptions.Where(x => x.IsPossible).Select(x => x.Route).ToList();

            loc.LastRouteOptions.Actual = routeOptions.ToArray();

            if (possibleRoutes.Any())
            {
                // Use the route selector to choose a next route
                var selector = loc.RouteSelector;
                var selected = selector.SelectRoute(possibleRoutes, loc, fromBlock, locDirection);
                if (selected == null)
                {
                    log.Info("No route selected for {0} [from {1} {2}]. Available routes: {3}", loc, fromBlock, locDirection, string.Join(", ", possibleRoutes.Select(x => x.ToString()).ToArray()));
                }
                else
                {
                    log.Info("Selected route {0} for {1} [from {2} {3}]", selected, loc, fromBlock, locDirection);
                }
                return(selected);
            }

            log.Info("No possible routes for {0} [from {1} {2}]", loc, fromBlock, locDirection);

            // No available routes
            return(null);
        }
        /// <summary>
        /// Try to choose a next route, unless the target block of the current route
        /// is set to wait.
        /// </summary>
        /// <returns>True if a next route has been chosen.</returns>
        private bool ChooseNextRoute(ILocState loc)
        {
            // Should we wait in the destination block?
            var route = loc.CurrentRoute.Actual;

            if ((route == null) ||
                (loc.WaitAfterCurrentRoute.Actual) ||
                (loc.HasNextRoute()) ||
                !ShouldControlAutomatically(loc))
            {
                // No need to choose a next route
                return(false);
            }

            // The loc can continue (if a free route is found)
            var nextRoute = ChooseRoute(loc, route.Route.To, route.Route.ToBlockSide.Invert(), true, 0);

            if (nextRoute == null)
            {
                // No route available
                return(false);
            }

            // We have a next route
            nextRoute.Lock(loc);
            loc.NextRoute.Actual = nextRoute;

            // Set all junctions correct
            nextRoute.Prepare();
            return(true);
        }
Пример #13
0
        /// <summary>
        /// Send the loc direction and F1-F4 of the given loc towards the railway.
        /// </summary>
        /// <return>True on success</return>
        public bool SendLocDirectionAndFunctions(ILocState loc)
        {
            log.Trace("SendLocDirectionAndFunctions: {0}", loc);
            var slot = RequestSlot(loc);

            if (slot == null)
            {
                log.Error("No slot available for {0}", loc);
                return(false);
            }

            // Send loc direction
            log.Trace("Send: LocoDirFuncRequest: slot={0}, direction={1}", slot.SlotNumber, loc.Direction.Requested);
            var forward = (loc.Direction.Requested == LocDirection.Forward);
            var f1      = loc.GetFunctionRequestedState(LocFunction.F1);
            var f2      = loc.GetFunctionRequestedState(LocFunction.F2);
            var f3      = loc.GetFunctionRequestedState(LocFunction.F3);
            var f4      = loc.GetFunctionRequestedState(LocFunction.F4);
            var dirMsg  = new LocoDirFuncRequest(slot.SlotNumber,
                                                 forward, loc.F0.Requested, f1, f2, f3, f4);

            dirMsg.Execute(lb);
            slot.Touch();
            return(true);
        }
Пример #14
0
 /// <summary>
 /// Fire the actions attached to the entering destination trigger.
 /// </summary>
 public void FireEnteringDestinationTrigger(ILocState loc)
 {
     if (!enteringDestinationTrigger.IsEmpty)
     {
         RailwayState.Dispatcher.PostAction(() => enteringDestinationTrigger.Execute(new ActionContext(loc)));
     }
 }
Пример #15
0
 /// <summary>
 /// Fire the actions attached to the destination reached trigger.
 /// </summary>
 public void FireDestinationReachedTrigger(ILocState loc)
 {
     if (!destinationReachedTrigger.IsEmpty)
     {
         RailwayState.Dispatcher.PostAction(() => destinationReachedTrigger.Execute(new ActionContext(loc)));
     }
 }
Пример #16
0
        /// <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));
        }
Пример #17
0
 /// <summary>
 /// Gets/sets the slot for the given loc.
 /// </summary>
 /// <returns>Null if not found</returns>
 public Slot this[ILocState loc]
 {
     get
     {
         if (loc == null)
         {
             throw new ArgumentNullException("loc");
         }
         var entry = slots.FirstOrDefault(x => (x != null) && (x.Loc == loc));
         return((entry != null) ? entry.Slot : null);
     }
     set
     {
         if (value == null)
         {
             for (var i = 0; i < slots.Length; i++)
             {
                 if ((slots[i] != null) && (slots[i].Loc == loc))
                 {
                     slots[i] = null;
                 }
             }
         }
         else
         {
             slots[value.SlotNumber] = new SlotWithLoc(value, 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 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>
 /// Remove the given loc from the list of automatically controlled locs.
 /// </summary>
 private void RemoveLocFromAutomaticControl(ILocState loc)
 {
     log.Info("Removing {0} from auto-loc-list", loc);
     autoLocs.Remove(loc);
     loc.AutomaticState.Actual          = AutoLocState.AssignRoute;
     loc.ControlledAutomatically.Actual = false;
     loc.PossibleDeadlock.Actual        = false;
 }
Пример #20
0
 /// <summary>
 /// Can the given underlying entity be locked by the intended owner?
 /// </summary>
 protected override bool CanLockUnderlyingEntity(ILockableState entity, ILocState owner, out ILocState lockedBy)
 {
     if (base.CanLockUnderlyingEntity(entity, owner, out lockedBy))
     {
         return(true);
     }
     return((entity == From) && entity.IsLockedBy(owner));
 }
Пример #21
0
        public void SelectLoc(ILocState value)
        {
            var item = lvLocs.Items.Cast <LocItem>().FirstOrDefault(x => x.LocState == value);

            if (item != null)
            {
                item.Selected = true;
            }
        }
Пример #22
0
        /// <summary>
        /// SetFunctionActualState set the actual state of a function in the given loc.
        /// </summary>
        public static void SetFunctionActualState(this ILocState loc, LocFunction function, bool value)
        {
            IStateProperty <bool> state;

            if (loc.TryGetFunctionState(function, out state))
            {
                state.Actual = value;
            }
        }
 /// <summary>
 /// Loc has been reset.
 /// </summary>
 private void OnAfterResetLoc(ILocState loc)
 {
     // Loc could have "occupied" sensors which have now been released.
     // Update sensors.
     foreach (var sensor in railwayState.SensorStates)
     {
         OnSensorActiveChanged(sensor);
     }
 }
Пример #24
0
        /// <summary>
        /// Send the speed and direction of the given loc towards the railway.
        /// </summary>
        protected override void OnSendLocSpeedAndDirection(ILocState loc)
        {
            Log.Trace("OnSendLocSpeedAndDirection: {0}", loc);
            try
            {
                var forward = (loc.Direction.Requested == LocDirection.Forward);
                var f1      = loc.GetFunctionRequestedState(LocFunction.F1);
                var f2      = loc.GetFunctionRequestedState(LocFunction.F2);
                var f3      = loc.GetFunctionRequestedState(LocFunction.F3);
                var f4      = loc.GetFunctionRequestedState(LocFunction.F4);
                client.LocCommand(loc.Address.ValueAsInt, loc.SpeedInSteps.Requested, forward, loc.F0.Requested, f1, f2, f3, f4);
                loc.Direction.Actual = loc.Direction.Requested;
                loc.Speed.Actual     = loc.Speed.Requested;
                loc.F0.Actual        = loc.F0.Requested;
                loc.SetFunctionActualState(LocFunction.F1, f1);
                loc.SetFunctionActualState(LocFunction.F2, f2);
                loc.SetFunctionActualState(LocFunction.F3, f3);
                loc.SetFunctionActualState(LocFunction.F4, f4);

                var f5 = loc.GetFunctionRequestedState(LocFunction.F5);
                var f6 = loc.GetFunctionRequestedState(LocFunction.F6);
                var f7 = loc.GetFunctionRequestedState(LocFunction.F7);
                var f8 = loc.GetFunctionRequestedState(LocFunction.F8);
                client.LocFunctions(loc.Address.ValueAsInt, f1, f2, f3, f4, f5, f6, f7, f8);
                loc.SetFunctionActualState(LocFunction.F1, f1);
                loc.SetFunctionActualState(LocFunction.F2, f2);
                loc.SetFunctionActualState(LocFunction.F3, f3);
                loc.SetFunctionActualState(LocFunction.F4, f4);
                loc.SetFunctionActualState(LocFunction.F5, f5);
                loc.SetFunctionActualState(LocFunction.F6, f6);
                loc.SetFunctionActualState(LocFunction.F7, f7);
                loc.SetFunctionActualState(LocFunction.F8, f8);

                var f9  = loc.GetFunctionRequestedState(LocFunction.F9);
                var f10 = loc.GetFunctionRequestedState(LocFunction.F10);
                var f11 = loc.GetFunctionRequestedState(LocFunction.F11);
                var f12 = loc.GetFunctionRequestedState(LocFunction.F12);
                var f13 = loc.GetFunctionRequestedState(LocFunction.F13);
                var f14 = loc.GetFunctionRequestedState(LocFunction.F14);
                var f15 = loc.GetFunctionRequestedState(LocFunction.F15);
                var f16 = loc.GetFunctionRequestedState(LocFunction.F16);
                client.LocFunctions2(loc.Address.ValueAsInt, f9, f10, f11, f12, f13, f14, f15, f16);
                loc.SetFunctionActualState(LocFunction.F9, f9);
                loc.SetFunctionActualState(LocFunction.F10, f10);
                loc.SetFunctionActualState(LocFunction.F11, f11);
                loc.SetFunctionActualState(LocFunction.F12, f12);
                loc.SetFunctionActualState(LocFunction.F13, f13);
                loc.SetFunctionActualState(LocFunction.F14, f14);
                loc.SetFunctionActualState(LocFunction.F15, f15);
                loc.SetFunctionActualState(LocFunction.F16, f16);
            }
            catch (Exception ex)
            {
                Log.Warn("Loc command failed: " + ex);
            }
        }
Пример #25
0
        /// <summary>
        /// GetFunctionActualState returns the actual state of a function in the given loc.
        /// If no such function exists, false is returned.
        /// </summary>
        public static bool GetFunctionActualState(this ILocState loc, LocFunction function)
        {
            IStateProperty <bool> state;

            if (loc.TryGetFunctionState(function, out state))
            {
                return(state.Actual);
            }
            return(false);
        }
            /// <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();
            }
Пример #27
0
 /// <summary>
 /// Save the current block state of the given loc.
 /// </summary>
 public void SetLocState(IRailwayState railwayState, ILocState loc, IBlockState currentBlock, BlockSide currentBlockEnterSide, LocDirection currentDirection)
 {
     // Write assignment
     using (var key = Registry.CurrentUser.CreateSubKey(GetKey(loc)))
     {
         key.SetValue(CurrentBlock, (currentBlock != null) ? currentBlock.EntityId : string.Empty);
         key.SetValue(CurrentBlockEnterSide, (currentBlockEnterSide == BlockSide.Back) ? 0 : 1);
         key.SetValue(CurrentDirection, (currentDirection == LocDirection.Forward) ? 0 : 1);
     }
 }
Пример #28
0
        /// <summary>
        /// Send the speed and direction of the given loc towards the railway.
        /// </summary>
        protected override void OnSendLocSpeedAndDirection(ILocState loc)
        {
            Log.Trace("OnSendLocSpeedAndDirection: {0}", loc);
            var direction = (loc.Direction.Requested == LocDirection.Forward);
            var packet    = Packets.CreateSpeedAndDirection(loc.Address.ValueAsInt, (byte)loc.SpeedInSteps.Requested, direction, loc.SpeedSteps);
            var data      = PacketTranslater.Translate(packet);

            sender.SendSpeedAndDirection(loc.Address.ValueAsInt, data);
            loc.Direction.Actual = loc.Direction.Requested;
            loc.Speed.Actual     = loc.Speed.Requested;
        }
Пример #29
0
        /// <summary>
        /// Put the data from the loc state into this slot.
        /// </summary>
        protected void UpdateSlotFromLoc(Slot slot, ILocState l)
        {
            slot.Address = l.Address.ValueAsInt;
            var spd = l.SpeedInSteps.Actual;

            slot.Speed = (spd == 1) ? 2 : spd;
            var dirf = DirFunc.None;

            if (l.Direction.Actual == LocDirection.Reverse)
            {
                dirf |= DirFunc.Direction;
            }
            if (l.F0.Actual)
            {
                dirf |= DirFunc.F0;
            }
            if (l.GetFunctionActualState(LocFunction.F1))
            {
                dirf |= DirFunc.F1;
            }
            if (l.GetFunctionActualState(LocFunction.F2))
            {
                dirf |= DirFunc.F2;
            }
            if (l.GetFunctionActualState(LocFunction.F3))
            {
                dirf |= DirFunc.F3;
            }
            if (l.GetFunctionActualState(LocFunction.F4))
            {
                dirf |= DirFunc.F4;
            }
            slot.DirF = dirf;
            var snd = Sound.None;

            if (l.GetFunctionActualState(LocFunction.F5))
            {
                snd |= Sound.Snd1;
            }
            if (l.GetFunctionActualState(LocFunction.F6))
            {
                snd |= Sound.Snd2;
            }
            if (l.GetFunctionActualState(LocFunction.F7))
            {
                snd |= Sound.Snd3;
            }
            if (l.GetFunctionActualState(LocFunction.F8))
            {
                snd |= Sound.Snd4;
            }
            slot.Sound = snd;
        }
Пример #30
0
 /// <summary>
 /// Prepare this state for use in a live railway.
 /// Make sure all relevant connections to other state objects are resolved.
 /// </summary>
 /// <returns>True if the entity is now ready for use in a live railway, false otherwise.</returns>
 protected override bool TryPrepareForUse(IStateUserInterface ui, IStatePersistence statePersistence)
 {
     if (Entity.Loc != null)
     {
         loc = RailwayState.LocStates[Entity.Loc];
         if (loc == null)
         {
             return(false);
         }
     }
     return(true);
 }