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?
|
if new_record?
|
||||||
self.domain ||= :diet
|
self.domain ||= :diet
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def movable?(direction)
|
def movable?(direction)
|
||||||
@ -47,14 +65,6 @@ class Quantity < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
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)
|
def self.filter(project, filters)
|
||||||
quantities = all
|
quantities = all
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="domain"><%= q.domain %></td>
|
<td class="domain"><%= q.domain %></td>
|
||||||
<td class="description"><%= q.description %></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">
|
<td class="action unwrappable">
|
||||||
<%= link_to l(:button_edit), edit_quantity_path(q), {
|
<%= link_to l(:button_edit), edit_quantity_path(q), {
|
||||||
remote: true,
|
remote: true,
|
||||||
|
@ -4,6 +4,7 @@ module BodyTracking
|
|||||||
require 'set'
|
require 'set'
|
||||||
|
|
||||||
class InvalidFormula < RuntimeError; end
|
class InvalidFormula < RuntimeError; end
|
||||||
|
class InvalidInputs < RuntimeError; end
|
||||||
|
|
||||||
class Formula
|
class Formula
|
||||||
def initialize(project, formula)
|
def initialize(project, formula)
|
||||||
@ -33,28 +34,36 @@ module BodyTracking
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get_quantities
|
def get_quantities
|
||||||
raise RuntimeError, 'Invalid formula' unless self.valid?
|
raise(InvalidFormula, 'Invalid formula') unless self.valid?
|
||||||
|
|
||||||
@quantities.to_a
|
@quantities.to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
#"params.values.first.each_with_index.map { |*, _index| #{@paramed_formula} }"
|
|
||||||
def calculate(inputs)
|
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
|
raise(InvalidFormula, 'Invalid formula') unless self.valid?
|
||||||
puts values.inspect
|
raise InvalidInputs unless params.values.all? { |v| v.length == length }
|
||||||
begin
|
|
||||||
get_binding(values).eval(@paramed_formula).map { |x| [x, nil] }
|
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
|
rescue Exception => e
|
||||||
puts e.message
|
puts e.message
|
||||||
[[nil, nil]] * inputs.values.first.length
|
[[nil, nil]] * length
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def get_binding(params)
|
def get_binding(params, _length)
|
||||||
binding
|
binding
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -73,6 +82,8 @@ module BodyTracking
|
|||||||
end
|
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
|
class FormulaBuilder < Ripper::SexpBuilder
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
super(*args)
|
super(*args)
|
||||||
@ -109,7 +120,7 @@ module BodyTracking
|
|||||||
|
|
||||||
def on_program(stmts)
|
def on_program(stmts)
|
||||||
@parts << {type: :indexed, content: join_stmts(stmts)}
|
@parts << {type: :indexed, content: join_stmts(stmts)}
|
||||||
[@identifiers, @parts]
|
[@identifiers.to_a, @parts]
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_string_content
|
def on_string_content
|
||||||
|
@ -67,7 +67,7 @@ module BodyTracking
|
|||||||
q, deps = unchecked_q.shift
|
q, deps = unchecked_q.shift
|
||||||
|
|
||||||
# quantity not computable (no formula) or not requiring calculation/computed
|
# 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] = subitems.delete(q.name) { {} }
|
||||||
completed_q[q.name].default = [nil, nil]
|
completed_q[q.name].default = [nil, nil]
|
||||||
next
|
next
|
||||||
@ -83,6 +83,7 @@ module BodyTracking
|
|||||||
# quantity with formula has all dependencies satisfied, requires calculation
|
# quantity with formula has all dependencies satisfied, requires calculation
|
||||||
if deps.empty?
|
if deps.empty?
|
||||||
output_ids = items.select { |i| subitems[q.name][i.id].nil? }.map(&:id)
|
output_ids = items.select { |i| subitems[q.name][i.id].nil? }.map(&:id)
|
||||||
|
byebug
|
||||||
input_q = q.formula_quantities
|
input_q = q.formula_quantities
|
||||||
inputs = input_q.map { |i_q| [i_q, completed_q[i_q.name].values_at(*output_ids)] }
|
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.calculate(inputs.to_h).each_with_index do |result, index|
|
||||||
|
Reference in New Issue
Block a user