1 #ifndef _ProductionQueue_h_
2 #define _ProductionQueue_h_
3 
4 #include "../util/Export.h"
5 #include "../universe/Enums.h"
6 
7 #include <deque>
8 #include <map>
9 #include <memory>
10 #include <set>
11 #include <string>
12 #include <boost/serialization/access.hpp>
13 #include <boost/signals2/signal.hpp>
14 #include <boost/uuid/uuid.hpp>
15 
16 class ResourcePool;
17 FO_COMMON_API extern const int INVALID_DESIGN_ID;
18 FO_COMMON_API extern const int INVALID_OBJECT_ID;
19 FO_COMMON_API extern const int ALL_EMPIRES;
20 
21 
22 struct FO_COMMON_API ProductionQueue {
23     /** The type that specifies a single production item (BuildType and name string). */
24     struct FO_COMMON_API ProductionItem {
25         explicit ProductionItem();
26         explicit ProductionItem(BuildType build_type_);             ///< basic ctor for BuildTypes only have one type of item (e.g. stockpile transfer item)
27         ProductionItem(BuildType build_type_, std::string name_);   ///< basic ctor for BuildTypes that use std::string to identify specific items (BuildingTypes)
28         ProductionItem(BuildType build_type_, int design_id_);      ///< basic ctor for BuildTypes that use int to indentify the design of the item (ShipDesigns)
29 
30         bool CostIsProductionLocationInvariant() const;             ///< indicates whether production location can change the cost of this item. This is useful for cachcing cost results per-location or once for all locations.
31 
32         bool operator<(const ProductionItem& rhs) const;
33 
34         bool EnqueueConditionPassedAt(int location_id) const;
35 
36         std::map<std::string, std::map<int, float>> CompletionSpecialConsumption(int location_id) const;// for each special name, what object ids have those special capacities reduced by what amount
37         std::map<MeterType, std::map<int, float>>   CompletionMeterConsumption(int location_id) const;  // for each meter type, what object ids have those meters reduced by what amount
38 
39         std::string Dump() const;
40 
41         BuildType   build_type = INVALID_BUILD_TYPE;
42         // only one of these may be valid, depending on BuildType
43         std::string name;
44         int         design_id = INVALID_DESIGN_ID;
45 
46     private:
47         friend class boost::serialization::access;
48         template <typename Archive>
49         void serialize(Archive& ar, const unsigned int version);
50     };
51 
52     /** The type of a single element in the production queue. */
53     struct FO_COMMON_API Element {
54         Element();
55 
56         Element(ProductionItem item_, int empire_id_,
57                 boost::uuids::uuid uuid_,
58                 int ordered_, int remaining_, int blocksize_,
59                 int location_, bool paused_ = false,
60                 bool allowed_imperial_stockpile_use_ = true);
61 
62         Element(BuildType build_type, std::string name, int empire_id_,
63                 boost::uuids::uuid uuid_,
64                 int ordered_, int remaining_, int blocksize_,
65                 int location_, bool paused_ = false,
66                 bool allowed_imperial_stockpile_use_ = true);
67 
68         Element(BuildType build_type, int design_id, int empire_id_,
69                 boost::uuids::uuid uuid_,
70                 int ordered_, int remaining_, int blocksize_,
71                 int location_, bool paused_ = false,
72                 bool allowed_imperial_stockpile_use_ = true);
73 
74         ProductionItem      item;
75         int                 empire_id = ALL_EMPIRES;
76         int                 ordered = 0;                ///< how many of item (blocks) to produce
77         int                 blocksize = 1;              ///< size of block to produce (default=1)
78         int                 remaining = 0;              ///< how many left to produce
79         int                 location = INVALID_OBJECT_ID;///< the ID of the UniverseObject at which this item is being produced
80         float               allocated_pp = 0.0f;        ///< PP allocated to this ProductionQueue Element by Empire production update
81         float               progress = 0.0f;            ///< fraction of this item that is complete.
82         float               progress_memory = 0.0f;     ///< updated by server turn processing; aides in allowing blocksize changes to be undone in same turn w/o progress loss
83         int                 blocksize_memory = 1;       ///< used along with progress_memory
84         int                 turns_left_to_next_item = -1;
85         int                 turns_left_to_completion = -1;
86         int                 rally_point_id = INVALID_OBJECT_ID;
87         bool                paused = false;
88         bool                allowed_imperial_stockpile_use = true;
89         boost::uuids::uuid  uuid;
90 
91         std::string Dump() const;
92 
93     private:
94         friend class boost::serialization::access;
95         template <typename Archive>
96         void serialize(Archive& ar, const unsigned int version);
97     };
98 
99     typedef std::deque<Element> QueueType;
100 
101     /** The ProductionQueue iterator type.  Dereference yields a Element. */
102     typedef QueueType::iterator iterator;
103     /** The const ProductionQueue iterator type.  Dereference yields a Element. */
104     typedef QueueType::const_iterator const_iterator;
105 
106     /** \name Structors */ //@{
107     ProductionQueue(int empire_id);
108     //@}
109 
110     /** \name Accessors */ //@{
111     int     ProjectsInProgress() const;         ///< Returns the number of production projects currently (perhaps partially) funded.
112     float   TotalPPsSpent() const;              ///< Returns the number of PPs currently spent on the projects in this queue.
EmpireIDProductionQueue113     int     EmpireID() const { return m_empire_id; }
114 
115     /** Returns map from sets of object ids that can share resources to amount
116       * of PP available in those groups of objects ; does not include stockpile */
117     std::map<std::set<int>, float> AvailablePP(const std::shared_ptr<ResourcePool>& industry_pool) const;
118 
119     /** Returns map from sets of object ids that can share resources to amount
120       * of PP allocated to production queue elements that have build locations
121       * in systems in the group. */
122     const std::map<std::set<int>, float>& AllocatedPP() const;
123 
124     /** Returns map from sets of object ids that can share resources to amount
125      * of stockpile PP allocated to production queue elements that have build locations
126      * in systems in the group. */
127     const std::map<std::set<int>, float>& AllocatedStockpilePP() const;
128 
129     /** Returns sum of stockpile meters of empire-owned objects. */
130     float StockpileCapacity() const;
131 
132     /** Returns the value expected for the Imperial Stockpile for the next turn, based on the current
133     * ProductionQueue allocations. */
ExpectedNewStockpileAmountProductionQueue134     float ExpectedNewStockpileAmount() const { return m_expected_new_stockpile_amount; }
135 
136     /** Returns the PP amount expected to be transferred via stockpiling projects to the Imperial Stockpile
137     * for the next turn, based on the current ProductionQueue allocations. */
ExpectedProjectTransferToStockpileProductionQueue138     float ExpectedProjectTransferToStockpile() const { return m_expected_project_transfer_to_stockpile; }
139 
140     /** Returns sets of object ids that have more available than allocated PP */
141     std::set<std::set<int>> ObjectsWithWastedPP(const std::shared_ptr<ResourcePool>& industry_pool) const;
142 
143     // STL container-like interface
144     bool            empty() const;
145     unsigned int    size() const;
146     const_iterator  begin() const;
147     const_iterator  end() const;
148     const_iterator  find(int i) const;
149     const Element&  operator[](int i) const;
150 
151     const_iterator  find(boost::uuids::uuid uuid) const;
152     int             IndexOfUUID(boost::uuids::uuid uuid) const;
153 
154     /** \name Mutators */ //@{
155     /** Recalculates the PPs spent on and number of turns left for each project in the queue.  Also
156       * determines the number of projects in progress, and the industry consumed by projects
157       * in each resource-sharing group of systems.  Does not actually "spend" the PP; a later call to
158       * empire->CheckProductionProgress() will actually spend PP, remove items from queue and create them
159       * in the universe. */
160     void        Update();
161 
162     // STL container-like interface
163     void        push_back(const Element& element);
164     void        insert(iterator it, const Element& element);
165     void        erase(int i);
166     iterator    erase(iterator it);
167 
168     iterator    begin();
169     iterator    end();
170     iterator    find(int i);
171     Element&    operator[](int i);
172 
173     void        clear();
174 
175     mutable boost::signals2::signal<void ()> ProductionQueueChangedSignal;
176     //@}
177 
178 private:
179     QueueType                       m_queue;
180     int                             m_projects_in_progress = 0;
181     std::map<std::set<int>, float>  m_object_group_allocated_pp;
182     std::map<std::set<int>, float>  m_object_group_allocated_stockpile_pp;
183     float                           m_expected_new_stockpile_amount = 0.0f;
184     float                           m_expected_project_transfer_to_stockpile = 0.0f;
185     int                             m_empire_id = ALL_EMPIRES;
186 
187     friend class boost::serialization::access;
188     template <typename Archive>
189     void serialize(Archive& ar, const unsigned int version);
190 };
191 
192 #endif //  _ProductionQueue_h_
193