diff options
Diffstat (limited to 'src/station_base.h')
-rw-r--r-- | src/station_base.h | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/src/station_base.h b/src/station_base.h index 974caa063..200d97a97 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -12,12 +12,14 @@ #ifndef STATION_BASE_H #define STATION_BASE_H +#include "core/random_func.hpp" #include "base_station_base.h" #include "newgrf_airport.h" #include "cargopacket.h" #include "industry_type.h" #include "linkgraph/linkgraph_type.h" #include "newgrf_storage.h" +#include <map> typedef Pool<BaseStation, StationID, 32, 64000> StationPool; extern StationPool _station_pool; @@ -25,6 +27,87 @@ extern StationPool _station_pool; static const byte INITIAL_STATION_RATING = 175; /** + * 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 + * look them up with a random number. A flow share is the difference between a + * key in a map and the previous key. So one key in the map doesn't actually + * mean anything by itself. + */ +class FlowStat { +public: + typedef std::map<uint32, StationID> SharesMap; + + /** + * Invalid constructor. This can't be called as a FlowStat must not be + * empty. However, the constructor must be defined and reachable for + * FlwoStat to be used in a std::map. + */ + inline FlowStat() {NOT_REACHED();} + + /** + * Create a FlowStat with an initial entry. + * @param st Station the initial entry refers to. + * @param flow Amount of flow for the initial entry. + */ + inline FlowStat(StationID st, uint flow) + { + assert(flow > 0); + this->shares[flow] = st; + } + + /** + * Add some flow to the end of the shares map. Only do that if you know + * that the station isn't in the map yet. Anything else may lead to + * inconsistencies. + * @param st Remote station. + * @param flow Amount of flow to be added. + */ + inline void AppendShare(StationID st, uint flow) + { + assert(flow > 0); + this->shares[(--this->shares.end())->first + flow] = st; + } + + uint GetShare(StationID st) const; + + void ChangeShare(StationID st, int flow); + + /** + * Get the actual shares as a const pointer so that they can be iterated + * over. + * @return Actual shares. + */ + inline const SharesMap *GetShares() const { return &this->shares; } + + /** + * Get a station a package can be routed to. This done by drawing a + * random number between 0 and sum_shares and then looking that up in + * the map with lower_bound. So each share gets selected with a + * probability dependent on its flow. + * @return A station ID from the shares map. + */ + inline StationID GetVia() const + { + assert(!this->shares.empty()); + return this->shares.upper_bound(RandomRange((--this->shares.end())->first - 1))->second; + } + + StationID GetVia(StationID excluded, StationID excluded2 = INVALID_STATION) const; + +private: + SharesMap shares; ///< Shares of flow to be sent via specified station (or consumed locally). +}; + +/** Flow descriptions by origin stations. */ +class FlowStatMap : public std::map<StationID, FlowStat> { +public: + void AddFlow(StationID origin, StationID via, uint amount); + void PassOnFlow(StationID origin, StationID via, uint amount); + void DeleteFlows(StationID via); + void FinalizeLocalConsumption(StationID self); +}; + +/** * Stores station stats for a single cargo. */ struct GoodsEntry { |