Fixed calculation for indexed formulas
Delegated Quantity formula calls
This commit is contained in:
parent
df8703ba3c
commit
aa26e66312
@ -29,25 +29,9 @@ 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
|
end
|
||||||
|
|
||||||
def formula=(value)
|
delegate :valid?, :quantities, :calculate, to: :f_obj, prefix: :formula, allow_nil: true
|
||||||
@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)
|
def movable?(direction)
|
||||||
case direction
|
case direction
|
||||||
@ -74,4 +58,10 @@ class Quantity < ActiveRecord::Base
|
|||||||
|
|
||||||
quantities
|
quantities
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def f_obj
|
||||||
|
Formula.new(self.project, self.formula) if self.formula?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -8,7 +8,7 @@ module BodyTracking
|
|||||||
|
|
||||||
class Formula
|
class Formula
|
||||||
def initialize(project, formula)
|
def initialize(project, formula)
|
||||||
@project_quantities = Quantity.where(project: project)
|
@project = project
|
||||||
@formula = formula
|
@formula = formula
|
||||||
@parts = nil
|
@parts = nil
|
||||||
@quantities = nil
|
@quantities = nil
|
||||||
@ -19,7 +19,7 @@ module BodyTracking
|
|||||||
identifiers, parts = parser.parse
|
identifiers, parts = parser.parse
|
||||||
errors = parser.errors
|
errors = parser.errors
|
||||||
|
|
||||||
quantities = @project_quantities.where(name: identifiers)
|
quantities = Quantity.where(project: @project, name: identifiers)
|
||||||
quantities_names = quantities.pluck(:name)
|
quantities_names = quantities.pluck(:name)
|
||||||
(identifiers - quantities_names).each do |q|
|
(identifiers - quantities_names).each do |q|
|
||||||
errors << [:unknown_quantity, {quantity: q}]
|
errors << [:unknown_quantity, {quantity: q}]
|
||||||
@ -33,27 +33,24 @@ module BodyTracking
|
|||||||
@quantities || self.validate.empty?
|
@quantities || self.validate.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_quantities
|
def quantities
|
||||||
raise(InvalidFormula, 'Invalid formula') unless self.valid?
|
raise(InvalidFormula, 'Invalid formula') unless self.valid?
|
||||||
|
|
||||||
@quantities.to_a
|
@quantities.to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
def calculate(inputs)
|
def calculate(inputs)
|
||||||
byebug
|
quantities = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h
|
||||||
params = inputs.map { |q, v| [q.name, v.transpose[0]] }.to_h
|
length = quantities.values.first.length
|
||||||
length = params.values.first.length
|
|
||||||
|
|
||||||
raise(InvalidFormula, 'Invalid formula') unless self.valid?
|
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 = []
|
args = []
|
||||||
@parts.each do |p|
|
@parts.each do |p|
|
||||||
args << get_binding(params, length)
|
code = p[:type] == :indexed ?
|
||||||
.eval(
|
"length.times.map { |index| #{p[:content]} }" : p[:content]
|
||||||
p[:type] == :indexed ? "length.times.map { |_index| #{p[:content]} }" :
|
args << get_binding(quantities, args, length).eval(code)
|
||||||
p[:content]
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
args.last.map { |v| [v, nil] }
|
args.last.map { |v| [v, nil] }
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
@ -63,7 +60,7 @@ module BodyTracking
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def get_binding(params, _length)
|
def get_binding(quantities, args, length)
|
||||||
binding
|
binding
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -206,7 +203,7 @@ module BodyTracking
|
|||||||
content: "quantities['#{left[1]}']#{dot.to_s}#{method}"}
|
content: "quantities['#{left[1]}']#{dot.to_s}#{method}"}
|
||||||
[:bt_quantity_method_call, "parts[#{part_index}]", part_index]
|
[:bt_quantity_method_call, "parts[#{part_index}]", part_index]
|
||||||
else
|
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
|
end
|
||||||
when :bt_quantity_method_call
|
when :bt_quantity_method_call
|
||||||
if mtype == :quantity_method
|
if mtype == :quantity_method
|
||||||
@ -258,7 +255,7 @@ module BodyTracking
|
|||||||
[
|
[
|
||||||
:bt_expression,
|
:bt_expression,
|
||||||
[left, right].map do |side|
|
[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.join(op.to_s)
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
@ -310,7 +307,7 @@ module BodyTracking
|
|||||||
when :bt_expression, :bt_numeric_method_call
|
when :bt_expression, :bt_numeric_method_call
|
||||||
token
|
token
|
||||||
when :bt_quantity
|
when :bt_quantity
|
||||||
"quantities['#{token}'][_index]"
|
"quantities['#{token}'][index]"
|
||||||
else
|
else
|
||||||
raise NotImplementedError, stmt.inspect
|
raise NotImplementedError, stmt.inspect
|
||||||
end
|
end
|
||||||
|
@ -83,10 +83,9 @@ 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.formula_calculate(inputs.to_h).each_with_index do |result, index|
|
||||||
subitems[q.name][output_ids[index]] = result
|
subitems[q.name][output_ids[index]] = result
|
||||||
end
|
end
|
||||||
unchecked_q.unshift([q, deps])
|
unchecked_q.unshift([q, deps])
|
||||||
|
Reference in New Issue
Block a user