Strong typedef: Use strong typedefs for date, date tick, minutes types

Add delta types
Adjust/add type conversion functions
Add various utility methods on types
Remove the various minute macros
Fix some minute conversion inconsistencies
This commit is contained in:
Jonathan G Rennison
2023-12-19 01:03:18 +00:00
parent 1e7b56e13a
commit 03e0ec8276
80 changed files with 538 additions and 431 deletions

View File

@@ -43,15 +43,23 @@
typedef btree::btree_map<const DispatchSchedule *, btree::btree_set<DateTicksScaled>> schdispatch_cache_t;
/** A scheduled order. */
typedef struct OrderDate
{
struct OrderDate {
const Order *order; ///< The order
const Vehicle *v; ///< The vehicle carrying out the order
DateTicks expected_date;///< The date on which the order is expected to complete
Ticks expected_tick; ///< The tick on which the order is expected to complete
Ticks lateness; ///< How late this order is expected to finish
DepartureStatus status; ///< Whether the vehicle has arrived to carry out the order yet
uint scheduled_waiting_time; ///< Scheduled waiting time if scheduled dispatch is used
} OrderDate;
Ticks scheduled_waiting_time; ///< Scheduled waiting time if scheduled dispatch is used
inline Ticks EffectiveWaitingTime() const
{
if (this->scheduled_waiting_time > 0) {
return this->scheduled_waiting_time;
} else {
return this->order->GetWaitTime();
}
}
};
static bool IsDeparture(const Order *order, StationID station) {
return (order->GetType() == OT_GOTO_STATION &&
@@ -93,7 +101,7 @@ static uint8 GetDepartureConditionalOrderMode(const Order *order, const Vehicle
return _settings_client.gui.departure_conditionals;
}
static bool VehicleSetNextDepartureTime(DateTicks *previous_departure, uint *waiting_time, const DateTicksScaled date_only_scaled, const Vehicle *v, const Order *order, bool arrived_at_timing_point, schdispatch_cache_t &dept_schedule_last)
static bool VehicleSetNextDepartureTime(Ticks *previous_departure, Ticks *waiting_time, const DateTicksScaled date_ticks_base, const Vehicle *v, const Order *order, bool arrived_at_timing_point, schdispatch_cache_t &dept_schedule_last)
{
if (HasBit(v->vehicle_flags, VF_SCHEDULED_DISPATCH)) {
auto is_current_implicit_order = [&v](const Order *o) -> bool {
@@ -115,7 +123,7 @@ static bool VehicleSetNextDepartureTime(DateTicks *previous_departure, uint *wai
DateTicksScaled earliest_departure = begin_time + ds.GetScheduledDispatchLastDispatch();
/* Earliest possible departure according to vehicle current timetable */
const uint32 ready_to_depart_time = date_only_scaled + *previous_departure + order->GetTravelTime() + order->GetTimetabledWait();
const DateTicksScaled ready_to_depart_time = date_ticks_base + *previous_departure + order->GetTravelTime() + order->GetTimetabledWait();
if (earliest_departure + max_delay < ready_to_depart_time) {
earliest_departure = ready_to_depart_time - max_delay - 1;
/* -1 because this number is actually a moment before actual departure */
@@ -141,8 +149,8 @@ static bool VehicleSetNextDepartureTime(DateTicks *previous_departure, uint *wai
}
}
*waiting_time = actual_departure - date_only_scaled - *previous_departure - order->GetTravelTime();
*previous_departure = actual_departure - date_only_scaled;
*waiting_time = (actual_departure - date_ticks_base).AsTicks() - *previous_departure - order->GetTravelTime();
*previous_departure = (actual_departure - date_ticks_base).AsTicks();
slot_cache.insert(actual_departure);
/* Return true means that vehicle lateness should be clear from this point onward */
@@ -185,18 +193,18 @@ static void ScheduledDispatchDepartureLocalFix(DepartureList *departure_list)
/* 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());
DateTicksScaled arr_a = a->scheduled_date - a->EffectiveWaitingTime();
DateTicksScaled arr_b = b->scheduled_date - b->EffectiveWaitingTime();
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;
const DateTicksScaled arrival = d_list[i]->scheduled_date - d_list[i]->EffectiveWaitingTime();
d_list[i]->scheduled_waiting_time = (departure_time_list[i] - arrival).AsTicks();
d_list[i]->scheduled_date = departure_time_list[i];
if (d_list[i]->scheduled_waiting_time == d_list[i]->order->GetWaitTime()) {
if (d_list[i]->scheduled_waiting_time == (Ticks)d_list[i]->order->GetWaitTime()) {
d_list[i]->scheduled_waiting_time = 0;
}
}
@@ -237,12 +245,11 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
std::vector<OrderDate*> next_orders;
/* The maximum possible date for departures to be scheduled to occur. */
DateTicksScaled max_date = GetDeparturesMaxTicksAhead();
const Ticks max_ticks = GetDeparturesMaxTicksAhead();
DateTicksScaled date_only_scaled = DateToScaledDateTicks(_date);
DateTicksScaled date_fract_scaled = ((DateTicksScaled)_date_fract * _settings_game.economy.day_length_factor) + _tick_skip_counter;
const DateTicksScaled date_ticks_base = _scaled_date_ticks;
/* The scheduled order in next_orders with the earliest expected_date field. */
/* The scheduled order in next_orders with the earliest expected_tick field. */
OrderDate *least_order = nullptr;
/* Cache for scheduled departure time */
@@ -272,20 +279,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
const Order *order = v->GetOrder(v->cur_implicit_order_index % v->GetNumOrders());
if (order == nullptr) continue;
DateTicks start_date = date_fract_scaled - v->current_order_time;
Ticks start_ticks = -((Ticks)v->current_order_time);
if (v->cur_timetable_order_index != INVALID_VEH_ORDER_ID && v->cur_timetable_order_index != v->cur_real_order_index) {
/* vehicle is taking a conditional order branch, adjust start time to compensate */
const Order *real_current_order = v->GetOrder(v->cur_real_order_index);
const Order *real_timetable_order = v->GetOrder(v->cur_timetable_order_index);
if (real_timetable_order->IsType(OT_CONDITIONAL)) {
start_date += (real_timetable_order->GetWaitTime() - real_current_order->GetTravelTime());
start_ticks += (real_timetable_order->GetWaitTime() - real_current_order->GetTravelTime());
} else {
/* This can also occur with implicit orders, when there are no real orders, do nothing */
}
}
DepartureStatus status = D_TRAVELLING;
bool should_reset_lateness = false;
uint waiting_time = 0;
Ticks waiting_time = 0;
/* If the vehicle is stopped in a depot, ignore it. */
if (v->IsStoppedInDepot()) {
@@ -301,20 +308,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
if (v->current_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING)) {
/* Account for the vehicle having reached the current order and being in the loading phase. */
status = D_ARRIVED;
start_date -= order->GetTravelTime() + ((v->lateness_counter < 0) ? v->lateness_counter : 0);
start_ticks -= order->GetTravelTime() + ((v->lateness_counter < 0) ? v->lateness_counter : 0);
require_travel_time = false;
}
/* Loop through the vehicle's orders until we've found a suitable order or we've determined that no such order exists. */
/* We only need to consider each order at most once. */
for (int i = v->GetNumOrders(); i > 0; --i) {
if (VehicleSetNextDepartureTime(&start_date, &waiting_time, date_only_scaled, v, order, status == D_ARRIVED, schdispatch_last_planned_dispatch)) {
if (VehicleSetNextDepartureTime(&start_ticks, &waiting_time, date_ticks_base, v, order, status == D_ARRIVED, schdispatch_last_planned_dispatch)) {
should_reset_lateness = true;
}
/* If the order is a conditional branch, handle it. */
if (order->IsType(OT_CONDITIONAL)) {
switch(GetDepartureConditionalOrderMode(order, v, start_date + date_only_scaled)) {
switch(GetDepartureConditionalOrderMode(order, v, date_ticks_base + start_ticks)) {
case 0: {
/* Give up */
break;
@@ -329,7 +336,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
break;
}
start_date -= order->GetTravelTime();
start_ticks -= order->GetTravelTime();
require_travel_time = false;
continue;
}
@@ -338,7 +345,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
if (status != D_CANCELLED) {
status = D_TRAVELLING;
}
start_date -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */
start_ticks -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */
order = (order->next == nullptr) ? v->GetFirstOrder() : order->next;
require_travel_time = true;
continue;
@@ -348,7 +355,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
}
/* If the scheduled departure date is too far in the future, stop. */
if (start_date - v->lateness_counter > max_date) {
if (start_ticks - v->lateness_counter > max_ticks) {
break;
}
@@ -363,7 +370,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
(type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
(type == D_ARRIVAL && IsArrival(order, station))) {
/* If the departure was scheduled to have already begun and has been cancelled, do not show it. */
if (start_date < 0 && status == D_CANCELLED) {
if (start_ticks < 0 && status == D_CANCELLED) {
break;
}
@@ -371,7 +378,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
od->order = order;
od->v = v;
/* We store the expected date for now, so that vehicles will be shown in order of expected time. */
od->expected_date = start_date;
od->expected_tick = start_ticks;
od->lateness = v->lateness_counter > 0 ? v->lateness_counter : 0;
od->status = status;
od->scheduled_waiting_time = waiting_time;
@@ -383,15 +390,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
/* If we are early, use the scheduled date as the expected date. We also take lateness to be zero. */
if (!should_reset_lateness && v->lateness_counter < 0 && !(v->current_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING))) {
od->expected_date -= v->lateness_counter;
od->expected_tick -= v->lateness_counter;
}
/* Update least_order if this is the current least order. */
if (least_order == nullptr) {
least_order = od;
} 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;
} else if (type == D_ARRIVAL) {
if ((least_order->expected_tick - least_order->lateness - least_order->EffectiveWaitingTime()) > (od->expected_tick - od->lateness - od->EffectiveWaitingTime())) {
least_order = od;
}
} else {
if ((least_order->expected_tick - least_order->lateness) > (od->expected_tick - od->lateness)) {
least_order = od;
}
}
next_orders.push_back(od);
@@ -420,22 +432,22 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
for(int i = 10000; i > 0; --i) {
/* I should probably try to convince you that this loop always terminates regardless of the safeguard. */
/* 1. next_orders contains at least one element. */
/* 2. The loop terminates if result->size() exceeds a fixed (for this loop) value, or if the least order's scheduled date is later than max_date. */
/* 2. The loop terminates if result->size() exceeds a fixed (for this loop) value, or if the least order's scheduled date is later than max_ticks. */
/* (We ignore the case that the least order's scheduled date has overflown, as it is a relative rather than absolute date.) */
/* 3. Every time we loop round, either result->size() will have increased -OR- we will have increased the expected_date of one of the elements of next_orders. */
/* 3. Every time we loop round, either result->size() will have increased -OR- we will have increased the expected_tick of one of the elements of next_orders. */
/* 4. Therefore the loop must eventually terminate. */
/* least_order is the best candidate for the next departure. */
/* First, we check if we can stop looking for departures yet. */
if (result->size() >= _settings_client.gui.max_departures ||
least_order->expected_date - least_order->lateness > max_date) {
least_order->expected_tick - least_order->lateness > max_ticks) {
break;
}
/* We already know the least order and that it's a suitable departure, so make it into a departure. */
Departure *d = new Departure();
d->scheduled_date = date_only_scaled + least_order->expected_date - least_order->lateness;
d->scheduled_date = date_ticks_base + least_order->expected_tick - least_order->lateness;
d->lateness = least_order->lateness;
d->status = least_order->status;
d->vehicle = least_order->v;
@@ -751,7 +763,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
/* Go to the next order so we don't add the current order again. */
order = (order->next == nullptr) ? least_order->v->GetFirstOrder() : order->next;
if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) {
if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) {
least_order->lateness = 0;
}
@@ -762,7 +774,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
/* If the order is a conditional branch, handle it. */
if (order->IsType(OT_CONDITIONAL)) {
switch(GetDepartureConditionalOrderMode(order, least_order->v, least_order->expected_date)) {
switch(GetDepartureConditionalOrderMode(order, least_order->v, least_order->expected_tick)) {
case 0: {
/* Give up */
break;
@@ -774,8 +786,8 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
break;
}
least_order->expected_date -= order->GetTravelTime(); /* Added in next VehicleSetNextDepartureTime */
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->expected_tick -= order->GetTravelTime(); /* Added in next VehicleSetNextDepartureTime */
if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) {
least_order->lateness = 0;
}
require_travel_time = false;
@@ -783,9 +795,9 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
}
case 2: {
/* Do not take the branch */
least_order->expected_date -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */
least_order->expected_tick -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */
order = (order->next == nullptr) ? least_order->v->GetFirstOrder() : order->next;
if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) {
if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) {
least_order->lateness = 0;
}
require_travel_time = true;
@@ -801,7 +813,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
}
/* If the departure is scheduled to be too late, then stop. */
if (least_order->expected_date - least_order->lateness > max_date) {
if (least_order->expected_tick - least_order->lateness > max_ticks) {
break;
}
@@ -815,7 +827,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
}
order = (order->next == nullptr) ? least_order->v->GetFirstOrder() : order->next;
if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) {
if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) {
least_order->lateness = 0;
}
require_travel_time = true;
@@ -826,7 +838,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
/* Make sure we don't try to get departures out of this order. */
/* This is cheaper than deleting it from next_orders. */
/* If we ever get to a state where _date * DAY_TICKS is close to INT_MAX, then we'll have other problems anyway as departures' scheduled dates will wrap around. */
least_order->expected_date = INT32_MAX;
least_order->expected_tick = INT32_MAX;
}
/* The vehicle can't possibly have arrived at its next candidate departure yet. */
@@ -838,15 +850,15 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
for (uint i = 0; i < next_orders.size(); ++i) {
OrderDate *od = next_orders[i];
DateTicks lod = least_order->expected_date - least_order->lateness;
DateTicks odd = od->expected_date - od->lateness;
DateTicks lod = least_order->expected_tick - least_order->lateness;
DateTicks odd = od->expected_tick - od->lateness;
if (type == D_ARRIVAL) {
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) {
if (lod > odd && od->expected_tick - od->lateness < max_ticks) {
least_order = od;
}
}
@@ -864,7 +876,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
return result;
}
DateTicksScaled GetDeparturesMaxTicksAhead()
Ticks GetDeparturesMaxTicksAhead()
{
if (_settings_time.time_in_minutes) {
return _settings_client.gui.max_departure_time_minutes * _settings_time.ticks_per_minute;