Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 12288d0e

History | View | Annotate | Download (44 KB)

1
//=========================================================================
2
//  SEQUENCECHARTFACADE.CC - part of
3
//                  OMNeT++/OMNEST
4
//           Discrete System Simulation in C++
5
//
6
//  Author: Levente Meszaros
7
//
8
//=========================================================================
9

    
10
/*--------------------------------------------------------------*
11
  Copyright (C) 2006-2008 OpenSim Ltd.
12

13
  This file is distributed WITHOUT ANY WARRANTY. See the file
14
  `license' for details on this and other legal matters.
15
*--------------------------------------------------------------*/
16

    
17
#include <stdio.h>
18
#include <algorithm>
19
#include <set>
20
#include <list>
21
#include <math.h>
22
#include "lcgrandom.h"
23
#include "ievent.h"
24
#include "ieventlog.h"
25
#include "event.h"
26
#include "messagedependency.h"
27
#include "sequencechartfacade.h"
28

    
29
USING_NAMESPACE
30

    
31
SequenceChartFacade::SequenceChartFacade(IEventLog *eventLog) : EventLogFacade(eventLog)
32
{
33
    timelineMode = NONLINEAR;
34
    timelineCoordinateSystemVersion = -1;
35
    undefineTimelineCoordinateSystem();
36

    
37
    nonLinearMinimumTimelineCoordinateDelta = 0.1;
38
    setNonLinearFocus(calculateNonLinearFocus());
39

    
40
    smallestComplexity = -1;
41
    largestComplexity = -1;
42

    
43
    smallestDuration = -1;
44
    largestDuration = -1;
45

    
46
    maximumOverlapping = -1;
47

    
48
    biggestEarliestProcessingTime = 0;
49

    
50
    biggestEndTimeEvent = NULL;
51

    
52
    cachedParallelSet.clear();
53
    cachedCriticalPath.clear();
54
}
55

    
56
void SequenceChartFacade::synchronize(FileReader::FileChangedState change)
57
{
58
    if (change != FileReader::UNCHANGED) {
59
        EventLogFacade::synchronize(change);
60

    
61
        setNonLinearFocus(calculateNonLinearFocus());
62

    
63
        if (timelineCoordinateOriginEventNumber != -1) {
64
            IEvent *event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber);
65

    
66
            if (event)
67
                relocateTimelineCoordinateSystem(event);
68
            else
69
                undefineTimelineCoordinateSystem();
70
        }
71
    }
72
}
73

    
74
double SequenceChartFacade::calculateNonLinearFocus()
75
{
76
    if (!eventLog->isEmpty()) {
77
        double lastEventSimulationTime = eventLog->getLastEvent()->getSimulationTime().dbl();
78
        double firstEventSimulationTime = eventLog->getFirstEvent()->getSimulationTime().dbl();
79
        double totalSimulationTimeDelta = lastEventSimulationTime - firstEventSimulationTime;
80

    
81
        if (totalSimulationTimeDelta == 0)
82
            totalSimulationTimeDelta = firstEventSimulationTime;
83

    
84
        if (totalSimulationTimeDelta == 0)
85
            return 1;
86
        else
87
            return totalSimulationTimeDelta / eventLog->getApproximateNumberOfEvents() / 10;
88
    }
89
    else
90
        return 1;
91
}
92

    
93
void SequenceChartFacade::setNonLinearMinimumTimelineCoordinateDelta(double value)
94
{
95
    Assert(value >= 0);
96
    nonLinearMinimumTimelineCoordinateDelta = value;
97
}
98

    
99
void SequenceChartFacade::setNonLinearFocus(double nonLinearFocus)
100
{
101
    Assert(nonLinearFocus >= 0);
102
    this->nonLinearFocus = nonLinearFocus;
103
}
104

    
105
void SequenceChartFacade::undefineTimelineCoordinateSystem()
106
{
107
    timelineCoordinateSystemVersion++;
108
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = -1;
109
    timelineCoordinateOriginSimulationTime = simtime_nil;
110
    timelineCoordinateOriginRealTime = 0;
111
}
112

    
113
void SequenceChartFacade::relocateTimelineCoordinateSystem(IEvent *event)
114
{
115
    Assert(event);
116

    
117
    timelineCoordinateSystemVersion++;
118
    timelineCoordinateOriginEventNumber = timelineCoordinateRangeStartEventNumber = timelineCoordinateRangeEndEventNumber = event->getEventNumber();
119
    timelineCoordinateOriginSimulationTime = event->getSimulationTime();
120
    timelineCoordinateOriginRealTime = event->getEarliestStartTime() / 1000000.0;
121
    event->cachedTimelineCoordinate = 0;
122
    event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
123
}
124

    
125
void SequenceChartFacade::setTimelineMode(TimelineMode timelineMode)
126
{
127
    this->timelineMode = timelineMode;
128

    
129
    if (timelineCoordinateOriginEventNumber != -1)
130
        relocateTimelineCoordinateSystem(eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber));
131
}
132

    
133
double SequenceChartFacade::IEvent_getTimelineCoordinate(ptr_t ptr)
134
{
135
    IEVENT_PTR(ptr);
136
    return getTimelineCoordinate((IEvent*)ptr);
137
}
138

    
139
double SequenceChartFacade::IEvent_getTimelineEventEndCoordinate(ptr_t ptr)
140
{
141
    IEVENT_PTR(ptr);
142
    return getTimelineEventEndCoordinate((IEvent*)ptr);
143
}
144

    
145
double SequenceChartFacade::getTimelineCoordinateDelta(double simulationTimeDelta)
146
{
147
    Assert(nonLinearFocus > 0);
148

    
149
    if (timelineMode == STEP)
150
        return 1;
151
    else
152
        return nonLinearMinimumTimelineCoordinateDelta + (1 - nonLinearMinimumTimelineCoordinateDelta) * atan(fabs(simulationTimeDelta) / nonLinearFocus) / PI * 2;
153
}
154

    
155
double SequenceChartFacade::getTimelineCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
156
{
157
    IEVENT_PTR(ptr);
158
    return getTimelineCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
159
}
160

    
161
double SequenceChartFacade::getTimelineEventEndCoordinate(ptr_t ptr, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
162
{
163
    IEVENT_PTR(ptr);
164
    return getTimelineEventEndCoordinate((IEvent *)ptr, lowerTimelineCoordinateCalculationLimit, upperTimelineCoordinateCalculationLimit);
165
}
166

    
167
double SequenceChartFacade::getTimelineCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
168
{
169
    Assert(event);
170
    Assert(event->getEventLog() == eventLog);
171
    Assert(timelineCoordinateSystemVersion != -1);
172
    Assert(timelineCoordinateOriginEventNumber != -1);
173

    
174
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion) {
175
        double timelineCoordinate;
176

    
177
        switch (timelineMode) {
178
            case REAL_TIME:
179
                timelineCoordinate = ((event->getEarliestStartTime()/1000000.0 - timelineCoordinateOriginRealTime));
180
                break;
181
            case SIMULATION_TIME:
182
                timelineCoordinate = (event->getSimulationTime() - timelineCoordinateOriginSimulationTime).dbl();
183
                break;
184
            case EVENT_NUMBER:
185
                timelineCoordinate = event->getEventNumber() - timelineCoordinateOriginEventNumber;
186
                break;
187
            case STEP:
188
            case NONLINEAR:
189
                {
190
                    IEvent *previousEvent = NULL;
191
                    // do we go forward from end or backward from start of known range
192
                    bool forward = event->getEventNumber() > timelineCoordinateRangeEndEventNumber;
193
                    IEvent *currentEvent = eventLog->getEventForEventNumber(forward ? timelineCoordinateRangeEndEventNumber : timelineCoordinateRangeStartEventNumber);
194

    
195
                    Assert(event->getEventNumber() < timelineCoordinateRangeStartEventNumber || timelineCoordinateRangeEndEventNumber < event->getEventNumber());
196

    
197
                    // TODO: LONG RUNNING OPERATION
198
                    // does a linear search towards the event to calculate the non linear timeline coordinate
199
                    do {
200
                        eventLog->progress();
201

    
202
                        Assert(currentEvent);
203
                        previousEvent = currentEvent;
204
                        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
205
                        Assert(currentEvent);
206

    
207
                        simtime_t previousSimulationTime = previousEvent->getSimulationTime();
208
                        double previousTimelineCoordinate = previousEvent->cachedTimelineCoordinate;
209
                        simtime_t simulationTime = currentEvent->getSimulationTime();
210
                        double timelineCoordinateDelta = getTimelineCoordinateDelta((simulationTime - previousSimulationTime).dbl());
211

    
212
                        if (forward) {
213
                            timelineCoordinate = previousTimelineCoordinate + timelineCoordinateDelta;
214

    
215
                            if (timelineCoordinate > upperTimelineCoordinateCalculationLimit)
216
                                return NaN;
217
                        }
218
                        else {
219
                            timelineCoordinate = previousTimelineCoordinate - timelineCoordinateDelta;
220

    
221
                            if (timelineCoordinate < lowerTimelineCoordinateCalculationLimit)
222
                                return NaN;
223
                        }
224

    
225
                        currentEvent->cachedTimelineCoordinate = timelineCoordinate;
226
                        currentEvent->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
227
                    }
228
                    while (currentEvent != event);
229

    
230
                    if (forward)
231
                        timelineCoordinateRangeEndEventNumber = event->getEventNumber();
232
                    else
233
                        timelineCoordinateRangeStartEventNumber = event->getEventNumber();
234
                }
235
                break;
236
            default:
237
                throw opp_runtime_error("Unknown timeline mode");
238
        }
239

    
240
        event->cachedTimelineCoordinate = timelineCoordinate;
241
        event->cachedTimelineCoordinateSystemVersion = timelineCoordinateSystemVersion;
242
    }
243

    
244
    return event->cachedTimelineCoordinate;
245
}
246

    
247
double SequenceChartFacade::getTimelineEventEndCoordinate(IEvent *event, double lowerTimelineCoordinateCalculationLimit, double upperTimelineCoordinateCalculationLimit)
248
{
249
    Assert(event);
250
    Assert(event->getEventLog() == eventLog);
251
    if(!eventLog->isLegacyTrace()) {
252
        return getTimelineCoordinate(event);
253
    }
254
        double timelineEventEndCoordinate;
255
        switch (timelineMode) {
256
            case REAL_TIME:
257
                timelineEventEndCoordinate = (event->getEarliestProcessingTime()/ 1000000.0 - timelineCoordinateOriginRealTime) ;
258
                break;
259
            case SIMULATION_TIME:
260
                timelineEventEndCoordinate = (event->getSimulationTime()+event->getEventEntry()->duration - timelineCoordinateOriginSimulationTime).dbl();
261
                break;
262
            default:
263
                return getTimelineCoordinate(event);
264
        }
265
    return timelineEventEndCoordinate;
266
}
267

    
268
double SequenceChartFacade::getCachedTimelineCoordinate(IEvent *event)
269
{
270
    Assert(event);
271
    Assert(timelineCoordinateSystemVersion != -1);
272
    Assert(timelineCoordinateOriginEventNumber != -1);
273

    
274
    if (this->timelineCoordinateSystemVersion > event->cachedTimelineCoordinateSystemVersion)
275
        return -1;
276
    else
277
        return event->cachedTimelineCoordinate;
278
}
279

    
280
IEvent *SequenceChartFacade::getEventForNonLinearTimelineCoordinate(double timelineCoordinate, bool &forward)
281
{
282
    Assert(timelineCoordinateOriginEventNumber != -1);
283
    IEvent *timelineCoordinateRangeStartEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeStartEventNumber);
284
    IEvent *timelineCoordinateRangeEndEvent = eventLog->getEventForEventNumber(timelineCoordinateRangeEndEventNumber);
285
    IEvent *currentEvent;
286

    
287
    Assert(timelineCoordinateRangeStartEvent && timelineCoordinateRangeEndEvent);
288

    
289
    if (timelineCoordinate <= getTimelineCoordinate(timelineCoordinateRangeStartEvent)) {
290
        forward = false;
291
        currentEvent = timelineCoordinateRangeStartEvent;
292
    }
293
    else if (getTimelineCoordinate(timelineCoordinateRangeEndEvent) <= timelineCoordinate) {
294
        forward = true;
295
        currentEvent = timelineCoordinateRangeEndEvent;
296
    }
297
    else {
298
        forward = true;
299
        currentEvent = timelineCoordinateRangeStartEvent;
300
    }
301

    
302
    // TODO: LONG RUNNING OPERATION
303
    // does a linear search towards requested non linear timeline coordinate
304
    while (currentEvent && (forward ? getTimelineCoordinate(currentEvent) < timelineCoordinate :
305
                                      timelineCoordinate <= getTimelineCoordinate(currentEvent)))
306
    {
307
        eventLog->progress();
308
        currentEvent = forward ? currentEvent->getNextEvent() : currentEvent->getPreviousEvent();
309
    }
310

    
311
    return currentEvent;
312
}
313

    
314
IEvent *SequenceChartFacade::getLastEventNotAfterTimelineCoordinate(double timelineCoordinate)
315
{
316
    if (eventLog->isEmpty())
317
        return NULL;
318

    
319
    switch (timelineMode) {
320
        case REAL_TIME:
321
        {
322
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
323
            IEvent* res = eventLog->getFirstEvent();
324
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
325
                if ((double) current->getEarliestStartTime() / 1000000.0 < timelineCoordinate) {
326
                    if (current->getEarliestStartTime() > res->getEarliestStartTime()) {
327
                        res = current;
328
                    }
329
                }
330
            }
331
            return res;
332
        }
333
        case SIMULATION_TIME:
334
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
335
        case EVENT_NUMBER:
336
            {
337
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
338

    
339
                if (eventNumber < 0)
340
                    return NULL;
341
                else
342
                    return eventLog->getLastEventNotAfterEventNumber(eventNumber);
343
            }
344
        case STEP:
345
        case NONLINEAR:
346
            {
347
                bool forward;
348
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
349
                currentEvent = forward ? (currentEvent ? currentEvent->getPreviousEvent() : eventLog->getLastEvent()) : currentEvent;
350

    
351
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) <= timelineCoordinate);
352
                return currentEvent;
353
            }
354
        default:
355
            throw opp_runtime_error("Unknown timeline mode");
356
    }
357
}
358

    
359
IEvent *SequenceChartFacade::getFirstEventNotBeforeTimelineCoordinate(double timelineCoordinate)
360
{
361
    if (eventLog->isEmpty())
362
        return NULL;
363

    
364
    switch (timelineMode) {
365
        case REAL_TIME:
366
        {
367
            //TODO MAKE THIS MORE EFFICIENT (i.e. sorted data structure)!
368
            IEvent* res = eventLog->getLastEvent();
369
            for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
370
                if ((double) current->getEarliestStartTime() / 1000000.0 > timelineCoordinate) {
371
                    if (current->getEarliestStartTime() < res->getEarliestStartTime()) {
372
                        res = current;
373
                    }
374
                }
375
            }
376
            return res;
377
        }
378
        case SIMULATION_TIME:
379
            return eventLog->getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
380
        case EVENT_NUMBER:
381
            {
382
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
383

    
384
                if (eventNumber < 0)
385
                    return eventLog->getFirstEvent();
386
                else
387
                    return eventLog->getFirstEventNotBeforeEventNumber(eventNumber);
388
            }
389
        case STEP:
390
        case NONLINEAR:
391
            {
392
                bool forward;
393
                IEvent *currentEvent = getEventForNonLinearTimelineCoordinate(timelineCoordinate, forward);
394
                currentEvent = forward ? currentEvent : (currentEvent ? currentEvent->getNextEvent() : eventLog->getFirstEvent());
395

    
396
                Assert(!currentEvent || getTimelineCoordinate(currentEvent) >= timelineCoordinate);
397
                return currentEvent;
398
            }
399
        default:
400
            throw opp_runtime_error("Unknown timeline mode");
401
    }
402
}
403

    
404
void SequenceChartFacade::extractSimulationTimesAndTimelineCoordinates(
405
    IEvent *event, IEvent *&nextEvent,
406
    simtime_t &eventSimulationTime, double &eventTimelineCoordinate,
407
    simtime_t &nextEventSimulationTime, double &nextEventTimelineCoordinate,
408
    simtime_t &simulationTimeDelta, double &timelineCoordinateDelta)
409
{
410
    // if before the first event
411
    if (event) {
412
        if (timelineMode==REAL_TIME) {
413
            eventSimulationTime = event->getEarliestStartTime() / 1000000.0;
414
        } else {
415
            eventSimulationTime = event->getSimulationTime();
416
        }
417
        eventTimelineCoordinate = getTimelineCoordinate(event);
418
    }
419
    else {
420
        eventSimulationTime = BigDecimal::Zero;
421
        IEvent *firstEvent = eventLog->getFirstEvent();
422
        eventTimelineCoordinate = getTimelineCoordinate(firstEvent);
423

    
424
        if (timelineMode == EVENT_NUMBER)
425
            eventTimelineCoordinate -= 1;
426
        else if (timelineMode == REAL_TIME)
427
            eventTimelineCoordinate -= getTimelineCoordinateDelta(0);
428
        else
429
            eventTimelineCoordinate -= getTimelineCoordinateDelta(firstEvent->getSimulationTime().dbl());
430
    }
431

    
432
    // linear approximation between two enclosing events
433
    nextEvent = event ? event->getNextEvent() : eventLog->getFirstEvent();
434

    
435
    if (nextEvent) {
436
        if(timelineMode==REAL_TIME) {
437
            nextEventSimulationTime = nextEvent->getEarliestStartTime() / 1000000.0;
438
        } else {
439
            nextEventSimulationTime = nextEvent->getSimulationTime();
440
        }
441

    
442
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
443

    
444
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
445
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
446
    }
447
}
448

    
449
simtime_t SequenceChartFacade::getSimulationTimeForTimelineCoordinate(double timelineCoordinate, bool upperLimit)
450
{
451
    Assert(!isNaN(timelineCoordinate));
452

    
453
    if (eventLog->isEmpty())
454
        return BigDecimal::Zero;
455

    
456
    simtime_t simulationTime;
457

    
458
    switch (timelineMode)
459
    {
460
        case REAL_TIME:
461
        {
462
            simulationTime = max(BigDecimal::Zero, min(biggestEarliestProcessingTime, (timelineCoordinate + timelineCoordinateOriginRealTime)));
463
        }
464
        break;
465
        case SIMULATION_TIME:
466
            {
467
                IEvent* largestEvent = (IEvent*) getLargestEndtimeInEventRange((ptr_t)(eventLog->getFirstEvent()),(ptr_t)(eventLog->getLastEvent()), upperLimit);
468
                simtime_t lastEventSimulationTime= largestEvent->getSimulationTime() + largestEvent->getEventEntry()->duration;
469
                simulationTime = max(BigDecimal::Zero, min(lastEventSimulationTime, timelineCoordinate + timelineCoordinateOriginSimulationTime));
470
            }
471
            break;
472
        case EVENT_NUMBER:
473
        case STEP:
474
        case NONLINEAR:
475
            {
476
                IEvent *nextEvent;
477
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
478
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
479

    
480
                IEvent *event = getLastEventNotAfterTimelineCoordinate(timelineCoordinate);
481
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
482
                                                             eventSimulationTime, eventTimelineCoordinate,
483
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
484
                                                             simulationTimeDelta, timelineCoordinateDelta);
485

    
486
                if (nextEvent) {
487
                    if (timelineCoordinateDelta == 0) {
488
                        // IMPORTANT NOTE: this is just an approximation
489
                        if (upperLimit)
490
                            simulationTime = nextEventSimulationTime;
491
                        else
492
                            simulationTime = eventSimulationTime;
493
                    }
494
                    else {
495
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
496
                        simulationTime = eventSimulationTime + simulationTimeDelta * (timelineCoordinate - eventTimelineCoordinate) / timelineCoordinateDelta;
497
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
498
                    }
499
                }
500
                else
501
                    simulationTime = eventSimulationTime;
502
            }
503
            break;
504
        default:
505
            throw opp_runtime_error("Unknown timeline mode");
506
    }
507

    
508
    Assert(!simulationTime.isNaN());
509
    Assert(simulationTime >= BigDecimal::Zero);
510
    /*if (timelineMode != REAL_TIME)
511
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
512
    */
513
    return simulationTime;
514
}
515

    
516
double SequenceChartFacade::getTimelineCoordinateForSimulationTime(simtime_t simulationTime, bool upperLimit)
517
{
518
    Assert(!simulationTime.isNaN());
519

    
520
    if (eventLog->isEmpty())
521
        return 0;
522

    
523
    Assert(simulationTime >= BigDecimal::Zero);
524
    /*if (timelineMode != REAL_TIME)
525
        Assert(simulationTime <= eventLog->getLastEvent()->getSimulationTime());
526
    */
527

    
528
    double timelineCoordinate;
529

    
530
    switch (timelineMode)
531
    {
532
        case REAL_TIME:
533
            //treat simulationTime as real time:
534
            timelineCoordinate = simulationTime.dbl() - timelineCoordinateOriginRealTime;
535
            break;
536
        case SIMULATION_TIME:
537
            timelineCoordinate = (simulationTime - timelineCoordinateOriginSimulationTime).dbl();
538
            break;
539
        case EVENT_NUMBER:
540
        case STEP:
541
        case NONLINEAR:
542
            {
543
                IEvent *nextEvent;
544
                simtime_t eventSimulationTime, nextEventSimulationTime, simulationTimeDelta;
545
                double eventTimelineCoordinate, nextEventTimelineCoordinate, timelineCoordinateDelta;
546

    
547
                IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
548
                extractSimulationTimesAndTimelineCoordinates(event, nextEvent,
549
                                                             eventSimulationTime, eventTimelineCoordinate,
550
                                                             nextEventSimulationTime, nextEventTimelineCoordinate,
551
                                                             simulationTimeDelta, timelineCoordinateDelta);
552

    
553
                if (nextEvent) {
554
                    if (simulationTimeDelta == BigDecimal::Zero) {
555
                        // IMPORTANT NOTE: this is just an approximation
556
                        if (upperLimit)
557
                            timelineCoordinate = nextEventTimelineCoordinate;
558
                        else
559
                            timelineCoordinate = eventTimelineCoordinate;
560
                    }
561
                    else {
562
                        simulationTime = max(eventSimulationTime, min(nextEventSimulationTime, simulationTime));
563
                        timelineCoordinate = eventTimelineCoordinate + timelineCoordinateDelta * (simulationTime - eventSimulationTime).dbl() / simulationTimeDelta.dbl();
564
                        timelineCoordinate = std::max(eventTimelineCoordinate, std::min(nextEventTimelineCoordinate, timelineCoordinate));
565
                    }
566
                }
567
                else
568
                    timelineCoordinate = eventTimelineCoordinate;
569
            }
570
            break;
571
        default:
572
            throw opp_runtime_error("Unknown timeline mode");
573
    }
574

    
575
    Assert(!isNaN(timelineCoordinate));
576

    
577
    return timelineCoordinate;
578
}
579

    
580
double SequenceChartFacade::getTimelineCoordinateForSimulationTimeAndEventInModule(simtime_t simulationTime, int moduleId)
581
{
582
    IEvent *event = eventLog->getLastEventNotAfterSimulationTime(simulationTime);
583

    
584
    while (event && event->getSimulationTime() == simulationTime) {
585
        if (event->getModuleId() == moduleId)
586
            return getTimelineCoordinate(event);
587

    
588
        event = event->getNextEvent();
589
    }
590

    
591
    return getTimelineCoordinateForSimulationTime(simulationTime);
592
}
593

    
594
std::vector<ptr_t> *SequenceChartFacade::getModuleMethodBeginEntries(ptr_t startEventPtr, ptr_t endEventPtr)
595
{
596
    IEvent *startEvent = (IEvent *)startEventPtr;
597
    IEvent *endEvent = (IEvent *)endEventPtr;
598
    Assert(startEvent);
599
    Assert(endEvent);
600
    std::vector<ptr_t> *moduleMethodBeginEntries = new std::vector<ptr_t>();
601

    
602
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
603
        eventLog->progress();
604

    
605
        for (int i = 0; i < event->getNumEventLogEntries(); i++) {
606
            EventLogEntry *eventLogEntry = event->getEventLogEntry(i);
607

    
608
            if (dynamic_cast<ModuleMethodBeginEntry *>(eventLogEntry))
609
                moduleMethodBeginEntries->push_back((ptr_t)eventLogEntry);
610
        }
611

    
612
        if (event == endEvent)
613
            break;
614
    }
615

    
616
    return moduleMethodBeginEntries;
617
}
618

    
619
std::vector<ptr_t> *SequenceChartFacade::getIntersectingMessageDependencies(ptr_t startEventPtr, ptr_t endEventPtr)
620
{
621
    IEvent *startEvent = (IEvent *)startEventPtr;
622
    IEvent *endEvent = (IEvent *)endEventPtr;
623
    Assert(startEvent);
624
    Assert(endEvent);
625
    std::set<ptr_t> messageDependencies;
626
    eventnumber_t startEventNumber = startEvent->getEventNumber();
627

    
628
    // TODO: LONG RUNNING OPERATION
629
    // this might take a while if start and end events are far away from each other
630
    // if not completed then some dependencies will not be included
631
    for (IEvent *event = startEvent;; event = event->getNextEvent()) {
632
        eventLog->progress();
633
        IMessageDependencyList *causes = event->getCauses();
634

    
635
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
636
            IMessageDependency *messageDependency = *it;
637

    
638
            if (messageDependency->getCauseEventNumber() < startEventNumber)
639
                messageDependencies.insert((ptr_t)messageDependency);
640
        }
641

    
642
        IMessageDependencyList *consequences = event->getConsequences();
643

    
644
        for (IMessageDependencyList::iterator it = consequences->begin(); it != consequences->end(); it++)
645
            messageDependencies.insert((ptr_t)*it);
646

    
647
        if (event == endEvent)
648
            break;
649
    }
650

    
651
    std::vector<ptr_t> *result = new std::vector<ptr_t>;
652
    result->resize(messageDependencies.size());
653
    std::copy(messageDependencies.begin(), messageDependencies.end(), result->begin());
654

    
655
    return result;
656
}
657

    
658
std::vector<int> SequenceChartFacade::getApproximateMessageDependencyCountAdjacencyMatrix(std::map<int, int> *moduleIdToAxisIndexMap, int numberOfSamples, int messageSendWeight, int messageReuseWeight)
659
{
660
    LCGRandom lcgRandom;
661
    std::vector<int> adjacencyMatrix;
662
    std::set<int> axisIndexSet;
663
    std::map<eventnumber_t, IEvent *> eventNumberToEventMap;
664

    
665
    for (std::map<int, int>::iterator it = moduleIdToAxisIndexMap->begin(); it != moduleIdToAxisIndexMap->end(); it++)
666
        axisIndexSet.insert(it->second);
667

    
668
    int numberOfAxes = axisIndexSet.size();
669
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
670

    
671
    for (int i = 0; i < numberOfSamples; i++)
672
    {
673
        // draw random
674
        double percentage = lcgRandom.next01();
675
        IEvent *event = eventLog->getApproximateEventAt(percentage);
676
        eventNumberToEventMap[event->getEventNumber()] = event;
677

    
678
        // look before origin
679
        if (timelineCoordinateOriginEventNumber != -1) {
680
            if (timelineCoordinateOriginEventNumber - i >= 0) {
681
                event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber - i);
682
                if (event)
683
                    eventNumberToEventMap[event->getEventNumber()] = event;
684
            }
685

    
686
            // look after origin
687
            event = eventLog->getEventForEventNumber(timelineCoordinateOriginEventNumber + i);
688
            if (event)
689
                eventNumberToEventMap[event->getEventNumber()] = event;
690
        }
691
    }
692

    
693
    for (std::map<eventnumber_t, IEvent *>::iterator it = eventNumberToEventMap.begin(); it != eventNumberToEventMap.end(); it++) {
694
        IEvent *event = it->second;
695
        IMessageDependencyList *causes = event->getCauses();
696

    
697
        for (IMessageDependencyList::iterator it = causes->begin(); it != causes->end(); it++) {
698
            IMessageDependency *messageDependency = *it;
699
            IEvent *causeEvent = messageDependency->getCauseEvent();
700
            IEvent *consequenceEvent = messageDependency->getConsequenceEvent();
701
            int weight = messageDependency->getIsReuse() ? messageReuseWeight : messageSendWeight;
702

    
703
            if (causeEvent && consequenceEvent && weight != 0) {
704
                int causeModuleId = causeEvent->getModuleId();
705
                int consequenceModuleId = consequenceEvent->getModuleId();
706

    
707
                std::map<int, int>::iterator causeModuleIdIt = moduleIdToAxisIndexMap->find(causeModuleId);
708
                std::map<int, int>::iterator consequenceModuleIdIt = moduleIdToAxisIndexMap->find(consequenceModuleId);
709

    
710
                if (causeModuleIdIt !=  moduleIdToAxisIndexMap->end() && consequenceModuleIdIt != moduleIdToAxisIndexMap->end())
711
                    adjacencyMatrix.at(causeModuleIdIt->second * numberOfAxes + consequenceModuleIdIt->second) += weight;
712
            }
713
        }
714
    }
715

    
716
    return adjacencyMatrix;
717
}
718

    
719

    
720
long SequenceChartFacade::getSmallestEventComplexity() {
721
    long complexity = 0;
722
    if (smallestComplexity < 0) {
723
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
724
             if (event->getEventEndEntry()) {
725
                 complexity = event->getEventEndEntry()->complexity;
726
             } else {
727
                 continue;
728
             }
729
             if (complexity < smallestComplexity || smallestComplexity < 0) {
730
                 smallestComplexity = complexity;
731
             }
732
             if (complexity > largestComplexity || largestComplexity < 0) {
733
                 largestComplexity = complexity;
734
             }
735
        }
736
    }
737
    if (smallestComplexity < 0) {
738
        smallestComplexity = 0;
739
    }
740
    return smallestComplexity;
741
}
742

    
743
long SequenceChartFacade::getLargestEventComplexity() {
744
    if (largestComplexity < 0) {
745
        getSmallestEventComplexity();
746
    }
747
    if (largestComplexity < 0) {
748
        largestComplexity = 0;
749
    }
750
    return largestComplexity;
751
}
752

    
753
simtime_t SequenceChartFacade::getSmallestEventDuration() {
754
    simtime_t duration = 0;
755
    if (smallestDuration < 0) {
756
        for (IEvent *event = eventLog->getFirstEvent();event != eventLog->getLastEvent(); event = event->getNextEvent()) {
757
             if (event->getEventEntry()) {
758
                 duration = event->getEventEntry()->duration;
759
             } else {
760
                 continue;
761
             }
762
             if (duration < smallestDuration || smallestDuration < 0) {
763
                 smallestDuration = duration;
764
             }
765
             if (duration > largestDuration || largestDuration < 0) {
766
                 largestDuration = duration;
767
             }
768
        }
769
    }
770
    if (smallestDuration < 0) {
771
        smallestDuration = 0;
772
    }
773
    return smallestDuration;
774
}
775

    
776
simtime_t SequenceChartFacade::getLargestEventDuration() {
777
    if (largestDuration < 0) {
778
        getSmallestEventComplexity();
779
    }
780
    if (largestDuration < 0) {
781
        largestDuration = 0;
782
    }
783
    return largestDuration;
784
}
785

    
786

    
787
IEvent* SequenceChartFacade::getPreviousBottleneck(IEvent* e, double threshold) {
788
    IEvent* next = e->getPreviousEvent();
789
    while (next) {
790
        if (isBottleneck(next,threshold)) {
791
            return next;
792
        }
793
        next = next->getPreviousEvent();
794
    }
795
    return e;
796
}
797

    
798
IEvent* SequenceChartFacade::getNextBottleneck(IEvent* e, double threshold) {
799
    IEvent* next = e->getNextEvent();
800
    while (next) {
801
        if (isBottleneck(next,threshold)) {
802
            return next;
803
        }
804
        next = next->getNextEvent();
805
    }
806
    return e;
807
}
808

    
809
/*
810
 * Returns whether an event not part of a set of parallel events with more than treshold elements.
811
 */
812
bool SequenceChartFacade::isBottleneck(IEvent* event, double threshold)
813
{
814
    if (isOnCriticalPath(event)) {
815
        return getOverlappingQuotient((ptr_t)event) <= threshold;
816
    }
817
    return false;
818
}
819
/*
820
 * Returns whether event is in the largest parallel set of selected.
821
 */
822
bool SequenceChartFacade::isParallelWithEvent(IEvent* event, IEvent* selected) {
823

    
824
    if (lastSelected != selected) {
825
        getLargestParallelSet(selected, &cachedParallelSet);
826
    }
827
    return cachedParallelSet.find((ptr_t)event) != cachedParallelSet.end();
828
}
829
/*
830
 * Returns the size of the largest set that is parallel with event.
831
 *
832
 * Works by calculating the first parallel set which does not contain event by
833
 * successively going backwards through all events starting from event.
834
 */
835
unsigned int SequenceChartFacade::getLargestParallelSetSize(IEvent* event)
836
{
837
    IEvent* prev = event;
838
    std::set<ptr_t> parallelSet;
839
    parallelSet.clear();
840
    unsigned int previousSize = 0;
841
    while (prev)
842
    {
843
        previousSize = parallelSet.size();
844

    
845
        getParallelSet(prev, &parallelSet);
846

    
847
        if (parallelSet.find((ptr_t) event) == parallelSet.end())
848
        {
849
            //The current set does not contain event.
850
            //Therefore the previous set was the largest Parallel Set.
851
            break;
852
        }
853
        prev = prev->getPreviousEvent();
854
    }
855
    return previousSize;
856
}
857
/*
858
 * Returns the largest set that is parallel with event.
859
 *
860
 * Works by calculating the first parallel set which does not contain event by
861
 * successively going backwards through all events starting from event.
862
 */
863
std::set<ptr_t>* SequenceChartFacade::getLargestParallelSet(IEvent* event, std::set<ptr_t>* parallelSet) {
864
    IEvent* prev = event;
865
    parallelSet->clear();
866
    while (prev)
867
    {
868
        getParallelSet(prev, parallelSet);
869
        if (parallelSet->find((ptr_t) event) == parallelSet->end())
870
        {
871
            //The current set does not contain event.
872
            //Therefore the previous set was the largest Parallel Set.
873
            break;
874
        }
875
        prev = prev->getPreviousEvent();
876
    }
877
    if (prev != event) {
878
        getParallelSet(prev->getNextEvent(), parallelSet);
879
    }
880
    return parallelSet;
881
}
882

    
883
/*
884
 * Calculates a set of those events that start after event but are still in parallel to event.
885
 * This means that no other event must end before the latest start time in this set.
886
 */
887
void SequenceChartFacade::getParallelSet(IEvent* event,
888
        std::set<ptr_t>* parallelSet)
889
{
890
    IEvent* next = event->getNextEvent();
891
    simtime_t smallestParallelEndtime = getSmallestParallelEndtime(event);
892
    parallelSet->clear();
893
    parallelSet->insert((ptr_t) event);
894
    while (next)
895
    {
896
        if ((next->getSimulationTime() >= event->getSimulationTime())
897
                && (smallestParallelEndtime >= next->getSimulationTime()))
898
        {
899
            if(parallelSet->find((ptr_t)(next->getCauseEvent())) == parallelSet->end()) {
900
                parallelSet->insert((ptr_t) next);
901
            }
902
        }
903
        else
904
        {
905
            break;
906
        }
907
        next = next->getNextEvent();
908
    }
909
}
910
/*
911
 *
912
 */
913
simtime_t SequenceChartFacade::getSmallestParallelEndtime(IEvent* event)
914
{
915
    simtime_t minimum = event->getSimulationTime()
916
            + event->getEventEntry()->duration;
917
    for (IEvent *current = eventLog->getFirstEvent(); current; current
918
            = current->getNextEvent())
919
    {
920
        if (current->getSimulationTime() >= event->getSimulationTime())
921
        {
922
            if ((current->getSimulationTime()
923
                    + current->getEventEntry()->duration)
924
                    > event->getSimulationTime())
925
            {
926
                if (minimum > (current->getSimulationTime()
927
                        + current->getEventEntry()->duration))
928
                {
929
                    minimum = current->getSimulationTime()
930
                            + current->getEventEntry()->duration;
931
                }
932
            }
933
            if (current->getSimulationTime() > minimum)
934
            { // After this, no overlapping can follow
935
                break;
936
            }
937
        }
938
    }
939
    return minimum;
940
}
941

    
942
/*
943
 * Determines whether the event lies on the critical path
944
 */
945
bool SequenceChartFacade::isOnCriticalPath(IEvent* event) {
946
    if (cachedCriticalPath.empty()) {
947
        calculateCriticalPath();
948
    }
949
    return (cachedCriticalPath.find((ptr_t)event) != cachedCriticalPath.end());
950
}
951

    
952
/*
953
 * Calculates the critical path of the run and stores it in the set cachedCriticalPath
954
 * Caches the earliestStartTimes of all events
955
 */
956
void SequenceChartFacade::calculateCriticalPath() {
957
    long maxEarliestProcessingTime = 0;
958
    IEvent* maxEarliestProcessingTimeEvent;
959

    
960
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
961
        simtime_t startTime = current->getSimulationTime();
962
        int moduleId = current->getModuleId();
963
        if(current->getEventEndEntry()) {
964
            current->_earliestProcessingTime = current->getComplexity();
965
        }
966

    
967
        current->setCriticalPredecessor(eventLog->getFirstEvent());
968

    
969
        for (IEvent *antecessor = eventLog->getFirstEvent(); antecessor; antecessor = antecessor->getNextEvent()) {
970
            if(antecessor==current) {
971
                break; //We have to consider earlier events only
972
            }
973
            if(antecessor->getModuleId() != moduleId && current->getCauseEvent() != antecessor) {
974
                continue; // Check if this is an antecessor
975
            }
976
            if(antecessor->_earliestProcessingTime+current->getComplexity() > current->_earliestProcessingTime) {
977
                current->_earliestProcessingTime = antecessor->_earliestProcessingTime+current->getComplexity();
978
                current->setCriticalPredecessor(antecessor);
979
            }
980
        }
981
        // Memorize max event
982
        if (maxEarliestProcessingTime < current->_earliestProcessingTime) {
983
            maxEarliestProcessingTime = current->_earliestProcessingTime;
984
            maxEarliestProcessingTimeEvent = current;
985
        }
986
    }
987
    //Cache an additional event ordering sorted by their earliestStartingTimes
988
    cacheRealTimeEventOrder();
989

    
990
    //Now produce the convex hull of critical antecessors/predecessors:
991
    cachedCriticalPath.clear();
992
    //Cache largest processing time:
993
    biggestEarliestProcessingTime = maxEarliestProcessingTime / 1000000.0;
994
    biggestEarliestProcessingTimeEvent = maxEarliestProcessingTimeEvent;
995
    for (IEvent *predecessor = maxEarliestProcessingTimeEvent; predecessor ; predecessor = predecessor->getCriticalPredecessor()) {
996
        cachedCriticalPath.insert((ptr_t)predecessor);
997
        if(predecessor->getEventNumber() == 0) {
998
            break;
999
        }
1000
    }
1001
}
1002
/*
1003
 * Returns the event with the largest calculated earliest Processing time in REAL_TIME mode
1004
 * or the largest endtime in other modes within the given event range.
1005
 */
1006
ptr_t SequenceChartFacade::getLargestEndtimeInEventRange(ptr_t startEventPtr,
1007
        ptr_t endEventPtr, bool duration)
1008
{
1009
    IEvent *startEvent = (IEvent *) startEventPtr;
1010
    IEvent *endEvent = (IEvent *) endEventPtr;
1011
    switch (timelineMode)
1012
    {
1013
    case REAL_TIME:
1014
    {
1015
        //Use cached result when range contains all events
1016
        if (startEvent == eventLog->getFirstEvent() && endEvent
1017
                == eventLog->getLastEvent())
1018
        {
1019
            return (ptr_t) biggestEarliestProcessingTimeEvent;
1020
        }
1021

    
1022
        long largest = 0;
1023
        IEvent* largestEvent = startEvent;
1024

    
1025
        for (IEvent* current = startEvent; current; current
1026
                = current->getNextEvent())
1027
        {
1028
            long temp = current->getEarliestProcessingTime();
1029
            if (temp > largest)
1030
            {
1031
                largest = temp;
1032
                largestEvent = current;
1033
            }
1034
            if (current == endEvent)
1035
            {
1036
                break;
1037
            }
1038
        }
1039
        return (ptr_t) largestEvent;
1040
    }
1041
    case SIMULATION_TIME:
1042
    case EVENT_NUMBER:
1043
    case STEP:
1044
    case NONLINEAR:
1045
    default:
1046
    {
1047
        if (!duration) {
1048
            return endEventPtr;
1049
        }
1050
        //Use cached result when range contains all events
1051
        if (startEvent == eventLog->getFirstEvent() && endEvent
1052
                == eventLog->getLastEvent() && biggestEndTimeEvent != NULL)
1053
        {
1054
            return (ptr_t) biggestEndTimeEvent;
1055
        }
1056
        simtime_t largest = 0;
1057
        IEvent* largestEvent = endEvent;
1058

    
1059
        for (IEvent* current = endEvent; current; current
1060
                = current->getPreviousEvent())
1061
        {
1062
            simtime_t temp = current->getSimulationTime()
1063
                    + current->getEventEntry()->duration;
1064
            if (temp > largest)
1065
            {
1066
                largest = temp;
1067
                largestEvent = current;
1068
            }
1069
            if (current == startEvent)
1070
            {
1071
                break;
1072
            }
1073
        }
1074
        if (startEvent == eventLog->getFirstEvent() && endEvent
1075
                == eventLog->getLastEvent())
1076
        {
1077
            biggestEndTimeEvent = largestEvent;
1078
        }
1079

    
1080
        return (ptr_t) largestEvent;
1081
    }
1082
    }
1083

    
1084
}
1085

    
1086
double SequenceChartFacade::getOverlapping(ptr_t eventPtr) {
1087
    long overlapping = 0;
1088
    IEvent* event = (IEvent*) eventPtr;
1089

    
1090
    long eventProcessingTime = event->getEarliestProcessingTime();
1091
    long eventStartTime = event->getEarliestStartTime();
1092

    
1093
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1094

    
1095
        if(current->getComplexity() == 0) {
1096
            continue;
1097
        }
1098

    
1099
        long currentStartTime = current->getEarliestStartTime();
1100
        long currentProcessingTime = current->getEarliestProcessingTime();
1101

    
1102
        if(eventStartTime <= currentStartTime && eventProcessingTime >= currentStartTime) {
1103
            overlapping += eventProcessingTime - currentStartTime;
1104
        } else if (currentStartTime <= eventStartTime && currentProcessingTime >= eventStartTime) {
1105
            overlapping += currentProcessingTime - eventStartTime;
1106
        } else if (currentStartTime <= eventStartTime && currentProcessingTime >= eventProcessingTime) {
1107
            overlapping += event->getComplexity();
1108
        }
1109
    }
1110
    return overlapping / (event->getComplexity() * 1.0);
1111
}
1112

    
1113
double SequenceChartFacade::getMaximumOverlapping() {
1114
    double maxOverlapping = 0;
1115
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1116
        if(!isOnCriticalPath(current) || current->getComplexity() == 0) {
1117
            continue;
1118
        }
1119
        double overlapping = getOverlapping((ptr_t) current);
1120
        if (overlapping > maxOverlapping){
1121
            maxOverlapping = overlapping;
1122
        }
1123
    }
1124
    return maxOverlapping;
1125
}
1126

    
1127
/*
1128
 * returns the quotient of
1129
 * relative overlapping cputime with the event / maximum relative overlapping
1130
 * cputime with any event of the critical path
1131
 */
1132
double SequenceChartFacade::getOverlappingQuotient(ptr_t eventPtr) {
1133

    
1134
    if (((IEvent*)eventPtr)->getComplexity() == 0) {
1135
        return 0;
1136
    }
1137
    double overlapping = getOverlapping(eventPtr);
1138

    
1139
    if (maximumOverlapping == -1) {
1140
        maximumOverlapping = getMaximumOverlapping();
1141
    }
1142

    
1143
    return overlapping / maximumOverlapping;
1144
}
1145

    
1146
bool SequenceChartFacade::isOverlappingInRealTimeDomain(ptr_t eventPtr1, ptr_t eventPtr2) {
1147
    long eventProcessingTime1 = ((IEvent*)eventPtr1)->getEarliestProcessingTime();
1148
    long eventStartTime1 = ((IEvent*)eventPtr1)->getEarliestStartTime();
1149
    long eventProcessingTime2 = ((IEvent*)eventPtr2)->getEarliestProcessingTime();
1150
    long eventStartTime2 = ((IEvent*)eventPtr2)->getEarliestStartTime();
1151

    
1152
    return !(eventProcessingTime1 < eventStartTime2 || eventProcessingTime2 < eventStartTime1);
1153
}
1154

    
1155

    
1156
bool compare_events_realtime (IEvent* a, IEvent* b)
1157
{
1158
  return a->getEarliestStartTime() <= b->getEarliestStartTime();
1159
}
1160

    
1161

    
1162
void SequenceChartFacade::cacheRealTimeEventOrder() {
1163
    //First Event is the same in both domains
1164
    eventLog->setFirstEventRealTime((Event*)eventLog->getFirstEvent());
1165
    int i = 0;
1166
    std::list<IEvent*> eventMap;
1167
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1168
        i++;
1169
        eventMap.push_back(current);
1170
    }
1171
    eventMap.sort(compare_events_realtime);
1172

    
1173
    IEvent* current = NULL;
1174
    IEvent* prev = NULL;
1175
    for (std::list<IEvent*>::iterator it = eventMap.begin(); it != eventMap.end(); it++) {
1176
        current = *it;
1177
        if (prev != NULL) {
1178
            prev->setNextEventRealTime(current);
1179
            current->setPreviousEventRealTime(prev);
1180
        }
1181
        prev = current;
1182
    }
1183
    //Set last event in eventlog
1184
    eventLog->setLastEventRealTime((Event*)prev);
1185
    //Test:
1186
    for (IEvent *current = eventLog->getFirstEventRealTime(); current; current = current->getNextEventRealTime()) {
1187
        printf("event %i, simtime %f, time %i \n",current->getEventNumber(), current->getSimulationTime().dbl(), current->getEarliestStartTime());
1188
    }
1189

    
1190

    
1191
}