1 package org.sim0mq.message.federationmanager;
2
3 import java.util.LinkedHashMap;
4 import java.util.Map;
5
6 import org.djunits.value.vdouble.scalar.Duration;
7 import org.djunits.value.vdouble.scalar.Time;
8 import org.djunits.value.vfloat.scalar.FloatDuration;
9 import org.djunits.value.vfloat.scalar.FloatTime;
10 import org.djutils.exceptions.Throw;
11 import org.djutils.serialization.SerializationException;
12 import org.sim0mq.Sim0MQException;
13 import org.sim0mq.message.MessageStatus;
14 import org.sim0mq.message.Sim0MQMessage;
15 import org.sim0mq.message.SimulationMessage;
16 import org.sim0mq.message.types.NumberDuration;
17 import org.sim0mq.message.types.NumberTime;
18
19
20
21
22
23
24
25
26
27 public class FM2SimRunControlMessage extends Sim0MQMessage
28 {
29
30
31
32
33 private final NumberDuration runDuration;
34
35
36
37
38
39 private final NumberDuration warmupDuration;
40
41
42
43
44
45 private final NumberTime offsetTime;
46
47
48 private final double speed;
49
50
51 private final int numberReplications;
52
53
54 private final int numberRandomStreams;
55
56
57 private final Map<Object, Long> streamMap = new LinkedHashMap<>();
58
59
60 private static final String MESSAGETYPE = "FM.2";
61
62
63 private static final long serialVersionUID = 20170424L;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 @SuppressWarnings("checkstyle:parameternumber")
88 public FM2SimRunControlMessage(final Object simulationRunId, final Object senderId, final Object receiverId,
89 final long messageId, final Object runDuration, final Object warmupDuration, final Object offsetTime,
90 final double speed, final int numberReplications, final int numberRandomStreams, final Map<Object, Long> streamMap)
91 throws Sim0MQException, NullPointerException
92 {
93 super(simulationRunId, senderId, receiverId, MESSAGETYPE, messageId, MessageStatus.NEW);
94 Throw.whenNull(runDuration, "runDuration cannot be null");
95 Throw.whenNull(warmupDuration, "warmupDuration cannot be null");
96 Throw.whenNull(offsetTime, "offsetTime cannot be null");
97 Throw.whenNull(streamMap, "streamMap cannot be null");
98
99 if (runDuration instanceof Duration)
100 {
101 this.runDuration = new NumberDuration((Duration) runDuration);
102 }
103 else if (runDuration instanceof FloatDuration)
104 {
105 this.runDuration = new NumberDuration((FloatDuration) runDuration);
106 }
107 else if (runDuration instanceof Number)
108 {
109 this.runDuration = new NumberDuration((Number) runDuration);
110 }
111 else
112 {
113 throw new Sim0MQException("runDuration should be Number, Duration or FloatDuration");
114 }
115
116 if (warmupDuration instanceof Duration)
117 {
118 this.warmupDuration = new NumberDuration((Duration) warmupDuration);
119 }
120 else if (warmupDuration instanceof FloatDuration)
121 {
122 this.warmupDuration = new NumberDuration((FloatDuration) warmupDuration);
123 }
124 else if (warmupDuration instanceof Number)
125 {
126 this.warmupDuration = new NumberDuration((Number) warmupDuration);
127 }
128 else
129 {
130 throw new Sim0MQException("warmupDuration should be Number, Duration or FloatDuration");
131 }
132
133 if (offsetTime instanceof Time)
134 {
135 this.offsetTime = new NumberTime((Time) offsetTime);
136 }
137 else if (offsetTime instanceof FloatTime)
138 {
139 this.offsetTime = new NumberTime((FloatTime) offsetTime);
140 }
141 else if (offsetTime instanceof Number)
142 {
143 this.offsetTime = new NumberTime((Number) offsetTime);
144 }
145 else
146 {
147 throw new Sim0MQException("offsetTime should be Number, Time or FloatTime");
148 }
149
150 this.speed = speed;
151
152 Throw.when(numberReplications <= 0, Sim0MQException.class, "numberReplications should be > 0");
153 this.numberReplications = numberReplications;
154
155 Throw.when(numberRandomStreams < 0, Sim0MQException.class, "numberRandomStreams should be >= 0");
156 Throw.when(numberRandomStreams != streamMap.size(), Sim0MQException.class,
157 "numberRandomStreams as given and in map are different");
158 this.numberRandomStreams = numberRandomStreams;
159 this.streamMap.putAll(streamMap);
160 }
161
162
163
164
165 public final NumberDuration getRunDuration()
166 {
167 return this.runDuration;
168 }
169
170
171
172
173 public final NumberDuration getWarmupDuration()
174 {
175 return this.warmupDuration;
176 }
177
178
179
180
181 public final NumberTime getOffsetTime()
182 {
183 return this.offsetTime;
184 }
185
186
187
188
189 public final double getSpeed()
190 {
191 return this.speed;
192 }
193
194
195
196
197 public final int getNumberReplications()
198 {
199 return this.numberReplications;
200 }
201
202
203
204
205 public final int getNumberRandomStreams()
206 {
207 return this.numberRandomStreams;
208 }
209
210
211
212
213 public final Map<Object, Long> getStreamMap()
214 {
215 return this.streamMap;
216 }
217
218
219
220
221 public static final String getMessageType()
222 {
223 return MESSAGETYPE;
224 }
225
226
227 @Override
228 public short getNumberOfPayloadFields()
229 {
230 return (short) (6 + 2 * this.numberRandomStreams);
231 }
232
233
234 @Override
235 public Object[] createObjectArray()
236 {
237 Object[] array = new Object[8 + getNumberOfPayloadFields()];
238 array[0] = getMagicNumber();
239 array[1] = getSimulationRunId();
240 array[2] = getSenderId();
241 array[3] = getReceiverId();
242 array[4] = getMessageTypeId();
243 array[5] = getMessageId();
244 array[6] = getMessageStatus();
245 array[7] = getNumberOfPayloadFields();
246 array[8] = this.runDuration.getObject();
247 array[9] = this.warmupDuration.getObject();
248 array[10] = this.offsetTime.getObject();
249 array[11] = this.speed;
250 array[12] = this.numberReplications;
251 array[13] = this.numberRandomStreams;
252 int i = 14;
253 for (Object key : this.streamMap.keySet())
254 {
255 array[i++] = key;
256 array[i++] = this.streamMap.get(key);
257 }
258 return array;
259 }
260
261
262 @Override
263 public byte[] createByteArray() throws Sim0MQException, SerializationException
264 {
265 Object[] array = new Object[getNumberOfPayloadFields()];
266 array[0] = this.runDuration.getObject();
267 array[1] = this.warmupDuration.getObject();
268 array[2] = this.offsetTime.getObject();
269 array[3] = this.speed;
270 array[4] = this.numberReplications;
271 array[5] = this.numberRandomStreams;
272 int i = 6;
273 for (Object key : this.streamMap.keySet())
274 {
275 array[i++] = key;
276 array[i++] = this.streamMap.get(key);
277 }
278 return SimulationMessage.encodeUTF8(getSimulationRunId(), getSenderId(), getReceiverId(), getMessageTypeId(),
279 getMessageId(), getMessageStatus(), array);
280 }
281
282
283
284
285
286
287
288
289 public static FM2SimRunControlMessage createMessage(final Object[] fields, final Object intendedReceiverId)
290 throws Sim0MQException
291 {
292 Map<Object, Long> streams = new LinkedHashMap<>();
293 int numberStreams = ((Integer) fields[13]).intValue();
294 check(fields, 6 + 2 * numberStreams, MESSAGETYPE, intendedReceiverId);
295 for (int i = 14; i < 14 + 2 * numberStreams; i += 2)
296 {
297 Object streamId = fields[i];
298 Long seed = ((Long) fields[i + 1]).longValue();
299 streams.put(streamId, seed);
300 }
301 return new FM2SimRunControlMessage(fields[1], fields[2], fields[3], ((Long) fields[5]).longValue(), fields[8],
302 fields[9], fields[10], ((Double) fields[11]).doubleValue(), ((Integer) fields[12]).intValue(), numberStreams,
303 streams);
304 }
305
306
307
308
309
310
311
312
313
314
315
316 public static class Builder extends Sim0MQMessage.Builder<FM2SimRunControlMessage.Builder>
317 {
318
319
320
321
322 private Object runDuration;
323
324
325
326
327
328 private Object warmupDuration;
329
330
331
332
333
334 private Object offsetTime;
335
336
337 private double speed;
338
339
340 private int numberReplications;
341
342
343 private Map<Object, Long> streamMap = new LinkedHashMap<>();
344
345
346
347
348 public Builder()
349 {
350
351 }
352
353
354
355
356
357 public final Builder setRunDurationNumber(final Number newRunDuration)
358 {
359 this.runDuration = newRunDuration;
360 return this;
361 }
362
363
364
365
366
367 public final Builder setRunDuration(final Duration newRunDuration)
368 {
369 this.runDuration = newRunDuration;
370 return this;
371 }
372
373
374
375
376
377 public final Builder setRunDurationFloat(final FloatDuration newRunDuration)
378 {
379 this.runDuration = newRunDuration;
380 return this;
381 }
382
383
384
385
386
387 public final Builder setWarmupDurationNumber(final Number newWarmupDuration)
388 {
389 this.warmupDuration = newWarmupDuration;
390 return this;
391 }
392
393
394
395
396
397 public final Builder setWarmupDuration(final Duration newWarmupDuration)
398 {
399 this.warmupDuration = newWarmupDuration;
400 return this;
401 }
402
403
404
405
406
407 public final Builder setWarmupDurationFloat(final FloatDuration newWarmupDuration)
408 {
409 this.warmupDuration = newWarmupDuration;
410 return this;
411 }
412
413
414
415
416
417 public final Builder setOffsetTimeNumber(final Number newOffsetTime)
418 {
419 this.offsetTime = newOffsetTime;
420 return this;
421 }
422
423
424
425
426
427 public final Builder setOffsetTime(final Time newOffsetTime)
428 {
429 this.offsetTime = newOffsetTime;
430 return this;
431 }
432
433
434
435
436
437 public final Builder setOffsetTimeFloat(final FloatTime newOffsetTime)
438 {
439 this.offsetTime = newOffsetTime;
440 return this;
441 }
442
443
444
445
446
447 public final Builder setSpeed(final double newSpeed)
448 {
449 this.speed = newSpeed;
450 return this;
451 }
452
453
454
455
456
457 public final Builder setNumberReplications(final int newNumberReplications)
458 {
459 this.numberReplications = newNumberReplications;
460 return this;
461 }
462
463
464
465
466
467 public final Builder setStreamMap(final Map<Object, Long> newStreamMap)
468 {
469 this.streamMap = newStreamMap;
470 return this;
471 }
472
473
474 @Override
475 public FM2SimRunControlMessage build() throws Sim0MQException, NullPointerException
476 {
477 return new FM2SimRunControlMessage(this.simulationRunId, this.senderId, this.receiverId, this.messageId,
478 this.runDuration, this.warmupDuration, this.offsetTime, this.speed, this.numberReplications,
479 this.streamMap.size(), this.streamMap);
480 }
481
482 }
483 }