From 2626cf1b54416d1521c229a12ffbac7862f7e9f9 Mon Sep 17 00:00:00 2001 From: teamhimeH Date: Sat, 4 Jan 2025 12:57:04 +0900 Subject: [PATCH] Switch the routing method for goods category --- dataobj/settings.cc | 4 +-- dataobj/settings.h | 20 ++--------- gui/halt_info.cc | 2 +- gui/route_search_frame.cc | 4 +-- gui/schedule_gui.cc | 6 ++-- gui/schedule_list.cc | 3 +- gui/settings_stats.cc | 16 --------- gui/settings_stats.h | 3 -- simconvoi.cc | 10 +++--- simhalt.cc | 74 ++++++++++++++++++--------------------- 10 files changed, 49 insertions(+), 93 deletions(-) diff --git a/dataobj/settings.cc b/dataobj/settings.cc index 13b7940db7c..83760296ba4 100644 --- a/dataobj/settings.cc +++ b/dataobj/settings.cc @@ -306,8 +306,8 @@ settings_t::settings_t() : citycar_route_weight_speed = 0; advance_to_end = true; + first_come_first_serve = false; MEMZERON(is_time_based_routing_enabled, 256); - goods_routing_policy = GRP_NF_RC; waiting_limit_for_first_come_first_serve = 500000; routecost_wait = 8; @@ -1658,7 +1658,7 @@ void settings_t::parse_simuconf( tabfile_t& simuconf, sint16& disp_width, sint16 citycar_route_weight_speed = contents.get_int("citycar_route_weight_speed", citycar_route_weight_speed); advance_to_end = contents.get_int("advance_to_end", advance_to_end); - goods_routing_policy = (goods_routing_policy_t)contents.get_int("goods_routing_policy", goods_routing_policy); + first_come_first_serve = contents.get_int("first_come_first_serve", first_come_first_serve); waiting_limit_for_first_come_first_serve = contents.get_int("waiting_limit_for_first_come_first_serve", waiting_limit_for_first_come_first_serve); diff --git a/dataobj/settings.h b/dataobj/settings.h index 4d1722f79cf..18a75edd1cb 100644 --- a/dataobj/settings.h +++ b/dataobj/settings.h @@ -32,21 +32,6 @@ struct citycar_routing_param_t sint16 weight_speed; }; -// The policy of how to route and loads the goods at stops. -enum goods_routing_policy_t { - // The goods routing is based on route cost. - // At stops, the goods to the nearest destination are loaded first. - GRP_NF_RC = 0, - - // The goods routing is based on route cost. - // At stops, the goods are loaded in the order of the arrival. - GRP_FIFO_RC = 1, - - // The goods routing is based on the estimated time to reach the destination. - // At stops, the goods are loaded in the order of the arrival. - GRP_FIFO_ET = 2, -}; - /** * Game settings */ @@ -346,7 +331,6 @@ class settings_t // The flag whether the time based goods routing is enabled for the goods. // The array index is the goods category index. bool is_time_based_routing_enabled[256]; - goods_routing_policy_t goods_routing_policy; // When the amount of waiting goods/passengers exceeds this value, // goods are loaded with "nearest first" policy to reduce the calculation load. @@ -713,8 +697,8 @@ class settings_t bool get_advance_to_end() const { return advance_to_end; } void set_advance_to_end(bool b) { advance_to_end = b; } - - goods_routing_policy_t get_goods_routing_policy() const { return goods_routing_policy; } + + bool get_first_come_first_serve() const { return first_come_first_serve; } uint32 get_waiting_limit_for_first_come_first_serve() const { return waiting_limit_for_first_come_first_serve; } diff --git a/gui/halt_info.cc b/gui/halt_info.cc index 9937f5c9969..3bf18ee92c2 100644 --- a/gui/halt_info.cc +++ b/gui/halt_info.cc @@ -658,7 +658,6 @@ void gui_halt_detail_t::update_connections( halthandle_t halt ) new_component_span("Direkt erreichbare Haltestellen", 2); bool has_stops = false; - const bool is_tgbr_enabled = world()->get_settings().get_goods_routing_policy() == goods_routing_policy_t::GRP_FIFO_ET; for (uint i=0; i const& connections = halt->get_connections(i); @@ -683,6 +682,7 @@ void gui_halt_detail_t::update_connections( halthandle_t halt ) sorted.insert_unique_ordered(conn, gui_halt_detail_t::compare_connection); } } + const bool is_tgbr_enabled = world()->get_settings().get_time_based_routing_enabled(i); FOR(vector_tpl, const& conn, sorted) { has_stops = true; diff --git a/gui/route_search_frame.cc b/gui/route_search_frame.cc index cefe6ba93ad..4df829c68d8 100644 --- a/gui/route_search_frame.cc +++ b/gui/route_search_frame.cc @@ -138,8 +138,8 @@ void route_search_frame_t::append_connection_row(haltestelle_t::connection_t con // construct weight text char text[16]; uint32 weight; - if( world()->get_settings().get_goods_routing_policy()==GRP_FIFO_ET ) { - // weight is in ticks. We have to convert it to the OTRP departure time unit. + if( world()->get_settings().get_time_based_routing_enabled(0) ) { + // When TBGR is enabled for pax, weight is in ticks. We have to convert it to the OTRP departure time unit. weight = (uint64)connection.weight * world()->get_settings().get_spacing_shift_divisor() / world()->ticks_per_world_month; } else { // weight is in route cost. diff --git a/gui/schedule_gui.cc b/gui/schedule_gui.cc index eb1cc421a97..1513c7a675d 100644 --- a/gui/schedule_gui.cc +++ b/gui/schedule_gui.cc @@ -1271,14 +1271,12 @@ void schedule_gui_t::extract_advanced_settings(bool yesno) { bt_transfer_interval.set_visible(yesno); lb_departure_slot_group.set_visible(yesno); departure_slot_group_selector.set_visible(yesno); + lb_tbgr_waiting_time.set_visible(yesno); + numimp_tbgr_waiting_time.set_visible(yesno); const bool coupling_waytype = schedule->get_waytype()!=road_wt && schedule->get_waytype()!=air_wt && schedule->get_waytype()!=water_wt; bt_wait_for_child.set_visible(coupling_waytype && yesno); bt_find_parent.set_visible(coupling_waytype && yesno); bt_reverse_convoy.set_visible(coupling_waytype && yesno); bt_reverse_coupling.set_visible(coupling_waytype && yesno); - - const bool is_tbgr_enabled = world()->get_settings().get_goods_routing_policy() == goods_routing_policy_t::GRP_FIFO_ET; - lb_tbgr_waiting_time.set_visible(is_tbgr_enabled && yesno); - numimp_tbgr_waiting_time.set_visible(is_tbgr_enabled && yesno); } diff --git a/gui/schedule_list.cc b/gui/schedule_list.cc index 24538ae9bb5..2821cec1f79 100644 --- a/gui/schedule_list.cc +++ b/gui/schedule_list.cc @@ -809,8 +809,7 @@ void schedule_list_gui_t::update_lineinfo(linehandle_t new_line) line = new_line; bt_withdraw_line.set_visible( line.is_bound() ); bt_show_journey_time.set_visible( line.is_bound() ); - const bool is_tbgr_enabled = world()->get_settings().get_goods_routing_policy()==goods_routing_policy_t::GRP_FIFO_ET; - bt_goods_waiting_time.set_visible( is_tbgr_enabled && line.is_bound() ); + bt_goods_waiting_time.set_visible( line.is_bound() ); reset_line_name(); } diff --git a/gui/settings_stats.cc b/gui/settings_stats.cc index 166b94aab77..4ee8ee76303 100644 --- a/gui/settings_stats.cc +++ b/gui/settings_stats.cc @@ -213,13 +213,6 @@ void settings_display_stats_t::read(settings_t* const) READ_BOOL_VALUE( env_t::player_finance_display_account ); } -static char const * const goods_routing_policy_string[] = -{ - "loading nearest first, routing with route cost", - "loading in arrival order, routing with route cost", - "loading in arrival order, routing with estimated time" -}; - void settings_routing_stats_t::init(settings_t const* const sets) { INIT_INIT @@ -253,14 +246,6 @@ void settings_routing_stats_t::init(settings_t const* const sets) SEPERATOR INIT_BOOL( "advance_to_end", sets->get_advance_to_end() ); INIT_BOOL( "first_come_first_serve", sets->first_come_first_serve ); - // combobox for trees generator - goods_routing_policy.clear_elements(); - for( uint32 i=0; i( goods_routing_policy_string[i], SYSCOL_TEXT ) ; - } - goods_routing_policy.set_selection( sets->get_goods_routing_policy() ); - goods_routing_policy.set_focusable( false ); - add_component( &goods_routing_policy, 2); INIT_NUM( "waiting_limit_for_first_come_first_serve", sets->get_waiting_limit_for_first_come_first_serve(), 100, 0x7FFFFFFFul, gui_numberinput_t::POWER2, false ); SEPERATOR INIT_NUM ( "base_waiting_ticks_for_rail_convoi", sets->base_waiting_ticks_for_rail_convoi, 0, 0x7FFFFFFFul, gui_numberinput_t::POWER2, false ); @@ -302,7 +287,6 @@ void settings_routing_stats_t::read(settings_t* const sets) READ_NUM_VALUE( sets->routecost_halt ); READ_BOOL_VALUE( sets->advance_to_end ); READ_BOOL_VALUE( sets->first_come_first_serve ); - sets->goods_routing_policy = (goods_routing_policy_t)::clamp(goods_routing_policy.get_selection(), (int)GRP_NF_RC, (int)GRP_FIFO_ET ); READ_NUM_VALUE( sets->waiting_limit_for_first_come_first_serve ); READ_NUM_VALUE( sets->base_waiting_ticks_for_rail_convoi ); diff --git a/gui/settings_stats.h b/gui/settings_stats.h index 49d807cf237..ca01ddf96c9 100644 --- a/gui/settings_stats.h +++ b/gui/settings_stats.h @@ -144,9 +144,6 @@ class settings_display_stats_t : protected settings_stats_t, public gui_aligned_ class settings_routing_stats_t : protected settings_stats_t, public gui_aligned_container_t { -private: - gui_combobox_t goods_routing_policy; - public: void init(settings_t const*); void read(settings_t*); diff --git a/simconvoi.cc b/simconvoi.cc index e2771da9364..8201770e6d9 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -3871,19 +3871,17 @@ void convoi_t::hat_gehalten(halthandle_t halt, uint32 halt_length_in_vehicle_ste uint16 convoi_t::fetch_goods_and_load(vehicle_t* vehicle, const halthandle_t halt, const vector_tpl destination_halts, uint32 requested_amount) { slist_tpl fetched_goods; - const goods_routing_policy_t goods_routing_policy = welt->get_settings().get_goods_routing_policy(); - if( goods_routing_policy==goods_routing_policy_t::GRP_NF_RC ) { - halt->fetch_goods_nearest_first(fetched_goods, vehicle->get_cargo_type(), requested_amount, destination_halts); - } else { - // GRP_FIFO_ET or GRP_FIFO_RC + if( welt->get_settings().get_first_come_first_serve() ) { halt->fetch_goods_FIFO(fetched_goods, vehicle->get_cargo_type(), requested_amount, destination_halts); + } else { + halt->fetch_goods_nearest_first(fetched_goods, vehicle->get_cargo_type(), requested_amount, destination_halts); } return vehicle->load_cargo(fetched_goods); } void convoi_t::push_goods_waiting_time_if_needed() { - if( welt->get_settings().get_goods_routing_policy()!=GRP_FIFO_ET || fetched_fresh_goods.empty() ) { + if( fetched_fresh_goods.empty() ) { // No need to calculate and push the goods waiting time. return; } diff --git a/simhalt.cc b/simhalt.cc index e515ae65532..6d0d8df7089 100644 --- a/simhalt.cc +++ b/simhalt.cc @@ -130,8 +130,15 @@ void haltestelle_t::step_all() last_reconnection_started_ticks = welt->get_ticks(); } - const bool is_tgbr_enabled = welt->get_settings().get_goods_routing_policy()==GRP_FIFO_ET; - if( status_step==0 && is_tgbr_enabled && welt->get_ticks() > last_reconnection_started_ticks + WEIGHT_UPDATE_INTERVAL_TICKS ) { + // Regurally update the connection weight only when time based routing is used. + bool is_tbgr_used = false; + for( uint8 catg_idx = 0; catg_idx < goods_manager_t::get_max_catg_index(); catg_idx++ ) { + if( welt->get_settings().get_time_based_routing_enabled(catg_idx) ) { + is_tbgr_used = true; + break; + } + } + if( status_step==0 && is_tbgr_used && welt->get_ticks() > last_reconnection_started_ticks + WEIGHT_UPDATE_INTERVAL_TICKS ) { status_step = WEIGHT_UPDATE; last_reconnection_started_ticks = welt->get_ticks(); } @@ -1248,9 +1255,6 @@ sint32 haltestelle_t::rebuild_connections() // previous halt supporting the ware categories of the serving line halthandle_t previous_halt[256]; - // true if the estimated time based goods routing is enabled. false if we use route cost calculation. - const bool is_tbgr_enabled = welt->get_settings().get_goods_routing_policy() == goods_routing_policy_t::GRP_FIFO_ET; - // first, remove all old entries if( staged_all_links ) { // rebuild_connections() is called before the staged links are commited. @@ -1351,16 +1355,14 @@ sint32 haltestelle_t::rebuild_connections() // now we add the schedule to the connection array const schedule_entry_t start_entry = schedule->entries[start_index-1]; - // aggregate_weight: When TBGR is enabled, (average goods waiting time) + (median journey time) - // When TBGR is disabled, it is route cost. e.g. WEIGHT_HALT + WEIGHT_WAIT * (stops count) - sint32 aggregate_weight; - if( is_tbgr_enabled ) { - // the journey time of the first entry contains the stopping time at the starting point, which should be excluded. - aggregate_weight = estimated_waiting_ticks(schedule, start_index-1) - start_entry.get_median_convoy_stopping_time(); - } - else { - aggregate_weight = WEIGHT_WAIT; - } + // We calculate the connection weight by both route cost and journey time, + // because it depends on the routing configuration for the goods category. + sint32 aggregate_weight_rc; // weight by route cost. WEIGHT_HALT + WEIGHT_WAIT * (stops count) + sint32 aggregate_weight_jt; // weight by journey time. (average goods waiting time) + (median journey time) + + // the journey time of the first entry contains the stopping time at the starting point, which should be excluded. + aggregate_weight_jt = estimated_waiting_ticks(schedule, start_index-1) - start_entry.get_median_convoy_stopping_time(); + aggregate_weight_rc = WEIGHT_WAIT; bool no_load_section = start_entry.is_no_load(); force_transfer_search |= (start_entry.is_unload_all() || start_entry.is_no_load() || start_entry.is_no_unload()); @@ -1372,9 +1374,7 @@ sint32 haltestelle_t::rebuild_connections() if( !current_halt.is_bound() ) { // ignore way points. // just count the journey time - if( is_tbgr_enabled ) { - aggregate_weight += schedule->get_median_journey_time(current_entry_index, speedbonus_kmh); - } + aggregate_weight_jt += schedule->get_median_journey_time(current_entry_index, speedbonus_kmh); continue; } if( current_halt == self ) { @@ -1387,11 +1387,8 @@ sint32 haltestelle_t::rebuild_connections() } } // reset aggregate weight and no_load_section - if( is_tbgr_enabled ) { - aggregate_weight = estimated_waiting_ticks(schedule, current_entry_index) - current_entry.get_median_convoy_stopping_time(); - } else { - aggregate_weight = WEIGHT_WAIT; - } + aggregate_weight_jt = estimated_waiting_ticks(schedule, current_entry_index) - current_entry.get_median_convoy_stopping_time(); + aggregate_weight_rc = WEIGHT_WAIT; force_transfer_search |= (current_entry.is_unload_all() || current_entry.is_no_load() || current_entry.is_no_unload()); no_load_section = current_entry.is_no_load(); interval = 0; @@ -1399,11 +1396,8 @@ sint32 haltestelle_t::rebuild_connections() } // Add weight - if( is_tbgr_enabled ) { - aggregate_weight += schedule->get_median_journey_time(current_entry_index, (uint32)speedbonus_kmh); - } else { - aggregate_weight += WEIGHT_HALT; - } + aggregate_weight_jt += schedule->get_median_journey_time(current_entry_index, (uint32)speedbonus_kmh); + aggregate_weight_rc += WEIGHT_HALT; if( current_entry.is_no_unload() || no_load_section ) { // do not add connection if this halt is set no_unload or if the previous self stop is set no_load. @@ -1429,6 +1423,7 @@ sint32 haltestelle_t::rebuild_connections() previous_halt[catg_index] = current_halt; // either add a new connection or update the weight of an existing connection where necessary + const uint32 aggregate_weight = welt->get_settings().get_time_based_routing_enabled(catg_index) ? aggregate_weight_jt : aggregate_weight_rc; connection_t *const existing_connection = staged_all_links[catg_index].connections.insert_unique_ordered( connection_t( current_halt, aggregate_weight, traveler ), connection_t::compare ); if( existing_connection && aggregate_weightweight ) { existing_connection->weight = aggregate_weight; @@ -2436,7 +2431,7 @@ bool haltestelle_t::vereinige_waren(const ware_t &ware) // merge cargos only when "load nearest first" policy is applied. const settings_t &settings = world()->get_settings(); const bool* wefl = waiting_amount_exceeds_FIFO_limit.access(ware.get_desc()->get_catg_index()); - if( settings.get_goods_routing_policy()!=GRP_NF_RC && (wefl==NULL || !*wefl) ) { + if( settings.get_first_come_first_serve() && (wefl==NULL || !*wefl) ) { return false; } @@ -2478,10 +2473,8 @@ std::shared_ptr haltestelle_t::add_goods_to_halt(halt_wait cargo_item_t goods_ref = cargo_item_t(new halt_waiting_goods_t(wg)); warray->append(goods_ref); - // Add the goods to fresh_cargo_ids if needed - if( world()->get_settings().get_goods_routing_policy()==goods_routing_policy_t::GRP_FIFO_ET ) { - fresh_cargo[wg.goods.get_desc()->get_catg_index()].push_back(std::weak_ptr(goods_ref)); - } + // Add the goods to fresh_cargo for the waiting time statistics + fresh_cargo[wg.goods.get_desc()->get_catg_index()].push_back(std::weak_ptr(goods_ref)); return goods_ref; } @@ -4256,23 +4249,26 @@ void haltestelle_t::calc_destination_halt(inthashtable_tplget_settings().get_goods_routing_policy()==goods_routing_policy_t::GRP_FIFO_ET; const schedule_t* schedule = std::visit( [&](const auto &t) { return t->get_schedule(); }, traveler ); - if( !is_tbgr_enabled || cnv->get_schedule()->is_temporary() || unregistered_journey_time_exists(schedule, cnv->get_owner()) ) { - // We accept all halts in reachable_halts - FOR(const minivec_tpl, const& i, goods_category_indexes) { + const bool accept_all_halts = schedule->is_temporary() || unregistered_journey_time_exists(schedule, cnv->get_owner()); + FOR(const minivec_tpl, const& i, goods_category_indexes) { + // Temporary schedule or route cost is used -> Accept all halts. + if( accept_all_halts || !welt->get_settings().get_time_based_routing_enabled(i) ) { FOR(const vector_tpl, const& rh, reachable_halts) { destination_halts.access(i)->append(rh.halt); } } - return; } const uint32 additional_ticks_by_schedule = (uint64)schedule->get_additional_base_waiting_time() * world()->ticks_per_world_month / world()->get_settings().get_spacing_shift_divisor(); const uint32 base_waiting_ticks = world()->get_settings().get_base_waiting_ticks(schedule->get_waytype()) + additional_ticks_by_schedule; FOR(const minivec_tpl, const& g_index, goods_category_indexes) { + if( !destination_halts.access(g_index)->empty() ) { + // The destination halts are already filled above. + continue; + } FOR(const vector_tpl, const& rh, reachable_halts) { connection_t connection; FOR(const vector_tpl, const& j, all_links[g_index].connections) { @@ -4309,7 +4305,7 @@ void haltestelle_t::calc_destination_halt(inthashtable_tplget_settings().get_goods_routing_policy()!=goods_routing_policy_t::GRP_FIFO_ET ) { + if( !world()->get_settings().get_time_based_routing_enabled(ware.get_index()) ) { // Not using time based goods routing -> Always reroute return true; }