Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "gui.h"
00015 #include "textbuf_gui.h"
00016 #include "strings_func.h"
00017 #include "window_func.h"
00018 #include "vehicle_func.h"
00019 #include "string_func.h"
00020 #include "window_gui.h"
00021 #include "timetable.h"
00022 #include "vehiclelist.h"
00023 #include "company_base.h"
00024 #include "date_func.h"
00025 #include "departures_gui.h"
00026 #include "station_base.h"
00027 #include "vehicle_gui_base.h"
00028 #include "vehicle_base.h"
00029 #include "vehicle_gui.h"
00030 #include "order_base.h"
00031 #include "settings_type.h"
00032 #include "core/smallvec_type.hpp"
00033 #include "date_type.h"
00034 #include "company_type.h"
00035 #include "cargo_type.h"
00036 #include "departures_func.h"
00037 #include "departures_type.h"
00038
00040 typedef struct OrderDate
00041 {
00042 const Order *order;
00043 const Vehicle *v;
00044 DateTicks expected_date;
00045 Ticks lateness;
00046 DepartureStatus status;
00047 } OrderDate;
00048
00049 static FORCEINLINE bool IsDeparture(const Order *order, StationID station) {
00050 return (order->GetType() == OT_GOTO_STATION &&
00051 (StationID)order->GetDestination() == station &&
00052 (order->GetLoadType() != OLFB_NO_LOAD ||
00053 _settings_client.gui.departure_show_all_stops) &&
00054 order->wait_time != 0);
00055 }
00056
00057 static FORCEINLINE bool IsVia(const Order *order, StationID station) {
00058 return ((order->GetType() == OT_GOTO_STATION ||
00059 order->GetType() == OT_GOTO_WAYPOINT) &&
00060 (StationID)order->GetDestination() == station &&
00061 (order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
00062 order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION));
00063 }
00064
00065 static FORCEINLINE bool IsArrival(const Order *order, StationID station) {
00066 return (order->GetType() == OT_GOTO_STATION &&
00067 (StationID)order->GetDestination() == station &&
00068 (order->GetUnloadType() != OUFB_NO_UNLOAD ||
00069 _settings_client.gui.departure_show_all_stops) &&
00070 order->wait_time != 0);
00071 }
00072
00081 DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5], DepartureType type, bool show_vehicles_via)
00082 {
00083
00084
00085
00086
00087
00088
00089
00090
00091 SmallVector<Departure*, 32> *result = new SmallVector<Departure*, 32>();
00092
00093
00094 SmallVector<OrderDate*, 32> next_orders;
00095
00096
00097 DateTicks max_date = _settings_client.gui.max_departure_time * DAY_TICKS;
00098
00099
00100 OrderDate *least_order = NULL;
00101
00102
00103
00104
00105
00106 for (uint i = 0; i < 4; ++i) {
00107 VehicleList vehicles;
00108
00109 if (!show_vehicle_types[i]) {
00110
00111 continue;
00112 }
00113
00114
00115 if (!GenerateVehicleSortList(&vehicles, VehicleListIdentifier(VL_STATION_LIST, (VehicleType)(VEH_TRAIN + i), MAX_COMPANIES, station).Pack())) {
00116
00117 return result;
00118 }
00119
00120
00121
00122 for (const Vehicle **v = vehicles.Begin(); v != vehicles.End(); v++) {
00123 if (_settings_client.gui.departure_only_passengers) {
00124 bool carries_passengers = false;
00125
00126 const Vehicle *u = *v;
00127 while (u != NULL) {
00128 if (u->cargo_type == CT_PASSENGERS) {
00129 carries_passengers = true;
00130 break;
00131 }
00132 u = u->Next();
00133 }
00134
00135 if (carries_passengers == false) {
00136 continue;
00137 }
00138 }
00139
00140 const Order *order = (*v)->GetOrder((*v)->cur_implicit_order_index % (*v)->GetNumOrders());
00141 DateTicks start_date = (DateTicks)_date_fract - (*v)->current_order_time;
00142 DepartureStatus status = D_TRAVELLING;
00143
00144
00145 if ((*v)->IsStoppedInDepot()) {
00146 continue;
00147 }
00148
00149
00150 if ((*v)->current_order.IsType(OT_GOTO_DEPOT) && (*v)->current_order.GetDepotActionType() & ODATFB_HALT) {
00151 status = D_CANCELLED;
00152 }
00153
00154 if ((*v)->current_order.IsType(OT_LOADING)) {
00155
00156 status = D_ARRIVED;
00157 start_date -= order->travel_time + (((*v)->lateness_counter < 0) ? (*v)->lateness_counter : 0);
00158 }
00159
00160
00161
00162 bool foundOrder = false;
00163 for (int i = (*v)->GetNumOrders(); i > 0; --i) {
00164 start_date += order->travel_time + order->wait_time;
00165
00166
00167 if (start_date - (*v)->lateness_counter > max_date) {
00168 break;
00169 }
00170
00171
00172 if (order->IsType(OT_CONDITIONAL)) {
00173 switch(_settings_client.gui.departure_conditionals) {
00174 case 0: {
00175
00176 break;
00177 }
00178 case 1: {
00179
00180 if (status != D_CANCELLED) {
00181 status = D_TRAVELLING;
00182 }
00183 order = (*v)->GetOrder(order->GetConditionSkipToOrder());
00184 if (order == NULL) {
00185 break;
00186 }
00187
00188 start_date -= order->travel_time;
00189
00190 continue;
00191 }
00192 case 2: {
00193
00194 if (status != D_CANCELLED) {
00195 status = D_TRAVELLING;
00196 }
00197 order = (order->next == NULL) ? (*v)->GetFirstOrder() : order->next;
00198 continue;
00199 }
00200 }
00201 }
00202
00203
00204 if (order->travel_time == 0) {
00205 break;
00206 }
00207
00208
00209 if (order->IsType(OT_IMPLICIT)) {
00210 order = (order->next == NULL) ? (*v)->GetFirstOrder() : order->next;
00211 continue;
00212 }
00213
00214
00215
00216 if ((type == D_DEPARTURE && IsDeparture(order, station)) ||
00217 (type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
00218 (type == D_ARRIVAL && IsArrival(order, station))) {
00219
00220 if (start_date < 0 && status == D_CANCELLED) {
00221 break;
00222 }
00223
00224 OrderDate *od = new OrderDate();
00225 od->order = order;
00226 od->v = *v;
00227
00228 od->expected_date = start_date;
00229 od->lateness = (*v)->lateness_counter > 0 ? (*v)->lateness_counter : 0;
00230 od->status = status;
00231
00232
00233 if ((*v)->lateness_counter < 0 && !(*v)->current_order.IsType(OT_LOADING)) {
00234 od->expected_date -= (*v)->lateness_counter;
00235 }
00236
00237
00238 if (least_order == NULL) {
00239 least_order = od;
00240 } else if (least_order->expected_date - least_order->lateness - (type == D_ARRIVAL ? least_order->order->wait_time : 0) > od->expected_date - od->lateness - (type == D_ARRIVAL ? od->order->wait_time : 0)) {
00241 least_order = od;
00242 }
00243
00244 *(next_orders.Append(1)) = od;
00245
00246 foundOrder = true;
00247
00248 break;
00249 } else {
00250
00251 if (status != D_CANCELLED) {
00252 status = D_TRAVELLING;
00253 }
00254 order = (order->next == NULL) ? (*v)->GetFirstOrder() : order->next;
00255 }
00256 }
00257 }
00258 }
00259
00260
00261 if (next_orders.Length() == 0) {
00262 return result;
00263 }
00264
00265
00266
00267 for(int i = 10000; i > 0; --i) {
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 if (result->Length() >= _settings_client.gui.max_departures ||
00279 least_order->expected_date - least_order->lateness > max_date) {
00280 break;
00281 }
00282
00283
00284 Departure *d = new Departure();
00285 d->scheduled_date = (DateTicks)_date * DAY_TICKS + least_order->expected_date - least_order->lateness;
00286 d->lateness = least_order->lateness;
00287 d->status = least_order->status;
00288 d->vehicle = least_order->v;
00289 d->type = type;
00290 d->order = least_order->order;
00291
00292
00293 const Order *order = least_order->order;
00294
00295 if (type == D_DEPARTURE) {
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 StationID candidate_via = INVALID_STATION;
00309
00310
00311
00312 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00313
00314 bool found_terminus = false;
00315 for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
00316
00317 if (order == least_order->order) {
00318
00319 found_terminus = (d->calling_at.Length() > 0);
00320 break;
00321 }
00322
00323
00324 if (order->IsType(OT_CONDITIONAL)) {
00325 switch(_settings_client.gui.departure_conditionals) {
00326 case 0: {
00327
00328 break;
00329 }
00330 case 1: {
00331
00332 order = least_order->v->GetOrder(order->GetConditionSkipToOrder());
00333 if (order == NULL) {
00334 break;
00335 }
00336 continue;
00337 }
00338 case 2: {
00339
00340 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00341 continue;
00342 }
00343 }
00344 }
00345
00346
00347 if (order->GetType() == OT_GOTO_STATION &&
00348 (StationID)order->GetDestination() == station &&
00349 (order->GetUnloadType() != OUFB_NO_UNLOAD ||
00350 _settings_client.gui.departure_show_all_stops) &&
00351 order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
00352 order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
00353
00354 found_terminus = (d->calling_at.Length() > 0);
00355 break;
00356 }
00357
00358
00359 if ((order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
00360 order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) &&
00361 order->GetType() == OT_GOTO_STATION &&
00362 d->via == INVALID_STATION) {
00363 candidate_via = (StationID)order->GetDestination();
00364 }
00365
00366
00367 if ((order->GetUnloadType() == OUFB_NO_UNLOAD &&
00368 !_settings_client.gui.departure_show_all_stops) ||
00369 (order->GetType() != OT_GOTO_STATION &&
00370 order->GetType() != OT_IMPLICIT) ||
00371 order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
00372 order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) {
00373 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00374 continue;
00375 }
00376
00377
00378 if (d->calling_at.Contains((StationID)order->GetDestination())) {
00379 found_terminus = true;
00380 break;
00381 }
00382
00383
00384 if ((order->GetType() == OT_GOTO_STATION ||
00385 order->GetType() == OT_IMPLICIT) &&
00386 order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
00387 order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
00388 if (d->via == INVALID_STATION && candidate_via == (StationID)order->GetDestination()) {
00389 d->via = (StationID)order->GetDestination();
00390 }
00391 d->terminus = (StationID)order->GetDestination();
00392 *(d->calling_at.Append(1)) = d->terminus;
00393 }
00394
00395
00396 if (order->GetType() == OT_GOTO_STATION &&
00397 order->GetUnloadType() == OUFB_UNLOAD) {
00398 if (d->calling_at.Length() > 0) {
00399 found_terminus = true;
00400 }
00401 break;
00402 }
00403
00404
00405 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00406 }
00407
00408 if (found_terminus) {
00409
00410 *(result->Append(1)) = d;
00411
00412
00413
00414 if (d->status != D_ARRIVED &&
00415 d->lateness > 0) {
00416 d->lateness -= least_order->order->wait_time;
00417 }
00418 }
00419 } else {
00420
00421
00422
00423
00424
00425
00426 d->scheduled_date -= order->wait_time;
00427
00428 const Order *candidate_origin = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00429 bool found_origin = false;
00430
00431 while (candidate_origin != least_order->order) {
00432 if ((candidate_origin->GetLoadType() != OLFB_NO_LOAD ||
00433 _settings_client.gui.departure_show_all_stops) &&
00434 (candidate_origin->GetType() == OT_GOTO_STATION ||
00435 candidate_origin->GetType() == OT_IMPLICIT) &&
00436 candidate_origin->GetDestination() != station) {
00437 const Order *o = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
00438 bool found_collision = false;
00439
00440
00441 while (o != least_order->order) {
00442 if (o->GetUnloadType() == OUFB_UNLOAD) {
00443 found_collision = true;
00444 break;
00445 }
00446
00447 if ((o->GetType() == OT_GOTO_STATION ||
00448 o->GetType() == OT_IMPLICIT) &&
00449 (o->GetDestination() == candidate_origin->GetDestination() ||
00450 o->GetDestination() == station)) {
00451 found_collision = true;
00452 break;
00453 }
00454
00455 o = (o->next == NULL) ? least_order->v->GetFirstOrder() : o->next;
00456 }
00457
00458
00459 if (!found_collision) {
00460 found_origin = true;
00461 break;
00462 }
00463 }
00464
00465 candidate_origin = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
00466 }
00467
00468 order = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
00469
00470 while (order != least_order->order) {
00471 if (order->GetType() == OT_GOTO_STATION &&
00472 (order->GetLoadType() != OLFB_NO_LOAD ||
00473 _settings_client.gui.departure_show_all_stops)) {
00474 *(d->calling_at.Append(1)) = (StationID)order->GetDestination();
00475 }
00476
00477 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00478 }
00479
00480 d->terminus = candidate_origin->GetDestination();
00481
00482 if (found_origin) {
00483 *(result->Append(1)) = d;
00484 }
00485 }
00486
00487
00488 order = least_order->order;
00489
00490
00491
00492
00493
00494 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00495 least_order->expected_date += order->travel_time + order->wait_time;
00496
00497
00498
00499 bool found_next_order = false;
00500 for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
00501
00502 if (order->IsType(OT_CONDITIONAL)) {
00503 switch(_settings_client.gui.departure_conditionals) {
00504 case 0: {
00505
00506 break;
00507 }
00508 case 1: {
00509
00510 order = least_order->v->GetOrder(order->GetConditionSkipToOrder());
00511 if (order == NULL) {
00512 break;
00513 }
00514
00515 least_order->expected_date += order->wait_time;
00516
00517 continue;
00518 }
00519 case 2: {
00520
00521 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00522 least_order->expected_date += order->travel_time + order->wait_time;
00523 continue;
00524 }
00525 }
00526 }
00527
00528
00529 if (order->IsType(OT_IMPLICIT)) {
00530 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00531 continue;
00532 }
00533
00534
00535 if (order->travel_time == 0) {
00536 break;
00537 }
00538
00539
00540 if (least_order->expected_date - least_order->lateness > max_date) {
00541 break;
00542 }
00543
00544
00545 if ((type == D_DEPARTURE && IsDeparture(order, station)) ||
00546 (type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
00547 (type == D_ARRIVAL && IsArrival(order, station))) {
00548 least_order->order = order;
00549 found_next_order = true;
00550 break;
00551 }
00552
00553 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00554 least_order->expected_date += order->travel_time + order->wait_time;
00555 }
00556
00557
00558 if (!found_next_order) {
00559
00560
00561
00562 least_order->expected_date = INT64_MAX;
00563 }
00564
00565
00566 if (least_order->status == D_ARRIVED) {
00567 least_order->status = D_TRAVELLING;
00568 }
00569
00570
00571 for (uint i = 0; i < next_orders.Length(); ++i) {
00572 OrderDate *od = *(next_orders.Get(i));
00573
00574 DateTicks lod = least_order->expected_date - least_order->lateness;
00575 DateTicks odd = od->expected_date - od->lateness;
00576
00577 if (type == D_ARRIVAL) {
00578 lod -= least_order->order->wait_time;
00579 odd -= od->order->wait_time;
00580 }
00581
00582 if (lod > odd && od->expected_date - od->lateness < max_date) {
00583 least_order = od;
00584 }
00585 }
00586 }
00587
00588
00589 return result;
00590 }