Added GUITest, ManualSwitch and one method to Timeline
[Mograsim.git] / era.mi / src / era / mi / logic / timeline / Timeline.java
1 package era.mi.logic.timeline;\r
2 \r
3 import java.util.PriorityQueue;\r
4 \r
5 /**\r
6  * Orders Events by the time they are due to be executed. Can execute Events individually.\r
7  * @author Fabian Stemmler\r
8  *\r
9  */\r
10 public class Timeline\r
11 {\r
12         private PriorityQueue<InnerEvent> events;\r
13         private long currentTime = 0;\r
14         \r
15         public Timeline(int initCapacity)\r
16         {\r
17                 events = new PriorityQueue<InnerEvent>(initCapacity, (a, b) -> {\r
18                         long difference = a.getTiming() - b.getTiming();\r
19                         if(difference == 0)\r
20                                 return 0;\r
21                         return difference < 0 ? -1 : 1;\r
22                 });\r
23         }\r
24         \r
25         public boolean hasNext()\r
26         {\r
27                 return !events.isEmpty();\r
28         }\r
29 \r
30         public void executeNext()\r
31         {\r
32                 InnerEvent first = events.poll();\r
33                 currentTime = first.getTiming();\r
34                 first.run();\r
35         }\r
36         \r
37         public void executeAll()\r
38         {\r
39                 while (hasNext())\r
40                         executeNext();\r
41         }\r
42         \r
43         /**\r
44          * Executes all events up to a given simulation timestamp. The simulation\r
45          * process can be constrained by a real world timestamp.\r
46          * \r
47          * @param timestamp  the simulation timestamp up to which the events will be\r
48          *                   processed\r
49          * @param stopMillis the System.currentTimeMillis() when simulation definitely\r
50          *                   needs to stop.\r
51          * @return if it was possible to fulfil the goal in the given real world time.\r
52          * @author Christian Femers\r
53          */\r
54         public ExecutionResult executeUpTo(long timestamp, long stopMillis)\r
55         {\r
56                 if (events.isEmpty())\r
57                 {\r
58                         currentTime = timestamp;\r
59                         return ExecutionResult.NOTHING_DONE;\r
60                 }\r
61                 int checkStop = 0;\r
62                 InnerEvent first = events.peek();\r
63                 while (first != null && first.getTiming() <= timestamp)\r
64                 {\r
65                         events.remove();\r
66                         currentTime = first.getTiming();\r
67                         first.run();\r
68                         // Don't check after every run\r
69                         checkStop = (checkStop + 1) % 10;\r
70                         if (checkStop == 0 && System.currentTimeMillis() >= stopMillis)\r
71                                 return ExecutionResult.RAN_OUT_OF_TIME;\r
72                         first = events.peek();\r
73                 }\r
74                 currentTime = timestamp;\r
75                 return ExecutionResult.DONE_IN_TIME;\r
76         }\r
77 \r
78         public long getSimulationTime()\r
79         {\r
80                 return currentTime;\r
81         }\r
82         \r
83         public void reset()\r
84         {\r
85                 events.clear();\r
86                 currentTime = 0;\r
87         }\r
88         \r
89         /**\r
90          * Adds an Event to the {@link Timeline}\r
91          * @param function The {@link TimelineEventHandler} that will be executed, when the {@link InnerEvent} occurs on the timeline.\r
92          * @param relativeTiming The amount of MI ticks in which the {@link InnerEvent} is called, starting from the current time.\r
93          */\r
94         public void addEvent(TimelineEventHandler function, int relativeTiming)\r
95         {\r
96                 long timing = currentTime + relativeTiming;\r
97                 events.add(new InnerEvent(function, new TimelineEvent(timing), timing));\r
98         }\r
99         \r
100         private class InnerEvent\r
101         {\r
102 \r
103                 private final long timing;\r
104                 private final TimelineEventHandler function;\r
105                 private final TimelineEvent event;\r
106                 \r
107                 /**\r
108                  * Creates an {@link InnerEvent}\r
109                  * @param function {@link TimelineEventHandler} to be executed when the {@link InnerEvent} occurs\r
110                  * @param timing Point in the MI simulation {@link Timeline}, at which the {@link InnerEvent} is executed;\r
111                  */\r
112                 InnerEvent(TimelineEventHandler function, TimelineEvent event, long timing)\r
113                 {\r
114                         this.function = function;\r
115                         this.event = event;\r
116                         this.timing = timing;\r
117                 }\r
118 \r
119                 public long getTiming()\r
120                 {\r
121                         return timing;\r
122                 }\r
123                 \r
124                 public void run()\r
125                 {\r
126                         function.handle(event);\r
127                 }\r
128                 \r
129                 @Override\r
130                 public String toString()\r
131                 {\r
132                         return event.toString();\r
133                 }\r
134         }\r
135         \r
136         @Override\r
137         public String toString()\r
138         {\r
139                 return "simulation time: " + currentTime + ", " + events.toString();\r
140         }\r
141         \r
142         public static long toNanoseconds(long ticks)\r
143         {\r
144                 return ticks; //TODO: Alter this when it has been determined how ticks should relate to real time.\r
145         }\r
146         \r
147         public enum ExecutionResult\r
148         {\r
149                 NOTHING_DONE, DONE_IN_TIME, RAN_OUT_OF_TIME \r
150         }\r
151 }