diff --git a/src/departures.cpp b/src/departures.cpp index 42da3d7a02..c1b84d6867 100644 --- a/src/departures.cpp +++ b/src/departures.cpp @@ -30,6 +30,7 @@ #include "order_base.h" #include "settings_type.h" #include "core/smallvec_type.hpp" +#include "core/sort_func.hpp" #include "date_type.h" #include "company_type.h" #include "cargo_type.h" @@ -38,6 +39,8 @@ #include #include +#include +#include /* A cache of used departure time for scheduled dispatch in departure time calculation */ typedef std::map> schdispatch_cache_t; @@ -144,6 +147,52 @@ static inline bool VehicleSetNextDepartureTime(DateTicks *previous_departure, ui return false; } +static void ScheduledDispatchDepartureLocalFix(DepartureList *departure_list) +{ + /* Seperate departure by each shared order group */ + std::map> separated_departure; + for (Departure** departure = departure_list->Begin(); departure != departure_list->End(); departure++) { + separated_departure[(*departure)->vehicle->orders.list->index].push_back(*departure); + } + + for (auto& pair : separated_departure) { + auto d_list = pair.second; + + /* If the group is scheduled dispatch, then */ + if (HasBit(d_list[0]->vehicle->vehicle_flags, VF_SCHEDULED_DISPATCH)) { + /* Separate departure time and sort them ascendently */ + std::vector departure_time_list; + for (const auto& d : d_list) { + departure_time_list.push_back(d->scheduled_date); + } + std::sort(departure_time_list.begin(), departure_time_list.end()); + + /* Sort the departure list by arrival time */ + std::sort(d_list.begin(), d_list.end(), [](const Departure * const &a, const Departure * const &b) -> bool { + DateTicksScaled arr_a = a->scheduled_date - (a->scheduled_waiting_time > 0 ? a->scheduled_waiting_time : a->order->GetWaitTime()); + DateTicksScaled arr_b = b->scheduled_date - (b->scheduled_waiting_time > 0 ? b->scheduled_waiting_time : b->order->GetWaitTime()); + return arr_a < arr_b; + }); + + /* Re-assign them sequentially */ + for (size_t i = 0; i < d_list.size(); i++) { + const DateTicksScaled arrival = d_list[i]->scheduled_date - (d_list[i]->scheduled_waiting_time > 0 ? d_list[i]->scheduled_waiting_time : d_list[i]->order->GetWaitTime()); + d_list[i]->scheduled_waiting_time = departure_time_list[i] - arrival; + d_list[i]->scheduled_date = departure_time_list[i]; + + if (d_list[i]->scheduled_waiting_time == d_list[i]->order->GetWaitTime()) { + d_list[i]->scheduled_waiting_time = 0; + } + } + } + } + + /* Re-sort the departure list */ + QSortT(departure_list->Begin(), departure_list->Length(), [](Departure * const *a, Departure * const *b) -> int { + return (*a)->scheduled_date - (*b)->scheduled_date; + }); +} + /** * Compute an up-to-date list of departures for a station. * @param station the station to compute the departures of @@ -326,7 +375,8 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], /* Update least_order if this is the current least order. */ if (least_order == NULL) { least_order = od; - } else if (least_order->expected_date - least_order->lateness - (type == D_ARRIVAL ? least_order->order->GetWaitTime() : 0) > od->expected_date - od->lateness - (type == D_ARRIVAL ? od->order->GetWaitTime() : 0)) { + } else if (int(least_order->expected_date - least_order->lateness - (type == D_ARRIVAL ? (least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime()) : 0)) > int(od->expected_date - od->lateness - (type == D_ARRIVAL ? (od->scheduled_waiting_time > 0 ? od->scheduled_waiting_time : od->order->GetWaitTime()) : 0))) { + /* Somehow my compiler perform an unsigned comparition above so integer cast is required */ least_order = od; } @@ -454,7 +504,7 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], } if (c.scheduled_date != 0 && (order->GetTravelTime() != 0 || order->IsTravelTimetabled())) { - c.scheduled_date += order->GetTravelTime(); + c.scheduled_date += order->GetTravelTime(); /* TODO smart terminal may not work correctly */ } else { c.scheduled_date = 0; } @@ -659,14 +709,18 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], break; } - least_order->expected_date += order->GetWaitTime(); + if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) { + least_order->lateness = 0; + } continue; } case 2: { /* Do not take the branch */ order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next; - least_order->expected_date += order->GetTravelTime() + order->GetWaitTime(); + if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) { + least_order->lateness = 0; + } continue; } } @@ -724,8 +778,8 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], DateTicks odd = od->expected_date - od->lateness; if (type == D_ARRIVAL) { - lod -= least_order->order->GetWaitTime(); - odd -= od->order->GetWaitTime(); + lod -= least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime(); + odd -= od->scheduled_waiting_time > 0 ? od->scheduled_waiting_time : od->order->GetWaitTime(); } if (lod > odd && od->expected_date - od->lateness < max_date) { @@ -740,6 +794,8 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], delete od; } + if (type == D_DEPARTURE) ScheduledDispatchDepartureLocalFix(result); + /* Done. Phew! */ return result; }