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