FlowStatMap: Replace RB-tree with btree-indexed vector
This commit is contained in:
@@ -660,7 +660,7 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
|
|||||||
if (flow_it == ge->flows.end()) {
|
if (flow_it == ge->flows.end()) {
|
||||||
cargo_next = INVALID_STATION;
|
cargo_next = INVALID_STATION;
|
||||||
} else {
|
} else {
|
||||||
FlowStat new_shares = flow_it->second;
|
FlowStat new_shares = *flow_it;
|
||||||
new_shares.ChangeShare(current_station, INT_MIN);
|
new_shares.ChangeShare(current_station, INT_MIN);
|
||||||
StationIDStack excluded = next_station;
|
StationIDStack excluded = next_station;
|
||||||
while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
|
while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
|
||||||
@@ -676,20 +676,20 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
|
|||||||
/* Rewrite an invalid source station to some random other one to
|
/* Rewrite an invalid source station to some random other one to
|
||||||
* avoid keeping the cargo in the vehicle forever. */
|
* avoid keeping the cargo in the vehicle forever. */
|
||||||
if (cp->source == INVALID_STATION && !ge->flows.empty()) {
|
if (cp->source == INVALID_STATION && !ge->flows.empty()) {
|
||||||
cp->source = ge->flows.begin()->first;
|
cp->source = ge->flows.FirstStationID();
|
||||||
}
|
}
|
||||||
bool restricted = false;
|
bool restricted = false;
|
||||||
FlowStatMap::const_iterator flow_it(ge->flows.find(cp->source));
|
FlowStatMap::const_iterator flow_it(ge->flows.find(cp->source));
|
||||||
if (flow_it == ge->flows.end()) {
|
if (flow_it == ge->flows.end()) {
|
||||||
cargo_next = INVALID_STATION;
|
cargo_next = INVALID_STATION;
|
||||||
} else {
|
} else {
|
||||||
cargo_next = flow_it->second.GetViaWithRestricted(restricted);
|
cargo_next = flow_it->GetViaWithRestricted(restricted);
|
||||||
}
|
}
|
||||||
action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
|
action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
|
||||||
if (restricted && action == MTA_TRANSFER) {
|
if (restricted && action == MTA_TRANSFER) {
|
||||||
/* If the flow is restricted we can't transfer to it. Choose an
|
/* If the flow is restricted we can't transfer to it. Choose an
|
||||||
* unrestricted one instead. */
|
* unrestricted one instead. */
|
||||||
cargo_next = flow_it->second.GetVia();
|
cargo_next = flow_it->GetVia();
|
||||||
action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
|
action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -57,7 +57,7 @@ void FlowMapper::Run(LinkGraphJob &job) const
|
|||||||
* LinkGraph::Monthly(). */
|
* LinkGraph::Monthly(). */
|
||||||
uint runtime = (job.StartDateTicks() / DAY_TICKS) - job.LastCompression() + 1;
|
uint runtime = (job.StartDateTicks() / DAY_TICKS) - job.LastCompression() + 1;
|
||||||
for (FlowStatMap::iterator i = flows.begin(); i != flows.end(); ++i) {
|
for (FlowStatMap::iterator i = flows.begin(); i != flows.end(); ++i) {
|
||||||
i->second.ScaleToMonthly(runtime);
|
i->ScaleToMonthly(runtime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Clear paths. */
|
/* Clear paths. */
|
||||||
|
@@ -146,27 +146,30 @@ void LinkGraphJob::FinaliseJob()
|
|||||||
* somewhere. Do delete them and also reroute relevant cargo if
|
* somewhere. Do delete them and also reroute relevant cargo if
|
||||||
* automatic distribution has been turned off for that cargo. */
|
* automatic distribution has been turned off for that cargo. */
|
||||||
for (FlowStatMap::iterator it(ge.flows.begin()); it != ge.flows.end();) {
|
for (FlowStatMap::iterator it(ge.flows.begin()); it != ge.flows.end();) {
|
||||||
FlowStatMap::iterator new_it = flows.find(it->first);
|
FlowStatMap::iterator new_it = flows.find(it->GetOrigin());
|
||||||
if (new_it == flows.end()) {
|
if (new_it == flows.end()) {
|
||||||
if (_settings_game.linkgraph.GetDistributionType(this->Cargo()) != DT_MANUAL) {
|
if (_settings_game.linkgraph.GetDistributionType(this->Cargo()) != DT_MANUAL) {
|
||||||
it->second.Invalidate();
|
it->Invalidate();
|
||||||
++it;
|
++it;
|
||||||
} else {
|
} else {
|
||||||
FlowStat shares(INVALID_STATION, 1);
|
FlowStat shares(INVALID_STATION, INVALID_STATION, 1);
|
||||||
it->second.SwapShares(shares);
|
it->SwapShares(shares);
|
||||||
ge.flows.erase(it++);
|
it = ge.flows.erase(it);
|
||||||
for (FlowStat::SharesMap::const_iterator shares_it(shares.GetShares()->begin());
|
for (FlowStat::SharesMap::const_iterator shares_it(shares.GetShares()->begin());
|
||||||
shares_it != shares.GetShares()->end(); ++shares_it) {
|
shares_it != shares.GetShares()->end(); ++shares_it) {
|
||||||
RerouteCargo(st, this->Cargo(), shares_it->second, st->index);
|
RerouteCargo(st, this->Cargo(), shares_it->second, st->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
it->second.SwapShares(new_it->second);
|
it->SwapShares(*new_it);
|
||||||
flows.erase(new_it);
|
flows.erase(new_it);
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ge.flows.insert(flows.begin(), flows.end());
|
for (FlowStatMap::iterator it(flows.begin()); it != flows.end(); ++it) {
|
||||||
|
ge.flows.insert(std::move(*it));
|
||||||
|
}
|
||||||
|
ge.flows.SortStorage();
|
||||||
InvalidateWindowData(WC_STATION_VIEW, st->index, this->Cargo());
|
InvalidateWindowData(WC_STATION_VIEW, st->index, this->Cargo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -187,8 +187,8 @@ public:
|
|||||||
const FlowStatMap &flows = this->job[node].Flows();
|
const FlowStatMap &flows = this->job[node].Flows();
|
||||||
FlowStatMap::const_iterator it = flows.find(this->job[source].Station());
|
FlowStatMap::const_iterator it = flows.find(this->job[source].Station());
|
||||||
if (it != flows.end()) {
|
if (it != flows.end()) {
|
||||||
this->it = it->second.GetShares()->begin();
|
this->it = it->GetShares()->begin();
|
||||||
this->end = it->second.GetShares()->end();
|
this->end = it->GetShares()->end();
|
||||||
} else {
|
} else {
|
||||||
this->it = FlowStat::empty_sharesmap.begin();
|
this->it = FlowStat::empty_sharesmap.begin();
|
||||||
this->end = FlowStat::empty_sharesmap.end();
|
this->end = FlowStat::empty_sharesmap.end();
|
||||||
|
@@ -523,18 +523,18 @@ static void RealSave_STNN(BaseStation *bst)
|
|||||||
_num_dests = (uint32)st->goods[i].cargo.Packets()->MapSize();
|
_num_dests = (uint32)st->goods[i].cargo.Packets()->MapSize();
|
||||||
_num_flows = 0;
|
_num_flows = 0;
|
||||||
for (FlowStatMap::const_iterator it(st->goods[i].flows.begin()); it != st->goods[i].flows.end(); ++it) {
|
for (FlowStatMap::const_iterator it(st->goods[i].flows.begin()); it != st->goods[i].flows.end(); ++it) {
|
||||||
_num_flows += (uint32)it->second.GetShares()->size();
|
_num_flows += (uint32)it->GetShares()->size();
|
||||||
}
|
}
|
||||||
SlObjectSaveFiltered(&st->goods[i], _filtered_goods_desc.data());
|
SlObjectSaveFiltered(&st->goods[i], _filtered_goods_desc.data());
|
||||||
for (FlowStatMap::const_iterator outer_it(st->goods[i].flows.begin()); outer_it != st->goods[i].flows.end(); ++outer_it) {
|
for (FlowStatMap::const_iterator outer_it(st->goods[i].flows.begin()); outer_it != st->goods[i].flows.end(); ++outer_it) {
|
||||||
const FlowStat::SharesMap *shares = outer_it->second.GetShares();
|
const FlowStat::SharesMap *shares = outer_it->GetShares();
|
||||||
uint32 sum_shares = 0;
|
uint32 sum_shares = 0;
|
||||||
FlowSaveLoad flow;
|
FlowSaveLoad flow;
|
||||||
flow.source = outer_it->first;
|
flow.source = outer_it->GetOrigin();
|
||||||
for (FlowStat::SharesMap::const_iterator inner_it(shares->begin()); inner_it != shares->end(); ++inner_it) {
|
for (FlowStat::SharesMap::const_iterator inner_it(shares->begin()); inner_it != shares->end(); ++inner_it) {
|
||||||
flow.via = inner_it->second;
|
flow.via = inner_it->second;
|
||||||
flow.share = inner_it->first - sum_shares;
|
flow.share = inner_it->first - sum_shares;
|
||||||
flow.restricted = inner_it->first > outer_it->second.GetUnrestricted();
|
flow.restricted = inner_it->first > outer_it->GetUnrestricted();
|
||||||
sum_shares = inner_it->first;
|
sum_shares = inner_it->first;
|
||||||
assert(flow.share > 0);
|
assert(flow.share > 0);
|
||||||
|
|
||||||
@@ -610,7 +610,7 @@ static void Load_STNN()
|
|||||||
if (!IsSavegameVersionBefore(SLV_187)) flow.restricted = (buffer->ReadByte() != 0);
|
if (!IsSavegameVersionBefore(SLV_187)) flow.restricted = (buffer->ReadByte() != 0);
|
||||||
|
|
||||||
if (fs == nullptr || prev_source != flow.source) {
|
if (fs == nullptr || prev_source != flow.source) {
|
||||||
fs = &(st->goods[i].flows.insert(st->goods[i].flows.end(), std::make_pair(flow.source, FlowStat(flow.via, flow.share, flow.restricted)))->second);
|
fs = &(*(st->goods[i].flows.insert(st->goods[i].flows.end(), FlowStat(flow.source, flow.via, flow.share, flow.restricted))));
|
||||||
} else {
|
} else {
|
||||||
fs->AppendShare(flow.via, flow.share, flow.restricted);
|
fs->AppendShare(flow.via, flow.share, flow.restricted);
|
||||||
}
|
}
|
||||||
|
@@ -195,11 +195,11 @@ void ScriptStationList_CargoPlanned::Add(StationID station_id, CargoID cargo, St
|
|||||||
FlowStatMap::const_iterator iter = collector.GE()->flows.begin();
|
FlowStatMap::const_iterator iter = collector.GE()->flows.begin();
|
||||||
FlowStatMap::const_iterator end = collector.GE()->flows.end();
|
FlowStatMap::const_iterator end = collector.GE()->flows.end();
|
||||||
for (; iter != end; ++iter) {
|
for (; iter != end; ++iter) {
|
||||||
const FlowStat::SharesMap *shares = iter->second.GetShares();
|
const FlowStat::SharesMap *shares = iter->GetShares();
|
||||||
uint prev = 0;
|
uint prev = 0;
|
||||||
for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin();
|
for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin();
|
||||||
flow_iter != shares->end(); ++flow_iter) {
|
flow_iter != shares->end(); ++flow_iter) {
|
||||||
collector.Update<Tselector>(iter->first, flow_iter->second, flow_iter->first - prev);
|
collector.Update<Tselector>(iter->GetOrigin(), flow_iter->second, flow_iter->first - prev);
|
||||||
prev = flow_iter->first;
|
prev = flow_iter->first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,11 +265,11 @@ ScriptStationList_CargoPlannedFromByVia::ScriptStationList_CargoPlannedFromByVia
|
|||||||
|
|
||||||
FlowStatMap::const_iterator iter = collector.GE()->flows.find(from);
|
FlowStatMap::const_iterator iter = collector.GE()->flows.find(from);
|
||||||
if (iter == collector.GE()->flows.end()) return;
|
if (iter == collector.GE()->flows.end()) return;
|
||||||
const FlowStat::SharesMap *shares = iter->second.GetShares();
|
const FlowStat::SharesMap *shares = iter->GetShares();
|
||||||
uint prev = 0;
|
uint prev = 0;
|
||||||
for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin();
|
for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin();
|
||||||
flow_iter != shares->end(); ++flow_iter) {
|
flow_iter != shares->end(); ++flow_iter) {
|
||||||
collector.Update<CS_FROM_BY_VIA>(iter->first, flow_iter->second, flow_iter->first - prev);
|
collector.Update<CS_FROM_BY_VIA>(iter->GetOrigin(), flow_iter->second, flow_iter->first - prev);
|
||||||
prev = flow_iter->first;
|
prev = flow_iter->first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,12 +24,16 @@
|
|||||||
#include "bitmap_type.h"
|
#include "bitmap_type.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
|
typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
|
||||||
extern StationPool _station_pool;
|
extern StationPool _station_pool;
|
||||||
|
|
||||||
static const byte INITIAL_STATION_RATING = 175;
|
static const byte INITIAL_STATION_RATING = 175;
|
||||||
|
|
||||||
|
class FlowStatMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flow statistics telling how much flow should be sent along a link. This is
|
* Flow statistics telling how much flow should be sent along a link. This is
|
||||||
* done by creating "flow shares" and using std::map's upper_bound() method to
|
* done by creating "flow shares" and using std::map's upper_bound() method to
|
||||||
@@ -38,6 +42,7 @@ static const byte INITIAL_STATION_RATING = 175;
|
|||||||
* mean anything by itself.
|
* mean anything by itself.
|
||||||
*/
|
*/
|
||||||
class FlowStat {
|
class FlowStat {
|
||||||
|
friend FlowStatMap;
|
||||||
public:
|
public:
|
||||||
typedef btree::btree_map<uint32, StationID> SharesMap;
|
typedef btree::btree_map<uint32, StationID> SharesMap;
|
||||||
|
|
||||||
@@ -52,15 +57,17 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a FlowStat with an initial entry.
|
* Create a FlowStat with an initial entry.
|
||||||
* @param st Station the initial entry refers to.
|
* @param origin Origin station for this flow.
|
||||||
|
* @param via Station the initial entry refers to.
|
||||||
* @param flow Amount of flow for the initial entry.
|
* @param flow Amount of flow for the initial entry.
|
||||||
* @param restricted If the flow to be added is restricted.
|
* @param restricted If the flow to be added is restricted.
|
||||||
*/
|
*/
|
||||||
inline FlowStat(StationID st, uint flow, bool restricted = false)
|
inline FlowStat(StationID origin, StationID via, uint flow, bool restricted = false)
|
||||||
{
|
{
|
||||||
assert(flow > 0);
|
assert(flow > 0);
|
||||||
this->shares[flow] = st;
|
this->shares[flow] = via;
|
||||||
this->unrestricted = restricted ? 0 : flow;
|
this->unrestricted = restricted ? 0 : flow;
|
||||||
|
this->origin = origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,14 +155,66 @@ public:
|
|||||||
|
|
||||||
void Invalidate();
|
void Invalidate();
|
||||||
|
|
||||||
|
inline StationID GetOrigin() const
|
||||||
|
{
|
||||||
|
return this->origin;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharesMap shares; ///< Shares of flow to be sent via specified station (or consumed locally).
|
SharesMap shares; ///< Shares of flow to be sent via specified station (or consumed locally).
|
||||||
uint unrestricted; ///< Limit for unrestricted shares.
|
uint unrestricted; ///< Limit for unrestricted shares.
|
||||||
|
StationID origin;
|
||||||
|
};
|
||||||
|
static_assert(std::is_nothrow_move_constructible<FlowStat>::value, "FlowStat must be nothrow move constructible");
|
||||||
|
|
||||||
|
template<typename cv_value, typename cv_container, typename cv_index_iter>
|
||||||
|
class FlowStatMapIterator
|
||||||
|
{
|
||||||
|
friend FlowStatMap;
|
||||||
|
friend FlowStatMapIterator<FlowStat, FlowStatMap, btree::btree_map<StationID, uint16>::iterator>;
|
||||||
|
friend FlowStatMapIterator<const FlowStat, const FlowStatMap, btree::btree_map<StationID, uint16>::const_iterator>;
|
||||||
|
public:
|
||||||
|
typedef FlowStat value_type;
|
||||||
|
typedef cv_value& reference;
|
||||||
|
typedef cv_value* pointer;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
|
||||||
|
FlowStatMapIterator(cv_container *fsm, cv_index_iter current) :
|
||||||
|
fsm(fsm), current(current) {}
|
||||||
|
|
||||||
|
FlowStatMapIterator(const FlowStatMapIterator<FlowStat, FlowStatMap, btree::btree_map<StationID, uint16>::iterator> &other) :
|
||||||
|
fsm(other.fsm), current(other.current) {}
|
||||||
|
|
||||||
|
reference operator*() const { return this->fsm->flows_storage[this->current->second]; }
|
||||||
|
pointer operator->() const { return &(this->fsm->flows_storage[this->current->second]); }
|
||||||
|
|
||||||
|
FlowStatMapIterator& operator++()
|
||||||
|
{
|
||||||
|
++this->current;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const FlowStatMapIterator& rhs) const { return this->current == rhs.current; }
|
||||||
|
bool operator!=(const FlowStatMapIterator& rhs) const { return !(operator==(rhs)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
cv_container *fsm;
|
||||||
|
cv_index_iter current;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Flow descriptions by origin stations. */
|
/** Flow descriptions by origin stations. */
|
||||||
class FlowStatMap : public std::map<StationID, FlowStat> {
|
class FlowStatMap {
|
||||||
|
std::vector<FlowStat> flows_storage;
|
||||||
|
btree::btree_map<StationID, uint16> flows_index;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using iterator = FlowStatMapIterator<FlowStat, FlowStatMap, btree::btree_map<StationID, uint16>::iterator>;
|
||||||
|
using const_iterator = FlowStatMapIterator<const FlowStat, const FlowStatMap, btree::btree_map<StationID, uint16>::const_iterator>;
|
||||||
|
|
||||||
|
friend iterator;
|
||||||
|
friend const_iterator;
|
||||||
|
|
||||||
uint GetFlow() const;
|
uint GetFlow() const;
|
||||||
uint GetFlowVia(StationID via) const;
|
uint GetFlowVia(StationID via) const;
|
||||||
uint GetFlowFrom(StationID from) const;
|
uint GetFlowFrom(StationID from) const;
|
||||||
@@ -167,6 +226,78 @@ public:
|
|||||||
void RestrictFlows(StationID via);
|
void RestrictFlows(StationID via);
|
||||||
void ReleaseFlows(StationID via);
|
void ReleaseFlows(StationID via);
|
||||||
void FinalizeLocalConsumption(StationID self);
|
void FinalizeLocalConsumption(StationID self);
|
||||||
|
|
||||||
|
private:
|
||||||
|
btree::btree_map<StationID, uint16>::iterator erase_priv(btree::btree_map<StationID, uint16>::iterator iter)
|
||||||
|
{
|
||||||
|
uint16 index = iter->second;
|
||||||
|
iter = this->flows_index.erase(iter);
|
||||||
|
if (index != this->flows_storage.size() - 1) {
|
||||||
|
this->flows_storage[index] = std::move(this->flows_storage.back());
|
||||||
|
this->flows_index[this->flows_storage[index].GetOrigin()] = index;
|
||||||
|
}
|
||||||
|
this->flows_storage.pop_back();
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
iterator begin() { return iterator(this, this->flows_index.begin()); }
|
||||||
|
const_iterator begin() const { return const_iterator(this, this->flows_index.begin()); }
|
||||||
|
iterator end() { return iterator(this, this->flows_index.end()); }
|
||||||
|
const_iterator end() const { return const_iterator(this, this->flows_index.end()); }
|
||||||
|
|
||||||
|
iterator find(StationID from)
|
||||||
|
{
|
||||||
|
return iterator(this, this->flows_index.find(from));
|
||||||
|
}
|
||||||
|
const_iterator find(StationID from) const
|
||||||
|
{
|
||||||
|
return const_iterator(this, this->flows_index.find(from));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return this->flows_index.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase(StationID st)
|
||||||
|
{
|
||||||
|
auto iter = this->flows_index.find(st);
|
||||||
|
if (iter != this->flows_index.end()) {
|
||||||
|
this->erase_priv(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator erase(iterator iter)
|
||||||
|
{
|
||||||
|
return iterator(this, this->erase_priv(iter.current));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, bool> insert(FlowStat flow_stat)
|
||||||
|
{
|
||||||
|
StationID st = flow_stat.GetOrigin();
|
||||||
|
auto res = this->flows_index.insert(std::pair<StationID, uint16>(st, this->flows_storage.size()));
|
||||||
|
if (res.second) {
|
||||||
|
this->flows_storage.push_back(std::move(flow_stat));
|
||||||
|
}
|
||||||
|
return std::make_pair(iterator(this, res.first), res.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator insert(iterator hint, FlowStat flow_stat)
|
||||||
|
{
|
||||||
|
auto res = this->flows_index.insert(hint.current, std::pair<StationID, uint16>(flow_stat.GetOrigin(), this->flows_storage.size()));
|
||||||
|
if (res->second == this->flows_storage.size()) {
|
||||||
|
this->flows_storage.push_back(std::move(flow_stat));
|
||||||
|
}
|
||||||
|
return iterator(this, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
StationID FirstStationID() const
|
||||||
|
{
|
||||||
|
return this->flows_index.begin()->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SortStorage();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -291,7 +422,7 @@ struct GoodsEntry {
|
|||||||
inline StationID GetVia(StationID source) const
|
inline StationID GetVia(StationID source) const
|
||||||
{
|
{
|
||||||
FlowStatMap::const_iterator flow_it(this->flows.find(source));
|
FlowStatMap::const_iterator flow_it(this->flows.find(source));
|
||||||
return flow_it != this->flows.end() ? flow_it->second.GetVia() : INVALID_STATION;
|
return flow_it != this->flows.end() ? flow_it->GetVia() : INVALID_STATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -305,7 +436,7 @@ struct GoodsEntry {
|
|||||||
inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
|
inline StationID GetVia(StationID source, StationID excluded, StationID excluded2 = INVALID_STATION) const
|
||||||
{
|
{
|
||||||
FlowStatMap::const_iterator flow_it(this->flows.find(source));
|
FlowStatMap::const_iterator flow_it(this->flows.find(source));
|
||||||
return flow_it != this->flows.end() ? flow_it->second.GetVia(excluded, excluded2) : INVALID_STATION;
|
return flow_it != this->flows.end() ? flow_it->GetVia(excluded, excluded2) : INVALID_STATION;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -4866,10 +4866,10 @@ void FlowStatMap::AddFlow(StationID origin, StationID via, uint flow)
|
|||||||
{
|
{
|
||||||
FlowStatMap::iterator origin_it = this->find(origin);
|
FlowStatMap::iterator origin_it = this->find(origin);
|
||||||
if (origin_it == this->end()) {
|
if (origin_it == this->end()) {
|
||||||
this->insert(std::make_pair(origin, FlowStat(via, flow)));
|
this->insert(FlowStat(origin, via, flow));
|
||||||
} else {
|
} else {
|
||||||
origin_it->second.ChangeShare(via, flow);
|
origin_it->ChangeShare(via, flow);
|
||||||
assert(!origin_it->second.GetShares()->empty());
|
assert(!origin_it->GetShares()->empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4885,13 +4885,13 @@ void FlowStatMap::PassOnFlow(StationID origin, StationID via, uint flow)
|
|||||||
{
|
{
|
||||||
FlowStatMap::iterator prev_it = this->find(origin);
|
FlowStatMap::iterator prev_it = this->find(origin);
|
||||||
if (prev_it == this->end()) {
|
if (prev_it == this->end()) {
|
||||||
FlowStat fs(via, flow);
|
FlowStat fs(origin, via, flow);
|
||||||
fs.AppendShare(INVALID_STATION, flow);
|
fs.AppendShare(INVALID_STATION, flow);
|
||||||
this->insert(std::make_pair(origin, fs));
|
this->insert(std::move(fs));
|
||||||
} else {
|
} else {
|
||||||
prev_it->second.ChangeShare(via, flow);
|
prev_it->ChangeShare(via, flow);
|
||||||
prev_it->second.ChangeShare(INVALID_STATION, flow);
|
prev_it->ChangeShare(INVALID_STATION, flow);
|
||||||
assert(!prev_it->second.GetShares()->empty());
|
assert(!prev_it->GetShares()->empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4902,7 +4902,7 @@ void FlowStatMap::PassOnFlow(StationID origin, StationID via, uint flow)
|
|||||||
void FlowStatMap::FinalizeLocalConsumption(StationID self)
|
void FlowStatMap::FinalizeLocalConsumption(StationID self)
|
||||||
{
|
{
|
||||||
for (FlowStatMap::iterator i = this->begin(); i != this->end(); ++i) {
|
for (FlowStatMap::iterator i = this->begin(); i != this->end(); ++i) {
|
||||||
FlowStat &fs = i->second;
|
FlowStat &fs = *i;
|
||||||
uint local = fs.GetShare(INVALID_STATION);
|
uint local = fs.GetShare(INVALID_STATION);
|
||||||
if (local > INT_MAX) { // make sure it fits in an int
|
if (local > INT_MAX) { // make sure it fits in an int
|
||||||
fs.ChangeShare(self, -INT_MAX);
|
fs.ChangeShare(self, -INT_MAX);
|
||||||
@@ -4928,11 +4928,11 @@ StationIDStack FlowStatMap::DeleteFlows(StationID via)
|
|||||||
{
|
{
|
||||||
StationIDStack ret;
|
StationIDStack ret;
|
||||||
for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) {
|
for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) {
|
||||||
FlowStat &s_flows = f_it->second;
|
FlowStat &s_flows = *f_it;
|
||||||
s_flows.ChangeShare(via, INT_MIN);
|
s_flows.ChangeShare(via, INT_MIN);
|
||||||
if (s_flows.GetShares()->empty()) {
|
if (s_flows.GetShares()->empty()) {
|
||||||
ret.Push(f_it->first);
|
ret.Push(f_it->GetOrigin());
|
||||||
this->erase(f_it++);
|
f_it = this->erase(f_it);
|
||||||
} else {
|
} else {
|
||||||
++f_it;
|
++f_it;
|
||||||
}
|
}
|
||||||
@@ -4947,7 +4947,7 @@ StationIDStack FlowStatMap::DeleteFlows(StationID via)
|
|||||||
void FlowStatMap::RestrictFlows(StationID via)
|
void FlowStatMap::RestrictFlows(StationID via)
|
||||||
{
|
{
|
||||||
for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
|
for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
|
||||||
it->second.RestrictShare(via);
|
it->RestrictShare(via);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4958,7 +4958,7 @@ void FlowStatMap::RestrictFlows(StationID via)
|
|||||||
void FlowStatMap::ReleaseFlows(StationID via)
|
void FlowStatMap::ReleaseFlows(StationID via)
|
||||||
{
|
{
|
||||||
for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
|
for (FlowStatMap::iterator it = this->begin(); it != this->end(); ++it) {
|
||||||
it->second.ReleaseShare(via);
|
it->ReleaseShare(via);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4970,7 +4970,7 @@ uint FlowStatMap::GetFlow() const
|
|||||||
{
|
{
|
||||||
uint ret = 0;
|
uint ret = 0;
|
||||||
for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
|
for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
|
||||||
ret += (--(i->second.GetShares()->end()))->first;
|
ret += (--(i->GetShares()->end()))->first;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -4984,7 +4984,7 @@ uint FlowStatMap::GetFlowVia(StationID via) const
|
|||||||
{
|
{
|
||||||
uint ret = 0;
|
uint ret = 0;
|
||||||
for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
|
for (FlowStatMap::const_iterator i = this->begin(); i != this->end(); ++i) {
|
||||||
ret += i->second.GetShare(via);
|
ret += i->GetShare(via);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -4998,7 +4998,7 @@ uint FlowStatMap::GetFlowFrom(StationID from) const
|
|||||||
{
|
{
|
||||||
FlowStatMap::const_iterator i = this->find(from);
|
FlowStatMap::const_iterator i = this->find(from);
|
||||||
if (i == this->end()) return 0;
|
if (i == this->end()) return 0;
|
||||||
return (--(i->second.GetShares()->end()))->first;
|
return (--(i->GetShares()->end()))->first;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5011,7 +5011,20 @@ uint FlowStatMap::GetFlowFromVia(StationID from, StationID via) const
|
|||||||
{
|
{
|
||||||
FlowStatMap::const_iterator i = this->find(from);
|
FlowStatMap::const_iterator i = this->find(from);
|
||||||
if (i == this->end()) return 0;
|
if (i == this->end()) return 0;
|
||||||
return i->second.GetShare(via);
|
return i->GetShare(via);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlowStatMap::SortStorage()
|
||||||
|
{
|
||||||
|
assert(this->flows_storage.size() == this->flows_index.size());
|
||||||
|
std::sort(this->flows_storage.begin(), this->flows_storage.end(), [](const FlowStat &a, const FlowStat &b) -> bool {
|
||||||
|
return a.origin < b.origin;
|
||||||
|
});
|
||||||
|
uint16 index = 0;
|
||||||
|
for (auto &it : this->flows_index) {
|
||||||
|
it.second = index;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern const TileTypeProcs _tile_type_station_procs = {
|
extern const TileTypeProcs _tile_type_station_procs = {
|
||||||
|
@@ -1513,9 +1513,9 @@ struct StationViewWindow : public Window {
|
|||||||
|
|
||||||
const FlowStatMap &flows = st->goods[i].flows;
|
const FlowStatMap &flows = st->goods[i].flows;
|
||||||
for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) {
|
for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) {
|
||||||
StationID from = it->first;
|
StationID from = it->GetOrigin();
|
||||||
CargoDataEntry *source_entry = cargo_entry->InsertOrRetrieve(from);
|
CargoDataEntry *source_entry = cargo_entry->InsertOrRetrieve(from);
|
||||||
const FlowStat::SharesMap *shares = it->second.GetShares();
|
const FlowStat::SharesMap *shares = it->GetShares();
|
||||||
uint32 prev_count = 0;
|
uint32 prev_count = 0;
|
||||||
for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) {
|
for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) {
|
||||||
StationID via = flow_it->second;
|
StationID via = flow_it->second;
|
||||||
@@ -1546,7 +1546,7 @@ struct StationViewWindow : public Window {
|
|||||||
const FlowStatMap &flowmap = Station::Get(next)->goods[cargo].flows;
|
const FlowStatMap &flowmap = Station::Get(next)->goods[cargo].flows;
|
||||||
FlowStatMap::const_iterator map_it = flowmap.find(source);
|
FlowStatMap::const_iterator map_it = flowmap.find(source);
|
||||||
if (map_it != flowmap.end()) {
|
if (map_it != flowmap.end()) {
|
||||||
const FlowStat::SharesMap *shares = map_it->second.GetShares();
|
const FlowStat::SharesMap *shares = map_it->GetShares();
|
||||||
uint32 prev_count = 0;
|
uint32 prev_count = 0;
|
||||||
for (FlowStat::SharesMap::const_iterator i = shares->begin(); i != shares->end(); ++i) {
|
for (FlowStat::SharesMap::const_iterator i = shares->begin(); i != shares->end(); ++i) {
|
||||||
tmp.InsertOrRetrieve(i->second)->Update(i->first - prev_count);
|
tmp.InsertOrRetrieve(i->second)->Update(i->first - prev_count);
|
||||||
@@ -1596,9 +1596,9 @@ struct StationViewWindow : public Window {
|
|||||||
{
|
{
|
||||||
const CargoDataEntry *source_dest = this->cached_destinations.Retrieve(i);
|
const CargoDataEntry *source_dest = this->cached_destinations.Retrieve(i);
|
||||||
for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) {
|
for (FlowStatMap::const_iterator it = flows.begin(); it != flows.end(); ++it) {
|
||||||
StationID from = it->first;
|
StationID from = it->GetOrigin();
|
||||||
const CargoDataEntry *source_entry = source_dest->Retrieve(from);
|
const CargoDataEntry *source_entry = source_dest->Retrieve(from);
|
||||||
const FlowStat::SharesMap *shares = it->second.GetShares();
|
const FlowStat::SharesMap *shares = it->GetShares();
|
||||||
for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) {
|
for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) {
|
||||||
const CargoDataEntry *via_entry = source_entry->Retrieve(flow_it->second);
|
const CargoDataEntry *via_entry = source_entry->Retrieve(flow_it->second);
|
||||||
for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End(); ++dest_it) {
|
for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End(); ++dest_it) {
|
||||||
|
Reference in New Issue
Block a user