Statistics
| Branch: | Revision:

root / src / eventlog / sequencechartfacade.cc @ 9bd9afa7

History | View | Annotate | Download (44.2 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
            IEvent* res = eventLog->getFirstEventRealTime();
323
            for (IEvent *current = eventLog->getFirstEventRealTime(); current; current = current->getNextEventRealTime()) {
324
                if ((double) current->getEarliestStartTime() / 1000000.0 < timelineCoordinate) {
325
                    if (current->getEarliestStartTime() > res->getEarliestStartTime()) {
326
                        res = current;
327
                    }
328
                } else {
329
                    break;
330
                }
331
            }
332
            return res;
333
        }
334
        case SIMULATION_TIME:
335
            return eventLog->getLastEventNotAfterSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
336
        case EVENT_NUMBER:
337
            {
338
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
339

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

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

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

    
365
    switch (timelineMode) {
366
        case REAL_TIME:
367
        {
368
            IEvent* res = eventLog->getLastEventRealTime();
369
            for (IEvent *current = eventLog->getFirstEventRealTime(); current; current = current->getNextEventRealTime()) {
370
                if ((double) current->getEarliestStartTime() / 1000000.0 > timelineCoordinate) {
371
                    if (current->getEarliestStartTime() < res->getEarliestStartTime()) {
372
                        res = current;
373
                    }
374
                } else {
375
                    break;
376
                }
377
            }
378
            return res;
379
        }
380
        case SIMULATION_TIME:
381
            return eventLog->getFirstEventNotBeforeSimulationTime(getSimulationTimeForTimelineCoordinate(timelineCoordinate));
382
        case EVENT_NUMBER:
383
            {
384
                eventnumber_t eventNumber = (eventnumber_t)floor(timelineCoordinate) + timelineCoordinateOriginEventNumber;
385

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

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

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

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

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

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

    
444
        nextEventTimelineCoordinate = getTimelineCoordinate(nextEvent);
445

    
446
        simulationTimeDelta = nextEventSimulationTime - eventSimulationTime;
447
        timelineCoordinateDelta = nextEventTimelineCoordinate - eventTimelineCoordinate;
448
    }
449
}
450

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

    
455
    if (eventLog->isEmpty())
456
        return BigDecimal::Zero;
457

    
458
    simtime_t simulationTime;
459

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

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

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

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

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

    
522
    if (eventLog->isEmpty())
523
        return 0;
524

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

    
530
    double timelineCoordinate;
531

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

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

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

    
577
    Assert(!isNaN(timelineCoordinate));
578

    
579
    return timelineCoordinate;
580
}
581

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

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

    
590
        event = event->getNextEvent();
591
    }
592

    
593
    return getTimelineCoordinateForSimulationTime(simulationTime);
594
}
595

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

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

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

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

    
614
        if (event == endEvent)
615
            break;
616
    }
617

    
618
    return moduleMethodBeginEntries;
619
}
620

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

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

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

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

    
644
        IMessageDependencyList *consequences = event->getConsequences();
645

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

    
649
        if (event == endEvent)
650
            break;
651
    }
652

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

    
657
    return result;
658
}
659

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

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

    
670
    int numberOfAxes = axisIndexSet.size();
671
    adjacencyMatrix.resize(numberOfAxes * numberOfAxes);
672

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

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

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

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

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

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

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

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

    
718
    return adjacencyMatrix;
719
}
720

    
721

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

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

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

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

    
788

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

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

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

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

    
847
        getParallelSet(prev, &parallelSet);
848

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

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

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

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

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

    
969
        current->setCriticalPredecessor(eventLog->getFirstEvent());
970

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

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

    
1024
        long largest = 0;
1025
        IEvent* largestEvent = startEvent;
1026

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

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

    
1082
        return (ptr_t) largestEvent;
1083
    }
1084
    }
1085

    
1086
}
1087

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

    
1092
    long eventProcessingTime = event->getEarliestProcessingTime();
1093
    long eventStartTime = event->getEarliestStartTime();
1094

    
1095
    for (IEvent *current = eventLog->getFirstEventRealTime(); current; current = current->getNextEventRealTime()) {
1096

    
1097
        if(current->getComplexity() == 0) {
1098
            continue;
1099
        }
1100

    
1101
        long currentStartTime = current->getEarliestStartTime();
1102
        long currentProcessingTime = current->getEarliestProcessingTime();
1103

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

    
1112
        if (current->getEarliestStartTime() > eventProcessingTime) {
1113
            break;
1114
        }
1115
    }
1116
    return overlapping / (event->getComplexity() * 1.0);
1117
}
1118

    
1119
double SequenceChartFacade::getMaximumOverlapping() {
1120
    double maxOverlapping = 0;
1121
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1122
        if(!isOnCriticalPath(current) || current->getComplexity() == 0) {
1123
            continue;
1124
        }
1125
        double overlapping = getOverlapping((ptr_t) current);
1126
        if (overlapping > maxOverlapping){
1127
            maxOverlapping = overlapping;
1128
        }
1129
    }
1130
    return maxOverlapping;
1131
}
1132

    
1133
/*
1134
 * returns the quotient of
1135
 * relative overlapping cputime with the event / maximum relative overlapping
1136
 * cputime with any event of the critical path
1137
 */
1138
double SequenceChartFacade::getOverlappingQuotient(ptr_t eventPtr) {
1139

    
1140
    if (((IEvent*)eventPtr)->getComplexity() == 0) {
1141
        return 0;
1142
    }
1143
    double overlapping = getOverlapping(eventPtr);
1144

    
1145
    if (maximumOverlapping == -1) {
1146
        maximumOverlapping = getMaximumOverlapping();
1147
    }
1148

    
1149
    return overlapping / maximumOverlapping;
1150
}
1151

    
1152
bool SequenceChartFacade::isOverlappingInRealTimeDomain(ptr_t eventPtr1, ptr_t eventPtr2) {
1153
    long eventProcessingTime1 = ((IEvent*)eventPtr1)->getEarliestProcessingTime();
1154
    long eventStartTime1 = ((IEvent*)eventPtr1)->getEarliestStartTime();
1155
    long eventProcessingTime2 = ((IEvent*)eventPtr2)->getEarliestProcessingTime();
1156
    long eventStartTime2 = ((IEvent*)eventPtr2)->getEarliestStartTime();
1157

    
1158
    return !(eventProcessingTime1 < eventStartTime2 || eventProcessingTime2 < eventStartTime1);
1159
}
1160

    
1161

    
1162
bool compare_events_realtime (IEvent* a, IEvent* b)
1163
{
1164
  return a->getEarliestStartTime() <= b->getEarliestStartTime();
1165
}
1166

    
1167

    
1168
void SequenceChartFacade::cacheRealTimeEventOrder() {
1169
    //First Event is the same in both domains
1170
    eventLog->setFirstEventRealTime((Event*)eventLog->getFirstEvent());
1171
    int i = 0;
1172
    std::list<IEvent*> eventMap;
1173
    for (IEvent *current = eventLog->getFirstEvent(); current; current = current->getNextEvent()) {
1174
        i++;
1175
        eventMap.push_back(current);
1176
    }
1177
    eventMap.sort(compare_events_realtime);
1178

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

    
1196

    
1197
}