5 #include "../core/math_func.hpp"
8 #include "../safeguards.h"
10 typedef std::queue<NodeID> NodeList;
61 return std::max(from.base.
supply * std::max(1U, to.base.
supply) * this->mod_size / 100 / this->demand_per_node, 1U);
73 return (to.base.
supply == 0 || to.undelivered_supply > 0) && to.base.
demand > 0;
133 if (job[from_id].base.demand > 0) {
134 uint demand_back = demand_forw * this->
mod_size / 100;
135 uint undelivered = job[to_id].undelivered_supply;
136 if (demand_back > undelivered) {
137 demand_back = undelivered;
138 demand_forw = std::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].base.supply > 0) {
178 if (job[node].base.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_t supply = scaler.EffectiveSupply(job[from_id], job[to_id]);
211 constexpr int32_t divisor_scale = 16;
222 const int32_t divisor = divisor_scale + ((this->
accuracy * scaled_distance * divisor_scale) / (this->
base_distance * 2));
223 assert(divisor >= divisor_scale);
225 uint demand_forw = 0;
226 if (divisor <= (supply * divisor_scale)) {
230 demand_forw = (supply * divisor_scale) / divisor;
231 }
else if (++chance > this->
accuracy * num_demands * num_supplies) {
237 demand_forw = std::min(demand_forw, job[from_id].undelivered_supply);
239 scaler.SetDemands(job, from_id, to_id, demand_forw);
241 if (scaler.HasDemandLeft(job[to_id])) {
247 if (job[from_id].undelivered_supply == 0)
break;
250 if (job[from_id].undelivered_supply != 0) {
251 supplies.push(from_id);
279 this->
mod_dist = 100 + ((over100 * over100) / 12);
282 switch (
settings.GetDistributionType(cargo)) {
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
A scaler for asymmetric distribution.
void AddNode(const Node &)
Nothing to do here.
uint EffectiveSupply(const Node &from, const Node &)
Get the effective supply of one node towards another one.
void SetDemandPerNode(uint)
Nothing to do here.
bool HasDemandLeft(const Node &to)
Check if there is any acceptance left for this node.
void CalcDemand(LinkGraphJob &job, Tscaler scaler)
Do the actual demand calculation, called from constructor.
DemandCalculator(LinkGraphJob &job)
Create the DemandCalculator and immediately do the calculation.
int32_t base_distance
Base distance for scaling purposes.
int32_t mod_dist
Distance modifier, determines how much demands decrease with distance.
int32_t accuracy
Accuracy of the calculation.
Class for calculation jobs to be run on link graphs.
const LinkGraphSettings & Settings() const
Get the link graph settings for this component.
NodeID Size() const
Get the size of the underlying link graph.
CargoID Cargo() const
Get the cargo of the underlying link graph.
Scale various things according to symmetric/asymmetric distribution.
void SetDemands(LinkGraphJob &job, NodeID from, NodeID to, uint demand_forw)
Set the demands between two nodes using the given base demand.
Scaler for symmetric distribution.
uint mod_size
Size modifier. Determines how much demands increase with the supply of the remote station.
uint EffectiveSupply(const Node &from, const Node &to)
Get the effective supply of one node towards another one.
uint demand_per_node
Mean demand associated with each node.
void SetDemandPerNode(uint num_demands)
Calculate the mean demand per node using the sum of supplies.
void AddNode(const Node &node)
Count a node's supply into the sum of supplies.
bool HasDemandLeft(const Node &to)
Check if there is any acceptance left for this node.
void SetDemands(LinkGraphJob &job, NodeID from, NodeID to, uint demand_forw)
Set the demands between two nodes using the given base demand.
uint supply_sum
Sum of all supplies in the component.
SymmetricScaler(uint mod_size)
Constructor.
uint32_t IntSqrt(uint32_t num)
Compute the integer square root.
Declaration of demand calculating link graph handler.
fluid_settings_t * settings
FluidSynth settings handle.
@ DT_ASYMMETRIC
Asymmetric distribution. Usually cargo will only travel in one direction.
@ DT_SYMMETRIC
Symmetric distribution. The same amount of cargo travels in each direction between each pair of nodes...
uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1)
Gets the biggest distance component (x or y) between the two given tiles plus the Manhattan distance,...
static debug_inline TileIndex TileXY(uint x, uint y)
Returns the TileIndex of a coordinate.
uint8_t accuracy
accuracy when calculating things on the link graph. low accuracy => low running time
uint8_t demand_distance
influence of distance between stations on the demand function
uint supply
Supply at the station.
uint demand
Acceptance at the station.
Size related data of the map.