private static string GetDisplayTimeForArrival(ScheduledArrival arrival, bool military) { StringBuilder result = new StringBuilder(); if (arrival.ScheduledArrivalTime != null) { result.Append($"({(int)(arrival.ScheduledDepartureTime - arrival.ScheduledArrivalTime.Value).TotalMinutes})"); } result.Append(arrival.ScheduledDepartureTime.ToString(military ? "HH:mm" : "h:mm")); if (arrival.IsDropOffOnly) { result.Append("D"); } return(result.ToString()); }
public override void NotifyEvent(ActivityEventType EventType) { playerTrain = simulator.OriginalPlayerTrain; switch (EventType) { // The train is stopped. case ActivityEventType.TrainStop: if (playerTrain.TrainType != TrainType.AiPlayerHosting && playerTrain.TrainAtStation() || playerTrain.TrainType == TrainType.AiPlayerHosting && (playerTrain as AITrain).MovementState == AiMovementState.StationStop) { if (simulator.TimetableMode || playerTrain.StationStops.Count == 0) { // If yes, we arrived if (ActualArrival == null) { ActualArrival = TimeSpan.FromSeconds((int)simulator.ClockTime); } arrived = true; // Figure out the boarding time // <CSComment> No midnight checks here? There are some in Train.CalculateDepartTime double plannedBoardingS = (ScheduledDeparture - ScheduledArrival).TotalSeconds; double punctualBoardingS = (ScheduledDeparture - ActualArrival.GetValueOrDefault(ScheduledArrival)).TotalSeconds; double expectedBoardingS = plannedBoardingS > 0 ? plannedBoardingS : PlatformEnd1.PlatformMinWaitingTime; BoardingS = punctualBoardingS; // default is leave on time if (punctualBoardingS < expectedBoardingS) // if not enough time for boarding { if (plannedBoardingS > 0 && plannedBoardingS < PlatformEnd1.PlatformMinWaitingTime) { // and tight schedule BoardingS = plannedBoardingS; // leave late with no recovery of time } else { // generous schedule BoardingS = Math.Max( punctualBoardingS, // leave on time PlatformEnd1.PlatformMinWaitingTime); // leave late with some recovery } } // ActArrive is usually same as ClockTime BoardingEndS = simulator.ClockTime + BoardingS; // But not if game starts after scheduled arrival. In which case actual arrival is assumed to be same as schedule arrival. double sinceActArriveS = (TimeSpan.FromSeconds((int)simulator.ClockTime) - ActualArrival.GetValueOrDefault(ScheduledArrival)).TotalSeconds; BoardingEndS -= sinceActArriveS; } else { // <CSComment> MSTS mode - player if (simulator.GameTime < 2) { // If the simulation starts with a scheduled arrive in the past, assume the train arrived on time. if (ScheduledArrival.TotalSeconds < simulator.ClockTime) { ActualArrival = ScheduledArrival; } } BoardingS = playerTrain.StationStops[0].ComputeStationBoardingTime(simulator.PlayerLocomotive.Train); if (BoardingS > 0 || ((double)(ScheduledDeparture - ScheduledArrival).TotalSeconds > 0 && playerTrain.PassengerCarsNumber == 1 && playerTrain.Cars.Count > 10)) { // accepted station stop because either freight train or passenger train or fake passenger train with passenger car on platform or fake passenger train // with Scheduled Depart > Scheduled Arrive // ActArrive is usually same as ClockTime BoardingEndS = simulator.ClockTime + BoardingS; if (!ActualArrival.HasValue) { ActualArrival = TimeSpan.FromSeconds((int)simulator.ClockTime); } arrived = true; // But not if game starts after scheduled arrival. In which case actual arrival is assumed to be same as schedule arrival. double sinceActArriveS = (TimeSpan.FromSeconds((int)simulator.ClockTime) - ActualArrival.GetValueOrDefault(ScheduledArrival)).TotalSeconds; BoardingEndS -= sinceActArriveS; double SchDepartS = ScheduledDeparture.TotalSeconds; BoardingEndS = Time.Compare.Latest((int)SchDepartS, (int)BoardingEndS); } } if (playerTrain.NextSignalObject[0] != null) { distanceToNextSignal = playerTrain.NextSignalObject[0].DistanceTo(playerTrain.FrontTDBTraveller); } } break; case ActivityEventType.TrainStart: // Train has started, we have things to do if we arrived before if (arrived) { ActualDeparture = TimeSpan.FromSeconds((int)simulator.ClockTime); CompletedAt = ActualDeparture.Value; // Completeness depends on the elapsed waiting time IsCompleted = maydepart; if (playerTrain.TrainType != TrainType.AiPlayerHosting) { playerTrain.ClearStation(PlatformEnd1.LinkedPlatformItemId, PlatformEnd2.LinkedPlatformItemId, true); } if (logStationStops) { StringBuilder stringBuild = new StringBuilder(); char separator = (char)simulator.Settings.DataLoggerSeparator; stringBuild.Append(PlatformEnd1.Station); stringBuild.Append(separator); stringBuild.Append(ScheduledArrival.ToString("c")); stringBuild.Append(separator); stringBuild.Append(ScheduledDeparture.ToString("c")); stringBuild.Append(separator); stringBuild.Append(ActualArrival.HasValue ? ActualArrival.Value.ToString("c") : "-"); stringBuild.Append(separator); stringBuild.Append(ActualDeparture.HasValue ? ActualDeparture.Value.ToString("c") : "-"); TimeSpan delay = ActualDeparture.HasValue ? (ActualDeparture - ScheduledDeparture).Value : TimeSpan.Zero; stringBuild.Append(separator); stringBuild.Append(delay.ToString("c")); stringBuild.Append(separator); stringBuild.Append(maydepart ? "Completed" : "NotCompleted"); stringBuild.Append('\n'); File.AppendAllText(logStationLogFile, stringBuild.ToString()); } } break; case ActivityEventType.Timer: // Waiting at a station if (arrived) { int remaining = (int)Math.Ceiling(BoardingEndS - simulator.ClockTime); if (remaining < 1) { DisplayColor = Color.LightGreen; } else if (remaining < 11) { DisplayColor = new Color(255, 255, 128); } else { DisplayColor = Color.White; } if (remaining < 120 && (playerTrain.TrainType != TrainType.AiPlayerHosting)) { playerTrain.ClearStation(PlatformEnd1.LinkedPlatformItemId, PlatformEnd2.LinkedPlatformItemId, false); } // Still have to wait if (remaining > 0) { DisplayMessage = Simulator.Catalog.GetString("Passenger boarding completes in {0:D2}:{1:D2}", remaining / 60, remaining % 60); //Debrief Eval if (simulator.PlayerLocomotive.SpeedMpS > 0 && !debriefEvalDepartBeforeBoarding) { Train train = simulator.PlayerLocomotive.Train; debriefEvalDepartBeforeBoarding = true; DebriefEvalDepartBeforeBoarding.Add(PlatformEnd1.Station); train.DbfEvalValueChanged = true; } } // May depart else if (!maydepart) { // check if signal ahead is cleared - if not, do not allow depart if (distanceToNextSignal >= 0 && distanceToNextSignal < 300 && playerTrain.NextSignalObject[0] != null && playerTrain.NextSignalObject[0].SignalLR(SignalFunction.Normal) == SignalAspectState.Stop && playerTrain.NextSignalObject[0].OverridePermission != SignalPermission.Granted) { DisplayMessage = Simulator.Catalog.GetString("Passenger boarding completed. Waiting for signal ahead to clear."); } else { maydepart = true; DisplayMessage = Simulator.Catalog.GetString("Passenger boarding completed. You may depart now."); simulator.SoundNotify = TrainEvent.PermissionToDepart; } debriefEvalDepartBeforeBoarding = false; //reset flag. Debrief Eval // if last task, show closure window // also set times in logfile if (NextTask == null) { if (logStationStops) { StringBuilder stringBuild = new StringBuilder(); char separator = (char)simulator.Settings.DataLoggerSeparator; stringBuild.Append(PlatformEnd1.Station); stringBuild.Append(separator); stringBuild.Append(ScheduledArrival.ToString("hh\\:mm\\:ss", CultureInfo.InvariantCulture)); stringBuild.Append(separator); stringBuild.Append('-'); stringBuild.Append(separator); stringBuild.Append(ActualArrival.HasValue ? ActualArrival.Value.ToString("c") : "-"); stringBuild.Append(separator); stringBuild.Append('-'); stringBuild.Append(separator); TimeSpan delay = ActualArrival.HasValue ? (ActualArrival - ScheduledArrival).Value : TimeSpan.Zero; stringBuild.Append(delay.ToString("c")); stringBuild.Append(separator); stringBuild.Append("Final stop"); stringBuild.Append('\n'); File.AppendAllText(logStationLogFile, stringBuild.ToString()); } IsCompleted = true; } } } else { // Checking missed station int tmp = (int)(simulator.ClockTime % 10); if (tmp != timerChk) { if (TrainMissedStation() && (playerTrain.TrainType != TrainType.AiPlayerHosting)) { playerTrain.ClearStation(PlatformEnd1.LinkedPlatformItemId, PlatformEnd2.LinkedPlatformItemId, true); IsCompleted = false; if (logStationStops) { StringBuilder stringBuild = new StringBuilder(); char separator = (char)simulator.Settings.DataLoggerSeparator; stringBuild.Append(PlatformEnd1.Station); stringBuild.Append(separator); stringBuild.Append(ScheduledArrival.ToString("c")); stringBuild.Append(separator); stringBuild.Append(ScheduledDeparture.ToString("c")); stringBuild.Append(separator); stringBuild.Append('-'); stringBuild.Append(separator); stringBuild.Append('-'); stringBuild.Append(separator); stringBuild.Append('-'); stringBuild.Append(separator); stringBuild.Append("Missed"); stringBuild.Append('\n'); File.AppendAllText(logStationLogFile, stringBuild.ToString()); } } } } break; } }