Added Formula test vectors
Improved FormulaBuilder based on vectors
This commit is contained in:
parent
ba4c98e213
commit
98207fc980
@ -14,13 +14,6 @@ module BodyTracking
|
|||||||
end
|
end
|
||||||
|
|
||||||
def validate
|
def validate
|
||||||
# TODO: add tests
|
|
||||||
# failing test vectors:
|
|
||||||
# - fcall disallowed: "abs(Fats)+Energy < 10"
|
|
||||||
# working test vectors:
|
|
||||||
# ((Energy-Calculated)/Energy).abs > 0.2
|
|
||||||
# Fats.nil? || Fats/Proteins > 2
|
|
||||||
|
|
||||||
parser = FormulaBuilder.new(@formula)
|
parser = FormulaBuilder.new(@formula)
|
||||||
identifiers, parts = parser.parse
|
identifiers, parts = parser.parse
|
||||||
errors = parser.errors
|
errors = parser.errors
|
||||||
@ -191,7 +184,7 @@ module BodyTracking
|
|||||||
[right[1], :unknown_method]
|
[right[1], :unknown_method]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise NotImplementedError
|
raise NotImplementedError, right.inspect
|
||||||
end
|
end
|
||||||
|
|
||||||
case left[0]
|
case left[0]
|
||||||
@ -211,7 +204,7 @@ module BodyTracking
|
|||||||
else
|
else
|
||||||
[:bt_numeric_method_call, "#{left[1]}#{dot.to_s}#{method}"]
|
[:bt_numeric_method_call, "#{left[1]}#{dot.to_s}#{method}"]
|
||||||
end
|
end
|
||||||
when :bt_numeric_method_call
|
when :bt_numeric_method_call, :bt_expression
|
||||||
if mtype == :quantity_method
|
if mtype == :quantity_method
|
||||||
# TODO: add error reporting
|
# TODO: add error reporting
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -219,7 +212,7 @@ module BodyTracking
|
|||||||
[:bt_numeric_method_call, "#{left[1]}#{dot.to_s}#{method}"]
|
[:bt_numeric_method_call, "#{left[1]}#{dot.to_s}#{method}"]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise NotImplementedError
|
raise NotImplementedError, left.inspect
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -279,10 +272,18 @@ module BodyTracking
|
|||||||
[:bt_quantity, token]
|
[:bt_quantity, token]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def on_float(token)
|
||||||
|
[:bt_expression, token]
|
||||||
|
end
|
||||||
|
|
||||||
def on_ident(token)
|
def on_ident(token)
|
||||||
[:bt_ident, token]
|
[:bt_ident, token]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def on_int(token)
|
||||||
|
[:bt_expression, token]
|
||||||
|
end
|
||||||
|
|
||||||
def on_kw(token)
|
def on_kw(token)
|
||||||
@disallowed[:keyword] << token unless token == 'nil'
|
@disallowed[:keyword] << token unless token == 'nil'
|
||||||
end
|
end
|
||||||
@ -295,10 +296,12 @@ module BodyTracking
|
|||||||
stmts.map do |stmt|
|
stmts.map do |stmt|
|
||||||
ttype, token = stmt
|
ttype, token = stmt
|
||||||
case ttype
|
case ttype
|
||||||
when :bt_expression
|
when :bt_expression, :bt_numeric_method_call
|
||||||
token
|
token
|
||||||
|
when :bt_quantity
|
||||||
|
"quantities['#{token}'][_index]"
|
||||||
else
|
else
|
||||||
raise NotImplementedError
|
raise NotImplementedError, stmt.inspect
|
||||||
end
|
end
|
||||||
end.join(';')
|
end.join(';')
|
||||||
end
|
end
|
||||||
|
@ -7,14 +7,61 @@ class FormulaTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_builder_parses_valid_formulas_properly
|
def test_builder_parses_valid_formulas_properly
|
||||||
|
# TODO: add tests
|
||||||
|
# failing test vectors:
|
||||||
|
# - fcall disallowed: "abs(Fats)+Energy < 10"
|
||||||
|
|
||||||
vector = [
|
vector = [
|
||||||
|
# Non-quantity expressions
|
||||||
'4', Set[], [
|
'4', Set[], [
|
||||||
{type: :indexed, content: '4*2'}
|
{type: :indexed, content: "4"}
|
||||||
|
],
|
||||||
|
'3.2', Set[], [
|
||||||
|
{type: :indexed, content: "3.2"}
|
||||||
|
],
|
||||||
|
'4 * 2', Set[], [
|
||||||
|
{type: :indexed, content: "4*2"}
|
||||||
|
],
|
||||||
|
'7.3 * 2.1', Set[], [
|
||||||
|
{type: :indexed, content: "7.3*2.1"}
|
||||||
|
],
|
||||||
|
'7 * 2.1', Set[], [
|
||||||
|
{type: :indexed, content: "7*2.1"}
|
||||||
],
|
],
|
||||||
|
|
||||||
#'4*2'
|
# Quantity expressions
|
||||||
#'Fats'
|
'Fats', Set['Fats'], [
|
||||||
#'fats'
|
{type: :indexed, content: "quantities['Fats'][_index]"}
|
||||||
|
],
|
||||||
|
'fats', Set['fats'], [
|
||||||
|
{type: :indexed, content: "quantities['fats'][_index]"}
|
||||||
|
],
|
||||||
|
'2 * Fats', Set['Fats'], [
|
||||||
|
{type: :indexed, content: "2*quantities['Fats'][_index]"}
|
||||||
|
],
|
||||||
|
'4*Proteins + 9*Fats + 4*Carbohydrates', Set['Proteins', 'Fats', 'Carbohydrates'], [
|
||||||
|
{type: :indexed, content: "4*quantities['Proteins'][_index]+" \
|
||||||
|
"9*quantities['Fats'][_index]+4*quantities['Carbohydrates'][_index]"}
|
||||||
|
],
|
||||||
|
'Weight * (Fats + 0.2)', Set['Weight', 'Fats'], [
|
||||||
|
{type: :indexed, content: "quantities['Weight'][_index]*" \
|
||||||
|
"(quantities['Fats'][_index]+0.2)"}
|
||||||
|
],
|
||||||
|
|
||||||
|
# Numeric method calls
|
||||||
|
'Fats.nil?', Set['Fats'], [
|
||||||
|
{type: :indexed, content: "quantities['Fats'][_index].nil?"}
|
||||||
|
],
|
||||||
|
'((Energy-Calculated)/Energy).abs', Set['Energy', 'Calculated'], [
|
||||||
|
{type: :indexed, content: "((quantities['Energy'][_index]-" \
|
||||||
|
"quantities['Calculated'][_index])/quantities['Energy'][_index]).abs"}
|
||||||
|
],
|
||||||
|
|
||||||
|
# Conditional expressions
|
||||||
|
'Fats.nil? || Fats/Proteins > 2', Set['Fats', 'Proteins'], [
|
||||||
|
{type: :indexed, content: "quantities['Fats'][_index].nil?||" \
|
||||||
|
"quantities['Fats'][_index]/quantities['Proteins'][_index]>2"}
|
||||||
|
],
|
||||||
]
|
]
|
||||||
|
|
||||||
vector.each_slice(3) do |formula, identifiers, parts|
|
vector.each_slice(3) do |formula, identifiers, parts|
|
||||||
|
Reference in New Issue
Block a user