Show predicted scheduled dispatch arr/dep times in timetable window
This commit is contained in:
@@ -618,6 +618,15 @@ private:
|
||||
int32 scheduled_dispatch_last_dispatch = 0; ///< Last vehicle dispatched offset
|
||||
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:
|
||||
/**
|
||||
* Get the vector of all scheduled dispatch slot
|
||||
@@ -629,6 +638,7 @@ public:
|
||||
void AddScheduledDispatch(uint32 offset);
|
||||
void RemoveScheduledDispatch(uint32 offset);
|
||||
void ClearScheduledDispatch() { this->scheduled_dispatch.clear(); }
|
||||
bool UpdateScheduledDispatchToDate(DateTicksScaled now);
|
||||
void UpdateScheduledDispatch();
|
||||
|
||||
/**
|
||||
@@ -701,6 +711,17 @@ public:
|
||||
* @return scheduled dispatch last dispatch
|
||||
*/
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -453,14 +453,11 @@ void DispatchSchedule::RemoveScheduledDispatch(uint32 offset)
|
||||
this->scheduled_dispatch.erase(erase_position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the scheduled dispatch start time to be the most recent possible.
|
||||
*/
|
||||
void DispatchSchedule::UpdateScheduledDispatch()
|
||||
bool DispatchSchedule::UpdateScheduledDispatchToDate(DateTicksScaled now)
|
||||
{
|
||||
bool update_windows = false;
|
||||
if (this->GetScheduledDispatchStartTick() == 0) {
|
||||
int64 start = _scaled_date_ticks - (_scaled_date_ticks % this->GetScheduledDispatchDuration());
|
||||
int64 start = now - (now % this->GetScheduledDispatchDuration());
|
||||
SchdispatchConvertToFullDateFract(
|
||||
start,
|
||||
&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 */
|
||||
while (this->GetScheduledDispatchStartTick() > _scaled_date_ticks) {
|
||||
while (this->GetScheduledDispatchStartTick() > now) {
|
||||
OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch;
|
||||
last_dispatch += this->GetScheduledDispatchDuration();
|
||||
this->scheduled_dispatch_last_dispatch = last_dispatch;
|
||||
@@ -484,7 +481,7 @@ void DispatchSchedule::UpdateScheduledDispatch()
|
||||
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. */
|
||||
while (this->GetScheduledDispatchStartTick() + this->GetScheduledDispatchDuration() <= _scaled_date_ticks) {
|
||||
while (this->GetScheduledDispatchStartTick() + this->GetScheduledDispatchDuration() <= now) {
|
||||
OverflowSafeInt32 last_dispatch = this->scheduled_dispatch_last_dispatch;
|
||||
last_dispatch -= this->GetScheduledDispatchDuration();
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
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 minimum = _scaled_date_ticks + wait_offset - max_delay;
|
||||
DateTicksScaled minimum = leave_time - max_delay;
|
||||
if (current_departure < minimum) {
|
||||
current_departure += dispatch_duration * ((minimum + dispatch_duration - current_departure - 1) / dispatch_duration);
|
||||
}
|
||||
@@ -850,7 +850,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
||||
ds.UpdateScheduledDispatch();
|
||||
|
||||
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) {
|
||||
SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||
v->lateness_counter = _scaled_date_ticks - slot + wait_offset;
|
||||
|
@@ -33,10 +33,16 @@
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
enum TimetableArrivalDepartureFlags {
|
||||
TADF_ARRIVAL_PREDICTED,
|
||||
TADF_DEPARTURE_PREDICTED,
|
||||
};
|
||||
|
||||
/** Container for the arrival/departure dates of a vehicle */
|
||||
struct TimetableArrivalDeparture {
|
||||
Ticks arrival; ///< The arrival time
|
||||
Ticks departure; ///< The departure time
|
||||
uint flags;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -121,8 +127,11 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
||||
/* Pre-initialize with unknown time */
|
||||
for (int i = 0; i < v->GetNumOrders(); ++i) {
|
||||
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.
|
||||
* As we may start at the current order, do a post-checking loop */
|
||||
do {
|
||||
@@ -134,12 +143,26 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
||||
if (!CanDetermineTimeTaken(order, true)) return;
|
||||
sum += order->GetTimetabledTravel();
|
||||
table[i].arrival = sum;
|
||||
if (predicted) SetBit(table[i].flags, TADF_ARRIVAL_PREDICTED);
|
||||
}
|
||||
|
||||
if (order->IsScheduledDispatchOrder(true) && !(i == start && !travelling)) return;
|
||||
if (!CanDetermineTimeTaken(order, false)) return;
|
||||
sum += order->GetTimetabledWait();
|
||||
if (order->IsScheduledDispatchOrder(true) && !(i == start && !travelling)) {
|
||||
extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time);
|
||||
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;
|
||||
if (predicted) SetBit(table[i].flags, TADF_DEPARTURE_PREDICTED);
|
||||
}
|
||||
|
||||
++i;
|
||||
@@ -694,17 +717,17 @@ struct TimetableWindow : Window {
|
||||
SetDParam(0, _scaled_date_ticks + arr_dep[i / 2].arrival);
|
||||
DrawString(time_left, time_right, y, STR_JUST_DATE_WALLCLOCK_TINY, TC_GREEN);
|
||||
} 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,
|
||||
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 {
|
||||
if (arr_dep[i / 2].departure != INVALID_TICKS) {
|
||||
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,
|
||||
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;
|
||||
|
Reference in New Issue
Block a user