Updated Formula::calculate to use FormulaBuilder
This commit is contained in:
parent
98207fc980
commit
df8703ba3c
@ -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
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
||||
</td>
|
||||
<td class="domain"><%= q.domain %></td>
|
||||
<td class="description"><%= q.description %></td>
|
||||
<td class="formula"><%= checked_image q.formula.present? %></td>
|
||||
<td class="formula"><%= checked_image q.formula? %></td>
|
||||
<td class="action unwrappable">
|
||||
<%= link_to l(:button_edit), edit_quantity_path(q), {
|
||||
remote: true,
|
||||
|
@ -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
|
||||
|
@ -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|
|
||||
|
Reference in New Issue
Block a user