public async Task <IActionResult> Post(SignalItem item) { _logger.LogInformation($"{nameof(Post)} {item.Message}"); await _signalHub.Clients.All.SendCoreAsync("ReceiveMessage", new[] { item.Message }); return(StatusCode(StatusCodes.Status200OK, true)); }
/// <summary> /// Default constructor /// </summary> /// <param name="originalTrItem">The original track item that we are representing for drawing</param> public DrawableSignalItem(TrackItem originalTrItem) : base(originalTrItem) { this.Description = "signal"; this.isNormal = true; // default value SignalItem originalSignalItem = originalTrItem as SignalItem; this.direction = originalSignalItem.Direction == 0 ? Traveller.TravellerDirection.Forward : Traveller.TravellerDirection.Backward; this.signalType = originalSignalItem.SignalType; }
/// <summary> /// Default constructor /// </summary> /// <param name="originalTrItem">The original track item that we are representing for drawing</param> public DrawableSignalItem(TrackItem originalTrItem) : base(originalTrItem) { this.Description = "signal"; this.isNormal = true; // default value SignalItem originalSignalItem = originalTrItem as SignalItem; this.direction = originalSignalItem.Direction; this.signalType = originalSignalItem.SignalType; }
/// <summary> /// /// </summary> /// <param name="item"></param> /// <param name="signal"></param> public AESignalItem(SignalItem item, SignalObject signal, TDBFile TDB) { typeWidget = (int)TypeWidget.SIGNAL_WIDGET; Item = item; Signal = signal; sigFonction = new List <SignalHead.MstsSignalFunction>(); foreach (var sig in Signal.SignalHeads) { sigFonction.Add(sig.sigFunction); if (sig.sigFunction == SignalHead.MstsSignalFunction.SPEED) { File.AppendAllText(@"C:\temp\AE.txt", "SPEED\n"); } } foreach (var fn in sigFonction) { File.AppendAllText(@"C:\temp\AE.txt", "FN " + fn + "\n"); } hasDir = false; Location.X = item.TileX * 2048 + item.X; Location.Y = item.TileZ * 2048 + item.Z; try { var node = TDB.TrackDB.TrackNodes[signal.trackNode]; Vector2 v2; if (node.TrVectorNode != null) { var ts = node.TrVectorNode.TrVectorSections[0]; v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z); } else if (node.TrJunctionNode != null) { var ts = node.UiD; v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z); } else { throw new Exception(); } var v1 = new Vector2(Location.X, Location.Y); var v3 = v1 - v2; v3.Normalize(); //v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 12f : -12f); v2 = v1 - Vector2.Multiply(v3, 12f); Dir.X = (float)v2.X; Dir.Y = (float)v2.Y; //v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 1.5f : -1.5f);//shift signal along the dir for 2m, so signals will not be overlapped v2 = v1 - Vector2.Multiply(v3, 1.5f); Location.X = (float)v2.X; Location.Y = (float)v2.Y; hasDir = true; } catch { } }
//================================================================================================// /// <summary> /// Set the signal type object from the SIGCFG file /// </summary> internal void SetSignalType(TrackItem[] trackItems, SignalConfigurationFile signalConfig) { SignalItem signalItem = (SignalItem)trackItems[TDBIndex]; // set signal type if (signalConfig.SignalTypes.ContainsKey(signalItem.SignalType)) { // set signal type SignalType = signalConfig.SignalTypes[signalItem.SignalType]; // get related signalscript SignalScriptProcessing.SignalScripts.Scripts.TryGetValue(SignalType, out signalScript); // set signal speeds foreach (SignalAspect aspect in SignalType.Aspects) { SpeedInfoSet[aspect.Aspect] = new SpeedInfo(aspect.SpeedLimit, aspect.SpeedLimit, aspect.Asap, aspect.Reset, aspect.NoSpeedReduction ? 1 : 0); } // set normal subtype OrtsNormalSubtypeIndex = SignalType.OrtsNormalSubTypeIndex; // update overall SignalNumClearAhead if (SignalFunction == SignalFunction.Normal) { MainSignal.SignalNumClearAheadMsts = Math.Max(MainSignal.SignalNumClearAheadMsts, SignalType.NumClearAhead_MSTS); MainSignal.SignalNumClearAheadOrts = Math.Max(MainSignal.SignalNumClearAheadOrts, SignalType.NumClearAhead_ORTS); MainSignal.SignalNumClearAheadActive = MainSignal.SignalNumClearAheadOrts; } // set approach control limits if (SignalType.ApproachControlDetails != null) { ApproachControlLimitPositionM = SignalType.ApproachControlDetails.ApproachControlPositionM; ApproachControlLimitSpeedMpS = SignalType.ApproachControlDetails.ApproachControlSpeedMpS; } else { ApproachControlLimitPositionM = null; ApproachControlLimitSpeedMpS = null; } if (SignalFunction == SignalFunction.Speed) { MainSignal.IsSignal = false; MainSignal.IsSpeedSignal = true; } } else { Trace.TraceWarning($"SignalObject trItem={MainSignal.TrackItemIndex}, trackNode={MainSignal.TrackNode} has SignalHead with undefined SignalType {signalItem.SignalType}."); } }
//================================================================================================// /// <summary> /// Constructor for signals /// </summary> public SignalHead(Signal signal, int trackItem, int tbdRef, SignalItem signalItem) { MainSignal = signal ?? throw new ArgumentNullException(nameof(signal)); TrackItemIndex = trackItem; TDBIndex = tbdRef; if (signalItem?.SignalDirections?.Count > 0) { TrackJunctionNode = signalItem.SignalDirections[0].TrackNode; JunctionPath = signalItem.SignalDirections[0].LinkLRPath; } }
/// <summary> /// /// </summary> /// <param name="sideItem"></param> /// <param name="signal"></param> public AESignalItem(SignalItem item, AESignalObject signal, TrackDatabaseFile TDB) { typeItem = (int)TypeItem.SIGNAL_ITEM; Item = item; Signal = signal; sigFonction = new List <MstsSignalFunction>(); foreach (var sig in Signal.SignalHeads) { sigFonction.Add(sig.sigFunction); } hasDir = false; Location.X = item.TileX * 2048 + item.X; Location.Y = item.TileZ * 2048 + item.Z; try { associateNode = TDB.TrackDB.TrackNodes[signal.trackNode]; Vector2 v2; if (associateNode.TrVectorNode != null) { associateNodeIdx = (int)associateNode.Index; var ts = associateNode.TrVectorNode.TrVectorSections[0]; v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z); } else if (associateNode.TrJunctionNode != null) { associateNodeIdx = associateNode.TrJunctionNode.Idx; var ts = associateNode.UiD; v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z); } else { throw new Exception(); } var v1 = new Vector2(Location.X, Location.Y); var v3 = v1 - v2; v3.Normalize(); v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 12f : -12f); //v2 = v1 - Vector2.Multiply(v3, 12f); Dir.X = (float)v2.X; Dir.Y = (float)v2.Y; //v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 1.5f : -1.5f);//shift signal along the dir for 2m, so signals will not be overlapped v2 = v1 - Vector2.Multiply(v3, 1.5f); Location.X = (float)v2.X; Location.Y = (float)v2.Y; hasDir = true; } catch { } }
public void ParserSignalLineTextTest1() { //Given string signalLine = " SG_ Pt_tiEdrvShOff : 50|12@1+ (1,0) [0|4095] \"min\" ED"; //When SignalItem item = DBCFileParser.ParserSignalLineText(signalLine); //Then Assert.Equal("Pt_tiEdrvShOff", item.SignalName); Assert.Equal(50u, item.StartBit); Assert.Equal(12u, item.SignalSize); Assert.Equal(SignalItem.ByteOrderEnum.Intel, item.ByteOrder); Assert.Equal(SignalItem.ValueTypeEnum.Unsigned, item.ValueType); Assert.Equal(1f, item.Factor); Assert.Equal(0f, item.Offset); Assert.Equal(0u, item.Min); Assert.Equal(4095u, item.Max); Assert.Equal("min", item.Unit); Assert.Contains("ED", item.Receiver); }
public void PopulateItemLists() { foreach (var item in F.simulator.TDB.TrackDB.TrItemTable) { switch (item.ItemType) { case TrItem.trItemType.trSIGNAL: if (item is SignalItem) { SignalItem si = item as SignalItem; if (si.SigObj >= 0 && si.SigObj < F.simulator.Signals.SignalObjects.Length) { var s = F.simulator.Signals.SignalObjects[si.SigObj]; if (s != null && s.isSignal && s.isSignalNormal()) { F.signals.Add(new SignalWidget(si, s)); } } } break; case TrItem.trItemType.trSIDING: // Sidings have 2 ends but are not always listed in pairs in the *.tdb file // Neither are their names unique (e.g. Bernina Bahn). // Find whether this siding is a new one or the other end of an old one. // If other end, then find the right-hand one as the location for a single label. // Note: Find() within a foreach() loop is O(n^2) but is only done at start. var oldSidingIndex = F.sidings.FindIndex(r => r.LinkId == item.TrItemId && r.Name == item.ItemName); if (oldSidingIndex < 0) { var newSiding = new SidingWidget(item as SidingItem); F.sidings.Add(newSiding); } else { var oldSiding = F.sidings[oldSidingIndex]; var oldLocation = oldSiding.Location; var newLocation = new PointF(item.TileX * 2048 + item.X, item.TileZ * 2048 + item.Z); // Because these are structs, not classes, compiler won't let you overwrite them. // Instead create a single item which replaces the 2 platform items. var replacement = new SidingWidget(item as SidingItem) { Location = GetMidPoint(oldLocation, newLocation) }; // Replace the old siding item with the replacement F.sidings.RemoveAt(oldSidingIndex); F.sidings.Add(replacement); } break; case TrItem.trItemType.trPLATFORM: // Platforms have 2 ends but are not always listed in pairs in the *.tdb file // Neither are their names unique (e.g. Bernina Bahn). // Find whether this platform is a new one or the other end of an old one. // If other end, then find the right-hand one as the location for a single label. var oldPlatformIndex = F.platforms.FindIndex(r => r.LinkId == item.TrItemId && r.Name == item.ItemName); if (oldPlatformIndex < 0) { var newPlatform = new PlatformWidget(item as PlatformItem) { Extent1 = new PointF(item.TileX * 2048 + item.X, item.TileZ * 2048 + item.Z) }; F.platforms.Add(newPlatform); } else { var oldPlatform = F.platforms[oldPlatformIndex]; var oldLocation = oldPlatform.Location; var newLocation = new PointF(item.TileX * 2048 + item.X, item.TileZ * 2048 + item.Z); // Because these are structs, not classes, compiler won't let you overwrite them. // Instead create a single item which replaces the 2 platform items. var replacement = new PlatformWidget(item as PlatformItem) { Extent1 = oldLocation , Extent2 = newLocation // Give it the right-hand location , Location = GetRightHandPoint(oldLocation, newLocation) }; // Replace the old platform item with the replacement F.platforms.RemoveAt(oldPlatformIndex); F.platforms.Add(replacement); } break; default: break; } } foreach (var p in F.platforms) { if (p.Extent1.IsEmpty || p.Extent2.IsEmpty) { Trace.TraceWarning("Platform '{0}' is incomplete as the two ends do not match. It will not show in full in the Timetable Tab of the Map Window", p.Name); } } }
public SignalShapeHead(Viewer viewer, SignalShape signalShape, int index, SignalHead signalHead, SignalItem mstsSignalItem, Formats.Msts.SignalShape.SignalSubObj mstsSignalSubObj) { Viewer = viewer; SignalShape = signalShape; #if DEBUG_SIGNAL_SHAPES Index = index; #endif SignalHead = signalHead; for (int mindex = 0; mindex <= signalShape.SharedShape.MatrixNames.Count - 1; mindex++) { string MatrixName = signalShape.SharedShape.MatrixNames[mindex]; if (String.Equals(MatrixName, mstsSignalSubObj.MatrixName)) { MatrixIndices.Add(mindex); } } if (!viewer.SIGCFG.SignalTypes.ContainsKey(mstsSignalSubObj.SignalSubSignalType)) { return; } var mstsSignalType = viewer.SIGCFG.SignalTypes[mstsSignalSubObj.SignalSubSignalType]; SignalTypeData = viewer.SignalTypeDataManager.Get(mstsSignalType); if (SignalTypeData.Semaphore) { // Check whether we have to correct the Semaphore position indexes following the strange rule of MSTS // Such strange rule is that, if there are only two animation steps in the related .s file, MSTS behaves as follows: // a SemaphorePos (2) in sigcfg.dat is executed as SemaphorePos (1) // a SemaphorePos (1) in sigcfg.dat is executed as SemaphorePos (0) // a SemaphorePos (0) in sigcfg.dat is executed as SemaphorePos (0) // First we check if there are only two animation steps if (signalShape.SharedShape.Animations != null && signalShape.SharedShape.Animations.Count != 0 && MatrixIndices.Count > 0 && signalShape.SharedShape.Animations[0].anim_nodes[MatrixIndices[0]].controllers.Count != 0 && signalShape.SharedShape.Animations[0].anim_nodes[MatrixIndices[0]].controllers[0].Count == 2) { // OK, now we check if maximum SemaphorePos is 2 (we won't correct if there are only SemaphorePos 1 and 0, // because they would both be executed as SemaphorePos (0) accordingly to above law, therefore leading to a static semaphore) float maxIndex = float.MinValue; foreach (SignalAspectData drAsp in SignalTypeData.DrawAspects.Values) { if (drAsp.SemaphorePos > maxIndex) { maxIndex = drAsp.SemaphorePos; } } if (maxIndex == 2) { // in this case we modify the SemaphorePositions for compatibility with MSTS. foreach (SignalAspectData drAsp in SignalTypeData.DrawAspects.Values) { switch ((int)drAsp.SemaphorePos) { case 2: drAsp.SemaphorePos = 1; break; case 1: drAsp.SemaphorePos = 0; break; default: break; } } if (!SignalTypeData.AreSemaphoresReindexed) { Trace.TraceInformation("Reindexing semaphore entries of signal type {0} for compatibility with MSTS", mstsSignalType.Name); SignalTypeData.AreSemaphoresReindexed = true; } } } foreach (int mindex in MatrixIndices) { if (mindex == 0 && (signalShape.SharedShape.Animations == null || signalShape.SharedShape.Animations.Count == 0 || signalShape.SharedShape.Animations[0].anim_nodes[mindex].controllers.Count == 0)) { continue; } AnimatedPart SemaphorePart = new AnimatedPart(signalShape); SemaphorePart.AddMatrix(mindex); SemaphoreParts.Add(SemaphorePart); } if (Viewer.Simulator.TRK.Tr_RouteFile.DefaultSignalSMS != null) { var soundPath = Viewer.Simulator.RoutePath + @"\\sound\\" + Viewer.Simulator.TRK.Tr_RouteFile.DefaultSignalSMS; try { Sound = new SoundSource(Viewer, SignalShape.Location.WorldLocation, Events.Source.MSTSSignal, soundPath); Viewer.SoundProcess.AddSoundSources(this, new List <SoundSourceBase>() { Sound }); } catch (Exception error) { Trace.WriteLine(new FileLoadException(soundPath, error)); } } } lightStates = new SignalLightState[SignalTypeData.Lights.Count]; for (var i = 0; i < SignalTypeData.Lights.Count; i++) { lightStates[i] = new SignalLightState(SignalTypeData.OnOffTimeS); } #if DEBUG_SIGNAL_SHAPES Console.Write(" HEAD type={0,-8} lights={1,-2} sem={2}", SignalTypeData.Type, SignalTypeData.Lights.Count, SignalTypeData.Semaphore); #endif }
public void LoadItemsFromMSTS() { #if SHOW_STOPWATCH Stopwatch stopWatch = new Stopwatch(); TimeSpan ts; string elapsedTime; if (File.Exists(@"C:\temp\stopwatch.txt")) { File.Delete(@"C:\temp\stopwatch.txt"); } #endif if (TDB == null || TDB.TrackDB == null || TDB.TrackDB.TrItemTable == null) { return; } foreach (GlobalItem item in orRouteConfig.AllItems) { if (item.GetType() == typeof(AEBufferItem)) { mstsItems.buffers.Add((AEBufferItem)item); } } Program.actEditor.DisplayStatusMessage("Start loading Track Nodes ..."); #if SHOW_STOPWATCH stopWatch.Start(); #endif nodes = TDB.TrackDB.TrackNodes; for (int nodeIdx = 0; nodeIdx < nodes.Length; nodeIdx++) { if (nodes[nodeIdx] != null) { TrackNode currNode = nodes[nodeIdx]; AEBufferItem foundBuffer; if (currNode.TrEndNode) { //Program.actEditor.DisplayStatusMessage("Init data for display... Load End Nodes: " + currNode.Index); try { foundBuffer = (AEBufferItem)orRouteConfig.AllItems.First(x => x.associateNodeIdx == currNode.Index); foundBuffer.updateNode(currNode); } catch (InvalidOperationException) { foundBuffer = new AEBufferItem((TrackNode)currNode); mstsItems.buffers.Add(foundBuffer); } #if SHOW_STOPWATCH ts = stopWatch.Elapsed; stopWatch.Reset(); // Format and display the TimeSpan value. elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); File.AppendAllText(@"C:\temp\stopwatch.txt", "One END node: " + elapsedTime + "\n"); stopWatch.Start(); #endif } else if (currNode.TrVectorNode != null && currNode.TrVectorNode.TrVectorSections != null) { //Program.actEditor.DisplayStatusMessage("Init data for display... Load Vector Nodes: " + currNode.Index); if (currNode.TrVectorNode.TrVectorSections.Length > 1) { AddSegments(currNode); TrVectorSection section = currNode.TrVectorNode.TrVectorSections[currNode.TrVectorNode.TrVectorSections.Length - 1]; MSTSCoord A = new MSTSCoord(section); TrPin pin = currNode.TrPins[1]; { TrackNode connectedNode = nodes[pin.Link]; int direction = DrawUtility.getDirection(currNode, connectedNode); if (A == connectedNode.getMSTSCoord(direction)) { continue; } AESegment aeSegment = new AESegment(A, connectedNode.getMSTSCoord(direction)); TrackSegment lineSeg = new TrackSegment(aeSegment, currNode, currNode.TrVectorNode.TrVectorSections.Length - 1, direction, TSectionDat); addTrItems(lineSeg, currNode); mstsItems.AddSegment(lineSeg); } #if SHOW_STOPWATCH ts = stopWatch.Elapsed; stopWatch.Reset(); // Format and display the TimeSpan value. elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); File.AppendAllText(@"C:\temp\stopwatch.txt", "One mult TRACK node: " + elapsedTime + "\n"); stopWatch.Start(); #endif } else { TrVectorSection s; s = currNode.TrVectorNode.TrVectorSections[0]; areaRoute.manageTiles(s.TileX, s.TileZ); foreach (TrPin pin in currNode.TrPins) { TrackNode connectedNode = nodes[pin.Link]; int direction = DrawUtility.getDirection(currNode, connectedNode); if (MSTSCoord.near(currNode.getMSTSCoord(direction), connectedNode.getMSTSCoord(direction))) { continue; } AESegment aeSegment = new AESegment(currNode.getMSTSCoord(direction), connectedNode.getMSTSCoord(direction)); TrackSegment lineSeg = new TrackSegment(aeSegment, currNode, 0, direction, TSectionDat); addTrItems(lineSeg, currNode); mstsItems.AddSegment(lineSeg); } #if SHOW_STOPWATCH ts = stopWatch.Elapsed; stopWatch.Reset(); // Format and display the TimeSpan value. elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); File.AppendAllText(@"C:\temp\stopwatch.txt", "One simple TRACK node: " + elapsedTime + "\n"); stopWatch.Start(); #endif } } else if (currNode.TrJunctionNode != null) { //Program.actEditor.DisplayStatusMessage("Init data for display... Load Junction Nodes: " + currNode.Index); mstsItems.switches.Add(new AEJunctionItem(currNode)); areaRoute.manageTiles(currNode.UiD.TileX, currNode.UiD.TileZ); #if SHOW_STOPWATCH ts = stopWatch.Elapsed; stopWatch.Reset(); // Format and display the TimeSpan value. elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); File.AppendAllText(@"C:\temp\stopwatch.txt", "One JN node: " + elapsedTime + "\n"); stopWatch.Start(); #endif } } } #if SPA_ADD var maxsize = maxX - minX > maxX - minX ? maxX - minX : maxX - minX; maxsize = (int)maxsize / 100 * 100; if (maxsize < 2000) { maxsize = 2000; } ZoomFactor = (decimal)maxsize; #endif #region AddItem Program.actEditor.DisplayStatusMessage("Init data for display... Load MSTS Items..."); foreach (var item in TDB.TrackDB.TrItemTable) { if (item.ItemType == TrItem.trItemType.trSIGNAL && Signals != null) { if (item is SignalItem) { #if SHOW_STOPWATCH Program.actEditor.DisplayStatusMessage("Init data for display... Load Items... Signal"); #endif SignalItem si = item as SignalItem; if (si.SigObj >= 0 && si.SigObj < Signals.SignalObjects.Length) { AESignalObject s = Signals.SignalObjects[si.SigObj]; if (s.isSignal) // && s.isSignalNormal()) { mstsItems.AddSignal(new AESignalItem(si, s, TDB)); } } } } } #if SHOW_STOPWATCH ts = stopWatch.Elapsed; // Format and display the TimeSpan value. elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); File.AppendAllText(@"C:\temp\stopwatch.txt", "Signals: " + elapsedTime + "\n"); stopWatch.Stop(); #endif #endregion }