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 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 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 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 && u->cargo_cap > 0) {
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 CallAt c = CallAt((StationID)order->GetDestination(), d->scheduled_date);
00316 for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
00317
00318 if (order == least_order->order) {
00319
00320 found_terminus = (d->calling_at.Length() > 0);
00321 break;
00322 }
00323
00324
00325 if (order->IsType(OT_CONDITIONAL)) {
00326 switch(_settings_client.gui.departure_conditionals) {
00327 case 0: {
00328
00329 break;
00330 }
00331 case 1: {
00332
00333 order = least_order->v->GetOrder(order->GetConditionSkipToOrder());
00334 if (order == NULL) {
00335 break;
00336 }
00337 continue;
00338 }
00339 case 2: {
00340
00341 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00342 continue;
00343 }
00344 }
00345 }
00346
00347
00348 if (order->GetType() == OT_GOTO_STATION &&
00349 (StationID)order->GetDestination() == station &&
00350 (order->GetUnloadType() != OUFB_NO_UNLOAD ||
00351 _settings_client.gui.departure_show_all_stops) &&
00352 order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
00353 order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
00354
00355 found_terminus = (d->calling_at.Length() > 0);
00356 break;
00357 }
00358
00359
00360 if ((order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
00361 order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) &&
00362 order->GetType() == OT_GOTO_STATION &&
00363 d->via == INVALID_STATION) {
00364 candidate_via = (StationID)order->GetDestination();
00365 }
00366
00367 if (c.scheduled_date != 0 && order->travel_time != 0) {
00368 c.scheduled_date += order->travel_time;
00369 } else {
00370 c.scheduled_date = 0;
00371 }
00372
00373 c.station = (StationID)order->GetDestination();
00374
00375
00376 if ((order->GetUnloadType() == OUFB_NO_UNLOAD &&
00377 !_settings_client.gui.departure_show_all_stops) ||
00378 (order->GetType() != OT_GOTO_STATION &&
00379 order->GetType() != OT_IMPLICIT) ||
00380 order->GetNonStopType() == ONSF_NO_STOP_AT_ANY_STATION ||
00381 order->GetNonStopType() == ONSF_NO_STOP_AT_DESTINATION_STATION) {
00382 c.scheduled_date += order->wait_time;
00383 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00384 continue;
00385 }
00386
00387
00388 if (d->calling_at.Contains(c)) {
00389 found_terminus = true;
00390 break;
00391 }
00392
00393
00394 if ((order->GetType() == OT_GOTO_STATION ||
00395 order->GetType() == OT_IMPLICIT) &&
00396 order->GetNonStopType() != ONSF_NO_STOP_AT_ANY_STATION &&
00397 order->GetNonStopType() != ONSF_NO_STOP_AT_DESTINATION_STATION) {
00398 if (d->via == INVALID_STATION && candidate_via == (StationID)order->GetDestination()) {
00399 d->via = (StationID)order->GetDestination();
00400 }
00401 d->terminus = c;
00402 *(d->calling_at.Append(1)) = c;
00403 }
00404
00405
00406 if (order->GetType() == OT_GOTO_STATION &&
00407 order->GetUnloadType() == OUFB_UNLOAD) {
00408 if (d->calling_at.Length() > 0) {
00409 found_terminus = true;
00410 }
00411 break;
00412 }
00413
00414 c.scheduled_date += order->wait_time;
00415
00416
00417 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00418 }
00419
00420 if (found_terminus) {
00421
00422 bool duplicate = false;
00423
00424 if (_settings_client.gui.departure_merge_identical) {
00425 for (uint i = 0; i < result->Length(); ++i) {
00426 if (*d == **(result->Get(i))) {
00427 duplicate = true;
00428 break;
00429 }
00430 }
00431 }
00432
00433 if (!duplicate) {
00434 *(result->Append(1)) = d;
00435
00436 if (_settings_client.gui.departure_smart_terminus && type == D_DEPARTURE) {
00437 for (uint i = 0; i < result->Length()-1; ++i) {
00438 Departure *d_first = *(result->Get(i));
00439 uint k = d_first->calling_at.Length()-2;
00440 for (uint j = d->calling_at.Length(); j > 0; --j) {
00441 CallAt c = CallAt(*(d->calling_at.Get(j-1)));
00442
00443 if (d_first->terminus >= c && d_first->calling_at.Length() >= 2) {
00444 d_first->terminus = CallAt(*(d_first->calling_at.Get(k)));
00445
00446 if (k == 0) break;
00447
00448 k--;
00449 }
00450 }
00451 }
00452 }
00453
00454
00455
00456 if (d->status != D_ARRIVED &&
00457 d->lateness > 0) {
00458 d->lateness -= least_order->order->wait_time;
00459 }
00460 }
00461 }
00462 } else {
00463
00464
00465
00466
00467
00468
00469 d->scheduled_date -= order->wait_time;
00470
00471 const Order *candidate_origin = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00472 bool found_origin = false;
00473
00474 while (candidate_origin != least_order->order) {
00475 if ((candidate_origin->GetLoadType() != OLFB_NO_LOAD ||
00476 _settings_client.gui.departure_show_all_stops) &&
00477 (candidate_origin->GetType() == OT_GOTO_STATION ||
00478 candidate_origin->GetType() == OT_IMPLICIT) &&
00479 candidate_origin->GetDestination() != station) {
00480 const Order *o = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
00481 bool found_collision = false;
00482
00483
00484 while (o != least_order->order) {
00485 if (o->GetUnloadType() == OUFB_UNLOAD) {
00486 found_collision = true;
00487 break;
00488 }
00489
00490 if ((o->GetType() == OT_GOTO_STATION ||
00491 o->GetType() == OT_IMPLICIT) &&
00492 (o->GetDestination() == candidate_origin->GetDestination() ||
00493 o->GetDestination() == station)) {
00494 found_collision = true;
00495 break;
00496 }
00497
00498 o = (o->next == NULL) ? least_order->v->GetFirstOrder() : o->next;
00499 }
00500
00501
00502 if (!found_collision) {
00503 found_origin = true;
00504 break;
00505 }
00506 }
00507
00508 candidate_origin = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
00509 }
00510
00511 order = (candidate_origin->next == NULL) ? least_order->v->GetFirstOrder() : candidate_origin->next;
00512
00513 while (order != least_order->order) {
00514 if (order->GetType() == OT_GOTO_STATION &&
00515 (order->GetLoadType() != OLFB_NO_LOAD ||
00516 _settings_client.gui.departure_show_all_stops)) {
00517 *(d->calling_at.Append(1)) = CallAt((StationID)order->GetDestination());
00518 }
00519
00520 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00521 }
00522
00523 d->terminus = CallAt((StationID)candidate_origin->GetDestination());
00524
00525 if (found_origin) {
00526 bool duplicate = false;
00527
00528 if (_settings_client.gui.departure_merge_identical) {
00529 for (uint i = 0; i < result->Length(); ++i) {
00530 if (*d == **(result->Get(i))) {
00531 duplicate = true;
00532 break;
00533 }
00534 }
00535 }
00536
00537 if (!duplicate) {
00538 *(result->Append(1)) = d;
00539 }
00540 }
00541 }
00542
00543
00544 order = least_order->order;
00545
00546
00547
00548
00549
00550 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00551 least_order->expected_date += order->travel_time + order->wait_time;
00552
00553
00554
00555 bool found_next_order = false;
00556 for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
00557
00558 if (order->IsType(OT_CONDITIONAL)) {
00559 switch(_settings_client.gui.departure_conditionals) {
00560 case 0: {
00561
00562 break;
00563 }
00564 case 1: {
00565
00566 order = least_order->v->GetOrder(order->GetConditionSkipToOrder());
00567 if (order == NULL) {
00568 break;
00569 }
00570
00571 least_order->expected_date += order->wait_time;
00572
00573 continue;
00574 }
00575 case 2: {
00576
00577 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00578 least_order->expected_date += order->travel_time + order->wait_time;
00579 continue;
00580 }
00581 }
00582 }
00583
00584
00585 if (order->IsType(OT_IMPLICIT)) {
00586 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00587 continue;
00588 }
00589
00590
00591 if (order->travel_time == 0) {
00592 break;
00593 }
00594
00595
00596 if (least_order->expected_date - least_order->lateness > max_date) {
00597 break;
00598 }
00599
00600
00601 if ((type == D_DEPARTURE && IsDeparture(order, station)) ||
00602 (type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
00603 (type == D_ARRIVAL && IsArrival(order, station))) {
00604 least_order->order = order;
00605 found_next_order = true;
00606 break;
00607 }
00608
00609 order = (order->next == NULL) ? least_order->v->GetFirstOrder() : order->next;
00610 least_order->expected_date += order->travel_time + order->wait_time;
00611 }
00612
00613
00614 if (!found_next_order) {
00615
00616
00617
00618 least_order->expected_date = INT64_MAX;
00619 }
00620
00621
00622 if (least_order->status == D_ARRIVED) {
00623 least_order->status = D_TRAVELLING;
00624 }
00625
00626
00627 for (uint i = 0; i < next_orders.Length(); ++i) {
00628 OrderDate *od = *(next_orders.Get(i));
00629
00630 DateTicks lod = least_order->expected_date - least_order->lateness;
00631 DateTicks odd = od->expected_date - od->lateness;
00632
00633 if (type == D_ARRIVAL) {
00634 lod -= least_order->order->wait_time;
00635 odd -= od->order->wait_time;
00636 }
00637
00638 if (lod > odd && od->expected_date - od->lateness < max_date) {
00639 least_order = od;
00640 }
00641 }
00642 }
00643
00644
00645 return result;
00646 }