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

new(duration, parent = nil, &block) click to toggle source

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 equivalent

a_serial = Bonito::SerialTimeline.new(1.week) do

please { 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.

Calls superclass method
# 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

*(other) click to toggle source

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
**(other) click to toggle source

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
+(other) click to toggle source

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
over(duration, &block) click to toggle source

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
please(&block) click to toggle source

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
repeat(times:, over:, &block) click to toggle source

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 current SerialTimeline

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
simultaneously(&block) click to toggle source

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
unused_duration() click to toggle source

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
use(*timelines) click to toggle source

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