1 #include "ResourcePool.h"
2
3 #include <boost/lexical_cast.hpp>
4
5 #include "../universe/ObjectMap.h"
6 #include "../universe/Planet.h"
7 #include "../universe/Enums.h"
8 #include "../util/AppInterface.h"
9 #include "../util/Logger.h"
10
11 //////////////////////////////////////////////////
12 // ResourcePool
13 //////////////////////////////////////////////////
ResourcePool()14 ResourcePool::ResourcePool() :
15 m_type(INVALID_RESOURCE_TYPE)
16 {}
17
ResourcePool(ResourceType type)18 ResourcePool::ResourcePool(ResourceType type) :
19 m_type(type)
20 {}
21
ObjectIDs() const22 const std::vector<int>& ResourcePool::ObjectIDs() const
23 { return m_object_ids; }
24
Stockpile() const25 float ResourcePool::Stockpile() const
26 { return m_stockpile; }
27
TotalOutput() const28 float ResourcePool::TotalOutput() const {
29 float retval = 0.0f;
30 for (const auto& entry : m_connected_object_groups_resource_output)
31 { retval += entry.second; }
32 return retval;
33 }
34
Output() const35 std::map<std::set<int>, float> ResourcePool::Output() const { return m_connected_object_groups_resource_output; }
36
GroupOutput(int object_id) const37 float ResourcePool::GroupOutput(int object_id) const {
38 // find group containing specified object
39 for (const auto& entry : m_connected_object_groups_resource_output) {
40 if (entry.first.count(object_id))
41 return entry.second;
42 }
43
44 // default return case:
45 //DebugLogger() << "ResourcePool::GroupOutput passed unknown object id: " << object_id;
46 return 0.0f;
47 }
48
49
TargetOutput() const50 float ResourcePool::TargetOutput() const {
51 float retval = 0.0f;
52 for (const auto& entry : m_connected_object_groups_resource_target_output)
53 { retval += entry.second; }
54 return retval;
55 }
56
GroupTargetOutput(int object_id) const57 float ResourcePool::GroupTargetOutput(int object_id) const {
58 // find group containing specified object
59 for (const auto& entry : m_connected_object_groups_resource_target_output) {
60 if (entry.first.count(object_id))
61 return entry.second;
62 }
63
64 // default return case:
65 DebugLogger() << "ResourcePool::GroupTargetOutput passed unknown object id: " << object_id;
66 return 0.0f;
67 }
68
TotalAvailable() const69 float ResourcePool::TotalAvailable() const {
70 float retval = m_stockpile;
71 for (const auto& entry : m_connected_object_groups_resource_output)
72 { retval += entry.second; }
73 return retval;
74 }
75
Available() const76 std::map<std::set<int>, float> ResourcePool::Available() const {
77 auto retval = m_connected_object_groups_resource_output;
78 return retval;
79 }
80
GroupAvailable(int object_id) const81 float ResourcePool::GroupAvailable(int object_id) const {
82 TraceLogger() << "ResourcePool::GroupAvailable(" << object_id << ")";
83 // available is production in this group
84 return GroupOutput(object_id);
85 }
86
Dump() const87 std::string ResourcePool::Dump() const {
88 std::string retval = "ResourcePool type = " + boost::lexical_cast<std::string>(m_type) +
89 " stockpile = " + std::to_string(m_stockpile) +
90 " object_ids: ";
91 for (int obj_id : m_object_ids)
92 retval += std::to_string(obj_id) + ", ";
93 return retval;
94 }
95
SetObjects(const std::vector<int> & object_ids)96 void ResourcePool::SetObjects(const std::vector<int>& object_ids)
97 { m_object_ids = object_ids; }
98
SetConnectedSupplyGroups(const std::set<std::set<int>> & connected_system_groups)99 void ResourcePool::SetConnectedSupplyGroups(const std::set<std::set<int>>& connected_system_groups)
100 { m_connected_system_groups = connected_system_groups; }
101
SetStockpile(float d)102 void ResourcePool::SetStockpile(float d)
103 { m_stockpile = d; }
104
Update()105 void ResourcePool::Update() {
106 //DebugLogger() << "ResourcePool::Update for type " << m_type;
107 // sum production from all ResourceCenters in each group, for resource point type appropriate for this pool
108 MeterType meter_type = ResourceToMeter(m_type);
109 MeterType target_meter_type = ResourceToTargetMeter(m_type);
110
111 if (INVALID_METER_TYPE == meter_type || INVALID_METER_TYPE == target_meter_type)
112 ErrorLogger() << "ResourcePool::Update() called when m_type can't be converted to a valid MeterType";
113
114 // zero to start...
115 m_connected_object_groups_resource_output.clear();
116 m_connected_object_groups_resource_target_output.clear();
117
118 // temporary storage: indexed by group of systems, which objects
119 // are located in that system group?
120 std::map<std::set<int>, std::set<std::shared_ptr<const UniverseObject>>>
121 system_groups_to_object_groups;
122
123
124 // for every object, find if a connected system group contains the object's
125 // system. If a group does, place the object into that system group's set
126 // of objects. If no group contains the object, place the object in its own
127 // single-object group.
128 for (auto& obj : Objects().find<const UniverseObject>(m_object_ids)) {
129 int object_id = obj->ID();
130 int object_system_id = obj->SystemID();
131 // can't generate resources when not in a system
132 if (object_system_id == INVALID_OBJECT_ID)
133 continue;
134
135 // is object's system in a system group?
136 std::set<int> object_system_group;
137 for (const auto& sys_group : m_connected_system_groups) {
138 if (sys_group.count(object_system_id)) {
139 object_system_group = sys_group;
140 break;
141 }
142 }
143
144 // if object's system is not in a system group, add it as its
145 // own entry in m_connected_object_groups_resource_output and m_connected_object_groups_resource_target_output
146 // this will allow the object to use its own locally produced
147 // resource when, for instance, distributing pp
148 if (object_system_group.empty()) {
149 object_system_group.insert(object_id); // just use this already-available set to store the object id, even though it is not likely actually a system
150
151 const auto* mmt = obj->GetMeter(meter_type);
152 m_connected_object_groups_resource_output[object_system_group] = mmt ? mmt->Current() : 0.0f;
153
154 const auto* mtmt = obj->GetMeter(target_meter_type);
155 m_connected_object_groups_resource_target_output[object_system_group] = mtmt ? mtmt->Current() : 0.0f;
156
157 continue;
158 }
159
160 // if resource center's system is in a system group, record which system
161 // group that is for later
162 system_groups_to_object_groups[object_system_group].insert(obj);
163 }
164
165 // sum the resource production for object groups, and store the total
166 // group production, indexed by group of object ids
167 for (auto& entry : system_groups_to_object_groups) {
168 const auto& object_group = entry.second;
169 std::set<int> object_group_ids;
170 float total_group_output = 0.0f;
171 float total_group_target_output = 0.0f;
172 for (auto& obj : object_group) {
173 if (const auto* m = obj->GetMeter(meter_type))
174 total_group_output += m->Current();
175 if (const auto* m = obj->GetMeter(target_meter_type))
176 total_group_target_output += m->Current();
177 object_group_ids.insert(obj->ID());
178 }
179 m_connected_object_groups_resource_output[object_group_ids] = total_group_output;
180 m_connected_object_groups_resource_target_output[object_group_ids] = total_group_target_output;
181 }
182
183 ChangedSignal();
184 }
185