57 lines
2.8 KiB
Diff
57 lines
2.8 KiB
Diff
# UNDF: UNDF-2026-000000996
|
|
--- a/Empire/Empire.cpp
|
|
+++ b/Empire/Empire.cpp
|
|
@@ -2263,6 +2263,14 @@ std::vector<std::string> Empire::CheckResearchProgress(
|
|
const std::vector<std::tuple<std::string_view, double, int>>& costs_times)
|
|
{
|
|
SanitizeResearchQueue(m_research_queue);
|
|
+
|
|
+ // Build hash map for O(1) lookup of tech cost/time by name.
|
|
+ // Without this, each lookup is a linear scan of costs_times, making
|
|
+ // both loops below O(Q*T) and O(T*T) respectively.
|
|
+ boost::unordered_flat_map<std::string_view, std::pair<double, int>> costs_times_map;
|
|
+ costs_times_map.reserve(costs_times.size());
|
|
+ for (const auto& [name, cost, time] : costs_times)
|
|
+ costs_times_map.emplace(name, std::pair{cost, time});
|
|
|
|
float spent_rp = 0.0f;
|
|
const float total_rp_available = m_research_pool.TotalAvailable();
|
|
@@ -2274,15 +2282,13 @@ std::vector<std::string> Empire::CheckResearchProgress(
|
|
// process items on queue
|
|
std::vector<std::string> to_erase_from_queue_and_grant_next_turn;
|
|
for (auto& elem : m_research_queue | range_filter(has_allocated_rp)) {
|
|
- const auto is_tech = [tech_name{elem.name}](const std::tuple<std::string_view, double, int>& ct)
|
|
- { return std::get<0>(ct) == tech_name; };
|
|
-
|
|
- const auto ct_it = range_find_if(costs_times, is_tech);
|
|
- if (ct_it == costs_times.end()) {
|
|
+ const auto ct_it = costs_times_map.find(elem.name);
|
|
+ if (ct_it == costs_times_map.end()) {
|
|
ErrorLogger() << "Missing tech " << elem.name << " cost time in CheckResearchProgress!";
|
|
continue;
|
|
}
|
|
- const float tech_cost = static_cast<float>(std::get<1>(*ct_it));
|
|
+ const float tech_cost = static_cast<float>(ct_it->second.first);
|
|
|
|
float& progress = m_research_progress[elem.name];
|
|
progress += elem.allocated_rp / std::max(EPSILON, tech_cost);
|
|
@@ -2328,16 +2334,13 @@ std::vector<std::string> Empire::CheckResearchProgress(
|
|
if (progress_fraction >= 1.0)
|
|
continue;
|
|
|
|
- const auto is_tech = [tech_name{tech_name}](const std::tuple<std::string_view, double, int>& ct)
|
|
- { return std::get<0>(ct) == tech_name; };
|
|
-
|
|
- const auto ct_it = range_find_if(costs_times, is_tech);
|
|
- if (ct_it == costs_times.end()) {
|
|
+ const auto ct_it = costs_times_map.find(tech_name);
|
|
+ if (ct_it == costs_times_map.end()) {
|
|
ErrorLogger() << "Missing tech " << tech_name << " cost time in CheckResearchProgress!";
|
|
continue;
|
|
}
|
|
|
|
- const double remaining_cost = std::get<1>(*ct_it) * (1.0 - progress_fraction);
|
|
+ const double remaining_cost = ct_it->second.first * (1.0 - progress_fraction);
|
|
costs_to_complete_available_unpaused_techs.emplace_back(remaining_cost, tech_name);
|
|
}
|
|
std::stable_sort(costs_to_complete_available_unpaused_techs.begin(),
|