Show predicted scheduled dispatch arr/dep times in timetable window

This commit is contained in:
Jonathan G Rennison
2022-01-14 22:53:55 +00:00
parent 8754e1c5d0
commit 21ef4902c6
4 changed files with 69 additions and 18 deletions

View File

@@ -618,6 +618,15 @@ private:
int32 scheduled_dispatch_last_dispatch = 0; ///< Last vehicle dispatched offset int32 scheduled_dispatch_last_dispatch = 0; ///< Last vehicle dispatched offset
int32 scheduled_dispatch_max_delay = 0; ///< Maximum allowed delay int32 scheduled_dispatch_max_delay = 0; ///< Maximum allowed delay
inline void CopyBasicFields(const DispatchSchedule &other)
{
this->scheduled_dispatch_duration = other.scheduled_dispatch_duration;
this->scheduled_dispatch_start_date = other.scheduled_dispatch_start_date;
this->scheduled_dispatch_start_full_date_fract = other.scheduled_dispatch_start_full_date_fract;
this->scheduled_dispatch_last_dispatch = other.scheduled_dispatch_last_dispatch;
this->scheduled_dispatch_max_delay = other.scheduled_dispatch_max_delay;
}
public: public:
/** /**
* Get the vector of all scheduled dispatch slot * Get the vector of all scheduled dispatch slot
@@ -629,6 +638,7 @@ public:
void AddScheduledDispatch(uint32 offset); void AddScheduledDispatch(uint32 offset);
void RemoveScheduledDispatch(uint32 offset); void RemoveScheduledDispatch(uint32 offset);
void ClearScheduledDispatch() { this->scheduled_dispatch.clear(); } void ClearScheduledDispatch() { this->scheduled_dispatch.clear(); }
bool UpdateScheduledDispatchToDate(DateTicksScaled now);
void UpdateScheduledDispatch(); void UpdateScheduledDispatch();
/** /**
@@ -701,6 +711,17 @@ public:
* @return scheduled dispatch last dispatch * @return scheduled dispatch last dispatch
*/ */
inline int32 GetScheduledDispatchDelay() const { return this->scheduled_dispatch_max_delay; } inline int32 GetScheduledDispatchDelay() const { return this->scheduled_dispatch_max_delay; }
inline void BorrowSchedule(DispatchSchedule &other)
{
this->CopyBasicFields(other);
this->scheduled_dispatch = std::move(other.scheduled_dispatch);
}
inline void ReturnSchedule(DispatchSchedule &other)
{
other.scheduled_dispatch = std::move(this->scheduled_dispatch);
}
}; };
/** /**

View File

@@ -453,14 +453,11 @@ void DispatchSchedule::RemoveScheduledDispatch(uint32 offset)
this->scheduled_dispatch.erase(erase_position); this->scheduled_dispatch.erase(erase_position);
} }
/** bool DispatchSchedule::UpdateScheduledDispatchToDate(DateTicksScaled now)
* Update the scheduled dispatch start time to be the most recent possible.
*/
void DispatchSchedule::UpdateScheduledDispatch()
{ {
bool update_windows = false; bool update_windows = false;
if (this->GetScheduledDispatchStartTick() == 0) { if (this->GetScheduledDispatchStartTick() == 0) {
int64 start = _scaled_date_ticks - (_scaled_date_ticks % this->GetScheduledDispatchDuration()); int64 start = now - (now % this->GetScheduledDispatchDuration());
SchdispatchConvertToFullDateFract( SchdispatchConvertToFullDateFract(
start, start,
&this->scheduled_dispatch_start_date, &this->scheduled_dispatch_start_full_date_fract); &this->scheduled_dispatch_start_date, &this->scheduled_dispatch_start_full_date_fract);
@@ -474,7 +471,7 @@ void DispatchSchedule::UpdateScheduledDispatch()
} }
} }
/* Most of the time this loop does not runs. It makes sure start date in in past */ /* Most of the time this loop does not runs. It makes sure start date in in past */
while (this->GetScheduledDispatchStartTick() > _scaled_date_ticks) { while (this->GetScheduledDispatchStartTick() > now) {
OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch; OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch;
last_dispatch += this->GetScheduledDispatchDuration(); last_dispatch += this->GetScheduledDispatchDuration();
this->scheduled_dispatch_last_dispatch = last_dispatch; this->scheduled_dispatch_last_dispatch = last_dispatch;
@@ -484,7 +481,7 @@ void DispatchSchedule::UpdateScheduledDispatch()
update_windows = true; update_windows = true;
} }
/* Most of the time this loop runs once. It makes sure the start date is as close to current time as possible. */ /* Most of the time this loop runs once. It makes sure the start date is as close to current time as possible. */
while (this->GetScheduledDispatchStartTick() + this->GetScheduledDispatchDuration() <= _scaled_date_ticks) { while (this->GetScheduledDispatchStartTick() + this->GetScheduledDispatchDuration() <= now) {
OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch; OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch;
last_dispatch -= this->GetScheduledDispatchDuration(); last_dispatch -= this->GetScheduledDispatchDuration();
this->scheduled_dispatch_last_dispatch = last_dispatch; this->scheduled_dispatch_last_dispatch = last_dispatch;
@@ -493,5 +490,15 @@ void DispatchSchedule::UpdateScheduledDispatch()
&this->scheduled_dispatch_start_date, &this->scheduled_dispatch_start_full_date_fract); &this->scheduled_dispatch_start_date, &this->scheduled_dispatch_start_full_date_fract);
update_windows = true; update_windows = true;
} }
if (update_windows) InvalidateWindowClassesData(WC_SCHDISPATCH_SLOTS, VIWD_MODIFY_ORDERS); return update_windows;
}
/**
* Update the scheduled dispatch start time to be the most recent possible.
*/
void DispatchSchedule::UpdateScheduledDispatch()
{
if (this->UpdateScheduledDispatchToDate(_scaled_date_ticks)) {
InvalidateWindowClassesData(WC_SCHDISPATCH_SLOTS, VIWD_MODIFY_ORDERS);
}
} }

View File

@@ -778,7 +778,7 @@ void UpdateSeparationOrder(Vehicle *v_start)
} }
} }
static DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, int wait_offset) DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time)
{ {
DateTicksScaled first_slot = -1; DateTicksScaled first_slot = -1;
const DateTicksScaled begin_time = ds.GetScheduledDispatchStartTick(); const DateTicksScaled begin_time = ds.GetScheduledDispatchStartTick();
@@ -794,7 +794,7 @@ static DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, int
} }
DateTicksScaled current_departure = begin_time + current_offset; DateTicksScaled current_departure = begin_time + current_offset;
DateTicksScaled minimum = _scaled_date_ticks + wait_offset - max_delay; DateTicksScaled minimum = leave_time - max_delay;
if (current_departure < minimum) { if (current_departure < minimum) {
current_departure += dispatch_duration * ((minimum + dispatch_duration - current_departure - 1) / dispatch_duration); current_departure += dispatch_duration * ((minimum + dispatch_duration - current_departure - 1) / dispatch_duration);
} }
@@ -850,7 +850,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
ds.UpdateScheduledDispatch(); ds.UpdateScheduledDispatch();
const int wait_offset = real_current_order->GetTimetabledWait(); const int wait_offset = real_current_order->GetTimetabledWait();
DateTicksScaled slot = GetScheduledDispatchTime(ds, wait_offset); DateTicksScaled slot = GetScheduledDispatchTime(ds, _scaled_date_ticks + wait_offset);
if (slot > -1) { if (slot > -1) {
SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED); SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
v->lateness_counter = _scaled_date_ticks - slot + wait_offset; v->lateness_counter = _scaled_date_ticks - slot + wait_offset;

View File

@@ -33,10 +33,16 @@
#include "safeguards.h" #include "safeguards.h"
enum TimetableArrivalDepartureFlags {
TADF_ARRIVAL_PREDICTED,
TADF_DEPARTURE_PREDICTED,
};
/** Container for the arrival/departure dates of a vehicle */ /** Container for the arrival/departure dates of a vehicle */
struct TimetableArrivalDeparture { struct TimetableArrivalDeparture {
Ticks arrival; ///< The arrival time Ticks arrival; ///< The arrival time
Ticks departure; ///< The departure time Ticks departure; ///< The departure time
uint flags;
}; };
/** /**
@@ -121,8 +127,11 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
/* Pre-initialize with unknown time */ /* Pre-initialize with unknown time */
for (int i = 0; i < v->GetNumOrders(); ++i) { for (int i = 0; i < v->GetNumOrders(); ++i) {
table[i].arrival = table[i].departure = INVALID_TICKS; table[i].arrival = table[i].departure = INVALID_TICKS;
table[i].flags = 0;
} }
bool predicted = false;
/* Cyclically loop over all orders until we reach the current one again. /* Cyclically loop over all orders until we reach the current one again.
* As we may start at the current order, do a post-checking loop */ * As we may start at the current order, do a post-checking loop */
do { do {
@@ -134,12 +143,26 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
if (!CanDetermineTimeTaken(order, true)) return; if (!CanDetermineTimeTaken(order, true)) return;
sum += order->GetTimetabledTravel(); sum += order->GetTimetabledTravel();
table[i].arrival = sum; table[i].arrival = sum;
if (predicted) SetBit(table[i].flags, TADF_ARRIVAL_PREDICTED);
} }
if (order->IsScheduledDispatchOrder(true) && !(i == start && !travelling)) return; if (order->IsScheduledDispatchOrder(true) && !(i == start && !travelling)) {
if (!CanDetermineTimeTaken(order, false)) return; extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time);
sum += order->GetTimetabledWait(); DispatchSchedule &ds = v->orders.list->GetDispatchScheduleByIndex(order->GetDispatchScheduleIndex());
DispatchSchedule predicted_ds;
predicted_ds.BorrowSchedule(ds);
predicted_ds.UpdateScheduledDispatchToDate(_scaled_date_ticks + sum);
DateTicksScaled slot = GetScheduledDispatchTime(predicted_ds, _scaled_date_ticks + sum + order->GetTimetabledWait());
predicted_ds.ReturnSchedule(ds);
if (slot <= -1) return;
sum = slot - _scaled_date_ticks;
predicted = true;
} else {
if (!CanDetermineTimeTaken(order, false)) return;
sum += order->GetTimetabledWait();
}
table[i].departure = sum; table[i].departure = sum;
if (predicted) SetBit(table[i].flags, TADF_DEPARTURE_PREDICTED);
} }
++i; ++i;
@@ -694,17 +717,17 @@ struct TimetableWindow : Window {
SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival); SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival);
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY, TC_GREEN); DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY, TC_GREEN);
} else { } else {
SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival + offset); SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival + (HasBit(arr_dep[i / 2].flags, TADF_ARRIVAL_PREDICTED) ? 0 : offset));
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY, DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY,
show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK); HasBit(arr_dep[i / 2].flags, TADF_ARRIVAL_PREDICTED) ? (TextColour)(TC_IS_PALETTE_COLOUR | TC_NO_SHADE | 4) : (show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK));
} }
} }
} else { } else {
if (arr_dep[i / 2].departure != INVALID_TICKS) { if (arr_dep[i / 2].departure != INVALID_TICKS) {
DrawString(abbr_left, abbr_right, y, STR_TIMETABLE_DEPARTURE_ABBREVIATION, i == selected ? TC_WHITE : TC_BLACK); DrawString(abbr_left, abbr_right, y, STR_TIMETABLE_DEPARTURE_ABBREVIATION, i == selected ? TC_WHITE : TC_BLACK);
SetDParam(0, _scaled_date_ticks + arr_dep[i/2].departure + offset); SetDParam(0, _scaled_date_ticks + arr_dep[i/2].departure + (HasBit(arr_dep[i / 2].flags, TADF_DEPARTURE_PREDICTED) ? 0 : offset));
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY, DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY,
show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK); HasBit(arr_dep[i / 2].flags, TADF_DEPARTURE_PREDICTED) ? (TextColour)(TC_IS_PALETTE_COLOUR | TC_NO_SHADE | 4) : (show_late ? TC_RED : i == selected ? TC_WHITE : TC_BLACK));
} }
} }
y += line_height; y += line_height;