class Bonito::SerialTimeline
A SerialTimeline
is a data structure with a duration (measured in seconds) that contains timelines
. A timeline
is any instance of a class that inherits from the Timeline base class.
A SerialTimeline
serves to define an interval in which it may be simulated that one or more Moment
objects are evaluated in series_.
A SerialTimeline
exposes methods that can either be used to define these Moment
objects directly or to create additional child data structures (i.e ParallelTimeline objects or further, child SerialTimeline
objects) which can in turn be provide more fine grained control over precisely when any given Moment
objects may be evaluated.
Example¶ ↑
Bonito.over(2.weeks) do please { puts Time.now } end
The above defines a SerialTimeline
(using the Bonito#over module method) that specifies a 2 week time period. A single Moment
is included in this serial (via the please
factory method). When the top level SerialTimeline
is evaluated (using a Runner object) the block
puts Time.now
is evaluated exactly once. Furthermore, the simulated time at which the block is evaluated will be contained at some point within the 2 week interval beginning on some start date provided when instantiating the Runner object.
As mentioned, it is also possible to include other data structures within SerialTimeline
objects, including other SerialTimeline
objects.
Example¶ ↑
We could use the over
method to add an empty SerialTimeline
to the previous example in order to force the already included Moment
to be evaluated during the last day of the 2 week period.
Bonito.over(2.weeks) do over(2.weeks - 1.day) # This defines an empty serial please { puts Time.now } end
The empty SerialTimeline
returned by the over
factory method consumes 13 days of the parent SerialTimeline
object's total duration of 2 weeks. This means that when this parent SerialTimeline
is evaluated, the Moment
will be as if it occurred during the final day of the 2 week period.
Finally, we may also define ParallelTimeline objects within serials using the simultaneously
method. These allow for multiple SerialTimeline
objects to be defined over the same time period and for any Moment
objects contained within to be interleaved when the parent SerialTimeline
is ultimately evaluated.
The simultaneously
method instantiates a ParallelTimeline object, whilst accepting a block. The block is evaluated within the context of the new ParallelTimeline. Timelines defined within this block will be evaluated in parallel.
Note that ParallelTimeline implements many of the same methods as SerialTimeline
Example¶ ↑
Bonito.over(2.weeks) do simultaneously do over 1.week do puts "SerialTimeline 1 #{Time.now}" end over 6.days, after: 1.day do puts "SerialTimeline 2 #{Time.now}" end end over 1.week {} # This defines an empty serial end
Now, when evaluating this SerialTimeline
both the blocks
puts "SerialTimeline 1 #{Time.now}"
and
puts "SerialTimeline 2 #{Time.now}"
will be evaluated once during the first week. The precise instant is chosen randomly within this interval with the only constraint being that the second block cannot be evaluated during the first day (This offset is controlled by the after
parameter of the simultaneously
method).
Note that the moment from the second SerialTimeline
could still be evaluated at a simulated time before that at which the moment from the first SerialTimeline
is evaluated.
Public Class Methods
Instantiate a new SerialTimeline
object
- duration
-
The total time period (in seconds) that the
SerialTimeline
encompasses - parent
-
If the
SerialTimeline
is a child of another Timeline, parent is this Timeline - block
-
A block that will be evaluated within the context of the newly created
SerialTimeline
. Note that the following two statements are equivalenta_serial =
Bonito::SerialTimeline.new(1.week)
doplease { p Time.now }
end
another_serial =
Bonito::SerialTimeline.new
1.week serial.please { p Time.now }
The ability to include a block in this way is in order to allow the code used to define a given SerialTimeline
will reflect its hierarchy.
# File lib/bonito/serial_timeline.rb, line 143 def initialize(duration, parent = nil, &block) @parent = parent @total_child_duration = 0 super duration instance_eval(&block) if block_given? end
Public Instance Methods
Repeatedly apply the +
method of the current SerialTimeline
to itself
- other
-
Denotes the number of times the current serial should be added to itself.
Returns a new SerialTimeline
object
Note that the following statements are equivalent for some serial serial
:
serial * 3 serial + serial + serial
# File lib/bonito/serial_timeline.rb, line 254 def *(other) SerialTimeline.new(duration * other) do use(*Array.new(other) { entries }.reduce(:+)) end end
Scale up a serial by parallelising it according to some factor
- other
-
An Integer denoting the degree of parallelism with which to scale the serial.
Returns a new ParallelTimeline whose child timelines are precisely the current serial repeated other
times.
# File lib/bonito/serial_timeline.rb, line 268 def **(other) this = self SerialTimeline.new(duration) do simultaneously { use(*Array.new(other) { this }) } end end
Combine two Windows into a single, larger SerialTimeline
object.
- other
-
Some other
SerialTimeline
object
Returns a SerialTimeline
object consisting of the ordered child Timeline objects of the current SerialTimeline
with the ordered child Timeline objects of other
appended to the end.
# File lib/bonito/serial_timeline.rb, line 234 def +(other) SerialTimeline.new duration + other.duration do use(*(to_a + other.to_a)) end end
Define a new SerialTimeline
and add it as a child to the current SerialTimeline
- duration
-
The duration (in seconds) of the newly created child
SerialTimeline
- block
-
A block passed to the new method on the child
SerialTimeline
object
Returns the newly created SerialTimeline
object
# File lib/bonito/serial_timeline.rb, line 166 def over(duration, &block) self.class.new(duration, self, &block).tap(&method(:use)) end
Define a new Moment
and add it as a child to the current SerialTimeline
- block
-
A block passed to the new method on the child
Moment
object
Returns the newly created Moment
object
# File lib/bonito/serial_timeline.rb, line 176 def please(&block) Moment.new(&block).tap(&method(:use)) end
Define a new serial and append it multiple times as a child of the current SerialTimeline
object.
- times
-
The number of times that the new
SerialTimeline
object to be appended to the currentSerialTimeline
- over
-
The total duration (in senconds) of the new repeated
SerialTimeline
objects. - block
-
A block passed to the new method on the child
SerialTimeline
object
Returns the current SerialTimeline
# File lib/bonito/serial_timeline.rb, line 196 def repeat(times:, over:, &block) repeated_block = proc { times.times { instance_eval(&block) } } over(over, &repeated_block) end
Define a new ParallelTimeline object append it as a child to the current SerialTimeline
. Also permit the evaluation of methods within the context of the new ParallelTimeline.
- block
-
A block to be passed to the new method on the child ParallelTimeline method.
Returns the current SerialTimeline
object
# File lib/bonito/serial_timeline.rb, line 210 def simultaneously(&block) use ParallelTimeline.new(&block) end
The the amount of duration remaining taking into account the duration of any Timeline objects included as children of the SerialTimeline
.
# File lib/bonito/serial_timeline.rb, line 152 def unused_duration duration - @total_child_duration end
Append an existing Timeline as a child of the current SerialTimeline
- timelines
-
An array of Timeline objects that will be appended, in order to the current
SerialTimeline
Returns the current SerialTimeline
object
# File lib/bonito/serial_timeline.rb, line 221 def use(*timelines) timelines.each { |timeline| send :<<, timeline } self end