// Possible interpretation (as found on internet, by krausyao) // TrPathNode ( AAAABBBB mainIdx passingIdx pdpIdx ) // AAAA wait time seconds in hexidecimal // BBBB (Also hexidecimal, so 16 bits) // Bit 0 - connected pdp-entry references a reversal-point (1/x1) // Bit 1 - waiting point (2/x2) // Bit 2 - intermediate point between switches (4/x4) // Bit 3 - 'other exit' is used (8/x8) // Bit 4 - 'optional Route' active (16/x10) // // But the interpretation below is a bit more complicated. // TODO. Since this interpretation belongs to the PATfile itself, // in principle it would be more logical to have it in PATfile.cs. But this leads to too much code duplication private void InterpretPathNodeFlags(PathNode tpn, PathDataPoint pdp, bool isTimetableMode) { if ((tpn.PathFlags & (PathFlags.WaitPoint | PathFlags.ReversalPoint)) == 0) { return; } // bit 0 and/or bit 1 is set. if ((tpn.PathFlags & PathFlags.ReversalPoint) != 0) { // if bit 0 is set: reversal Type = AIPathNodeType.Reverse; } else { // bit 0 is not set, but bit 1 is set:waiting point Type = AIPathNodeType.Stop; //<CSComment> tests showed me that value 9 in pdp is generated when the waiting point (or also //a path start or end point) are dragged within the path editor of the MSTS activity editor; the points are still valid; // however, as a contradictory case of the past has been reported, the check is skipped only when the enhanced compatibility flag is on; if (pdp.IsInvalid && isTimetableMode) // not a valid point { Type = AIPathNodeType.Invalid; } } WaitTimeS = tpn.WaitTime; // get the AAAA part. // computations for absolute wait times are made within AITrain.cs /* if (WaitTimeS >= 30000 && WaitTimeS < 40000) * { * // real wait time. * // waitTimeS (in decimal notation) = 3HHMM (hours and minuts) * int hour = (WaitTimeS / 100) % 100; * int minute = WaitTimeS % 100; * WaitUntil = 60 * (minute + 60 * hour); * WaitTimeS = 0; * }*/ // computations are made within AITrain.cs /* else if (WaitTimeS >= 40000 && WaitTimeS < 60000) * { * // Uncouple if a wait=stop point * // waitTimeS (in decimal notation) = 4NNSS (uncouple NN cars, wait SS seconds) * // or 5NNSS (uncouple NN cars, keep rear, wait SS seconds) * NCars = (WaitTimeS / 100) % 100; * if (WaitTimeS >= 50000) * NCars = -NCars; * WaitTimeS %= 100; * if (Type == AIPathNodeType.Stop) * Type = AIPathNodeType.Uncouple; * } * else if (WaitTimeS >= 60000) // this is old and should be removed/reused * { * // waitTimes = 6xSSS with waitTime SSS seconds. * WaitTimeS %= 1000; * } */ }
/// <summary> /// Creates a single trainpathNode and initializes everything that do not depend on other nodes. /// The trainpath constructor will initialize the rest. /// </summary> protected TrainpathNode(PathDataPoint pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : this(trackDB, tsectionDat) { Location = pdp.Location; if (pdp.IsInvalid) // not a valid point { this.SetBroken(NodeStatus.SetAsInvalid); } }
public bool IsVisited; // true if the train has visited this node /// <summary> /// Creates a single AIPathNode and initializes everything that do not depend on other nodes. /// The AIPath constructor will initialize the rest. /// </summary> public AIPathNode(PathNode tpn, PathDataPoint pdp, TrackDB trackDB, bool isTimetableMode) { ID = (int)tpn.PathDataPoint; InterpretPathNodeFlags(tpn, pdp, isTimetableMode); Location = pdp.Location; if (pdp.IsJunction) { JunctionIndex = FindJunctionOrEndIndex(Location, trackDB, true); } }
/// <summary> /// Sort of constructor. But it creates the right sub-class /// </summary> /// <returns>A sub-class object properly initialized</returns> public static TrainpathNode CreatePathNode(PathNode tpn, PathDataPoint pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) { if (pdp.IsJunction) { // we do not use tpn: this means we do not interpret the flags return(new TrainpathJunctionNode(pdp, trackDB, tsectionDat)); } else { return(new TrainpathVectorNode(tpn, pdp, trackDB, tsectionDat)); } }
/// <summary> /// Constructor based on PAT file information. /// </summary> /// <param name="tpn">TrPathNode from .pat file</param> /// <param name="pdp">TrackPDP from .pat file</param> /// <param name="trackDB"></param> /// <param name="tsectionDat"></param> public TrainpathVectorNode(PathNode tpn, PathDataPoint pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : base(pdp, trackDB, tsectionDat) { try { Traveller traveller = new Traveller(tsectionDat, trackDB.TrackNodes, this.Location); CopyDataFromTraveller(traveller); } catch { SetBroken(NodeStatus.NotOnTrack); } ForwardOriented = true; // only initial setting InterpretPathNodeFlags(tpn); }
/// <summary> /// Constructor based on the data given in the .pat file /// </summary> /// <param name="pdp">Corresponding PDP in the .patfile</param> /// <param name="trackDB"></param> /// <param name="tsectionDat"></param> public TrainpathJunctionNode(PathDataPoint pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : base(pdp, trackDB, tsectionDat) { JunctionIndex = FindJunctionOrEndIndex(true); }