An adapter that connects method calls to an LSystem::RulesEngine's generations.
The map of symbols to production methods
Inheritance callback – add class-instance variables to the subclass
.
# File lib/l_system/production_adapter.rb, line 19
def self::inherited( subclass )
super
subclass.instance_variable_set( :@production_map, {} )
subclass.instance_variable_set( :@callbacks, {} )
end
Create a new instance of the ProductionAdapter
.
# File lib/l_system/production_adapter.rb, line 83
def initialize
@production_map = self.class.production_map
end
Register a callback that will be called at the end of each new generation. It will be called with the result of the this generation, which will be nil
if no result callback is declared.
# File lib/l_system/production_adapter.rb, line 72
def self::on_finish( &block )
self.log.debug "Declaring on_finish callback: %p" % [ block ]
define_method( :on_finish, &block )
end
Register a callback that will be called at the start of each new generation. It will be called with the result of the last generation, or nil
if this is the 0th (axiom) generation.
# File lib/l_system/production_adapter.rb, line 52
def self::on_start( &block )
self.log.debug "Declaring on_start callback: %p" % [ block ]
define_method( :on_start, &block )
end
Declare a Hash of symbols to methods that should be called when one appears in a generation.
# File lib/l_system/production_adapter.rb, line 33
def self::production_map( productions={} )
unless productions.empty?
self.production_map = productions
end
return @production_map
end
Set the Hash of symbols to methods that should be called when one appears in a generation.
# File lib/l_system/production_adapter.rb, line 44
def self::production_map=( new_map )
@production_map.replace( new_map )
end
Register a callback that will be called to obtain the result of running a generation. The result of calling the block
will be passed to this generation's on_finish callback (if there is one), the next generation's on_start callback (if there is one and there's successive geneation), and returned from run
if this was the last generation.
# File lib/l_system/production_adapter.rb, line 63
def self::result( &block )
self.log.debug "Declaring result callback: %p" % [ block ]
define_method( :result, &block )
end
Return a Hash of symbols to bound Methods to call for their productions from the current production_map
.
# File lib/l_system/production_adapter.rb, line 139
def make_dispatch_table
return self.class.production_map.each_with_object( {} ) do |(symbol, method_name), hash|
hash[ symbol ] = self.method( method_name )
end
end
Run productions for each generation produced by the given rules_engine
up to iterations
times.
# File lib/l_system/production_adapter.rb, line 99
def run( rules_engine, iterations )
self.log.debug "Running %p for up to %d iterations" % [ rules_engine, iterations ]
return rules_engine.each.with_index.inject( nil ) do |result, (generation, i)|
self.log.debug "Running generation %d" % [ i ]
self.on_start( i, result ) if self.respond_to?( :on_start )
self.run_generation( generation )
result = self.result( i ) if self.respond_to?( :result )
self.log.debug "Result [%d] is: %p" % [ i, result ]
self.on_finish( i, result ) if self.respond_to?( :on_finish )
break result if i >= iterations - 1
result
end
end
Run the specified generation
by calling productions for each of its symbols.
# File lib/l_system/production_adapter.rb, line 118
def run_generation( generation )
# Make a new one every time to support self-mutating adapters
dispatch_table = self.make_dispatch_table
generation.each_char do |symbol|
callback = dispatch_table[ symbol ]
unless callback
self.log.warn "No production for symbol %p" % [ symbol ]
next
end
self.log.debug "%p -> %p" % [ symbol, callback ]
callback.call
end
end