1
0

Updated Formula get_quantities/calculate for new parsing algo

This commit is contained in:
cryptogopher 2019-11-11 15:10:02 +01:00
parent 613c26728c
commit 2e477921e9

View File

@ -4,10 +4,13 @@ module BodyTracking
QUANTITY_TTYPES = [:on_ident, :on_tstring_content, :on_const] QUANTITY_TTYPES = [:on_ident, :on_tstring_content, :on_const]
FUNCTIONS = ['abs', 'nil?'] FUNCTIONS = ['abs', 'nil?']
class InvalidFormula < RuntimeError; end
class Formula class Formula
def initialize(project, formula) def initialize(project, formula)
@project = project @project = project
@formula = formula @formula = formula
@paramed_formula = nil
@quantities = nil
end end
def validate def validate
@ -60,9 +63,9 @@ module BodyTracking
when :var_ref when :var_ref
vtype, vname, vloc = token vtype, vname, vloc = token
case vtype case vtype
when vtype == :@conts when :@const
identifiers << vname identifiers << vname
when vtype == :@kw when :@kw
disallowed[:keyword] << token if vname != 'nil' disallowed[:keyword] << token if vname != 'nil'
end end
when :@int, :@float when :@int, :@float
@ -76,32 +79,44 @@ module BodyTracking
# 4th: check if identifiers used in formula correspond to existing quantities # 4th: check if identifiers used in formula correspond to existing quantities
identifiers.uniq! identifiers.uniq!
quantities = @project.quantities.where(name: identifiers).pluck(:name) quantities = @project.quantities.where(name: identifiers)
(identifiers - quantities).each { |q| errors << [:unknown_quantity, {quantity: q}] } quantities_names = quantities.pluck(:name)
(identifiers - quantities_names).each do |q|
errors << [:unknown_quantity, {quantity: q}]
end
if errors.empty?
@quantities = quantities
@paramed_formula = Ripper.lex(@formula).map do |*, ttype, token|
if QUANTITY_TTYPES.include?(ttype) && quantities_names.include?(token)
"params['#{token}']"
else
token
end
end.join
end
errors errors
end end
def valid? def valid?
self.validate.empty? self.validate if @quantities.nil?
!@quantities.nil?
end end
def get_quantities def get_quantities
q_names = Ripper.lex(@formula).map do |*, ttype, token| raise RuntimeError, 'Invalid formula' unless self.valid?
token if is_token_quantity?(ttype, token)
end.compact @quantities.to_a
@project.quantities.where(name: q_names).to_a
end end
def calculate(inputs) def calculate(inputs)
paramed_formula = Ripper.lex(@formula).map do |*, ttype, token| raise RuntimeError, 'Invalid formula' unless self.valid?
is_token_quantity?(ttype, token) ? "params['#{token}']" : token
end.join
inputs.map do |i, values| inputs.map do |i, values|
puts values.inspect puts values.inspect
begin begin
[i, [get_binding(values).eval(paramed_formula), nil]] [i, [get_binding(values).eval(@paramed_formula), nil]]
rescue Exception => e rescue Exception => e
puts e.message puts e.message
[i, [nil, nil]] [i, [nil, nil]]
@ -111,10 +126,6 @@ module BodyTracking
private private
def is_token_quantity?(ttype, token)
QUANTITY_TTYPES.include?(ttype) && !FUNCTIONS.include?(token)
end
def get_binding(params) def get_binding(params)
binding binding
end end