7 #include "../safeguards.h" 9 typedef std::queue<NodeID> NodeList;
39 this->supply_sum += node.
Supply();
48 this->demand_per_node =
max(this->supply_sum / num_demands, 1U);
60 return max(from.
Supply() *
max(1U, to.
Supply()) * this->mod_size / 100 / this->demand_per_node, 1U);
72 return (to.
Supply() == 0 || to.UndeliveredSupply() > 0) && to.
Demand() > 0;
133 if (job[from_id].Demand() > 0) {
134 uint demand_back = demand_forw * this->mod_size / 100;
135 uint undelivered = job[to_id].UndeliveredSupply();
136 if (demand_back > undelivered) {
137 demand_back = undelivered;
138 demand_forw =
max(1U, demand_back * 100 / this->mod_size);
156 job[from_id].DeliverSupply(to_id, demand_forw);
164 template<
class Tscaler>
169 uint num_supplies = 0;
170 uint num_demands = 0;
172 for (NodeID node = 0; node < job.
Size(); node++) {
173 scaler.AddNode(job[node]);
174 if (job[node].Supply() > 0) {
178 if (job[node].Demand() > 0) {
184 if (num_supplies == 0 || num_demands == 0)
return;
189 scaler.SetDemandPerNode(num_demands);
192 while (!supplies.empty() && !demands.empty()) {
193 NodeID from_id = supplies.front();
196 for (uint i = 0; i < num_demands; ++i) {
197 assert(!demands.empty());
198 NodeID to_id = demands.front();
200 if (from_id == to_id) {
202 if (demands.empty() && supplies.empty())
return;
208 int32 supply = scaler.EffectiveSupply(job[from_id], job[to_id]);
212 int32 distance = this->max_distance - (this->max_distance -
214 this->mod_dist / 100;
217 int32 divisor = this->accuracy * (this->mod_dist - 50) / 100 +
218 this->accuracy * distance / this->max_distance + 1;
222 uint demand_forw = 0;
223 if (divisor <= supply) {
227 demand_forw = supply / divisor;
228 }
else if (++chance > this->accuracy * num_demands * num_supplies) {
234 demand_forw =
min(demand_forw, job[from_id].UndeliveredSupply());
236 scaler.SetDemands(job, from_id, to_id, demand_forw);
238 if (scaler.HasDemandLeft(job[to_id])) {
244 if (job[from_id].UndeliveredSupply() == 0)
break;
247 if (job[from_id].UndeliveredSupply() != 0) {
248 supplies.push(from_id);
270 this->
mod_dist = 100 + over100 * over100;
273 switch (settings.GetDistributionType(cargo)) {
uint mod_size
Size modifier. Determines how much demands increase with the supply of the remote station...
uint Demand() const
Get demand of wrapped node.
uint supply_sum
Sum of all supplies in the component.
bool HasDemandLeft(const Node &to)
Check if there is any acceptance left for this node.
void SetDemandPerNode(uint num_demands)
Calculate the mean demand per node using the sum of supplies.
uint Supply() const
Get supply of wrapped node.
uint EffectiveSupply(const Node &from, const Node &to)
Get the effective supply of one node towards another one.
uint EffectiveSupply(const Node &from, const Node &)
Get the effective supply of one node towards another one.
void SetDemands(LinkGraphJob &job, NodeID from, NodeID to, uint demand_forw)
Set the demands between two nodes using the given base demand.
void SetDemands(LinkGraphJob &job, NodeID from, NodeID to, uint demand_forw)
Set the demands between two nodes using the given base demand.
uint demand_per_node
Mean demand associated with each node.
Symmetric distribution. The same amount of cargo travels in each direction between each pair of nodes...
void CalcDemand(LinkGraphJob &job, Tscaler scaler)
Do the actual demand calculation, called from constructor.
Asymmetric distribution. Usually cargo will only travel in one direction.
static T max(const T a, const T b)
Returns the maximum of two values.
int32 mod_dist
Distance modifier, determines how much demands decrease with distance.
DemandCalculator(LinkGraphJob &job)
Create the DemandCalculator and immediately do the calculation.
const LinkGraphSettings & Settings() const
Get the link graph settings for this component.
bool HasDemandLeft(const Node &to)
Check if there is any acceptance left for this node.
void SetDemandPerNode(uint)
Nothing to do here.
SymmetricScaler(uint mod_size)
Constructor.
Declaration of demand calculating link graph handler.
static T min(const T a, const T b)
Returns the minimum of two values.
uint8 accuracy
accuracy when calculating things on the link graph. low accuracy => low running time ...
Scale various things according to symmetric/asymmetric distribution.
A scaler for asymmetric distribution.
CargoID Cargo() const
Get the cargo of the underlying link graph.
void AddNode(const Node &node)
Count a node's supply into the sum of supplies.
int32 accuracy
Accuracy of the calculation.
uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1)
Gets the biggest distance component (x or y) between the two given tiles plus the Manhattan distance...
uint Size() const
Get the size of the underlying link graph.
static uint MapMaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
uint8 demand_size
influence of supply ("station size") on the demand function
void AddNode(const Node &)
Nothing to do here.
byte CargoID
Cargo slots to indicate a cargo type within a game.
static uint MapMaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
static TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
Class for calculation jobs to be run on link graphs.
uint8 demand_distance
influence of distance between stations on the demand function
Scaler for symmetric distribution.