1
0

Updated Formula::calculate to use FormulaBuilder

This commit is contained in:
cryptogopher 2020-01-27 00:59:33 +01:00
parent 98207fc980
commit df8703ba3c
4 changed files with 44 additions and 22 deletions

View File

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

View File

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

View File

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

View File

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