diff --git a/app/models/quantity.rb b/app/models/quantity.rb index eb81c98..5e558b8 100644 --- a/app/models/quantity.rb +++ b/app/models/quantity.rb @@ -29,25 +29,9 @@ class Quantity < ActiveRecord::Base if new_record? self.domain ||= :diet end - @formula = Formula.new(self.project, self.formula) end - def formula=(value) - @formula = Formula.new(self.project, value) - super(value) - end - - def formula_valid? - @formula.valid? - end - - def formula_quantities - @formula.get_quantities - end - - def calculate(inputs) - @formula.calculate(inputs) - end + delegate :valid?, :quantities, :calculate, to: :f_obj, prefix: :formula, allow_nil: true def movable?(direction) case direction @@ -74,4 +58,10 @@ class Quantity < ActiveRecord::Base quantities end + + private + + def f_obj + Formula.new(self.project, self.formula) if self.formula? + end end diff --git a/lib/body_tracking/formula.rb b/lib/body_tracking/formula.rb index bfd63ef..de3e702 100644 --- a/lib/body_tracking/formula.rb +++ b/lib/body_tracking/formula.rb @@ -8,7 +8,7 @@ module BodyTracking class Formula def initialize(project, formula) - @project_quantities = Quantity.where(project: project) + @project = project @formula = formula @parts = nil @quantities = nil @@ -19,7 +19,7 @@ module BodyTracking identifiers, parts = parser.parse errors = parser.errors - quantities = @project_quantities.where(name: identifiers) + quantities = Quantity.where(project: @project, name: identifiers) quantities_names = quantities.pluck(:name) (identifiers - quantities_names).each do |q| errors << [:unknown_quantity, {quantity: q}] @@ -33,27 +33,24 @@ module BodyTracking @quantities || self.validate.empty? end - def get_quantities + def quantities raise(InvalidFormula, 'Invalid formula') unless self.valid? @quantities.to_a end def calculate(inputs) - byebug - params = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h - length = params.values.first.length + quantities = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h + length = quantities.values.first.length raise(InvalidFormula, 'Invalid formula') unless self.valid? - raise InvalidInputs unless params.values.all? { |v| v.length == length } + raise InvalidInputs unless quantities.values.all? { |v| v.length == length } args = [] @parts.each do |p| - args << get_binding(params, length) - .eval( - p[:type] == :indexed ? "length.times.map { |_index| #{p[:content]} }" : - p[:content] - ) + code = p[:type] == :indexed ? + "length.times.map { |index| #{p[:content]} }" : p[:content] + args << get_binding(quantities, args, length).eval(code) end args.last.map { |v| [v, nil] } rescue Exception => e @@ -63,7 +60,7 @@ module BodyTracking private - def get_binding(params, _length) + def get_binding(quantities, args, length) binding end end @@ -206,7 +203,7 @@ module BodyTracking content: "quantities['#{left[1]}']#{dot.to_s}#{method}"} [:bt_quantity_method_call, "parts[#{part_index}]", part_index] else - [:bt_numeric_method_call, "quantities['#{left[1]}'][_index]#{dot.to_s}#{method}"] + [:bt_numeric_method_call, "quantities['#{left[1]}'][index]#{dot.to_s}#{method}"] end when :bt_quantity_method_call if mtype == :quantity_method @@ -258,7 +255,7 @@ module BodyTracking [ :bt_expression, [left, right].map do |side| - side[0] == :bt_quantity ? "quantities['#{side[1]}'][_index]" : "#{side[1]}" + side[0] == :bt_quantity ? "quantities['#{side[1]}'][index]" : "#{side[1]}" end.join(op.to_s) ] end @@ -310,7 +307,7 @@ module BodyTracking when :bt_expression, :bt_numeric_method_call token when :bt_quantity - "quantities['#{token}'][_index]" + "quantities['#{token}'][index]" else raise NotImplementedError, stmt.inspect end diff --git a/lib/body_tracking/items_with_quantities.rb b/lib/body_tracking/items_with_quantities.rb index 919c3db..48966c3 100644 --- a/lib/body_tracking/items_with_quantities.rb +++ b/lib/body_tracking/items_with_quantities.rb @@ -83,10 +83,9 @@ module BodyTracking # quantity with formula has all dependencies satisfied, requires calculation if deps.empty? output_ids = items.select { |i| subitems[q.name][i.id].nil? }.map(&:id) - byebug input_q = q.formula_quantities inputs = input_q.map { |i_q| [i_q, completed_q[i_q.name].values_at(*output_ids)] } - q.calculate(inputs.to_h).each_with_index do |result, index| + q.formula_calculate(inputs.to_h).each_with_index do |result, index| subitems[q.name][output_ids[index]] = result end unchecked_q.unshift([q, deps])