Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "demands.h"
|
||||
#include "../core/math_func.hpp"
|
||||
#include <queue>
|
||||
|
||||
#include "../safeguards.h"
|
||||
@@ -207,23 +208,26 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
|
||||
int32_t supply = scaler.EffectiveSupply(job[from_id], job[to_id]);
|
||||
assert(supply > 0);
|
||||
|
||||
/* Scale the distance by mod_dist around max_distance */
|
||||
int32_t distance = this->max_distance - (this->max_distance -
|
||||
(int32_t)DistanceMaxPlusManhattan(job[from_id].base.xy, job[to_id].base.xy)) *
|
||||
this->mod_dist / 100;
|
||||
constexpr int32_t divisor_scale = 16;
|
||||
|
||||
int32_t scaled_distance = this->base_distance;
|
||||
if (this->mod_dist > 0) {
|
||||
const int32_t distance = DistanceMaxPlusManhattan(job[from_id].base.xy, job[to_id].base.xy);
|
||||
/* Scale distance around base_distance by (mod_dist * (100 / 1024)).
|
||||
* mod_dist may be > 1024, so clamp result to be non-negative */
|
||||
scaled_distance = std::max(0, this->base_distance + (((distance - this->base_distance) * this->mod_dist) / 1024));
|
||||
}
|
||||
|
||||
/* Scale the accuracy by distance around accuracy / 2 */
|
||||
int32_t divisor = this->accuracy * (this->mod_dist - 50) / 100 +
|
||||
this->accuracy * distance / this->max_distance + 1;
|
||||
|
||||
assert(divisor > 0);
|
||||
const int32_t divisor = divisor_scale + ((this->accuracy * scaled_distance * divisor_scale) / (this->base_distance * 2));
|
||||
assert(divisor >= divisor_scale);
|
||||
|
||||
uint demand_forw = 0;
|
||||
if (divisor <= supply) {
|
||||
if (divisor <= (supply * divisor_scale)) {
|
||||
/* At first only distribute demand if
|
||||
* effective supply / accuracy divisor >= 1
|
||||
* Others are too small or too far away to be considered. */
|
||||
demand_forw = supply / divisor;
|
||||
demand_forw = (supply * divisor_scale) / divisor;
|
||||
} else if (++chance > this->accuracy * num_demands * num_supplies) {
|
||||
/* After some trying, if there is still supply left, distribute
|
||||
* demand also to other nodes. */
|
||||
@@ -256,7 +260,7 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
|
||||
* @param job Job to calculate the demands for.
|
||||
*/
|
||||
DemandCalculator::DemandCalculator(LinkGraphJob &job) :
|
||||
max_distance(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(Map::MaxX(), Map::MaxY())))
|
||||
base_distance(IntSqrt(DistanceMaxPlusManhattan(TileXY(0,0), TileXY(Map::MaxX(), Map::MaxY()))))
|
||||
{
|
||||
const LinkGraphSettings &settings = job.Settings();
|
||||
CargoID cargo = job.Cargo();
|
||||
@@ -264,9 +268,15 @@ DemandCalculator::DemandCalculator(LinkGraphJob &job) :
|
||||
this->accuracy = settings.accuracy;
|
||||
this->mod_dist = settings.demand_distance;
|
||||
if (this->mod_dist > 100) {
|
||||
/* Increase effect of mod_dist > 100 */
|
||||
/* Increase effect of mod_dist > 100.
|
||||
* Quadratic:
|
||||
* 100 --> 100
|
||||
* 150 --> 308
|
||||
* 200 --> 933
|
||||
* 255 --> 2102
|
||||
*/
|
||||
int over100 = this->mod_dist - 100;
|
||||
this->mod_dist = 100 + over100 * over100;
|
||||
this->mod_dist = 100 + ((over100 * over100) / 12);
|
||||
}
|
||||
|
||||
switch (settings.GetDistributionType(cargo)) {
|
||||
|
||||
@@ -14,9 +14,9 @@ public:
|
||||
DemandCalculator(LinkGraphJob &job);
|
||||
|
||||
private:
|
||||
int32_t max_distance; ///< Maximum distance possible on the map.
|
||||
int32_t mod_dist; ///< Distance modifier, determines how much demands decrease with distance.
|
||||
int32_t accuracy; ///< Accuracy of 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.
|
||||
|
||||
template<class Tscaler>
|
||||
void CalcDemand(LinkGraphJob &job, Tscaler scaler);
|
||||
|
||||
@@ -115,7 +115,7 @@ void LinkGraphOverlay::RebuildCache()
|
||||
}
|
||||
}
|
||||
if (this->IsPointVisible(pta, &dpi)) {
|
||||
this->cached_stations.push_back(std::make_pair(from, supply));
|
||||
this->cached_stations.emplace_back(from, supply);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,7 +314,7 @@ void LinkGraphOverlay::DrawContent(Point pta, Point ptb, const LinkProperties &c
|
||||
GfxDrawLine(pta.x, pta.y + offset_y, ptb.x, ptb.y + offset_y, colour, width, dash);
|
||||
}
|
||||
|
||||
GfxDrawLine(pta.x, pta.y, ptb.x, ptb.y, _colour_gradient[COLOUR_GREY][1], width);
|
||||
GfxDrawLine(pta.x, pta.y, ptb.x, ptb.y, GetColourGradient(COLOUR_GREY, SHADE_DARKEST), width);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,9 +333,9 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
|
||||
uint r = width * 2 + width * 2 * std::min(200U, i.second) / 200;
|
||||
|
||||
LinkGraphOverlay::DrawVertex(pt.x, pt.y, r,
|
||||
_colour_gradient[st->owner != OWNER_NONE ?
|
||||
Company::Get(st->owner)->colour : COLOUR_GREY][5],
|
||||
_colour_gradient[COLOUR_GREY][1]);
|
||||
GetColourGradient(st->owner != OWNER_NONE ?
|
||||
Company::Get(st->owner)->colour : COLOUR_GREY, SHADE_LIGHT),
|
||||
GetColourGradient(COLOUR_GREY, SHADE_DARKEST));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
|
||||
* Draw a square symbolizing a producer of cargo.
|
||||
* @param x X coordinate of the middle of the vertex.
|
||||
* @param y Y coordinate of the middle of the vertex.
|
||||
* @param size Y and y extend of the vertex.
|
||||
* @param size x and y extent of the vertex.
|
||||
* @param colour Colour with which the vertex will be filled.
|
||||
* @param border_colour Colour for the border of the vertex.
|
||||
*/
|
||||
@@ -352,15 +352,10 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
|
||||
size--;
|
||||
int w1 = size / 2;
|
||||
int w2 = size / 2 + size % 2;
|
||||
int borderwidth = ScaleGUITrad(1);
|
||||
|
||||
GfxFillRect(x - w1 - borderwidth, y - w1 - borderwidth, x + w2 + borderwidth, y + w2 + borderwidth, border_colour);
|
||||
GfxFillRect(x - w1, y - w1, x + w2, y + w2, colour);
|
||||
|
||||
w1++;
|
||||
w2++;
|
||||
GfxDrawLine(x - w1, y - w1, x + w2, y - w1, border_colour);
|
||||
GfxDrawLine(x - w1, y + w2, x + w2, y + w2, border_colour);
|
||||
GfxDrawLine(x - w1, y - w1, x - w1, y + w2, border_colour);
|
||||
GfxDrawLine(x + w2, y - w1, x + w2, y + w2, border_colour);
|
||||
}
|
||||
|
||||
bool LinkGraphOverlay::ShowTooltip(Point pt, TooltipCloseCondition close_cond)
|
||||
@@ -401,7 +396,7 @@ bool LinkGraphOverlay::ShowTooltip(Point pt, TooltipCloseCondition close_cond)
|
||||
const auto time = link.time ? back_time ? ((link.time + back_time) / 2) : link.time : back_time;
|
||||
if (time > 0) {
|
||||
SetDParam(0, time);
|
||||
tooltip_extension += GetString(STR_LINKGRAPH_STATS_TOOLTIP_TIME_EXTENSION);
|
||||
AppendStringInPlace(tooltip_extension, STR_LINKGRAPH_STATS_TOOLTIP_TIME_EXTENSION);
|
||||
}
|
||||
SetDParam(0, link.cargo);
|
||||
SetDParam(1, link.Usage());
|
||||
@@ -543,11 +538,11 @@ static constexpr NWidgetPart _nested_linkgraph_legend_widgets[] = {
|
||||
static_assert(WID_LGL_SATURATION_LAST - WID_LGL_SATURATION_FIRST ==
|
||||
lengthof(LinkGraphOverlay::LINK_COLOURS[0]) - 1);
|
||||
|
||||
static WindowDesc _linkgraph_legend_desc(__FILE__, __LINE__,
|
||||
static WindowDesc _linkgraph_legend_desc(
|
||||
WDP_AUTO, "toolbar_linkgraph", 0, 0,
|
||||
WC_LINKGRAPH_LEGEND, WC_NONE,
|
||||
0,
|
||||
std::begin(_nested_linkgraph_legend_widgets), std::end(_nested_linkgraph_legend_widgets)
|
||||
_nested_linkgraph_legend_widgets
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -555,10 +550,10 @@ static WindowDesc _linkgraph_legend_desc(__FILE__, __LINE__,
|
||||
*/
|
||||
void ShowLinkGraphLegend()
|
||||
{
|
||||
AllocateWindowDescFront<LinkGraphLegendWindow>(&_linkgraph_legend_desc, 0);
|
||||
AllocateWindowDescFront<LinkGraphLegendWindow>(_linkgraph_legend_desc, 0);
|
||||
}
|
||||
|
||||
LinkGraphLegendWindow::LinkGraphLegendWindow(WindowDesc *desc, int window_number) : Window(desc)
|
||||
LinkGraphLegendWindow::LinkGraphLegendWindow(WindowDesc &desc, int window_number) : Window(desc)
|
||||
{
|
||||
this->num_cargo = _sorted_cargo_specs.size();
|
||||
|
||||
@@ -586,7 +581,7 @@ void LinkGraphLegendWindow::SetOverlay(std::shared_ptr<LinkGraphOverlay> overlay
|
||||
}
|
||||
}
|
||||
|
||||
void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize)
|
||||
void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize)
|
||||
{
|
||||
if (IsInsideMM(widget, WID_LGL_SATURATION_FIRST, WID_LGL_SATURATION_LAST + 1)) {
|
||||
StringID str = STR_NULL;
|
||||
@@ -601,7 +596,7 @@ void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension *size, [
|
||||
Dimension dim = GetStringBoundingBox(str, FS_SMALL);
|
||||
dim.width += padding.width;
|
||||
dim.height += padding.height;
|
||||
*size = maxdim(*size, dim);
|
||||
size = maxdim(size, dim);
|
||||
}
|
||||
}
|
||||
if (IsInsideMM(widget, WID_LGL_CARGO_FIRST, WID_LGL_CARGO_LAST + 1)) {
|
||||
@@ -609,7 +604,7 @@ void LinkGraphLegendWindow::UpdateWidgetSize(WidgetID widget, Dimension *size, [
|
||||
Dimension dim = GetStringBoundingBox(cargo->abbrev, FS_SMALL);
|
||||
dim.width += padding.width;
|
||||
dim.height += padding.height;
|
||||
*size = maxdim(*size, dim);
|
||||
size = maxdim(size, dim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
* @param scale Desired thickness of lines and size of station dots.
|
||||
*/
|
||||
LinkGraphOverlay(Window *w, WidgetID wid, CargoTypes cargo_mask, CompanyMask company_mask, uint scale) :
|
||||
window(w), widget_id(wid), cargo_mask(cargo_mask), company_mask(company_mask), scale(scale)
|
||||
window(w), widget_id(wid), cargo_mask(cargo_mask), company_mask(company_mask), scale(scale), dirty(true)
|
||||
{}
|
||||
|
||||
void Draw(const DrawPixelInfo *dpi);
|
||||
@@ -105,10 +105,10 @@ void ShowLinkGraphLegend();
|
||||
*/
|
||||
struct LinkGraphLegendWindow : Window {
|
||||
public:
|
||||
LinkGraphLegendWindow(WindowDesc *desc, int window_number);
|
||||
LinkGraphLegendWindow(WindowDesc &desc, int window_number);
|
||||
void SetOverlay(std::shared_ptr<LinkGraphOverlay> overlay);
|
||||
|
||||
void UpdateWidgetSize(WidgetID widget, Dimension *size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension *fill, [[maybe_unused]] Dimension *resize) override;
|
||||
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override;
|
||||
void DrawWidget(const Rect &r, WidgetID widget) const override;
|
||||
bool OnTooltip([[maybe_unused]] Point pt, WidgetID widget, TooltipCloseCondition close_cond) override;
|
||||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override;
|
||||
|
||||
@@ -19,7 +19,7 @@ static const LinkGraphJobID INVALID_LINK_GRAPH_JOB = UINT16_MAX;
|
||||
typedef uint16_t NodeID;
|
||||
static const NodeID INVALID_NODE = UINT16_MAX;
|
||||
|
||||
enum DistributionType : byte {
|
||||
enum DistributionType : uint8_t {
|
||||
DT_BEGIN = 0,
|
||||
DT_MIN = 0,
|
||||
DT_MANUAL = 0, ///< Manual distribution. No link graph calculations are run.
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
*/
|
||||
EdgeAnnotation &operator[](NodeID to)
|
||||
{
|
||||
auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
|
||||
auto it = std::ranges::find_if(this->edges, [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
|
||||
assert(it != this->edges.end());
|
||||
return *it;
|
||||
}
|
||||
@@ -113,7 +113,7 @@ public:
|
||||
*/
|
||||
const EdgeAnnotation &operator[](NodeID to) const
|
||||
{
|
||||
auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
|
||||
auto it = std::ranges::find_if(this->edges, [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
|
||||
assert(it != this->edges.end());
|
||||
return *it;
|
||||
}
|
||||
@@ -346,14 +346,12 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
/*
|
||||
* Some boundaries to clamp against in order to avoid integer overflows.
|
||||
*/
|
||||
enum PathCapacityBoundaries {
|
||||
PATH_CAP_MULTIPLIER = 16,
|
||||
PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER,
|
||||
PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER
|
||||
};
|
||||
static constexpr int PATH_CAP_MULTIPLIER = 16;
|
||||
static constexpr int PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER;
|
||||
static constexpr int PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER;
|
||||
|
||||
uint distance; ///< Sum(distance of all legs up to this one).
|
||||
uint capacity; ///< This capacity is min(capacity) fom all edges.
|
||||
|
||||
@@ -86,9 +86,9 @@ void LinkGraphSchedule::JoinNext()
|
||||
*/
|
||||
/* static */ void LinkGraphSchedule::Run(LinkGraphJob *job)
|
||||
{
|
||||
for (uint i = 0; i < lengthof(instance.handlers); ++i) {
|
||||
for (const auto &handler : instance.handlers) {
|
||||
if (job->IsJobAborted()) return;
|
||||
instance.handlers[i]->Run(*job);
|
||||
handler->Run(*job);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -143,12 +143,12 @@ void LinkGraphSchedule::ShiftDates(TimerGameEconomy::Date interval)
|
||||
*/
|
||||
LinkGraphSchedule::LinkGraphSchedule()
|
||||
{
|
||||
this->handlers[0] = new InitHandler;
|
||||
this->handlers[1] = new DemandHandler;
|
||||
this->handlers[2] = new MCFHandler<MCF1stPass>;
|
||||
this->handlers[3] = new FlowMapper(false);
|
||||
this->handlers[4] = new MCFHandler<MCF2ndPass>;
|
||||
this->handlers[5] = new FlowMapper(true);
|
||||
this->handlers[0] = std::make_unique<InitHandler>();
|
||||
this->handlers[1] = std::make_unique<DemandHandler>();
|
||||
this->handlers[2] = std::make_unique<MCFHandler<MCF1stPass>>();
|
||||
this->handlers[3] = std::make_unique<FlowMapper>(false);
|
||||
this->handlers[4] = std::make_unique<MCFHandler<MCF2ndPass>>();
|
||||
this->handlers[5] = std::make_unique<FlowMapper>(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,9 +157,6 @@ LinkGraphSchedule::LinkGraphSchedule()
|
||||
LinkGraphSchedule::~LinkGraphSchedule()
|
||||
{
|
||||
this->Clear();
|
||||
for (uint i = 0; i < lengthof(this->handlers); ++i) {
|
||||
delete this->handlers[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,7 @@ private:
|
||||
friend SaveLoadTable GetLinkGraphScheduleDesc();
|
||||
|
||||
protected:
|
||||
ComponentHandler *handlers[6]; ///< Handlers to be run for each job.
|
||||
std::array<std::unique_ptr<ComponentHandler>, 6> handlers{}; ///< Handlers to be run for each job.
|
||||
GraphList schedule; ///< Queue for new jobs.
|
||||
JobList running; ///< Currently running jobs.
|
||||
|
||||
|
||||
@@ -70,8 +70,6 @@ LinkRefresher::LinkRefresher(Vehicle *vehicle, HopSet *seen_hops, bool allow_mer
|
||||
vehicle(vehicle), seen_hops(seen_hops), cargo(INVALID_CARGO), allow_merge(allow_merge),
|
||||
is_full_loading(is_full_loading)
|
||||
{
|
||||
memset(this->capacities, 0, sizeof(this->capacities));
|
||||
|
||||
/* Assemble list of capacities and set last loading stations to 0. */
|
||||
for (Vehicle *v = this->vehicle; v != nullptr; v = v->Next()) {
|
||||
this->refit_capacities.push_back(RefitDesc(v->cargo_type, v->cargo_cap, v->refit_cap));
|
||||
@@ -102,7 +100,7 @@ bool LinkRefresher::HandleRefit(CargoID refit_cargo)
|
||||
|
||||
/* Back up the vehicle's cargo type */
|
||||
CargoID temp_cid = v->cargo_type;
|
||||
byte temp_subtype = v->cargo_subtype;
|
||||
uint8_t temp_subtype = v->cargo_subtype;
|
||||
v->cargo_type = this->cargo;
|
||||
v->cargo_subtype = GetBestFittingSubType(v, v, this->cargo);
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ protected:
|
||||
typedef std::set<Hop> HopSet;
|
||||
|
||||
Vehicle *vehicle; ///< Vehicle for which the links should be refreshed.
|
||||
uint capacities[NUM_CARGO]; ///< Current added capacities per cargo ID in the consist.
|
||||
CargoArray capacities{}; ///< Current added capacities per cargo ID in the consist.
|
||||
RefitList refit_capacities; ///< Current state of capacity remaining from previous refits versus overall capacity per vehicle in the consist.
|
||||
HopSet *seen_hops; ///< Hops already seen. If the same hop is seen twice we stop the algorithm. This is shared between all Refreshers of the same run.
|
||||
CargoID cargo; ///< Cargo given in last refit order.
|
||||
|
||||
Reference in New Issue
Block a user