-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEvent.cpp
More file actions
215 lines (174 loc) · 6.24 KB
/
Event.cpp
File metadata and controls
215 lines (174 loc) · 6.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/************************************************************
* SimLib simulation library for event-based simulations *
* Author: Martin Ubl (A16N0026P) *
* ublm@students.zcu.cz *
************************************************************/
#include "Event.h"
#include "Process.h"
#include "Simulation.h"
#include <random>
#include <algorithm>
SimEvent::SimEvent(SimulationPtr simulation, uint32_t objectClass)
: SimulationObject(SimulationObjectType::EVENT, simulation, objectClass),
m_randomEngine(simulation->GetTrueRandomNumber())
{
//
}
SimEvent::~SimEvent()
{
//
}
void SimEvent::_AddSelectionCriteria(ObjectSelectionCriteria crit, uint64_t critParam, ObjectSelectionMode mode, uint32_t modeParam)
{
m_criterias.resize(m_criterias.size() + 1);
size_t i = m_criterias.size() - 1;
m_criterias[i].criteria = crit;
m_criterias[i].critParam.asUInt64 = critParam;
m_criterias[i].mode = mode;
m_criterias[i].modeParam = modeParam;
}
void SimEvent::Run()
{
// valid simulation object is required
SimulationPtr simulation = GetSimulation();
if (!simulation)
return;
SimulationObjectList objlist;
// not empty criterias - filter
if (!m_criterias.empty())
{
size_t i = 0;
SelectionCriteria& crit = m_criterias[i];
// the first filter is processed separatelly due to need of calling specialized version of "Get" method
// in fact this would not be needed, but instead of copying objects, this is slightly closer to being "optimal"
switch (crit.criteria)
{
case ObjectSelectionCriteria::GUID:
{
auto ptr = simulation->GetObjectByGUID(crit.critParam.asUInt64);
if (ptr)
objlist.push_back(ptr);
break;
}
case ObjectSelectionCriteria::TYPE:
{
objlist = simulation->GetObjectsByType(crit.critParam.asSimType);
break;
}
case ObjectSelectionCriteria::CLASS:
{
objlist = simulation->GetObjectsByClass(crit.critParam.asUInt32);
break;
}
}
// also perform separate mode selection
PerformModeSelection(objlist, crit);
// now apply all criterias separatelly in a generic way
for (; i < m_criterias.size(); i++)
{
crit = m_criterias[i];
PerformCriteriaSelection(objlist, crit);
PerformModeSelection(objlist, crit);
// no need to apply more criterias, if the list is empty
if (objlist.empty())
break;
}
}
else // if no criterias at all - select all objects
objlist = simulation->GetAllObjects();
// call user-defined filters
FilterObjects(objlist);
// now we are ready!
BeforeExecute();
// iterate through all objects in list and execute event on them
for (auto obj : objlist)
{
ExecuteOn(obj);
if (obj->GetType() == SimulationObjectType::PROCESS)
obj->ToProcess()->ReceiveEvent(*this);
}
AfterExecute();
// destroy event object, if not rescheduled (or not scheduled periodically)
if (!HasPeriodicSchedule() && !GetCurrentCalendar())
Terminate();
}
void SimEvent::PerformCriteriaSelection(SimulationObjectList& objList, SelectionCriteria& crit)
{
auto itr = objList.begin();
switch (crit.criteria)
{
case ObjectSelectionCriteria::GUID:
itr = std::remove_if(objList.begin(), objList.end(), [=](SimulationObjectPtr obj) { return obj->GetGUID() != crit.critParam.asUInt64; });
break;
case ObjectSelectionCriteria::TYPE:
itr = std::remove_if(objList.begin(), objList.end(), [=](SimulationObjectPtr obj) { return obj->GetType() != crit.critParam.asSimType; });
break;
case ObjectSelectionCriteria::CLASS:
itr = std::remove_if(objList.begin(), objList.end(), [=](SimulationObjectPtr obj) { return obj->GetObjectClass() != crit.critParam.asUInt32; });
break;
}
objList.erase(itr, objList.end());
}
void SimEvent::PerformModeSelection(SimulationObjectList& objList, SelectionCriteria& crit)
{
switch (crit.mode)
{
case ObjectSelectionMode::ALL:
break;
case ObjectSelectionMode::ONE:
{
if (objList.size() <= 1)
return;
// generate random index (will be used)
std::uniform_int_distribution<size_t> indexRandDist(0, objList.size() - 1);
size_t i = indexRandDist(m_randomEngine);
// move iterator to that "index"
auto itr = objList.begin();
std::advance(itr, i);
// get pointer, erase list and put pointer back in
SimulationObjectPtr obj = *itr;
objList.clear();
objList.push_back(obj);
break;
}
case ObjectSelectionMode::K_OF_N:
{
// no need to perform "0 of N"
if (crit.modeParam == 0)
{
objList.clear();
return;
}
// ..or "N of N" selection
if (crit.modeParam >= objList.size())
return;
// shuffle the list
std::vector<SimulationObjectPtr> tmpVec(objList.begin(), objList.end());
std::shuffle(tmpVec.begin(), tmpVec.end(), m_randomEngine);
objList.assign(tmpVec.begin(), tmpVec.end());
// leave just first K elements
auto itr = objList.begin();
std::advance(itr, crit.modeParam);
// the rest is erased
while (itr != objList.end())
itr = objList.erase(itr);
break;
}
}
}
void SimEvent::FilterObjects(SimulationObjectList& objectList)
{
//
}
void SimEvent::BeforeExecute()
{
//
}
void SimEvent::AfterExecute()
{
//
}
void SimEvent::ExecuteOn(SimulationObjectPtr object)
{
//
}