1
0

Fixed calculation for indexed formulas

Delegated Quantity formula calls
This commit is contained in:
cryptogopher 2020-02-04 00:13:49 +01:00
parent df8703ba3c
commit aa26e66312
3 changed files with 21 additions and 35 deletions

View File

@ -29,25 +29,9 @@ 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
delegate :valid?, :quantities, :calculate, to: :f_obj, prefix: :formula, allow_nil: true
def movable?(direction)
case direction
@ -74,4 +58,10 @@ class Quantity < ActiveRecord::Base
quantities
end
private
def f_obj
Formula.new(self.project, self.formula) if self.formula?
end
end

View File

@ -8,7 +8,7 @@ module BodyTracking
class Formula
def initialize(project, formula)
@project_quantities = Quantity.where(project: project)
@project = project
@formula = formula
@parts = nil
@quantities = nil
@ -19,7 +19,7 @@ module BodyTracking
identifiers, parts = parser.parse
errors = parser.errors
quantities = @project_quantities.where(name: identifiers)
quantities = Quantity.where(project: @project, name: identifiers)
quantities_names = quantities.pluck(:name)
(identifiers - quantities_names).each do |q|
errors << [:unknown_quantity, {quantity: q}]
@ -33,27 +33,24 @@ module BodyTracking
@quantities || self.validate.empty?
end
def get_quantities
def quantities
raise(InvalidFormula, 'Invalid formula') unless self.valid?
@quantities.to_a
end
def calculate(inputs)
byebug
params = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h
length = params.values.first.length
quantities = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h
length = quantities.values.first.length
raise(InvalidFormula, 'Invalid formula') unless self.valid?
raise InvalidInputs unless params.values.all? { |v| v.length == length }
raise InvalidInputs unless quantities.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]
)
code = p[:type] == :indexed ?
"length.times.map { |index| #{p[:content]} }" : p[:content]
args << get_binding(quantities, args, length).eval(code)
end
args.last.map { |v| [v, nil] }
rescue Exception => e
@ -63,7 +60,7 @@ module BodyTracking
private
def get_binding(params, _length)
def get_binding(quantities, args, length)
binding
end
end
@ -206,7 +203,7 @@ module BodyTracking
content: "quantities['#{left[1]}']#{dot.to_s}#{method}"}
[:bt_quantity_method_call, "parts[#{part_index}]", part_index]
else
[:bt_numeric_method_call, "quantities['#{left[1]}'][_index]#{dot.to_s}#{method}"]
[:bt_numeric_method_call, "quantities['#{left[1]}'][index]#{dot.to_s}#{method}"]
end
when :bt_quantity_method_call
if mtype == :quantity_method
@ -258,7 +255,7 @@ module BodyTracking
[
:bt_expression,
[left, right].map do |side|
side[0] == :bt_quantity ? "quantities['#{side[1]}'][_index]" : "#{side[1]}"
side[0] == :bt_quantity ? "quantities['#{side[1]}'][index]" : "#{side[1]}"
end.join(op.to_s)
]
end
@ -310,7 +307,7 @@ module BodyTracking
when :bt_expression, :bt_numeric_method_call
token
when :bt_quantity
"quantities['#{token}'][_index]"
"quantities['#{token}'][index]"
else
raise NotImplementedError, stmt.inspect
end

View File

@ -83,10 +83,9 @@ 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|
q.formula_calculate(inputs.to_h).each_with_index do |result, index|
subitems[q.name][output_ids[index]] = result
end
unchecked_q.unshift([q, deps])