Пример #1
0
        /// <summary> Call of GetWeaveItem(..) can be speed up by NOT reading the weave file on any call. </summary>
        /// <param name="dispatcher"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public static TrackWeaveItem GetWeaveItem(Dispatcher.Dispatcher dispatcher, int x, int y)
        {
            var m = dispatcher.Model as ViewModels.RailwayEssentialModel;

            if (m == null)
            {
                return(null);
            }

            var prj = m.Project;

            var             weaveFilepath = Path.Combine(prj.Dirpath, prj.Track.Weave);
            TrackWeaveItems weaverItems   = new TrackWeaveItems();

            if (!weaverItems.Load(weaveFilepath))
            {
                return(null);
            }

            foreach (var e in weaverItems.Items)
            {
                if (e?.VisuX == x && e.VisuY == y)
                {
                    return(e);
                }
            }

            return(null);
        }
Пример #2
0
        public bool InitializeWeaving(TrackPlanParser.Track track, string weaveFilepath)
        {
            if (_track == null)
            {
                _track = track;
            }

            if (_trackWeaver == null)
            {
                _trackWeaver = new TrackWeaver.TrackWeaver();
            }
            else
            {
                _trackWeaver.WovenSeam.Clear();
            }

            TrackWeaveItems weaverItems = new TrackWeaveItems();

            if (!weaverItems.Load(weaveFilepath))
            {
                return(false);
            }

            foreach (var item in weaverItems.Items)
            {
                if (item == null)
                {
                    continue;
                }

                switch (item.Type)
                {
                case WeaveItemT.S88:
                {
                    var s88Item = _dataProvider.GetObjectBy(item.ObjectId) as S88;

                    if (s88Item != null)
                    {
                        var trackObject = _track.Get(item.VisuX, item.VisuY);

                        if (trackObject != null)
                        {
                            _trackWeaver.Link(s88Item, trackObject,
                                              () =>
                                {
                                    var res = s88Item.Pin((uint)item.Pin);
                                    return(new TrackCheckResult {
                                        State = res
                                    });
                                });
                        }
                    }
                }
                break;

                case WeaveItemT.Switch:
                {
                    var switchItem = _dataProvider.GetObjectBy(item.ObjectId) as Switch;

                    if (switchItem != null)
                    {
                        var trackObject = _track.Get(item.VisuX, item.VisuY);

                        switchItem.InvertCommand = item.InvertSwitch;

                        _trackWeaver.Link(switchItem, trackObject,
                                          () => {
                                TrackCheckResult.SwitchDirection direction = TrackCheckResult.SwitchDirection.Straight;

                                if (switchItem.State == 0)
                                {
                                    direction = TrackCheckResult.SwitchDirection.Straight;
                                }
                                else
                                {
                                    direction = TrackCheckResult.SwitchDirection.Turn;
                                }

                                return(new TrackCheckResult {
                                    Direction = direction
                                });
                            });
                    }
                }
                break;

                    // TODO add other item weaves :-D
                }
            }

            return(true);
        }
        public void Start()
        {
            if (_cts != null)
            {
                return;
            }

            _cts = new CancellationTokenSource();
            _tkn = _cts.Token;

            Task = new Task(() =>
            {
                // **********************************************************************
                // ** Route Thread
                // **********************************************************************

                bool isRouteSet           = false;                 // flag initialization of route's handling thread
                Locomotive locObject      = null;                  // the current locomotive on the route
                List <ItemData> routeData = new List <ItemData>(); // s88 and switches on the route

                for (;;)
                {
                    var s = SrcBlock.ToString().Replace(" ", "");
                    var d = DestBlock.ToString().Replace(" ", "");

                    if (!isRouteSet)
                    {
                        Route.IsBusy = true;
                        isRouteSet   = true;
                        Autoplayer?.SetRoute(Route, true);
                        int locObjectId = -1;
                        if (Autoplayer != null)
                        {
                            locObjectId = Autoplayer.GetLocObjectIdOfRoute(Route);
                        }
                        locObject = Model.Dispatcher.GetDataProvider().GetObjectBy(locObjectId) as Locomotive;
                        DestBlock.SetLocomotivePreviewObjectId(locObjectId);

                        if (locObject != null)
                        {
                            Model?.LogAutoplay($"{Prefix} Locomotive: {locObject.Name}");
                            Trace.WriteLine($"{Prefix} Locomotive: {locObject.Name}");
                        }

                        TrackWeaveItems weaverItems = new TrackWeaveItems();
                        var weaveFilepath           = Path.Combine(Model.Project.Dirpath, Model.Project.Track.Weave);
                        if (!weaverItems.Load(weaveFilepath))
                        {
                            throw new Exception("Reading weave file failed.");
                        }

                        Dictionary <TrackInfo, List <IItem> > trackObjects = new Dictionary <TrackInfo, List <IItem> >();

                        foreach (var pt in Route)
                        {
                            if (pt == null)
                            {
                                continue;
                            }

                            var item = Model.TrackEntity.Track.Get(pt.X, pt.Y);
                            if (item == null)
                            {
                                continue;
                            }

                            var itemObjects = Model.Dispatcher.Weaver.GetObject(item);
                            if (itemObjects.Count == 0)
                            {
                                continue;
                            }

                            if (trackObjects.ContainsKey(item))
                            {
                                trackObjects[item].AddRange(itemObjects);
                            }
                            else
                            {
                                trackObjects.Add(item, itemObjects);
                            }
                        }

                        #region DEBUG route's track info
                        Trace.WriteLine($"{Prefix} Route's track infos:");
                        foreach (var info in trackObjects.Keys)
                        {
                            var objs = trackObjects[info];

                            Trace.Write($"{Prefix} {info}: ");
                            foreach (var o in objs)
                            {
                                Trace.Write($"{o.ObjectId}, ");
                            }
                            Trace.WriteLine("||");
                        }
                        #endregion

                        Dictionary <TrackInfo, S88> s88TrackObjects = new Dictionary <TrackInfo, S88>();
                        Dictionary <TrackInfo, TrackInformation.Switch> switchTrackObjects = new Dictionary <TrackInfo, TrackInformation.Switch>();

                        #region prepare route data

                        foreach (var trackInfo in trackObjects.Keys)
                        {
                            var itemObjects = trackObjects[trackInfo];
                            if (itemObjects.Count == 0)
                            {
                                continue;
                            }

                            foreach (var obj in itemObjects)
                            {
                                if (obj == null)
                                {
                                    continue;
                                }

                                if (obj is S88)
                                {
                                    s88TrackObjects.Add(trackInfo, obj as S88);
                                }

                                if (obj is TrackInformation.Switch)
                                {
                                    switchTrackObjects.Add(trackInfo, obj as TrackInformation.Switch);
                                }
                            }
                        }

                        foreach (var trackInfo in s88TrackObjects.Keys)
                        {
                            var s88Obj = s88TrackObjects[trackInfo];

                            var fnc = Weaver.GetCheckFnc(s88Obj, trackInfo);
                            if (fnc == null)
                            {
                                Model.LogError($"S88-Checker is missing: {s88Obj}");
                            }

                            var data = new ItemData
                            {
                                Route      = Route,
                                Info       = trackInfo,
                                Item       = s88Obj,
                                S88Checker = fnc
                            };

                            routeData.Add(data);
                        }

                        foreach (var trackInfo in switchTrackObjects.Keys)
                        {
                            var switchObj = switchTrackObjects[trackInfo];

                            var data = new ItemData
                            {
                                Route = Route,
                                Info  = trackInfo,
                                Item  = switchObj
                            };

                            routeData.Add(data);
                        }

                        var sensorsAndEvents = GetBlockData(DestBlock);
                        if (sensorsAndEvents != null)
                        {
                            foreach (var sensorName in sensorsAndEvents.Keys)
                            {
                                var eventName = sensorsAndEvents[sensorName];

                                TrackInfo sensorTrackInfo = null;

                                foreach (var item in Model.TrackEntity.Track)
                                {
                                    if (item == null || string.IsNullOrEmpty(item.Name))
                                    {
                                        continue;
                                    }

                                    if (item.Name.Equals(sensorName))
                                    {
                                        sensorTrackInfo = item;
                                        break;
                                    }
                                }

                                if (sensorTrackInfo != null)
                                {
                                    var it = Get(routeData, sensorTrackInfo.X, sensorTrackInfo.Y);

                                    if (it == null)
                                    {
                                        var s88Obj = Helper.GetObject(Model.Dispatcher, Model.TrackEntity.Track, sensorTrackInfo.X, sensorTrackInfo.Y);

                                        var fnc = Weaver.GetCheckFnc(s88Obj, sensorTrackInfo);
                                        if (fnc == null)
                                        {
                                            Model.LogError($"S88-Checker is missing: {s88Obj}");
                                        }

                                        var data = new ItemData
                                        {
                                            Route          = Route,
                                            Info           = sensorTrackInfo,
                                            Item           = s88Obj,
                                            DestBlockEvent = eventName,
                                            S88Checker     = fnc
                                        };

                                        routeData.Add(data);
                                    }
                                    else
                                    {
                                        it.DestBlockEvent = eventName;
                                    }

                                    Trace.WriteLine($"{Prefix} Sensor({sensorName}) with Event({eventName})");
                                }
                            }
                        }

                        #endregion

                        #region set switches to let the locomotive pass the route

                        foreach (var data in routeData)
                        {
                            if (data == null || !data.IsSwitch || data.ItemSwitch == null)
                            {
                                continue;
                            }

                            var sw = data.ItemSwitch;
                            var v  = data.HasSwitchTurn ? 0 : 1;
                            if (sw.InvertCommand)
                            {
                                if (v == 1)
                                {
                                    v = 0;
                                }
                                else
                                {
                                    v = 1;
                                }
                            }
                            var vs = v == 1 ? "TURN" : "STRAIGHT";
                            Trace.WriteLine($"{Prefix} Switch '{sw.Name1}' change to '{vs}'");
                            sw.ChangeDirection(v);
                        }

                        #endregion

                        if (locObject != null)
                        {
                            locObject.ChangeDirection(false);
                            locObject.ChangeSpeed(locObject.MaxSpeedPercentage);
                        }

                        Model?.LogAutoplay($"{Prefix} {s}  TO  {d}");
                        Trace.WriteLine($"{Prefix} {s}  TO  {d}");

                        Model.UiSyncCtx?.Send((x) =>
                        {
                            Model.TrackEntity.UpdateAllVisualBlocks();
                        }, null);
                    }

                    foreach (var s88Data in routeData)
                    {
                        if (s88Data == null || !s88Data.IsS88 || s88Data.ItemS88 == null)
                        {
                            continue;
                        }

                        if (s88Data.S88HasBeenHandled)
                        {
                            continue;
                        }

                        bool state = false;
                        try
                        {
                            var bb = s88Data.S88Checker();
                            if (bb != null && bb.State != null)
                            {
                                state = bb.State.Value;
                            }
                        }
                        catch (Exception ex)
                        {
                            Model?.LogAutoplay($"{Prefix} {ex.Message}");
                            Trace.WriteLine($"{Prefix} {ex.Message}");
                        }

                        if (state)
                        {
                            s88Data.S88HasBeenHandled = true;

                            //Model?.LogAutoplay($"{Prefix} {s88Data.Info} {s88Data.ItemS88} state '{state}' -> {s88Data.DestBlockEvent}");

                            string evName = s88Data.DestBlockEvent;
                            if (!string.IsNullOrEmpty(evName))
                            {
                                var stopped = false;

                                if (evName.Equals("enter", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (locObject != null)
                                    {
                                        var blockSpeed = locObject.BlockSpeedPercentage;
                                        if (blockSpeed >= locObject.MaxSpeedPercentage)
                                        {
                                            blockSpeed = -1;
                                        }

                                        if (blockSpeed <= 0)
                                        {
                                            var currentSpeed = locObject.Speed;
                                            currentSpeed    -= (int)(currentSpeed / 2.0f);
                                            locObject.ChangeSpeed(currentSpeed);
                                        }
                                        else
                                        {
                                            locObject.ChangeSpeed(blockSpeed);
                                        }

                                        //locObject.ChangeSpeed(Locomotive.SpeedBlockEntered);
                                    }

                                    Trace.WriteLine($"{Prefix} New speed {Locomotive.SpeedBlockEntered} for {locObject.Name}");
                                }
                                else if (evName.Equals("enter in", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (locObject != null)
                                    {
                                        var currentSpeed  = locObject.Speed;
                                        var secondsToStop = 3;
                                        int speedSteps    = currentSpeed / secondsToStop;

                                        var o = locObject;

                                        var task = Task.Run(() =>
                                        {
                                            currentSpeed -= speedSteps;

                                            if (currentSpeed <= 0)
                                            {
                                                o?.ChangeSpeed(Locomotive.SpeedStop);
                                            }
                                            else
                                            {
                                                o?.ChangeSpeed(currentSpeed);
                                            }

                                            Trace.WriteLine($"{Prefix} Loc speed {locObject.Name} is {currentSpeed}");

                                            Thread.Sleep(1 * 1000);
                                        });

                                        task.Wait();

                                        stopped = true;
                                    }
                                }
                                else if (evName.Equals("in", StringComparison.OrdinalIgnoreCase))
                                {
                                    if (locObject != null)
                                    {
                                        locObject.ChangeSpeed(Locomotive.SpeedStop);
                                    }

                                    Trace.WriteLine($"{Prefix} STOP {Locomotive.SpeedStop}");

                                    stopped = true;
                                }

                                if (stopped)
                                {
                                    // move loc from source block to destination block
                                    // reset current route
                                    // be ready for next routing decision

                                    SrcBlock.SetLocomotiveObjectId(-1);
                                    DestBlock.SetLocomotiveObjectId(locObject.ObjectId);
                                    DestBlock.SetLocomotivePreviewObjectId(-1);
                                    Model.UiSyncCtx?.Send(x =>
                                    {
                                        Autoplayer.SetRoute(Route, false);
                                        Model.TrackEntity.UpdateAllVisualBlocks();
                                        Model.Save();
                                    }, null);
                                    Route.IsBusy        = false;
                                    Route.StartBusiness = DateTime.MaxValue;
                                    Route.StopBusiness  = DateTime.Now;

                                    if (_cts != null)
                                    {
                                        try
                                        {
                                            _cts.Dispose();
                                            _cts = null;
                                        }
                                        catch
                                        {
                                            // ignore
                                        }
                                    }

                                    return;
                                }
                            }
                        }
                    }

                    #region Thread stuff

                    Thread.Sleep(1 * 125);

                    if (_tkn.IsCancellationRequested)
                    {
                        Trace.WriteLine($"{Prefix} Stop requested...");
                        Route.IsBusy = false;
                        return;
                    }

                    #endregion
                }

                // **********************************************************************
                // ** END Route Thread
                // **********************************************************************
            }, _tkn);

            Task?.Start();
        }