From 9c3c647039a2364c5e1bfd0e98630745fe35ba75 Mon Sep 17 00:00:00 2001 From: AMacro Date: Sun, 11 Feb 2024 12:26:43 +1000 Subject: [PATCH 1/7] Added route switch finding Finds switches between current location and end of line/branch Finds intersection of main line rout with second platform at next station --- RouteManager.UMM/info.json | 2 +- RouteManager/Properties/AssemblyInfo.cs | 2 +- RouteManager/RouteManager.csproj | 2 + RouteManager/v2/core/AutoEngineer.cs | 37 +++- RouteManager/v2/core/DestinationManager.cs | 163 +++++++++++++++++- RouteManager/v2/core/StationManager.cs | 13 +- RouteManager/v2/dataStructures/LocoTelem.cs | 2 + .../v2/dataStructures/RouteSwitchData.cs | 61 +++++++ RouteManager/v2/harmonyPatches/GraphPatch.cs | 87 ++++++++++ .../v2/harmonyPatches/RouteManagerUI.cs | 33 ++++ 10 files changed, 388 insertions(+), 14 deletions(-) create mode 100644 RouteManager/v2/dataStructures/RouteSwitchData.cs create mode 100644 RouteManager/v2/harmonyPatches/GraphPatch.cs diff --git a/RouteManager.UMM/info.json b/RouteManager.UMM/info.json index 2da3ad2..1efab31 100644 --- a/RouteManager.UMM/info.json +++ b/RouteManager.UMM/info.json @@ -1,6 +1,6 @@ { "Id": "RouteManager", - "Version": "2.0.0.8", + "Version": "2.0.0.9", "DisplayName": "Dispatcher", "Author": "Erabior", "AssemblyName": "RouteManager.UMM.dll", diff --git a/RouteManager/Properties/AssemblyInfo.cs b/RouteManager/Properties/AssemblyInfo.cs index 05d6af6..a392ca9 100644 --- a/RouteManager/Properties/AssemblyInfo.cs +++ b/RouteManager/Properties/AssemblyInfo.cs @@ -38,6 +38,6 @@ internal class AppVersion { - public const string Version = "2.0.0.8"; + public const string Version = "2.0.0.9"; } diff --git a/RouteManager/RouteManager.csproj b/RouteManager/RouteManager.csproj index 0b7f53f..62c7350 100644 --- a/RouteManager/RouteManager.csproj +++ b/RouteManager/RouteManager.csproj @@ -118,10 +118,12 @@ + + diff --git a/RouteManager/v2/core/AutoEngineer.cs b/RouteManager/v2/core/AutoEngineer.cs index a3af48f..b573bfb 100644 --- a/RouteManager/v2/core/AutoEngineer.cs +++ b/RouteManager/v2/core/AutoEngineer.cs @@ -94,15 +94,30 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) LocoTelem.clearedForDeparture[locomotive] = false; RouteManager.logger.LogToDebug(String.Format("Loco: {0} \t has ID: {1}", locomotive.DisplayName, locomotive.id), LogLevel.Debug); - + //Set some initial values - LocoTelem.closestStation[locomotive] = StationManager.GetClosestStation_dev(locomotive); //closest station will only return a station marked as a stop - LocoTelem.currentDestination[locomotive] = StationManager.getNextStation_dev(locomotive);//LocoTelem.closestStation[locomotive].Item1; - //StationManager.getInitialDestination(locomotive); + //closest station will only return a station marked as a stop + //LocoTelem.closestStation[locomotive] = StationManager.GetClosestStation_dev(locomotive); + LocoTelem.currentDestination[locomotive] = StationManager.getNextStation_dev(locomotive); //set locomotive drive direction LocoTelem.locoTravelingForward[locomotive] = GetDirection(locomotive, LocoTelem.currentDestination[locomotive]); + //get route info - what are the switches on our route and what state do they need to be in? + List switchRequirements; + PassengerStop alarka = PassengerStop.FindAll().Where(stop => stop.identifier == "alarka").First(); + + if (DestinationManager.GetRouteSwitches(locomotive.LocationF, (Track.Location)alarka.TrackSpans.First().lower , out switchRequirements)) + { + //we have the total route to end of line/branch + // Check if the next station has multiple platforms and find the last common switch + DestinationManager.PlanNextRoute(locomotive.LocationF, LocoTelem.currentDestination[locomotive], ref switchRequirements); + } + else + { + //oh-oh we're flying blind! + } + LocoTelem.closestStationNeedsUpdated[locomotive] = false; LocoTelem.CenterCar[locomotive] = TrainManager.GetCenterCoach(locomotive); @@ -408,9 +423,11 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) //TEMP LOGIC float distanceToStation = float.MaxValue; bool delayExecution = false; - //float olddist = float.MaxValue; - float trainVelocity = 0; + float trainVelocity; int stationPadding = 10; + float distanceToSwitch=float.MaxValue; + RouteSwitchData nextSwitch; + //Loop through transit logic @@ -427,6 +444,14 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) yield return null; } + nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + //check our next switch distance + distanceToSwitch = DestinationManager.GetDistanceToSwitch(locomotive, nextSwitch); + if (distanceToSwitch <= 400) + { + + } + //Getting close to a station update some values... //Cheeky optimization to reduce excessive logging... if (distanceToStation != float.MaxValue) diff --git a/RouteManager/v2/core/DestinationManager.cs b/RouteManager/v2/core/DestinationManager.cs index 01e7bd5..9770ea5 100644 --- a/RouteManager/v2/core/DestinationManager.cs +++ b/RouteManager/v2/core/DestinationManager.cs @@ -7,6 +7,7 @@ using Track; using UnityEngine; using RouteManager.v2.Logging; +using UnityEngine.Rendering; namespace RouteManager.v2.core { @@ -18,6 +19,13 @@ public static class DestinationManager "almond", "nantahala", "topton", "rhodo", "andrews" }; + public static readonly List orderedStations_dev = new List + { + "sylva", "dillsboro", "wilmot", "whittier", "ela", "bryson", "hemingway", "alarkajct", "cochran", "alarka", "cochran", + "almond", "nantahala", "topton", "rhodo", "andrews" + }; + + //Update the list of stations to stop at. public static void SetStopStations(Car car, List selectedStops) { @@ -84,8 +92,10 @@ public static float GetDistanceToStation(Car locomotive, PassengerStop station) Graph trackGraph = Graph.Shared; float shortestDistance = float.MaxValue; + + //Todo: use end of train in direction of travel, rather than locomotive Car centerCar = LocoTelem.CenterCar[locomotive]; - centerCar.GetCenterPosition(trackGraph); + //centerCar.GetCenterPosition(trackGraph); //Check all tracks associated with a station foreach (TrackSpan trackSpan in station.TrackSpans) @@ -120,6 +130,154 @@ public static float GetDistanceToStation(Car locomotive, PassengerStop station) return shortestDistance; } + //Returns True if node is a switch + //Returns False if node is not a switch + //switchNormal will be true if the traversal is the normal path, false if it's the reverse path and null if not traversable + // i.e. moving from normal to reversed branch + public static bool PathIsNormal(TrackSegment from, TrackSegment to, out TrackNode? trackSwitch, out bool? switchNormal) + { + trackSwitch = GetCommonNode(from,to) ?? throw new Exception($"No common node for From: {from.id}, To: {to.id}"); + + + RouteManager.logger.LogToDebug($"PathIsNormal: From: {from?.id}, {from?.name}, To: {to?.id}, {to?.name}, Node: {trackSwitch?.id}, {trackSwitch?.name}", LogLevel.Verbose); + + bool result = Graph.Shared.DecodeSwitchAt(trackSwitch, out TrackSegment enter, out TrackSegment normal, out TrackSegment reversed); + + if (result) + { + //we have switch, determine if we can go between from and to + if (from == enter && to == normal || from == normal && to == enter) + { + switchNormal = true; + } + else if (from == enter && to == reversed || from == reversed && to == enter) + { + switchNormal = false; + } + else + { + RouteManager.logger.LogToError($"PathIsNormal: Unable to traverse switch"); + RouteManager.logger.LogToDebug($"PathIsNormal: Result: {result}, Enter: {enter?.id}, Normal: {normal?.id}, Reversed: {reversed?.id}", LogLevel.Verbose); + + switchNormal = null; + } + } + else + { + //not a switch + switchNormal = null; + return false; + } + + return true; + } + + public static TrackNode? GetCommonNode(TrackSegment a, TrackSegment b) + { + + if (a == null || b == null) + return null; + + if (a.a == b.a || a.a == b.b) { + return a.a; + } + else if (a.b == b.a || a.b == b.b) + { + return a.b; + } + + return null; + } + + public static bool GetRouteSwitches(Location start, Location destination, out List switchRequirements) + { + switchRequirements = new List(); + + //alarka hack - if Alarka is on our list, we need to use this as our final destination first and plan the route in 2 segments + //will need to be updated to make a general solution for branch lines + + //TODO: put hack in + //PassengerStop alarka = PassengerStop.FindAll().Where(stop => stop.identifier == "alarka").First(); + //(Track.Location)alarka.TrackSpans.First().lower + //RouteManager.logger.LogToDebug($"Finding Route to Alarka (segments) {loco.DisplayName} to {alarka?.name}..."); + //RouteManager.logger.LogToDebug($"Current Location F: {loco.LocationF}, Location A: {loco.LocationA}, Location B: {loco.LocationB}"); + // + + List segmentSteps = Graph.Shared.FindRoute(start, destination); + + RouteManager.logger.LogToDebug($"Route found: {segmentSteps.Count} steps:"); + + for (int i = 0; i < segmentSteps.Count - 1; i++) + { + TrackSegment seg = segmentSteps[i]; + TrackSegment segNext = segmentSteps[i + 1]; + + bool? requiredSwitchState; + bool isSwitch = DestinationManager.PathIsNormal(seg, segNext, out TrackNode trackSwitch, out requiredSwitchState); + + if (isSwitch && requiredSwitchState != null) + { + //RouteManager.logger.LogToDebug($"\r\nSeg.a: {seg.a.id}, {seg.a.name}\r\nSeg.b: {seg.b.id}, {seg.b.name}\r\nSegNext.a: {segNext.a.id}, {segNext.a.name}\r\nSegNext.b: {segNext.b.id}, {segNext.b.name}", LogLevel.Debug); + //RouteManager.logger.LogToDebug($"\t\t\tSegment: {seg?.id}, {seg?.name}, {seg?.trackClass}, Node A: {seg?.a.name}, Node B: {seg?.b.name}, Desired switch pos normal: {requiredSwitchState}", LogLevel.Debug); + + switchRequirements.Add(new RouteSwitchData(trackSwitch, seg, segNext, (bool)requiredSwitchState)); + } + else if (isSwitch && requiredSwitchState == null) + { + RouteManager.logger.LogToError("Unable to resolve path!"); + return false; + } + + } + + return true; + } + + public static float GetDistanceToSwitch(Car locomotive, RouteSwitchData trackSwitch) + { + RouteManager.logger.LogToDebug($"Loco: {locomotive.DisplayName} getting distance to switch {trackSwitch.trackSwitch?.id}", LogLevel.Trace); + + Graph trackGraph = Graph.Shared; + + //ToDo: use end of train, rather than locomotive + Car centerCar = LocoTelem.CenterCar[locomotive]; + + //centerCar.GetCenterPosition(trackGraph); + + Location swLocation = new Location(trackSwitch.segmentFrom, 0f, trackSwitch.segmentFrom.EndForNode(trackSwitch.trackSwitch)); + + float distanceA = trackGraph.FindDistance(centerCar.LocationA, swLocation); + float distanceB = trackGraph.FindDistance(centerCar.LocationB, swLocation); + + return Math.Min(distanceA, distanceB); + } + + public static void PlanNextRoute(Location start,PassengerStop nextStation, ref List mainRoute) + { + TrackSpan[] tracks = nextStation.TrackSpans.ToArray(); + + if (tracks.Length > 1) + { + Location secondPlatform = (Location)tracks[1].lower; + + List requirementsP2; + if (GetRouteSwitches(start, secondPlatform, out requirementsP2)) + { + //found a route to second platform + //find last common node + RouteSwitchData common = mainRoute.Intersect(requirementsP2, new RouteSwitchDataComparer()).Last(); + if (common != null) + { + common.isDecision = true; + } + else + { + //routes don't intersect + RouteManager.logger.LogToDebug("No intersection of routes to second platform!", LogLevel.Debug); + } + } + } + } /************************************************************************************************************************** * @@ -190,9 +348,8 @@ public static PassengerStop IsTransferStationSelected(PassengerStop transferFrom { //Trace Function //RouteManager.logger.LogToDebug("ENTERED FUNCTION: IsPickupStationSelected", LogLevel.Trace); - PassengerStop transferTo; - bool result = LocoTelem.UITransferStationSelections[locomotive].TryGetValue(transferFrom.identifier, out transferTo); + bool result = LocoTelem.UITransferStationSelections[locomotive].TryGetValue(transferFrom.identifier, out PassengerStop transferTo); //Trace Function //RouteManager.logger.LogToDebug("EXITING FUNCTION: IsPickupStationSelected", LogLevel.Trace); diff --git a/RouteManager/v2/core/StationManager.cs b/RouteManager/v2/core/StationManager.cs index 996a642..8bc53df 100644 --- a/RouteManager/v2/core/StationManager.cs +++ b/RouteManager/v2/core/StationManager.cs @@ -155,7 +155,7 @@ public static (PassengerStop,float) GetClosestStation(Car currentCar) return (closestStation, closestDistance); } - public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) + public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) { //Trace Logging RouteManager.logger.LogToDebug("ENTERED FUNCTION: GetClosestStation_dev", LogLevel.Trace); @@ -177,6 +177,7 @@ public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) { RouteManager.logger.LogToError("Could not obtain locomotive's front position."); return (null, 0); + } //Debugging Output @@ -198,7 +199,7 @@ public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) { float distance = 0; - RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}"); + RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}",LogLevel.Debug); try { @@ -232,6 +233,7 @@ public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) closestDistance = distance; closestStation = station; } + } //Debug output @@ -243,6 +245,10 @@ public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) return (closestStation, closestDistance); } + public static IEnumerator<(PassengerStop, float)> CalculateDistanceToStation() + { + yield return (null, float.MaxValue); + } //Attempt to determine midroute station better when starting the coroutine. public static PassengerStop getInitialDestination(Car locomotive) @@ -398,7 +404,8 @@ public static PassengerStop getNextStation_dev(Car locomotive) if (!LocoTelem.currentDestination.ContainsKey(locomotive) || LocoTelem.currentDestination[locomotive] == default(PassengerStop)) { //No Destination set so for now, assume closest station. - currentStation = GetClosestStation_dev(locomotive).Item1; + LocoTelem.closestStation[locomotive] = GetClosestStation_dev(locomotive); + currentStation = LocoTelem.closestStation[locomotive].Item1; RouteManager.logger.LogToDebug(String.Format("Loco {0} does not have a destination. Defaulting to closest station {1}", locomotive.DisplayName, currentStation.identifier), LogLevel.Debug); } else diff --git a/RouteManager/v2/dataStructures/LocoTelem.cs b/RouteManager/v2/dataStructures/LocoTelem.cs index 0d76b6e..5a3ff78 100644 --- a/RouteManager/v2/dataStructures/LocoTelem.cs +++ b/RouteManager/v2/dataStructures/LocoTelem.cs @@ -1,6 +1,7 @@ using Model; using RollingStock; using System.Collections.Generic; +using Track; namespace RouteManager.v2.dataStructures @@ -26,6 +27,7 @@ public class LocoTelem public static Dictionary currentDestination { get; private set; } = new Dictionary(); public static Dictionary> previousDestinations { get; private set; } = new Dictionary>(); public static Dictionary previousDestination { get; private set; } = new Dictionary(); + public static Dictionary> routeSwitchRequirements { get; private set; } = new Dictionary>(); public static Dictionary> lowFuelQuantities { get; private set; } = new Dictionary>(); public static Dictionary> UIPickupStationSelections { get; private set; } = new Dictionary>(); diff --git a/RouteManager/v2/dataStructures/RouteSwitchData.cs b/RouteManager/v2/dataStructures/RouteSwitchData.cs new file mode 100644 index 0000000..bed9e83 --- /dev/null +++ b/RouteManager/v2/dataStructures/RouteSwitchData.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Track; + +namespace RouteManager.v2.dataStructures +{ + public class RouteSwitchData + { + public TrackNode trackSwitch; //switch we're interested in + public TrackSegment segmentFrom; //track we're coming from + public TrackSegment segmentTo; //track we're going to + public bool requiredStateNormal; //switch state to make the traversal + public bool isDecision; //this switch selects between two platforms + + + public RouteSwitchData(TrackNode trackSwitch, TrackSegment segmentFrom, TrackSegment segmentTo, bool requiredStateNormal) + { + this.trackSwitch = trackSwitch; + this.segmentFrom = segmentFrom; + this.segmentTo = segmentTo; + this.requiredStateNormal = requiredStateNormal; + } + + public override string ToString() + { + return $"Switch ID: {this.trackSwitch.id}, From: {segmentFrom.id}, To: {segmentTo.id}, Is Decision: {this.isDecision}"; + } + } + + public class RouteSwitchDataComparer : IEqualityComparer + { + + #region IEqualityComparer Members + + + public bool Equals(RouteSwitchData x, RouteSwitchData y) + { + //no null check here, you might want to do that, or correct that to compare just one part of your object + return x.trackSwitch == y.trackSwitch; + } + + + public int GetHashCode(RouteSwitchData obj) + { + unchecked + { + var hash = 17; + //same here, if you only want to get a hashcode on a, remove the line with b + hash = hash * 23 + obj.trackSwitch.GetHashCode(); + hash = hash * 23 + obj.trackSwitch.GetHashCode(); + + return hash; + } + } + + #endregion + } +} diff --git a/RouteManager/v2/harmonyPatches/GraphPatch.cs b/RouteManager/v2/harmonyPatches/GraphPatch.cs new file mode 100644 index 0000000..7284f45 --- /dev/null +++ b/RouteManager/v2/harmonyPatches/GraphPatch.cs @@ -0,0 +1,87 @@ +using HarmonyLib; +using System.Net; +using System; +using System.Reflection; +using Track; +using RouteManager.v2.Logging; +using Microsoft.SqlServer.Server; +using TriangleNet.Geometry; + + + +namespace RouteManager.v2.harmonyPatches +{ + + + [HarmonyPatch(typeof(Graph))] + public static class GraphPatch + { + public delegate void delSegmentsReachableFrom(TrackSegment segment, TrackSegment.End end, out TrackSegment normal, out TrackSegment reversed); + public delegate void delCheckSwitchAgainstMovement(TrackSegment seg, TrackSegment nextSegment, TrackNode node); + + public static delSegmentsReachableFrom SegmentsReachableFrom; + public static delCheckSwitchAgainstMovement CheckSwitchAgainstMovement; + + + [HarmonyPostfix] + [HarmonyPatch(typeof(Graph), "Awake")] + public static void Awake(Graph __instance) + { + + RouteManager.logger.LogToDebug($"Graph.Awake()", LogLevel.Trace); + + //set up delegates to access private methods + /* + SegmentsReachableFrom = (DelSegmentsReachableFrom)Delegate.CreateDelegate(typeof(DelSegmentsReachableFrom), + null, + Graph.Shared.GetType().GetMethod("SegmentsReachableFrom", + BindingFlags.NonPublic | BindingFlags.Instance) + ); + */ + + /* + MethodInfo dynMethod = Graph.Shared.GetType().GetMethod("SegmentsReachableFrom", + BindingFlags.NonPublic | BindingFlags.Instance); + dynMethod.Invoke(Graph.Shared, new object[] { segment, end, normal, reversed }); + */ + + SegmentsReachableFrom = (delSegmentsReachableFrom)Delegate.CreateDelegate(typeof(delSegmentsReachableFrom), + Graph.Shared, + Graph.Shared.GetType().GetMethod("SegmentsReachableFrom", + BindingFlags.NonPublic | BindingFlags.Instance) + ); + + CheckSwitchAgainstMovement = (delCheckSwitchAgainstMovement)Delegate.CreateDelegate(typeof(delCheckSwitchAgainstMovement), + Graph.Shared, + Graph.Shared.GetType().GetMethod("CheckSwitchAgainstMovement", + BindingFlags.NonPublic | BindingFlags.Instance) + ); + + RouteManager.logger.LogToDebug($"EXITING Graph.Awake()", LogLevel.Trace); + } + + /*public static void DelSegmentsReachableFrom(TrackSegment segment, TrackSegment.End end, out TrackSegment normal, out TrackSegment reversed) + { + SegmentsReachableFrom(segment, end, out normal, out reversed); + }*/ + + /* + [HarmonyPrefix] + [HarmonyPatch(typeof(Graph), "SegmentsReachableFrom")] + public static void SegmentsReachableFrom(Graph __instance) + { + RouteManager.logger.LogToDebug($"Graph.SegmentsReachableFrom()", LogLevel.Trace); + + } + + [HarmonyPostfix] + [HarmonyPatch(typeof(Graph), "SegmentsReachableFrom")] + public static void SegmentsReachableFromPost(Graph __instance) + { + RouteManager.logger.LogToDebug($"Leaving Graph.SegmentsReachableFrom()", LogLevel.Trace); + + } + */ + } + +} \ No newline at end of file diff --git a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs index 4a0a214..31d3c55 100644 --- a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs +++ b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs @@ -15,6 +15,11 @@ using RouteManager.v2.Logging; using RouteManager.v2.UI; using UI.Common; +using Track; +using System.Collections.Generic; +using Microsoft.SqlServer.Server; +using TriangleNet.Geometry; +using KeyValue.Runtime; namespace RouteManager.v2.harmonyPatches @@ -251,6 +256,34 @@ static bool Prefix(CarInspector __instance, UIPanelBuilder builder) RouteManagerWindow.Show(car); }); + builder.AddButtonSelectable("Test Reachable", placeHolder, delegate + { + + PassengerStop alarka = PassengerStop.FindAll().Where(stop => stop.identifier == "alarka").First(); + + RouteManager.logger.LogToDebug($"Finding Route to Alarka (segments) {car.DisplayName} to {alarka?.name}..."); + RouteManager.logger.LogToDebug($"Current Location F: {car.LocationF}, Location A: {car.LocationA}, Location B: {car.LocationB}"); + + List segmentSteps = Graph.Shared.FindRoute(car.LocationF, (Track.Location)alarka.TrackSpans.First().lower); + + RouteManager.logger.LogToDebug($"Route found: {segmentSteps.Count} steps:"); + + for (int i = 0; i < segmentSteps.Count -1; i++) + { + TrackSegment seg = segmentSteps[i]; + TrackSegment segNext = segmentSteps[i + 1]; + + bool? requiredSwitchState; + bool isSwitch = DestinationManager.PathIsNormal(seg, segNext, out TrackNode? node, out requiredSwitchState); + + if (isSwitch) + { + RouteManager.logger.LogToDebug($"\r\nSeg.a: {seg.a.id}, {seg.a.name}\r\nSeg.b: {seg.b.id}, {seg.b.name}\r\nSegNext.a: {segNext.a.id}, {segNext.a.name}\r\nSegNext.b: {segNext.b.id}, {segNext.b.name}", LogLevel.Debug); + RouteManager.logger.LogToDebug($"\t\t\tSegment: {seg?.id}, {seg?.name}, {seg?.trackClass}, Node A: {seg?.a.name}, Node B: {seg?.b.name}, Desired switch pos normal: {requiredSwitchState}",LogLevel.Debug); + } + + } + }); builder.AddExpandingVerticalSpacer(); } else From 154fc4d49ec60c98ab5f1e58aba9de5d947c3acc Mon Sep 17 00:00:00 2001 From: AMacro Date: Sun, 11 Feb 2024 14:58:53 +1000 Subject: [PATCH 2/7] Added ability to check state of switch at approach Need to determine distance without absolute --- RouteManager/v2/core/AutoEngineer.cs | 95 +++++++++++++++++-- RouteManager/v2/core/DestinationManager.cs | 89 +++++++++++++---- RouteManager/v2/dataStructures/LocoTelem.cs | 1 + .../v2/harmonyPatches/RouteManagerUI.cs | 2 + 4 files changed, 162 insertions(+), 25 deletions(-) diff --git a/RouteManager/v2/core/AutoEngineer.cs b/RouteManager/v2/core/AutoEngineer.cs index b573bfb..c0a7e08 100644 --- a/RouteManager/v2/core/AutoEngineer.cs +++ b/RouteManager/v2/core/AutoEngineer.cs @@ -97,7 +97,7 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) //Set some initial values //closest station will only return a station marked as a stop - //LocoTelem.closestStation[locomotive] = StationManager.GetClosestStation_dev(locomotive); + LocoTelem.closestStation[locomotive] = StationManager.GetClosestStation_dev(locomotive); LocoTelem.currentDestination[locomotive] = StationManager.getNextStation_dev(locomotive); //set locomotive drive direction @@ -106,7 +106,7 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) //get route info - what are the switches on our route and what state do they need to be in? List switchRequirements; PassengerStop alarka = PassengerStop.FindAll().Where(stop => stop.identifier == "alarka").First(); - + if (DestinationManager.GetRouteSwitches(locomotive.LocationF, (Track.Location)alarka.TrackSpans.First().lower , out switchRequirements)) { //we have the total route to end of line/branch @@ -118,27 +118,46 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) //oh-oh we're flying blind! } + LocoTelem.routeSwitchRequirements[locomotive] = switchRequirements; + LocoTelem.closestStationNeedsUpdated[locomotive] = false; LocoTelem.CenterCar[locomotive] = TrainManager.GetCenterCoach(locomotive); //set initial passenger loading TrainManager.CopyStationsFromLocoToCoaches_dev(locomotive); + RouteManager.logger.LogToDebug($"Copy complete", LogLevel.Debug); + + RouteManager.logger.LogToDebug($"Closest station: {LocoTelem.closestStation.ContainsKey(locomotive)} Center Car: {LocoTelem.CenterCar.ContainsKey(locomotive)}", LogLevel.Debug); + //Give time for passenger loading/unloading if already at the station if (Vector3.Distance(LocoTelem.closestStation[locomotive].Item1.CenterPoint, LocoTelem.CenterCar[locomotive].GetCenterPosition(Graph.Shared)) <= 15f) //StationManager.isTrainInStation(LocoTelem.CenterCar[locomotive])) { + RouteManager.logger.LogToDebug($"We're close", LogLevel.Debug); while (!wasCurrentStopServed_dev(locomotive)) { yield return new WaitForSeconds(1); } + RouteManager.logger.LogToDebug($"Stop Served", LogLevel.Debug); + if (RouteManager.Settings.showDepartureMessage) RouteManager.logger.LogToConsole(String.Format("{0} has departed for {1}", Hyperlink.To(locomotive), LocoTelem.currentDestination[locomotive].DisplayName.ToUpper())); - + + RouteManager.logger.LogToDebug($"Clearing", LogLevel.Debug); LocoTelem.clearedForDeparture[locomotive] = true; + RouteManager.logger.LogToDebug($"Cleared", LogLevel.Debug); } + + + /************************************************** + * + * Initialisation complete, start main routines + * + ***************************************************/ + //Feature Ehancement #30 LocoTelem.initialSpeedSliderSet[locomotive] = false; @@ -425,9 +444,11 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) bool delayExecution = false; float trainVelocity; int stationPadding = 10; - float distanceToSwitch=float.MaxValue; - RouteSwitchData nextSwitch; + //get initial data + RouteSwitchData nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First();; + float distanceToSwitch = float.MinValue; + bool stopForSwitch = false; //Loop through transit logic @@ -444,12 +465,72 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) yield return null; } - nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + while(distanceToSwitch <= 0) + { + //remove the first switch + RouteManager.logger.LogToDebug($"Removing switch: {nextSwitch.trackSwitch.id}, Distance: {distanceToSwitch}", LogLevel.Debug); + LocoTelem.routeSwitchRequirements[locomotive].Remove(nextSwitch); + + nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + distanceToSwitch = DestinationManager.GetDistanceToSwitch(locomotive, nextSwitch); + } + //check our next switch distance distanceToSwitch = DestinationManager.GetDistanceToSwitch(locomotive, nextSwitch); + RouteManager.logger.LogToDebug($"Approaching: {nextSwitch.trackSwitch.id}, Distance: {distanceToSwitch}", LogLevel.Debug); if (distanceToSwitch <= 400) { - + if(nextSwitch.requiredStateNormal && nextSwitch.trackSwitch.isThrown) + { + //switch is not in the required position + if(nextSwitch.isDecision) + { + //check if we can leave on an alternate platform + TrackSpan[] ts = LocoTelem.currentDestination[locomotive].TrackSpans.ToArray(); + /* + if (LocoTelem.nextPassengerPlatform[locomotive] == null) + { + LocoTelem.nextPassengerPlatform[locomotive] = 0; + } + + while (LocoTelem.nextPassengerPlatform[locomotive] < ts.Length -1 ) + { + //Try the next plaform + LocoTelem.nextPassengerPlatform[locomotive]++; + Location pNext = (Location)ts[(int)LocoTelem.nextPassengerPlatform[locomotive]].lower; + + //can a route be found? + List mainRoute = LocoTelem.routeSwitchRequirements[locomotive]; + } + */ + + Location pNext = (Location)ts[1].lower; + List mainRoute = LocoTelem.routeSwitchRequirements[locomotive]; + + if (!DestinationManager.PlanRouteDeviation(ref mainRoute, nextSwitch, locomotive.LocationF, pNext )) + { + //we can't enter this platform come to a stop + stopForSwitch = true; + + } + RouteManager.logger.LogToDebug($"Locomotive {locomotive.DisplayName}: route updated for Switch"); + } + else + { + stopForSwitch = true; + } + } + + if (stopForSwitch) + { + RouteManager.logger.LogToConsole(String.Format("Locomotive {0} is holding at a switch; required state {1}", Hyperlink.To(locomotive), nextSwitch.requiredStateNormal ? "NORMAL" : "REVERSED")); + while (nextSwitch.requiredStateNormal == nextSwitch.trackSwitch.isThrown) + { + StateManager.ApplyLocal(new AutoEngineerCommand(locomotive.id, AutoEngineerMode.Road, LocoTelem.locoTravelingForward[locomotive], (int)0, null)); + yield return new WaitForSeconds(1); + } + stopForSwitch = false; + } } //Getting close to a station update some values... diff --git a/RouteManager/v2/core/DestinationManager.cs b/RouteManager/v2/core/DestinationManager.cs index 9770ea5..33fa5f2 100644 --- a/RouteManager/v2/core/DestinationManager.cs +++ b/RouteManager/v2/core/DestinationManager.cs @@ -255,28 +255,81 @@ public static float GetDistanceToSwitch(Car locomotive, RouteSwitchData trackSwi public static void PlanNextRoute(Location start,PassengerStop nextStation, ref List mainRoute) { TrackSpan[] tracks = nextStation.TrackSpans.ToArray(); - + if (tracks.Length > 1) { - Location secondPlatform = (Location)tracks[1].lower; + PlanNextRoute(start, (Location)tracks[1].lower, ref mainRoute, out RouteSwitchData commonPoint); + } + } + + public static bool PlanNextRoute(Location start, Location nextPlatform, ref List mainRoute, out RouteSwitchData commonPoint) + { + commonPoint = null; - List requirementsP2; - if (GetRouteSwitches(start, secondPlatform, out requirementsP2)) + List requirementsP2; + if (GetRouteSwitches(start, nextPlatform, out requirementsP2)) + { + //found a route to second platform + //find last common node + commonPoint = mainRoute.Intersect(requirementsP2, new RouteSwitchDataComparer()).Last(); + if (commonPoint != null) { - //found a route to second platform - //find last common node - RouteSwitchData common = mainRoute.Intersect(requirementsP2, new RouteSwitchDataComparer()).Last(); - if (common != null) - { - common.isDecision = true; - } - else - { - //routes don't intersect - RouteManager.logger.LogToDebug("No intersection of routes to second platform!", LogLevel.Debug); - } + //common point between leaving the station and the current main route + commonPoint.isDecision = true; + //new route from P2 + mainRoute = requirementsP2; + } + else + { + //routes don't intersect + RouteManager.logger.LogToDebug("No intersection of routes to second platform!", LogLevel.Debug); + return false; + } + } + return true; + } + + public static bool PlanRouteDeviation(ref List mainRoute, RouteSwitchData nextSwitch, Location current, Location nextPlatform) + { + + //can we get to the next platform? + if (DestinationManager.PlanNextRoute(current, nextPlatform, ref mainRoute, out RouteSwitchData commonPoint1)) + { + //find the last location on the mainRoute + Location finalDestination = new Location(mainRoute.Last().segmentTo, 0, mainRoute.Last().segmentTo.EndForNode(mainRoute.Last().trackSwitch)); + + List newRoute = new List(mainRoute); + //can we get from the next platform to the final destination + if (DestinationManager.PlanNextRoute(nextPlatform, finalDestination, ref newRoute, out RouteSwitchData commonPoint2)) + { + //we can get in and out, without breaking our route, lets update the route + + //flip the current switch requirements at our common switches + commonPoint1.requiredStateNormal = !commonPoint1.requiredStateNormal; + commonPoint2.requiredStateNormal = !commonPoint2.requiredStateNormal; + + //merge the two routes + int index1 = mainRoute.IndexOf(commonPoint1); + int index2 = mainRoute.IndexOf(commonPoint2); + + int indexNewRoute = newRoute.IndexOf(commonPoint2); + + index1++; + + //remove all elements between common points + mainRoute.RemoveRange(index1, index2 - index1); + + //insert any new elements + mainRoute.InsertRange(index1, newRoute.Take(indexNewRoute)); + + return true; } } + + + //can't deviate + return false; + } /************************************************************************************************************************** @@ -293,8 +346,8 @@ public static void PlanNextRoute(Location start,PassengerStop nextStation, ref L ***************************************************************************************************************************/ - //Determine if station is selected - public static bool IsStopStationSelected(PassengerStop stop, Car locomotive) + //Determine if station is selected + public static bool IsStopStationSelected(PassengerStop stop, Car locomotive) { //Trace Function //RouteManager.logger.LogToDebug("ENTERED FUNCTION: IsStopStationSelected", LogLevel.Trace); diff --git a/RouteManager/v2/dataStructures/LocoTelem.cs b/RouteManager/v2/dataStructures/LocoTelem.cs index 5a3ff78..4c782d9 100644 --- a/RouteManager/v2/dataStructures/LocoTelem.cs +++ b/RouteManager/v2/dataStructures/LocoTelem.cs @@ -28,6 +28,7 @@ public class LocoTelem public static Dictionary> previousDestinations { get; private set; } = new Dictionary>(); public static Dictionary previousDestination { get; private set; } = new Dictionary(); public static Dictionary> routeSwitchRequirements { get; private set; } = new Dictionary>(); + public static Dictionary nextPassengerPlatform { get; private set; } = new Dictionary(); public static Dictionary> lowFuelQuantities { get; private set; } = new Dictionary>(); public static Dictionary> UIPickupStationSelections { get; private set; } = new Dictionary>(); diff --git a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs index 31d3c55..2601974 100644 --- a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs +++ b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs @@ -256,6 +256,7 @@ static bool Prefix(CarInspector __instance, UIPanelBuilder builder) RouteManagerWindow.Show(car); }); + /* builder.AddButtonSelectable("Test Reachable", placeHolder, delegate { @@ -284,6 +285,7 @@ static bool Prefix(CarInspector __instance, UIPanelBuilder builder) } }); + */ builder.AddExpandingVerticalSpacer(); } else From 843a5c4c5e7c4f56a3d339f817e60d3533efe054 Mon Sep 17 00:00:00 2001 From: AMacro Date: Mon, 12 Feb 2024 19:27:35 +1000 Subject: [PATCH 3/7] Improved switch state detection Factors in all switches within 400m More testing required --- RouteManager/v2/core/AutoEngineer.cs | 178 ++++++++++++------ RouteManager/v2/core/DestinationManager.cs | 41 ++-- RouteManager/v2/core/TrainManager.cs | 19 ++ .../v2/dataStructures/RouteSwitchData.cs | 4 +- .../v2/harmonyPatches/RouteManagerUI.cs | 7 +- 5 files changed, 177 insertions(+), 72 deletions(-) diff --git a/RouteManager/v2/core/AutoEngineer.cs b/RouteManager/v2/core/AutoEngineer.cs index c0a7e08..4671135 100644 --- a/RouteManager/v2/core/AutoEngineer.cs +++ b/RouteManager/v2/core/AutoEngineer.cs @@ -141,14 +141,15 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) } RouteManager.logger.LogToDebug($"Stop Served", LogLevel.Debug); + } - if (RouteManager.Settings.showDepartureMessage) - RouteManager.logger.LogToConsole(String.Format("{0} has departed for {1}", Hyperlink.To(locomotive), LocoTelem.currentDestination[locomotive].DisplayName.ToUpper())); - RouteManager.logger.LogToDebug($"Clearing", LogLevel.Debug); - LocoTelem.clearedForDeparture[locomotive] = true; - RouteManager.logger.LogToDebug($"Cleared", LogLevel.Debug); - } + if (RouteManager.Settings.showDepartureMessage) + RouteManager.logger.LogToConsole(String.Format("{0} has departed for {1}", Hyperlink.To(locomotive), LocoTelem.currentDestination[locomotive].DisplayName.ToUpper())); + + RouteManager.logger.LogToDebug($"Clearing", LogLevel.Debug); + LocoTelem.clearedForDeparture[locomotive] = true; + RouteManager.logger.LogToDebug($"Cleared", LogLevel.Debug); @@ -446,9 +447,11 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) int stationPadding = 10; //get initial data - RouteSwitchData nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First();; + RouteSwitchData nextSwitch; float distanceToSwitch = float.MinValue; bool stopForSwitch = false; + bool checkNextSwitch = true; + int nextSwitchIndex; //Loop through transit logic @@ -465,72 +468,135 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) yield return null; } - while(distanceToSwitch <= 0) - { - //remove the first switch - RouteManager.logger.LogToDebug($"Removing switch: {nextSwitch.trackSwitch.id}, Distance: {distanceToSwitch}", LogLevel.Debug); - LocoTelem.routeSwitchRequirements[locomotive].Remove(nextSwitch); + /* + * Check all switches that are up to 400 metres away + */ + + //get the first switch in the list + nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + nextSwitchIndex = 0; - nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + if (nextSwitch != null) + { distanceToSwitch = DestinationManager.GetDistanceToSwitch(locomotive, nextSwitch); + checkNextSwitch = true; } - - //check our next switch distance - distanceToSwitch = DestinationManager.GetDistanceToSwitch(locomotive, nextSwitch); - RouteManager.logger.LogToDebug($"Approaching: {nextSwitch.trackSwitch.id}, Distance: {distanceToSwitch}", LogLevel.Debug); - if (distanceToSwitch <= 400) + + while (checkNextSwitch) { - if(nextSwitch.requiredStateNormal && nextSwitch.trackSwitch.isThrown) + //remove switche if it's beneath/behind us + if(distanceToSwitch <= 0 && nextSwitch != null) + { + //remove the switch + RouteManager.logger.LogToDebug($"Removing switch: {nextSwitch.trackSwitch.id}, Distance: {distanceToSwitch}", LogLevel.Debug); + LocoTelem.routeSwitchRequirements[locomotive].Remove(nextSwitch); + + //find the next switch and calculate the distance + nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + nextSwitchIndex = 0; + + //no more switches + if (nextSwitch == null) + break; + } + else + { + break; + } + + //check our next switch distance + distanceToSwitch = DestinationManager.GetDistanceToSwitch(locomotive, nextSwitch); + RouteManager.logger.LogToDebug($"Approaching: {nextSwitch.trackSwitch.id}, Distance: {distanceToSwitch}", LogLevel.Debug); + + if (distanceToSwitch <= 400) { - //switch is not in the required position - if(nextSwitch.isDecision) + //Check switch state vs requirements: Need normal and is reverse || need reverse and is normal + if (nextSwitch.requiredStateNormal && nextSwitch.trackSwitch.isThrown || + !nextSwitch.requiredStateNormal && !nextSwitch.trackSwitch.isThrown) { - //check if we can leave on an alternate platform - TrackSpan[] ts = LocoTelem.currentDestination[locomotive].TrackSpans.ToArray(); - /* - if (LocoTelem.nextPassengerPlatform[locomotive] == null) + RouteManager.logger.LogToDebug($"Switch {nextSwitch.trackSwitch.id} state incorrect req normal: {nextSwitch.requiredStateNormal}, is reversed: {nextSwitch.trackSwitch.isThrown}", LogLevel.Debug); + //switch is not in the required position, is it marked as able to be routed around? + //Currently we are ony looking at passenger platforms but in the future, we might want to look at track segments for complex switch yards + if (nextSwitch.isRoutable) { - LocoTelem.nextPassengerPlatform[locomotive] = 0; - } - - while (LocoTelem.nextPassengerPlatform[locomotive] < ts.Length -1 ) - { - //Try the next plaform - LocoTelem.nextPassengerPlatform[locomotive]++; - Location pNext = (Location)ts[(int)LocoTelem.nextPassengerPlatform[locomotive]].lower; - - //can a route be found? + RouteManager.logger.LogToDebug($"Switch is routable", LogLevel.Debug); + //check if we can leave on an alternate platform + TrackSpan[] ts = LocoTelem.currentDestination[locomotive].TrackSpans.ToArray(); + + /* + **** work in progress - check all platforms *** + if (LocoTelem.nextPassengerPlatform[locomotive] == null) + { + LocoTelem.nextPassengerPlatform[locomotive] = 0; + } + + while (LocoTelem.nextPassengerPlatform[locomotive] < ts.Length -1 ) + { + //Try the next plaform + LocoTelem.nextPassengerPlatform[locomotive]++; + Location pNext = (Location)ts[(int)LocoTelem.nextPassengerPlatform[locomotive]].lower; + + //can a route be found? + List mainRoute = LocoTelem.routeSwitchRequirements[locomotive]; + } + */ + + Location pNext = (Location)ts[1].lower; List mainRoute = LocoTelem.routeSwitchRequirements[locomotive]; - } - */ - - Location pNext = (Location)ts[1].lower; - List mainRoute = LocoTelem.routeSwitchRequirements[locomotive]; - if (!DestinationManager.PlanRouteDeviation(ref mainRoute, nextSwitch, locomotive.LocationF, pNext )) + if (pNext == null || !DestinationManager.PlanRouteDeviation(ref mainRoute, nextSwitch, locomotive.LocationF, pNext)) + { + //we can't enter this platform come to a stop + stopForSwitch = true; + RouteManager.logger.LogToDebug($"Deviation unsuccessful", LogLevel.Debug); + } + else + { + RouteManager.logger.LogToDebug($"Locomotive {locomotive.DisplayName}: route updated for switch"); + } + } + else { - //we can't enter this platform come to a stop stopForSwitch = true; - + RouteManager.logger.LogToDebug($"Switch is unroutable", LogLevel.Debug); } - RouteManager.logger.LogToDebug($"Locomotive {locomotive.DisplayName}: route updated for Switch"); } - else + + if (stopForSwitch) { - stopForSwitch = true; + RouteManager.logger.LogToConsole(String.Format("{0} is holding at a switch; required state: {1}", Hyperlink.To(locomotive), nextSwitch.requiredStateNormal ? "NORMAL" : "REVERSED")); + + //wait for the switch to clear + while (nextSwitch.requiredStateNormal == nextSwitch.trackSwitch.isThrown) + { + StateManager.ApplyLocal(new AutoEngineerCommand(locomotive.id, AutoEngineerMode.Road, LocoTelem.locoTravelingForward[locomotive], (int)0, null)); + yield return new WaitForSeconds(1); + } + + RouteManager.logger.LogToDebug($"Switch {nextSwitch.trackSwitch.id} cleared", LogLevel.Debug); + stopForSwitch = false; } } + else + { + RouteManager.logger.LogToDebug($"No switches within 400m", LogLevel.Debug); + checkNextSwitch = false; + break; + } - if (stopForSwitch) + //Get the switch after the current one + RouteManager.logger.LogToDebug($"Getting subsequent switch, index: {nextSwitchIndex}, count: {LocoTelem.routeSwitchRequirements[locomotive].Count() - 1}", LogLevel.Debug); + if (nextSwitchIndex < LocoTelem.routeSwitchRequirements[locomotive].Count() - 1) { - RouteManager.logger.LogToConsole(String.Format("Locomotive {0} is holding at a switch; required state {1}", Hyperlink.To(locomotive), nextSwitch.requiredStateNormal ? "NORMAL" : "REVERSED")); - while (nextSwitch.requiredStateNormal == nextSwitch.trackSwitch.isThrown) - { - StateManager.ApplyLocal(new AutoEngineerCommand(locomotive.id, AutoEngineerMode.Road, LocoTelem.locoTravelingForward[locomotive], (int)0, null)); - yield return new WaitForSeconds(1); - } - stopForSwitch = false; + nextSwitchIndex++; + + nextSwitch = LocoTelem.routeSwitchRequirements[locomotive][nextSwitchIndex + 1]; + distanceToSwitch = DestinationManager.GetDistanceToSwitch(locomotive, nextSwitch); } + else + { + checkNextSwitch = false; + } } //Getting close to a station update some values... @@ -587,7 +653,7 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) //Try again in 5 seconds if (delayExecution) { - yield return new WaitForSeconds(5); + yield return new WaitForSeconds(1);//5); } /***************************************************************** @@ -616,7 +682,7 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) RouteManager.logger.LogToDebug($"{locomotive.DisplayName} distance to station: {distanceToStation} Speed: {trainVelocity} Max speed: {(int)LocoTelem.RMMaxSpeed[locomotive]}"); generalTransit(locomotive); - yield return new WaitForSeconds(5); + yield return new WaitForSeconds(1);// 5); } //Entering Destination Boundary else if (distanceToStation <= 400 && distanceToStation > 300) diff --git a/RouteManager/v2/core/DestinationManager.cs b/RouteManager/v2/core/DestinationManager.cs index 33fa5f2..ff7c19f 100644 --- a/RouteManager/v2/core/DestinationManager.cs +++ b/RouteManager/v2/core/DestinationManager.cs @@ -7,7 +7,7 @@ using Track; using UnityEngine; using RouteManager.v2.Logging; -using UnityEngine.Rendering; +using Network; namespace RouteManager.v2.core { @@ -239,17 +239,30 @@ public static float GetDistanceToSwitch(Car locomotive, RouteSwitchData trackSwi Graph trackGraph = Graph.Shared; - //ToDo: use end of train, rather than locomotive - Car centerCar = LocoTelem.CenterCar[locomotive]; - - //centerCar.GetCenterPosition(trackGraph); + //use end of train, rather than centre car + Car leading = TrainManager.GetLeadingEnd(locomotive); + Location swLocation = new Location(trackSwitch.segmentFrom, 0f, trackSwitch.segmentFrom.EndForNode(trackSwitch.trackSwitch)); - float distanceA = trackGraph.FindDistance(centerCar.LocationA, swLocation); - float distanceB = trackGraph.FindDistance(centerCar.LocationB, swLocation); + float distanceA = trackGraph.FindDistance(leading.LocationA, swLocation); + float distanceB = trackGraph.FindDistance(leading.LocationB, swLocation); + float closestEndDistance = Math.Min(distanceA, distanceB); + + float straightLineDistance = Vector3.Distance(leading.GetCenterPosition(trackGraph), swLocation.GetPosition()); + Vector3 heading = swLocation.GetPosition() - leading.GetCenterPosition(trackGraph); - return Math.Min(distanceA, distanceB); + RouteManager.logger.LogToDebug($"Straight Line: {straightLineDistance}, Heading: {heading}, Heading.mag: {heading.magnitude}, Direction: {heading/heading.magnitude}"); + RouteManager.logger.LogToDebug($"Heading sign: {(heading.x >0 && (heading.x > -heading.y && heading.x mainRoute) @@ -275,7 +288,7 @@ public static bool PlanNextRoute(Location start, Location nextPlatform, ref List if (commonPoint != null) { //common point between leaving the station and the current main route - commonPoint.isDecision = true; + commonPoint.isRoutable = true; //new route from P2 mainRoute = requirementsP2; } @@ -316,11 +329,13 @@ public static bool PlanRouteDeviation(ref List mainRoute, Route index1++; - //remove all elements between common points - mainRoute.RemoveRange(index1, index2 - index1); + if(index1 != index2) { + //remove all elements between common points + mainRoute.RemoveRange(index1, index2 - index1); - //insert any new elements - mainRoute.InsertRange(index1, newRoute.Take(indexNewRoute)); + //insert any new elements + mainRoute.InsertRange(index1, newRoute.Take(indexNewRoute)); + } return true; } diff --git a/RouteManager/v2/core/TrainManager.cs b/RouteManager/v2/core/TrainManager.cs index 2ba1f59..4cad3b0 100644 --- a/RouteManager/v2/core/TrainManager.cs +++ b/RouteManager/v2/core/TrainManager.cs @@ -14,6 +14,8 @@ using Model.Definition.Data; using RouteManager.v2.Logging; using RollingStock; +using System.Runtime.CompilerServices; +using Network; namespace RouteManager.v2.core { @@ -131,6 +133,23 @@ public static void RMbell(Car locomotive, bool IsBell) StateManager.ApplyLocal(new PropertyChange(locomotive.id, Control.Bell, IsBell)); } + public static Car GetLeadingEnd(Car locomotive) + { + //int index = locomotive.set.IndexOfCar(locomotive).GetValueOrDefault(0); + bool right = LocoTelem.locoTravelingEastWard[locomotive]; + bool forward = LocoTelem.locoTravelingForward[locomotive]; + + //!right && !forward || !right && forward **simplifies to** !right || !forward + if (!right || !forward) //locomotive.velocity < 0) + { + return locomotive.EnumerateCoupled(Car.LogicalEnd.A).Last(); + } + //right && forward || right && !forward **simplifies to** right + else + { + return locomotive.EnumerateCoupled(Car.LogicalEnd.A).First(); + } + } public static Car GetCenterCoach(Car locomotive) { var graph = Graph.Shared; diff --git a/RouteManager/v2/dataStructures/RouteSwitchData.cs b/RouteManager/v2/dataStructures/RouteSwitchData.cs index bed9e83..d888d8c 100644 --- a/RouteManager/v2/dataStructures/RouteSwitchData.cs +++ b/RouteManager/v2/dataStructures/RouteSwitchData.cs @@ -13,7 +13,7 @@ public class RouteSwitchData public TrackSegment segmentFrom; //track we're coming from public TrackSegment segmentTo; //track we're going to public bool requiredStateNormal; //switch state to make the traversal - public bool isDecision; //this switch selects between two platforms + public bool isRoutable; //we can ignore the state of this switch and route around it public RouteSwitchData(TrackNode trackSwitch, TrackSegment segmentFrom, TrackSegment segmentTo, bool requiredStateNormal) @@ -26,7 +26,7 @@ public RouteSwitchData(TrackNode trackSwitch, TrackSegment segmentFrom, TrackSeg public override string ToString() { - return $"Switch ID: {this.trackSwitch.id}, From: {segmentFrom.id}, To: {segmentTo.id}, Is Decision: {this.isDecision}"; + return $"Switch ID: {this.trackSwitch.id}, From: {segmentFrom.id}, To: {segmentTo.id}, Is Decision: {this.isRoutable}"; } } diff --git a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs index 2601974..500cf5c 100644 --- a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs +++ b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs @@ -20,6 +20,7 @@ using Microsoft.SqlServer.Server; using TriangleNet.Geometry; using KeyValue.Runtime; +using Network; namespace RouteManager.v2.harmonyPatches @@ -215,6 +216,7 @@ static bool Prefix(CarInspector __instance, UIPanelBuilder builder) LocoTelem.RMMaxSpeed[car] = (int)(value * 5f); SetOrdersValue(null, null, (int) LocoTelem.RMMaxSpeed[car], null); }, 0f, num / 5, wholeNumbers: true); + builder.AddField("Max Speed", control); /********************************************************************************** @@ -255,7 +257,10 @@ static bool Prefix(CarInspector __instance, UIPanelBuilder builder) { RouteManagerWindow.Show(car); }); - + builder.AddButtonSelectable("Test Reachable", placeHolder, delegate + { + Multiplayer.Broadcast($"Leading End: {TrainManager.GetLeadingEnd(car)?.DisplayName}"); + }); /* builder.AddButtonSelectable("Test Reachable", placeHolder, delegate { From 3d3a597a049b039c472f4a02c47c9a7bbc97ca34 Mon Sep 17 00:00:00 2001 From: AMacro Date: Mon, 12 Feb 2024 20:28:09 +1000 Subject: [PATCH 4/7] Sync with upstream --- RouteManager.UMM/info.json | 3 ++- RouteManager/Properties/AssemblyInfo.cs | 2 +- post-build.ps1 | 4 ++++ repository.json | 8 ++++++++ 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 repository.json diff --git a/RouteManager.UMM/info.json b/RouteManager.UMM/info.json index 1efab31..e1ebe96 100644 --- a/RouteManager.UMM/info.json +++ b/RouteManager.UMM/info.json @@ -6,5 +6,6 @@ "AssemblyName": "RouteManager.UMM.dll", "EntryMethod": "RouteManager.UMM.RMUMM.Load", "ManagerVersion": "0.27.8", - "HomePage": "https://github.com/Erabior/RouteManager" + "HomePage": "https://github.com/Erabior/RouteManager", + "Repository": "https://raw.githubusercontent.com/Erabior/RouteManager/dev/repository.json" } diff --git a/RouteManager/Properties/AssemblyInfo.cs b/RouteManager/Properties/AssemblyInfo.cs index a392ca9..8951ea5 100644 --- a/RouteManager/Properties/AssemblyInfo.cs +++ b/RouteManager/Properties/AssemblyInfo.cs @@ -38,6 +38,6 @@ internal class AppVersion { - public const string Version = "2.0.0.9"; + public const string Version = "2.1.0.1"; } diff --git a/post-build.ps1 b/post-build.ps1 index c05f1f6..b2b5fae 100644 --- a/post-build.ps1 +++ b/post-build.ps1 @@ -23,6 +23,10 @@ if($Type -eq "UMM"){ $json.Version = $Ver $json | ConvertTo-Json -depth 32| set-content ($ProjDir + '\info.json') + $json = Get-Content ($SolnDir + 'repository.json') -raw | ConvertFrom-Json + $json.Releases | Where{$_.id -eq 'RouteManager'} | ForEach{$_.Version = $Ver} + $json | ConvertTo-Json -depth 32| set-content ($SolnDir + '\repository.json') + #Files to be compressed if we make a UMM zip $compress = @{ Path = ($ProjDir + "bin\Release\RouteManager.UMM.dll"), ($ProjDir + '\info.json') diff --git a/repository.json b/repository.json new file mode 100644 index 0000000..6d51120 --- /dev/null +++ b/repository.json @@ -0,0 +1,8 @@ +{ + "Releases": [ + { + "Id": "RouteManager", + "Version": "2.1.0.0" + } + ] +} From da3df879b68c9c02051157a9b8cd534109032c55 Mon Sep 17 00:00:00 2001 From: AMacro Date: Mon, 12 Feb 2024 20:38:01 +1000 Subject: [PATCH 5/7] Sync --- RouteManager.UMM/info.json | 2 +- repository.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RouteManager.UMM/info.json b/RouteManager.UMM/info.json index e1ebe96..c0a823e 100644 --- a/RouteManager.UMM/info.json +++ b/RouteManager.UMM/info.json @@ -1,6 +1,6 @@ { "Id": "RouteManager", - "Version": "2.0.0.9", + "Version": "2.1.0.1", "DisplayName": "Dispatcher", "Author": "Erabior", "AssemblyName": "RouteManager.UMM.dll", diff --git a/repository.json b/repository.json index 6d51120..a18eff2 100644 --- a/repository.json +++ b/repository.json @@ -2,7 +2,7 @@ "Releases": [ { "Id": "RouteManager", - "Version": "2.1.0.0" + "Version": "2.1.0.1" } ] } From cf4a95cc049f32b9d58554529ae6233027bd3465 Mon Sep 17 00:00:00 2001 From: AMacro Date: Mon, 12 Feb 2024 21:21:52 +1000 Subject: [PATCH 6/7] Tidy-up after merge --- RouteManager/v2/core/AutoEngineer.cs | 172 +++-------- RouteManager/v2/core/StationManager.cs | 412 +++++-------------------- 2 files changed, 122 insertions(+), 462 deletions(-) diff --git a/RouteManager/v2/core/AutoEngineer.cs b/RouteManager/v2/core/AutoEngineer.cs index 9f6bece..2921a2c 100644 --- a/RouteManager/v2/core/AutoEngineer.cs +++ b/RouteManager/v2/core/AutoEngineer.cs @@ -81,119 +81,6 @@ public IEnumerator AutoEngineerControlRoutine(Car locomotive) yield break; } - public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) - { - //Trace Function - RouteManager.logger.LogToDebug("ENTERED FUNCTION: AutoEngineerControlRoutine_dev", LogLevel.Trace); - - //Debug - RouteManager.logger.LogToDebug("Dev Coroutine Triggered!", LogLevel.Verbose); - RouteManager.logger.LogToDebug(String.Format("Loco: {0} \t Route Mode: {1}", locomotive.DisplayName, LocoTelem.RouteMode[locomotive]), LogLevel.Debug); - - //Setup departure clearances - LocoTelem.clearedForDeparture[locomotive] = false; - - RouteManager.logger.LogToDebug(String.Format("Loco: {0} \t has ID: {1}", locomotive.DisplayName, locomotive.id), LogLevel.Debug); - - //Set some initial values - //closest station will only return a station marked as a stop - LocoTelem.closestStation[locomotive] = StationManager.GetClosestStation_dev(locomotive); - LocoTelem.currentDestination[locomotive] = StationManager.getNextStation_dev(locomotive); - - //set locomotive drive direction - LocoTelem.locoTravelingForward[locomotive] = GetDirection(locomotive, LocoTelem.currentDestination[locomotive]); - - //get route info - what are the switches on our route and what state do they need to be in? - List switchRequirements; - PassengerStop alarka = PassengerStop.FindAll().Where(stop => stop.identifier == "alarka").First(); - - if (DestinationManager.GetRouteSwitches(locomotive.LocationF, (Track.Location)alarka.TrackSpans.First().lower , out switchRequirements)) - { - //we have the total route to end of line/branch - // Check if the next station has multiple platforms and find the last common switch - DestinationManager.PlanNextRoute(locomotive.LocationF, LocoTelem.currentDestination[locomotive], ref switchRequirements); - } - else - { - //oh-oh we're flying blind! - } - - LocoTelem.routeSwitchRequirements[locomotive] = switchRequirements; - - LocoTelem.closestStationNeedsUpdated[locomotive] = false; - LocoTelem.CenterCar[locomotive] = TrainManager.GetCenterCoach(locomotive); - - //set initial passenger loading - TrainManager.CopyStationsFromLocoToCoaches_dev(locomotive); - - RouteManager.logger.LogToDebug($"Copy complete", LogLevel.Debug); - - RouteManager.logger.LogToDebug($"Closest station: {LocoTelem.closestStation.ContainsKey(locomotive)} Center Car: {LocoTelem.CenterCar.ContainsKey(locomotive)}", LogLevel.Debug); - - //Give time for passenger loading/unloading if already at the station - if (Vector3.Distance(LocoTelem.closestStation[locomotive].Item1.CenterPoint, LocoTelem.CenterCar[locomotive].GetCenterPosition(Graph.Shared)) <= 15f) //StationManager.isTrainInStation(LocoTelem.CenterCar[locomotive])) - { - RouteManager.logger.LogToDebug($"We're close", LogLevel.Debug); - - while (!wasCurrentStopServed_dev(locomotive)) - { - yield return new WaitForSeconds(1); - } - - RouteManager.logger.LogToDebug($"Stop Served", LogLevel.Debug); - } - - - if (RouteManager.Settings.showDepartureMessage) - RouteManager.logger.LogToConsole(String.Format("{0} has departed for {1}", Hyperlink.To(locomotive), LocoTelem.currentDestination[locomotive].DisplayName.ToUpper())); - - RouteManager.logger.LogToDebug($"Clearing", LogLevel.Debug); - LocoTelem.clearedForDeparture[locomotive] = true; - RouteManager.logger.LogToDebug($"Cleared", LogLevel.Debug); - - - - /************************************************** - * - * Initialisation complete, start main routines - * - ***************************************************/ - - //Feature Ehancement #30 - LocoTelem.initialSpeedSliderSet[locomotive] = false; - - //Route Mode is enabled! - while (LocoTelem.RouteMode[locomotive]) - { - if (needToExitCoroutine_dev(locomotive)) - { - yield break; - } - - RouteManager.logger.LogToDebug(String.Format("Locomotive {0} center of train is car {1}", locomotive.DisplayName, LocoTelem.CenterCar[locomotive].DisplayName), LogLevel.Verbose); - - if (LocoTelem.TransitMode[locomotive]) - { - RouteManager.logger.LogToDebug(String.Format("Locomotive {0} is entering into transit mode", locomotive.DisplayName), LogLevel.Verbose); - yield return locomotiveTransitControl_dev(locomotive); - } - else - { - RouteManager.logger.LogToDebug(String.Format("Locomotive {0} is entering into Station Stop mode", locomotive.DisplayName), LogLevel.Verbose); - yield return locomotiveStationStopControl_dev(locomotive); - } - - yield return null; - } - - //Locomotive is no longer in Route Mode - RouteManager.logger.LogToDebug(String.Format("Loco: {0} \t Route mode was disabled! Stopping Coroutine.", locomotive.DisplayName, LogLevel.Debug)); - - //Trace Function - RouteManager.logger.LogToDebug("EXITING FUNCTION: AutoEngineerControlRoutine", LogLevel.Trace); - yield break; - } - //Locomotive Enroute to Destination public IEnumerator locomotiveTransitControl(Car locomotive) { @@ -695,8 +582,6 @@ private static void onArrival(Car locomotive) RouteManager.logger.LogToDebug("EXITING FUNCTION: onArrival", LogLevel.Trace); } - - //Check to see if passengers are unloaded private static bool wasCurrentStopServed(Car locomotive) { @@ -814,7 +699,6 @@ private static bool passStillWaiting(Car locomotive, PassengerMarker? marker) } - //Initial checks to determine if we can continue with the coroutine private bool needToExitCoroutine(Car locomotive) { @@ -920,8 +804,6 @@ private static bool GetDirection(Car locomotive, PassengerStop stop) ************************************************************************************************************/ - - public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) { //Trace Function @@ -937,34 +819,69 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) RouteManager.logger.LogToDebug(String.Format("Loco: {0} \t has ID: {1}", locomotive.DisplayName, locomotive.id), LogLevel.Debug); //Set some initial values - LocoTelem.closestStation[locomotive] = StationManager.GetClosestStation_dev(locomotive); //closest station will only return a station marked as a stop - LocoTelem.currentDestination[locomotive] = StationManager.getNextStation_dev(locomotive);//LocoTelem.closestStation[locomotive].Item1; - //StationManager.getInitialDestination(locomotive); + //closest station will only return a station marked as a stop + LocoTelem.closestStation[locomotive] = StationManager.GetClosestStation_dev(locomotive); + LocoTelem.currentDestination[locomotive] = StationManager.getNextStation_dev(locomotive); //set locomotive drive direction LocoTelem.locoTravelingForward[locomotive] = GetDirection(locomotive, LocoTelem.currentDestination[locomotive]); + //get route info - what are the switches on our route and what state do they need to be in? + List switchRequirements; + PassengerStop alarka = PassengerStop.FindAll().Where(stop => stop.identifier == "alarka").First(); + + if (DestinationManager.GetRouteSwitches(locomotive.LocationF, (Track.Location)alarka.TrackSpans.First().lower, out switchRequirements)) + { + //we have the total route to end of line/branch + // Check if the next station has multiple platforms and find the last common switch + DestinationManager.PlanNextRoute(locomotive.LocationF, LocoTelem.currentDestination[locomotive], ref switchRequirements); + } + else + { + //oh-oh we're flying blind! + } + + LocoTelem.routeSwitchRequirements[locomotive] = switchRequirements; + LocoTelem.closestStationNeedsUpdated[locomotive] = false; LocoTelem.CenterCar[locomotive] = TrainManager.GetCenterCoach(locomotive); //set initial passenger loading TrainManager.CopyStationsFromLocoToCoaches_dev(locomotive); + RouteManager.logger.LogToDebug($"Copy complete", LogLevel.Debug); + + RouteManager.logger.LogToDebug($"Closest station: {LocoTelem.closestStation.ContainsKey(locomotive)} Center Car: {LocoTelem.CenterCar.ContainsKey(locomotive)}", LogLevel.Debug); + //Give time for passenger loading/unloading if already at the station if (Vector3.Distance(LocoTelem.closestStation[locomotive].Item1.CenterPoint, LocoTelem.CenterCar[locomotive].GetCenterPosition(Graph.Shared)) <= 15f) //StationManager.isTrainInStation(LocoTelem.CenterCar[locomotive])) { + RouteManager.logger.LogToDebug($"We're close", LogLevel.Debug); while (!wasCurrentStopServed_dev(locomotive)) { yield return new WaitForSeconds(1); } - if (RouteManager.Settings.showDepartureMessage) - RouteManager.logger.LogToConsole(String.Format("{0} has departed for {1}", Hyperlink.To(locomotive), LocoTelem.currentDestination[locomotive].DisplayName.ToUpper())); - - LocoTelem.clearedForDeparture[locomotive] = true; + RouteManager.logger.LogToDebug($"Stop Served", LogLevel.Debug); } + + if (RouteManager.Settings.showDepartureMessage) + RouteManager.logger.LogToConsole(String.Format("{0} has departed for {1}", Hyperlink.To(locomotive), LocoTelem.currentDestination[locomotive].DisplayName.ToUpper())); + + RouteManager.logger.LogToDebug($"Clearing", LogLevel.Debug); + LocoTelem.clearedForDeparture[locomotive] = true; + RouteManager.logger.LogToDebug($"Cleared", LogLevel.Debug); + + + + /************************************************** + * + * Initialisation complete, start main routines + * + ***************************************************/ + //Feature Ehancement #30 LocoTelem.initialSpeedSliderSet[locomotive] = false; @@ -1000,6 +917,7 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) yield break; } + //Locomotive Enroute to Destination public IEnumerator locomotiveTransitControl_dev(Car locomotive) { @@ -1049,7 +967,7 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) */ //get the first switch in the list - nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].FirstOrDefault(); nextSwitchIndex = 0; if (nextSwitch != null) @@ -1068,7 +986,7 @@ public IEnumerator locomotiveTransitControl_dev(Car locomotive) LocoTelem.routeSwitchRequirements[locomotive].Remove(nextSwitch); //find the next switch and calculate the distance - nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].First(); + nextSwitch = LocoTelem.routeSwitchRequirements[locomotive].FirstOrDefault(); nextSwitchIndex = 0; //no more switches diff --git a/RouteManager/v2/core/StationManager.cs b/RouteManager/v2/core/StationManager.cs index bbdda18..d993094 100644 --- a/RouteManager/v2/core/StationManager.cs +++ b/RouteManager/v2/core/StationManager.cs @@ -155,101 +155,6 @@ public static (PassengerStop,float) GetClosestStation(Car currentCar) return (closestStation, closestDistance); } - public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) - { - //Trace Logging - RouteManager.logger.LogToDebug("ENTERED FUNCTION: GetClosestStation_dev", LogLevel.Trace); - - //Debugging Output - RouteManager.logger.LogToDebug(String.Format("Car {0} calculating closest station...", currentCar.DisplayName), LogLevel.Debug); - - // Initialize variables; - PassengerStop closestStation = null; - float closestDistance = float.MaxValue; - Graph graph = Graph.Shared; - - //Get front of the locomotive's location - Location locoFront = currentCar.LocationA; - Location locoRear = currentCar.LocationB; - - // If locoFront is null then bail - if (locoFront == null) - { - RouteManager.logger.LogToError("Could not obtain locomotive's front position."); - return (null, 0); - - } - - //Debugging Output - RouteManager.logger.LogToDebug(String.Format("Car {0} centerpoint {1} Facing right {2}", currentCar.DisplayName, locoFront.GetPosition(), currentCar.Orientation > 0), LogLevel.Verbose); - - /* - RouteManager.logger.LogToDebug("List Platform Locations", LogLevel.Verbose); - - foreach (PassengerStop station in PassengerStop.FindAll().Where(ps => !ps.ProgressionDisabled)) - { - RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}"); - RouteManager.logger.LogToDebug($"Station {station.name} Lower: {((Location)station.TrackSpans.First().lower).GetPosition()}, Rot: {((Location)station.TrackSpans.First().lower).GetPositionRotation()}, Direction: {((Location)station.TrackSpans.First().lower).GetDirection()}"); - RouteManager.logger.LogToDebug($"Station {station.name} Upper: {((Location)station.TrackSpans.First().upper).GetPosition()}, Rot: {((Location)station.TrackSpans.First().upper).GetPositionRotation()}, Direction: {((Location)station.TrackSpans.First().upper).GetDirection()}"); - }*/ - - - // Iterate over each station that has been progress unlocked and station is a selected stop - foreach (PassengerStop station in PassengerStop.FindAll().Where(ps => !ps.ProgressionDisabled && LocoTelem.stopStations[currentCar].Contains(ps))) - { - float distance = 0; - - RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}",LogLevel.Debug); - - try - { - // Calculate the distance between the locomotive and the station's platform centre - float distanceF = (graph.FindDistance(locoFront, (Location)station.TrackSpans.First().lower) + graph.FindDistance(locoFront, (Location)station.TrackSpans.First().upper)) / 2; - float distanceR = (graph.FindDistance(locoRear, (Location)station.TrackSpans.First().lower) + graph.FindDistance(locoRear, (Location)station.TrackSpans.First().upper)) /2; - - if (isStationRight(currentCar, station) && currentCar.Orientation > 0 || - !isStationRight(currentCar, station) && currentCar.Orientation < 0) - { - distance = distanceF; - } - else if(isStationRight(currentCar, station) && currentCar.Orientation < 0 || - !isStationRight(currentCar, station) && currentCar.Orientation > 0) - { - distance = distanceR; - } - - RouteManager.logger.LogToDebug($"Graph distance from {currentCar.DisplayName} to {station.identifier}: Front: {distanceF}, Rear: {distanceR}", LogLevel.Verbose); - - } - catch - { - RouteManager.logger.LogToDebug($"Error calculating graph distance", LogLevel.Verbose); - return (null, float.MaxValue); - } - - // Keep track of the closest station - if (distance < closestDistance) - { - closestDistance = distance; - closestStation = station; - } - - } - - //Debug output - RouteManager.logger.LogToDebug(String.Format("Car {0} Closest Station was: {1}", currentCar.DisplayName, closestStation.identifier), LogLevel.Debug); - - //Trace Logging - RouteManager.logger.LogToDebug("EXITING FUNCTION: GetClosestStation_dev", LogLevel.Trace); - - return (closestStation, closestDistance); - } - - public static IEnumerator<(PassengerStop, float)> CalculateDistanceToStation() - { - yield return (null, float.MaxValue); - } - //Attempt to determine midroute station better when starting the coroutine. public static PassengerStop getInitialDestination(Car locomotive) { @@ -332,115 +237,6 @@ public static PassengerStop getNextStation(Car locomotive) } - public static PassengerStop getNextStation_dev(Car locomotive) - { - PassengerStop nextStop = null; - PassengerStop currentStation = default(PassengerStop); - int currentStationIndex = -1; - - //Set a current destination if it does not exist, else use the current destination. - if (!LocoTelem.currentDestination.ContainsKey(locomotive) || LocoTelem.currentDestination[locomotive] == default(PassengerStop)) - { - //No Destination set so for now, assume closest station. - LocoTelem.closestStation[locomotive] = GetClosestStation_dev(locomotive); - currentStation = LocoTelem.closestStation[locomotive].Item1; - RouteManager.logger.LogToDebug(String.Format("Loco {0} does not have a destination. Defaulting to closest station {1}", locomotive.DisplayName, currentStation.identifier), LogLevel.Debug); - } - else - { - currentStation = LocoTelem.currentDestination[locomotive]; - } - - Dictionary stationsLookup = PassengerStop.FindAll().ToDictionary(stop => stop.identifier, stop => stop); - - //Get Selected menu items - List selectedStationIdentifiers = LocoTelem.stopStations[locomotive] - .Select(passengerStop => passengerStop.identifier) - .Distinct() - .ToList(); - - //Convert selected menu items into an ordered list of station stops - List orderedstopStations = DestinationManager.orderedStations.Where(item => selectedStationIdentifiers.Contains(item)).ToList(); - - currentStationIndex = orderedstopStations.IndexOf(currentStation.identifier); - - RouteManager.logger.LogToDebug($"Current Index: {currentStationIndex} Travelling East: {LocoTelem.locoTravelingEastWard[locomotive]} osStations Count: {orderedstopStations.Count()}", LogLevel.Trace); - - if (currentStationIndex < 0) - { - //find the current station index - int closestIndex = DestinationManager.orderedStations.FindIndex(stop => stop.Equals(currentStation.identifier)); - if (LocoTelem.locoTravelingEastWard[locomotive]) - { - //what are the stops after this point? - string nextStopStation = DestinationManager.orderedStations.Take(closestIndex - 1).Where(station => orderedstopStations.Contains(station)).Last(); - - if (nextStopStation != null) - { - nextStop = stationsLookup[nextStopStation]; - } - else - { - //past the end of the line, get the last stop station - LocoTelem.locoTravelingEastWard[locomotive] = false; - nextStop = stationsLookup[orderedstopStations.Last()]; - } - - } - else - { - //what are the stops after this point? - string nextStopStation = DestinationManager.orderedStations.Skip(closestIndex + 1).Where(station => orderedstopStations.Contains(station)).First(); - - if (nextStopStation != null) - { - nextStop = stationsLookup[nextStopStation]; - } - else - { - //past the end of the line, get the last stop station - LocoTelem.locoTravelingEastWard[locomotive] = true; - nextStop = stationsLookup[orderedstopStations.First()]; - } - } - } - else - { - - if (LocoTelem.locoTravelingEastWard[locomotive]) - { - if (currentStationIndex <= 0) - { - //we're at the end of the line - LocoTelem.locoTravelingEastWard[locomotive] = false; - nextStop = stationsLookup[orderedstopStations[currentStationIndex + 1]]; - } - else - { - nextStop = stationsLookup[orderedstopStations[currentStationIndex - 1]]; - } - } - else - { - if (currentStationIndex >= orderedstopStations.Count() - 1) - { - //we're at the end of the line - LocoTelem.locoTravelingEastWard[locomotive] = true; - nextStop = stationsLookup[orderedstopStations[currentStationIndex - 1]]; - } - else - { - nextStop = stationsLookup[orderedstopStations[currentStationIndex + 1]]; - } - } - } - - RouteManager.logger.LogToDebug(String.Format("Loco {0} next stop determined to be: {1}", locomotive.DisplayName, nextStop.identifier), LogLevel.Debug); - - return nextStop; - } - - //Brand new station logic. private static PassengerStop calculateNextStation(List orderedstopStations, List selectedPassengerStops, PassengerStop currentStation, Car locomotive) { @@ -661,95 +457,6 @@ public static bool isStationRight(Car locomotive, PassengerStop station) ************************************************************************************************************/ - - public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) - { - //Trace Logging - RouteManager.logger.LogToDebug("ENTERED FUNCTION: GetClosestStation_dev", LogLevel.Trace); - - //Debugging Output - RouteManager.logger.LogToDebug(String.Format("Car {0} calculating closest station...", currentCar.DisplayName), LogLevel.Debug); - - // Initialize variables; - PassengerStop closestStation = null; - float closestDistance = float.MaxValue; - Graph graph = Graph.Shared; - - //Get front of the locomotive's location - Location locoFront = currentCar.LocationA; - Location locoRear = currentCar.LocationB; - - // If locoFront is null then bail - if (locoFront == null) - { - RouteManager.logger.LogToError("Could not obtain locomotive's front position."); - return (null, 0); - } - - //Debugging Output - RouteManager.logger.LogToDebug(String.Format("Car {0} centerpoint {1} Facing right {2}", currentCar.DisplayName, locoFront.GetPosition(), currentCar.Orientation > 0), LogLevel.Verbose); - - /* - RouteManager.logger.LogToDebug("List Platform Locations", LogLevel.Verbose); - - foreach (PassengerStop station in PassengerStop.FindAll().Where(ps => !ps.ProgressionDisabled)) - { - RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}"); - RouteManager.logger.LogToDebug($"Station {station.name} Lower: {((Location)station.TrackSpans.First().lower).GetPosition()}, Rot: {((Location)station.TrackSpans.First().lower).GetPositionRotation()}, Direction: {((Location)station.TrackSpans.First().lower).GetDirection()}"); - RouteManager.logger.LogToDebug($"Station {station.name} Upper: {((Location)station.TrackSpans.First().upper).GetPosition()}, Rot: {((Location)station.TrackSpans.First().upper).GetPositionRotation()}, Direction: {((Location)station.TrackSpans.First().upper).GetDirection()}"); - }*/ - - - // Iterate over each station that has been progress unlocked and station is a selected stop - foreach (PassengerStop station in PassengerStop.FindAll().Where(ps => !ps.ProgressionDisabled && LocoTelem.stopStations[currentCar].Contains(ps))) - { - float distance = 0; - - RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}"); - - try - { - // Calculate the distance between the locomotive and the station's platform centre - float distanceF = (graph.FindDistance(locoFront, (Location)station.TrackSpans.First().lower) + graph.FindDistance(locoFront, (Location)station.TrackSpans.First().upper)) / 2; - float distanceR = (graph.FindDistance(locoRear, (Location)station.TrackSpans.First().lower) + graph.FindDistance(locoRear, (Location)station.TrackSpans.First().upper)) / 2; - - if (isStationRight(currentCar, station) && currentCar.Orientation > 0 || - !isStationRight(currentCar, station) && currentCar.Orientation < 0) - { - distance = distanceF; - } - else if (isStationRight(currentCar, station) && currentCar.Orientation < 0 || - !isStationRight(currentCar, station) && currentCar.Orientation > 0) - { - distance = distanceR; - } - - RouteManager.logger.LogToDebug($"Graph distance from {currentCar.DisplayName} to {station.identifier}: Front: {distanceF}, Rear: {distanceR}", LogLevel.Verbose); - - } - catch - { - RouteManager.logger.LogToDebug($"Error calculating graph distance", LogLevel.Verbose); - return (null, float.MaxValue); - } - - // Keep track of the closest station - if (distance < closestDistance) - { - closestDistance = distance; - closestStation = station; - } - } - - //Debug output - RouteManager.logger.LogToDebug(String.Format("Car {0} Closest Station was: {1}", currentCar.DisplayName, closestStation.identifier), LogLevel.Debug); - - //Trace Logging - RouteManager.logger.LogToDebug("EXITING FUNCTION: GetClosestStation_dev", LogLevel.Trace); - - return (closestStation, closestDistance); - } - public static PassengerStop getNextStation_dev(Car locomotive) { PassengerStop nextStop = null; @@ -760,7 +467,8 @@ public static PassengerStop getNextStation_dev(Car locomotive) if (!LocoTelem.currentDestination.ContainsKey(locomotive) || LocoTelem.currentDestination[locomotive] == default(PassengerStop)) { //No Destination set so for now, assume closest station. - currentStation = GetClosestStation_dev(locomotive).Item1; + LocoTelem.closestStation[locomotive] = GetClosestStation_dev(locomotive); + currentStation = LocoTelem.closestStation[locomotive].Item1; RouteManager.logger.LogToDebug(String.Format("Loco {0} does not have a destination. Defaulting to closest station {1}", locomotive.DisplayName, currentStation.identifier), LogLevel.Debug); } else @@ -856,67 +564,101 @@ public static PassengerStop getNextStation_dev(Car locomotive) return nextStop; } - - /* - public static PassengerStop getInitialDestination_dev(Car locomotive) + public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) { + //Trace Logging + RouteManager.logger.LogToDebug("ENTERED FUNCTION: GetClosestStation_dev", LogLevel.Trace); - if (isTrainInStation(locomotive)) - { - return LocoTelem.closestStation[locomotive]; - } - else + //Debugging Output + RouteManager.logger.LogToDebug(String.Format("Car {0} calculating closest station...", currentCar.DisplayName), LogLevel.Debug); + + // Initialize variables; + PassengerStop closestStation = null; + float closestDistance = float.MaxValue; + Graph graph = Graph.Shared; + + //Get front of the locomotive's location + Location locoFront = currentCar.LocationA; + Location locoRear = currentCar.LocationB; + + // If locoFront is null then bail + if (locoFront == null) { + RouteManager.logger.LogToError("Could not obtain locomotive's front position."); + return (null, 0); } + //Debugging Output + RouteManager.logger.LogToDebug(String.Format("Car {0} centerpoint {1} Facing right {2}", currentCar.DisplayName, locoFront.GetPosition(), currentCar.Orientation > 0), LogLevel.Verbose); + /* - PassengerStop nextStation = getNextStation(locomotive); + RouteManager.logger.LogToDebug("List Platform Locations", LogLevel.Verbose); + + foreach (PassengerStop station in PassengerStop.FindAll().Where(ps => !ps.ProgressionDisabled)) + { + RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}"); + RouteManager.logger.LogToDebug($"Station {station.name} Lower: {((Location)station.TrackSpans.First().lower).GetPosition()}, Rot: {((Location)station.TrackSpans.First().lower).GetPositionRotation()}, Direction: {((Location)station.TrackSpans.First().lower).GetDirection()}"); + RouteManager.logger.LogToDebug($"Station {station.name} Upper: {((Location)station.TrackSpans.First().upper).GetPosition()}, Rot: {((Location)station.TrackSpans.First().upper).GetPositionRotation()}, Direction: {((Location)station.TrackSpans.First().upper).GetDirection()}"); + }*/ - RouteManager.logger.LogToDebug(String.Format("Loco {0} determining initial destination", locomotive.DisplayName), LogLevel.Debug); - //Make sure a previous destination is set - if (LocoTelem.previousDestinations.ContainsKey(locomotive)) + // Iterate over each station that has been progress unlocked and station is a selected stop + foreach (PassengerStop station in PassengerStop.FindAll().Where(ps => !ps.ProgressionDisabled && LocoTelem.stopStations[currentCar].Contains(ps))) { - RouteManager.logger.LogToDebug(String.Format("Loco {0} has previous destinations", locomotive.DisplayName), LogLevel.Verbose); - //Compare Previous Destination - //If we have not visited the closest station - if (!LocoTelem.previousDestinations[locomotive].Contains(LocoTelem.closestStation[locomotive].Item1)) + float distance = 0; + + RouteManager.logger.LogToDebug($"Station {station.name} neighbours: {string.Join(", ", station.neighbors.Select(ps => ps.identifier).ToArray())}", LogLevel.Debug); + + try { - RouteManager.logger.LogToDebug(String.Format("Loco {0} has previous destinations not containing closeset station", locomotive.DisplayName), LogLevel.Verbose); - //If the closest station is selected.... - if (LocoTelem.stopStations[locomotive].Contains(LocoTelem.closestStation[locomotive].Item1)) + // Calculate the distance between the locomotive and the station's platform centre + float distanceF = (graph.FindDistance(locoFront, (Location)station.TrackSpans.First().lower) + graph.FindDistance(locoFront, (Location)station.TrackSpans.First().upper)) / 2; + float distanceR = (graph.FindDistance(locoRear, (Location)station.TrackSpans.First().lower) + graph.FindDistance(locoRear, (Location)station.TrackSpans.First().upper)) / 2; + + if (isStationRight(currentCar, station) && currentCar.Orientation > 0 || + !isStationRight(currentCar, station) && currentCar.Orientation < 0) { - RouteManager.logger.LogToDebug(String.Format("Loco {0} Initial destintion is the closest: {1}", locomotive.DisplayName, LocoTelem.closestStation[locomotive].Item1)); - return LocoTelem.closestStation[locomotive].Item1; + distance = distanceF; } + else if (isStationRight(currentCar, station) && currentCar.Orientation < 0 || + !isStationRight(currentCar, station) && currentCar.Orientation > 0) + { + distance = distanceR; + } + + RouteManager.logger.LogToDebug($"Graph distance from {currentCar.DisplayName} to {station.identifier}: Front: {distanceF}, Rear: {distanceR}", LogLevel.Verbose); + } - } - else - { - //If the closest station is selected.... - if (LocoTelem.stopStations[locomotive].Contains(LocoTelem.closestStation[locomotive].Item1)) - { - RouteManager.logger.LogToDebug(String.Format("Loco {0} Initial destintion is the closest: {1}", locomotive.DisplayName, LocoTelem.closestStation[locomotive].Item1)); - return LocoTelem.closestStation[locomotive].Item1; - } - else if (LocoTelem.stopStations[locomotive].Contains(LocoTelem.currentDestination[locomotive]) && !LocoTelem.previousDestinations[locomotive].Contains(LocoTelem.currentDestination[locomotive])) + catch { - RouteManager.logger.LogToDebug(String.Format("Loco {0} Initial destintion is the current: {1}", locomotive.DisplayName, LocoTelem.currentDestination[locomotive])); - return LocoTelem.currentDestination[locomotive]; + RouteManager.logger.LogToDebug($"Error calculating graph distance", LogLevel.Verbose); + return (null, float.MaxValue); } - else + + // Keep track of the closest station + if (distance < closestDistance) { - RouteManager.logger.LogToDebug(String.Format("Loco {0} Initial destintion is not the closest: {1}", locomotive.DisplayName, nextStation)); - return nextStation; + closestDistance = distance; + closestStation = station; } + } - //Worst case, Just default to the next station - RouteManager.logger.LogToDebug(String.Format("Loco {0} getInitialDestination reached default case! Station was: {1}", locomotive.DisplayName, nextStation), LogLevel.Error); - return nextStation; - - }*/ + //Debug output + RouteManager.logger.LogToDebug(String.Format("Car {0} Closest Station was: {1}", currentCar.DisplayName, closestStation.identifier), LogLevel.Debug); + + //Trace Logging + RouteManager.logger.LogToDebug("EXITING FUNCTION: GetClosestStation_dev", LogLevel.Trace); + + return (closestStation, closestDistance); + } + + //Future use - try to avoid lag when calculating closest station + public static IEnumerator<(PassengerStop, float)> CalculateDistanceToStation() + { + yield return (null, float.MaxValue); + } } } From 87a9747b05c7eff6b3fc3b10416f59e49080ca8d Mon Sep 17 00:00:00 2001 From: AMacro Date: Mon, 12 Feb 2024 21:38:05 +1000 Subject: [PATCH 7/7] Remove unused references --- RouteManager/v2/core/AutoEngineer.cs | 11 ++++++++--- RouteManager/v2/core/DestinationManager.cs | 1 - RouteManager/v2/core/StationManager.cs | 5 ++--- RouteManager/v2/core/TrainManager.cs | 2 -- RouteManager/v2/dataStructures/LocoTelem.cs | 2 -- RouteManager/v2/dataStructures/RouteSwitchData.cs | 6 +----- RouteManager/v2/dataStructures/StationInformation.cs | 6 +----- RouteManager/v2/dataStructures/StationMapData.cs | 7 +------ RouteManager/v2/harmonyPatches/GraphPatch.cs | 4 +--- RouteManager/v2/harmonyPatches/RouteManagerUI.cs | 5 ----- 10 files changed, 14 insertions(+), 35 deletions(-) diff --git a/RouteManager/v2/core/AutoEngineer.cs b/RouteManager/v2/core/AutoEngineer.cs index 2921a2c..f5a8781 100644 --- a/RouteManager/v2/core/AutoEngineer.cs +++ b/RouteManager/v2/core/AutoEngineer.cs @@ -10,10 +10,8 @@ using System.Linq; using UnityEngine; using RouteManager.v2.Logging; -using Network; using RollingStock; using Track; -using static Game.Reputation.PassengerReputationCalculator; namespace RouteManager.v2.core { @@ -828,12 +826,19 @@ public IEnumerator AutoEngineerControlRoutine_dev(Car locomotive) //get route info - what are the switches on our route and what state do they need to be in? List switchRequirements; + + + + //Dev/testing only to be replaced once logic is working PassengerStop alarka = PassengerStop.FindAll().Where(stop => stop.identifier == "alarka").First(); + //End dev/testing code + + //get all switches on our route from current location to end of line/end of branch line if (DestinationManager.GetRouteSwitches(locomotive.LocationF, (Track.Location)alarka.TrackSpans.First().lower, out switchRequirements)) { //we have the total route to end of line/branch - // Check if the next station has multiple platforms and find the last common switch + // Check if the next station has multiple platforms and find the last common switch - this is used later if we find ourselves against a switch DestinationManager.PlanNextRoute(locomotive.LocationF, LocoTelem.currentDestination[locomotive], ref switchRequirements); } else diff --git a/RouteManager/v2/core/DestinationManager.cs b/RouteManager/v2/core/DestinationManager.cs index ff7c19f..e6084bf 100644 --- a/RouteManager/v2/core/DestinationManager.cs +++ b/RouteManager/v2/core/DestinationManager.cs @@ -7,7 +7,6 @@ using Track; using UnityEngine; using RouteManager.v2.Logging; -using Network; namespace RouteManager.v2.core { diff --git a/RouteManager/v2/core/StationManager.cs b/RouteManager/v2/core/StationManager.cs index d993094..ab34f6d 100644 --- a/RouteManager/v2/core/StationManager.cs +++ b/RouteManager/v2/core/StationManager.cs @@ -1,5 +1,4 @@ -using Game.Events; -using Model; +using Model; using RollingStock; using RouteManager.v2.dataStructures; using RouteManager.v2.Logging; @@ -655,7 +654,7 @@ public static (PassengerStop, float) GetClosestStation_dev(Car currentCar) } - //Future use - try to avoid lag when calculating closest station + //Future use - try to avoid lag when calculating closest station by public static IEnumerator<(PassengerStop, float)> CalculateDistanceToStation() { yield return (null, float.MaxValue); diff --git a/RouteManager/v2/core/TrainManager.cs b/RouteManager/v2/core/TrainManager.cs index c89acd4..b91e071 100644 --- a/RouteManager/v2/core/TrainManager.cs +++ b/RouteManager/v2/core/TrainManager.cs @@ -14,8 +14,6 @@ using Model.Definition.Data; using RouteManager.v2.Logging; using RollingStock; -using System.Runtime.CompilerServices; -using Network; namespace RouteManager.v2.core { diff --git a/RouteManager/v2/dataStructures/LocoTelem.cs b/RouteManager/v2/dataStructures/LocoTelem.cs index d64d016..5ef39f9 100644 --- a/RouteManager/v2/dataStructures/LocoTelem.cs +++ b/RouteManager/v2/dataStructures/LocoTelem.cs @@ -1,8 +1,6 @@ using Model; using RollingStock; using System.Collections.Generic; -using Track; - namespace RouteManager.v2.dataStructures { diff --git a/RouteManager/v2/dataStructures/RouteSwitchData.cs b/RouteManager/v2/dataStructures/RouteSwitchData.cs index d888d8c..6c38266 100644 --- a/RouteManager/v2/dataStructures/RouteSwitchData.cs +++ b/RouteManager/v2/dataStructures/RouteSwitchData.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; using Track; namespace RouteManager.v2.dataStructures diff --git a/RouteManager/v2/dataStructures/StationInformation.cs b/RouteManager/v2/dataStructures/StationInformation.cs index b3418fa..f2a03e9 100644 --- a/RouteManager/v2/dataStructures/StationInformation.cs +++ b/RouteManager/v2/dataStructures/StationInformation.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace RouteManager.v2.dataStructures { diff --git a/RouteManager/v2/dataStructures/StationMapData.cs b/RouteManager/v2/dataStructures/StationMapData.cs index 24dea0b..4e43588 100644 --- a/RouteManager/v2/dataStructures/StationMapData.cs +++ b/RouteManager/v2/dataStructures/StationMapData.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using UnityEngine; +using UnityEngine; namespace RouteManager.v2.dataStructures { diff --git a/RouteManager/v2/harmonyPatches/GraphPatch.cs b/RouteManager/v2/harmonyPatches/GraphPatch.cs index 7284f45..51c0666 100644 --- a/RouteManager/v2/harmonyPatches/GraphPatch.cs +++ b/RouteManager/v2/harmonyPatches/GraphPatch.cs @@ -1,11 +1,9 @@ using HarmonyLib; -using System.Net; using System; using System.Reflection; using Track; using RouteManager.v2.Logging; -using Microsoft.SqlServer.Server; -using TriangleNet.Geometry; + diff --git a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs index 500cf5c..77295ea 100644 --- a/RouteManager/v2/harmonyPatches/RouteManagerUI.cs +++ b/RouteManager/v2/harmonyPatches/RouteManagerUI.cs @@ -15,11 +15,6 @@ using RouteManager.v2.Logging; using RouteManager.v2.UI; using UI.Common; -using Track; -using System.Collections.Generic; -using Microsoft.SqlServer.Server; -using TriangleNet.Geometry; -using KeyValue.Runtime; using Network;