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|
|