diff --git a/app/models/quantity.rb b/app/models/quantity.rb index eab2dfa..eb81c98 100644 --- a/app/models/quantity.rb +++ b/app/models/quantity.rb @@ -29,6 +29,24 @@ 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 def movable?(direction) @@ -47,14 +65,6 @@ class Quantity < ActiveRecord::Base end end - def formula_quantities - Formula.new(self.project, self.formula).get_quantities - end - - def calculate(inputs) - Formula.new(self.project, self.formula).calculate(inputs) - end - def self.filter(project, filters) quantities = all diff --git a/app/views/quantities/_index.html.erb b/app/views/quantities/_index.html.erb index d80b7c1..8cd2434 100644 --- a/app/views/quantities/_index.html.erb +++ b/app/views/quantities/_index.html.erb @@ -43,7 +43,7 @@ <%= q.domain %> <%= q.description %> - <%= checked_image q.formula.present? %> + <%= checked_image q.formula? %> <%= link_to l(:button_edit), edit_quantity_path(q), { remote: true, diff --git a/lib/body_tracking/formula.rb b/lib/body_tracking/formula.rb index 3f38e81..bfd63ef 100644 --- a/lib/body_tracking/formula.rb +++ b/lib/body_tracking/formula.rb @@ -4,6 +4,7 @@ module BodyTracking require 'set' class InvalidFormula < RuntimeError; end + class InvalidInputs < RuntimeError; end class Formula def initialize(project, formula) @@ -33,28 +34,36 @@ module BodyTracking end def get_quantities - raise RuntimeError, 'Invalid formula' unless self.valid? + raise(InvalidFormula, 'Invalid formula') unless self.valid? @quantities.to_a end - #"params.values.first.each_with_index.map { |*, _index| #{@paramed_formula} }" def calculate(inputs) - raise RuntimeError, 'Invalid formula' unless self.valid? + byebug + params = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h + length = params.values.first.length - values = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h - puts values.inspect - begin - get_binding(values).eval(@paramed_formula).map { |x| [x, nil] } - rescue Exception => e - puts e.message - [[nil, nil]] * inputs.values.first.length + raise(InvalidFormula, 'Invalid formula') unless self.valid? + raise InvalidInputs unless params.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] + ) end + args.last.map { |v| [v, nil] } + rescue Exception => e + puts e.message + [[nil, nil]] * length end private - def get_binding(params) + def get_binding(params, _length) binding end end @@ -73,6 +82,8 @@ module BodyTracking end + # List of events with parameter count: + # https://github.com/racker/ruby-1.9.3-lucid/blob/master/ext/ripper/eventids1.c class FormulaBuilder < Ripper::SexpBuilder def initialize(*args) super(*args) @@ -109,7 +120,7 @@ module BodyTracking def on_program(stmts) @parts << {type: :indexed, content: join_stmts(stmts)} - [@identifiers, @parts] + [@identifiers.to_a, @parts] end def on_string_content diff --git a/lib/body_tracking/items_with_quantities.rb b/lib/body_tracking/items_with_quantities.rb index ded289f..919c3db 100644 --- a/lib/body_tracking/items_with_quantities.rb +++ b/lib/body_tracking/items_with_quantities.rb @@ -67,7 +67,7 @@ module BodyTracking q, deps = unchecked_q.shift # quantity not computable (no formula) or not requiring calculation/computed - if q.formula.blank? || (subitems[q.name].length == items.count) + if !q.formula? || !q.formula_valid? || (subitems[q.name].length == items.count) completed_q[q.name] = subitems.delete(q.name) { {} } completed_q[q.name].default = [nil, nil] next @@ -83,6 +83,7 @@ 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|