Module: DRP::RuleEngine

Defined in:
lib/rule_engine.rb

Instance Method Summary collapse

Instance Method Details

#begin_rulesObject



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rule_engine.rb', line 88

def begin_rules
  # if it is true or :finished, see end_rules & method_added
  if @__drp__defining_rules 
    raise DRPError, 'begin rules may only be called once'
  else
    @__drp__rules = {}
    @__drp__defining_rules = true
    @__drp__weights = []
    @__drp__max__depths = []
    # NB max_depth should come first here in case user changes
    # the default to some weight which needs to know the max_depth
    max_depth DEFAULT[:max_depth]
    weight DEFAULT[:weight]
  end
end

#end_rulesObject

NB the two methods defined via define_method in end_rules will be instance methods in instances of classes which are extended by this module. they are here because they are closures referencing the ‘name’ and ‘all_methods’ variables respectively. other non-closure methods are in module InstanceMethods



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/rule_engine.rb', line 111

def end_rules

  @__drp__defining_rules = :finished

  all_methods = {}

  @__drp__rules.each do |name, weights_and_max_depths|

    methods = []

    weights_and_max_depths.each_with_index do |w_md, i|
      methods.push ["__drp__#{name}__#{i}"] + w_md
    end

    all_methods[name] = methods

    define_method name do |*args|

      useable_methods = @__drp__rule__methods[name].select do |meth|
        meth.expressed?
      end

      case useable_methods.size

        when 0
        default_rule_method *args          

        when 1
        __drp__call__method(useable_methods.first, args)

        else
        __drp__call__method(__drp__choose__method(useable_methods), args)

      end
      
    end # define_method name do


  end # @__drp__rules.each do

  define_method :__drp__init do

    @__drp__rule__methods = {}
    @__drp__depth__stack = []
    @__drp__rule__method__stack = []

    all_methods.each do |name, arg_array|
      @__drp__rule__methods[name] = arg_array.collect do |args|
        RuleMethod.new self, *args
      end
    end

    self

  end

end

#max_depth(*args, &block) ⇒ Object

sets the maximum obtainable depth of the rule methods which follow it in the listing. max_depths are set for each instance of the class you extended with DRP::RuleEngine upon initialization (or when you call init_drp), once and only once, and remains set to that static value. max depths are always integer values.

it may be used in any of the following four ways:

scalar, all following rule_methods are set to given value

max_depth 1

range, each following rule_method is initialized to some integer from range.start to range.end inclusive using a linear mapping of a codon gotten via the method next_meta_codon.

max_depth 1..2

same as the previous but uses the function given, at present the only function implemented is i_linear (integer linear), which is the default action when no function is given, so at present this is useless.

max_depth 1..2, :function

block, each following rule_method is initialized to some integer given by your block. the formal parameters to your supplied block are counted, and the appropriate number of codons harvested using InstanceMethods#next_meta_codon are passed to the block.

max_depth { |next_meta_codon, ...| ... }

see example_2.rb



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/rule_engine.rb', line 207

def max_depth *args, &block
  
  sz = args.size
  are_args = sz > 0
  md = nil
  
  if block_given?
    if are_args
      raise ArgumentError, 'max_depth called with both arguments and a block', caller
    else
      md = MaxDepths::ProcMaxDepth.new(block)
    end
  else
    case sz
    when 1
      arg = args[0]
      case arg
      when Numeric
        md = MaxDepths::StaticMaxDepth.new arg.to_i
      when Range
        md = MaxDepths::MappedMaxDepth.new arg
      else
        raise ArgumentError, 'bad argument to max_depth', caller
      end
    when 2
      arg1, arg2 = args
      if (arg1.kind_of? Range) && (arg2.kind_of? Symbol)
        md = MaxDepths::MappedMaxDepth.new arg1, arg2
      else
        raise ArgumentError, 'bad argument to max_depth', caller
      end
    else 
      raise ArgumentError, "too many (#{sz}) args passed to max_depth", caller
    end # case sz
  end # if block_given

  @__drp__max__depths << md

end

#new(*a, &b) ⇒ Object



54
55
56
# File 'lib/rule_engine.rb', line 54

def new *a, &b 
  super.__drp__init
end

#weight(*args, &block) ⇒ Object



281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/rule_engine.rb', line 281

def weight *args, &block
  bg, are_args = block_given?, args.size > 0
  if bg && are_args
    raise ArgumentError, 'weight called with both arguments and a block', caller
  elsif bg
    @__drp__weights << Weights::ProcStaticWeight.factory(block)
  elsif are_args
    @__drp__weights << Weights::StaticWeight.factory(args)
  else
    raise ArgumentError, 'weight called with neither args nor block', caller
  end 
end

#weight_fcd(*args, &block) ⇒ Object

def weight_dyn *args, &block

  bg, are_args = block_given?, args.size > 0
  if bg && are_args
    __drp__error "weight_dyn called with both args and block"
  elsif bg
    @__drp__weights << Weights::ProcDynamicWeight.factory(block)
  elsif are_args
    @__drp__weights << Weights::DynamicWeight.factory(args)
  else
    raise ArgumentError, 'weight_dyn called with neither args nor block', caller
  end 
end


309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/rule_engine.rb', line 309

def weight_fcd *args, &block
  bg, are_args = block_given?, args.size > 0
  if bg && are_args
    __drp__error "weight_fcd called with both args and block"
  elsif bg
    @__drp__weights << Weights::ProcWeightFromCurrentDepth.factory(block)
  elsif are_args
    @__drp__weights << Weights::WeightFromCurrentDepth.factory(args)
  else
    raise ArgumentError, 'weight_fcd called with neither args nor block', caller
  end 
end