1 #include "stdafx.h"
2 #include "workshops.h"
3 #include "collective.h"
4 #include "item_factory.h"
5 #include "item.h"
6 #include "workshop_item.h"
7 
Workshops(const EnumMap<WorkshopType,vector<Item>> & options)8 Workshops::Workshops(const EnumMap<WorkshopType, vector<Item>>& options)
9     : types([&options] (WorkshopType t) { return Type(options[t]);}) {
10 }
11 
get(WorkshopType type)12 Workshops::Type& Workshops::get(WorkshopType type) {
13   return types[type];
14 }
15 
get(WorkshopType type) const16 const Workshops::Type& Workshops::get(WorkshopType type) const {
17   return types[type];
18 }
19 
20 SERIALIZATION_CONSTRUCTOR_IMPL(Workshops)
SERIALIZE_DEF(Workshops,types)21 SERIALIZE_DEF(Workshops, types)
22 
23 Workshops::Type::Type(const vector<Item>& o) : options(o) {}
24 
SERIALIZATION_CONSTRUCTOR_IMPL2(Workshops::Type,Type)25 SERIALIZATION_CONSTRUCTOR_IMPL2(Workshops::Type, Type)
26 SERIALIZE_DEF(Workshops::Type, options, queued, debt)
27 
28 
29 const vector<Workshops::Item>& Workshops::Type::getOptions() const {
30   return options;
31 }
32 
stackQueue()33 void Workshops::Type::stackQueue() {
34   vector<Item> tmp;
35   for (auto& elem : queued)
36     if (!tmp.empty() && elem.indexInWorkshop == tmp.back().indexInWorkshop)
37       tmp.back().number += elem.number;
38     else
39       tmp.push_back(elem);
40   queued = tmp;
41 }
42 
addDebt(CostInfo cost)43 void Workshops::Type::addDebt(CostInfo cost) {
44   debt[cost.id] += cost.value;
45 }
46 
queue(int index,int count)47 void Workshops::Type::queue(int index, int count) {
48   CHECK(count > 0);
49   Item newElem = options[index];
50   newElem.indexInWorkshop = index;
51   addDebt(newElem.cost * count);
52   if (!queued.empty() && queued.back().indexInWorkshop == index)
53     queued.back().number += count;
54   else {
55     queued.push_back(newElem);
56     queued.back().number = count;
57   }
58   stackQueue();
59 }
60 
unqueue(int index)61 void Workshops::Type::unqueue(int index) {
62   if (index >= 0 && index < queued.size()) {
63     if (queued[index].state.value_or(0) == 0)
64       addDebt(-queued[index].cost * queued[index].number);
65     else
66       addDebt(-queued[index].cost * (queued[index].number - 1));
67     queued.removeIndexPreserveOrder(index);
68   }
69   stackQueue();
70 }
71 
changeNumber(int index,int number)72 void Workshops::Type::changeNumber(int index, int number) {
73   CHECK(number > 0);
74   if (index >= 0 && index < queued.size()) {
75     auto& elem = queued[index];
76     addDebt(CostInfo(elem.cost.id, elem.cost.value) * (number - elem.number));
77     elem.number = number;
78   }
79 }
80 
81 static const double prodMult = 0.1;
82 
isIdle() const83 bool Workshops::Type::isIdle() const {
84   return queued.empty() || !queued[0].state;
85 }
86 
scheduleItems(WCollective collective)87 void Workshops::scheduleItems(WCollective collective) {
88   for (auto type : ENUM_ALL(WorkshopType))
89     types[type].scheduleItems(collective);
90 }
91 
scheduleItems(WCollective collective)92 void Workshops::Type::scheduleItems(WCollective collective) {
93   if (queued.empty() || queued[0].state)
94     return;
95   for (int i : All(queued))
96     if (collective->hasResource(queued[i].cost)) {
97       if (i > 0)
98         swap(queued[0], queued[i]);
99       collective->takeResource(queued[0].cost);
100       addDebt(-queued[0].cost);
101       queued[0].state = 0;
102       return;
103     }
104 }
105 
addWork(double amount)106 vector<PItem> Workshops::Type::addWork(double amount) {
107   if (!queued.empty() && queued[0].state) {
108     auto& product = queued[0];
109     *product.state += amount * prodMult / product.workNeeded;
110     if (*product.state >= 1) {
111       vector<PItem> ret = product.type.get(product.batchSize);
112       product.state = none;
113       if (!--product.number)
114         queued.removeIndexPreserveOrder(0);
115       return ret;
116     }
117   }
118   return {};
119 }
120 
getQueued() const121 const vector<Workshops::Item>& Workshops::Type::getQueued() const {
122   return queued;
123 }
124 
getDebt(CollectiveResourceId resource) const125 int Workshops::getDebt(CollectiveResourceId resource) const {
126   int ret = 0;
127   for (auto type : ENUM_ALL(WorkshopType))
128     ret += types[type].debt[resource];
129   return ret;
130 }
131 
132