ProductionAdapter

class
Superclass
Object
Extended With
Loggability

An adapter that connects method calls to an LSystem::RulesEngine's generations.

Attributes

production_map[R]

The map of symbols to production methods

Public Class Methods

anchor
inherited( subclass )

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
anchor
new()

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
anchor
on_finish( &block )

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
anchor
on_start( &block )

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
anchor
production_map( productions={} )

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
anchor
production_map=( new_map )

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
anchor
result( &block )

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

Public Instance Methods

anchor
make_dispatch_table()

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
anchor
run( rules_engine, iterations )

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
anchor
run_generation( generation )

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