event_queue - 

Register, update and discard events in a timeline.

A queue of event is used to register objects associated with a start time and a duration and to return them when they are active.

The main class is EventQueue. It controls a timeline and register events. Event can be any kind of object, usually specific time-related domain objects should be used.

The auxiliary class EventInfo registers and control information about each event. It can also be used for fluent programming and create new events relatively to existing ones.

Basic usage

The event queue is created empty, and can handle any kind of data.

var eq = new EventQueue[String]

To register an event, add it with a start time and a duration. Note that the time is relative to the current time frame in the queue.

eq.add("1..2", 1.0, 1.0)
eq.add("2..10", 2.0, 8.0)

To register instantaneous event, use a 0.0 duration (or no duration)

eq.add("1.5", 1.5)

To get active events, use update with a time difference. This returns a sequence of currently active events.

var es = eq.update(1.0) # What is active after 1 unit of time?
assert es.length == 1

Each update increments the time frame of the queue and returns an updated information about active events.

es = eq.update(1.0) # What is active after an other unit of time?
assert eq.time == 2.0

assert es.length == 3

Results of the update method contains a lot of information.

Obviously the original events:

assert es[0].event == "1..2"
assert es[1].event == "1.5"
assert es[2].event == "2..10"

The time since the begin of the event:

assert es[0].time == 1.0 # Started 1 unit of time ago
assert es[1].time == 0.5
assert es[2].time == 0.0

The completion ratio of the event until its termination:

assert es[0].completion == 1.0 # has just finished
assert es[1].completion == inf # completion ratio does not make sense for instant events
assert es[2].completion == 0.0

And a lot of other things, just look at EventInfo.

Expiration and control

When update returns events, occurrences count the number of time an event is returned by update. It can be used for instance to see if it is the first time that a specific event is active.

assert es[0].occurrences == 2 # it is the second time we see it
assert es[1].occurrences == 1 # instant one
assert es[2].occurrences == 1

The duration is used to automatically manage the expiration of the event.

Note that if a event expires during an update, then it is still returned by the function. This is the way to handle instant events and newly expired events.

To distinguish them has_expired can be used.

assert es[0].has_expired == true  # just finished
assert es[1].has_expired == true  # instant one
assert es[2].has_expired == false

On the next update, the already expired events are not returned again.

es = eq.update(1.0) # What is active after an other unit of time?
assert eq.time == 3.0
assert es.length == 1
assert es.first.event == "2..10"

The expire method can force the expiration of an event.

es = eq.update(1.0)
assert es.is_empty

Fluent programming

The add method (and its derivates) returns a EventInfo object that can be used to have information about the newly registered event but also to chain the creation of time-related events.

For instance, the following example registers 4 events, each one relative to the previous one:

eq = new EventQueue[String]
eq.add("e1", 10.0, 5.0).
   add_after("e2", 2.0, 5.0).
   add_sync("e3", 2.0, 5.0).
   add_before("e4", 2.0, 5.0)

This can be decomposed as:

eq = new EventQueue[String]
var e1 = eq.add("e1", 10.0, 5.0)
assert e1.start == 10.0 # First event starts at 10

var e2 = e1.add_after("e2", 2.0, 5.0) # starts 2 units of time after the end of e1
assert e2.start == 17.0 # So starts at 10 + 5 + 2

var e3 = e2.add_sync("e3", 2.0, 5.0) # starts 2 units of time after the begin of e2
assert e3.start == 19.0 # So starts at 17 + 2

var e4 = e3.add_before("e4", 2.0, 5.0) # ends 2 units of time before the start of e3
assert e4.start == 12.0