diff --git a/app/models/logic.rb b/app/models/logic.rb index ea9552ed3..6945a0db2 100644 --- a/app/models/logic.rb +++ b/app/models/logic.rb @@ -8,12 +8,23 @@ module Logic end def self.class_from_name(name) - [Constant, Empty] + [Constant, Empty, LessThan, LessThanEq, Eq, GreaterThanEq, GreaterThan, EmptyOperator] .find { |c| c.name == name } end + def ds_eq(left, right) = Logic::Eq.new(left, right) + + def greater_than(left, right) = Logic::GreaterThan.new(left, right) + + def greater_than_eq(left, right) = Logic::GreaterThanEq.new(left, right) + + def less_than(left, right) = Logic::LessThan.new(left, right) + + def less_than_eq(left, right) = Logic::LessThanEq.new(left, right) + def constant(value) = Logic::Constant.new(value) def empty = Logic::Empty.new + def empty_operator(left, right) = Logic::EmptyOperator.new(left, right) end diff --git a/app/models/logic/binary_operator.rb b/app/models/logic/binary_operator.rb new file mode 100644 index 000000000..85b7fb49c --- /dev/null +++ b/app/models/logic/binary_operator.rb @@ -0,0 +1,46 @@ +class Logic::BinaryOperator < Logic::Term + attr_reader :left, :right + + def initialize(left, right) + @left, @right = left, right + end + + def to_h + { + "op" => self.class.name, + "left" => @left.to_h, + "right" => @right.to_h + } + end + + def self.from_h(h) + self.new(Logic.from_h(h['left']), Logic.from_h(h['right'])) + end + + def errors(stable_ids = []) + errors = [] + + if @left.type != :number || @right.type != :number + errors += ["les types sont incompatibles : #{self}"] + end + + errors + @left.errors(stable_ids) + @right.errors(stable_ids) + end + + def type = :boolean + + def compute(champs = []) + l = @left.compute(champs) + r = @right.compute(champs) + + l.send(operation, r) + end + + def to_s = "(#{@left} #{operation} #{@right})" + + def ==(other) + self.class == other.class && + @left == other.left && + @right == other.right + end +end diff --git a/app/models/logic/empty_operator.rb b/app/models/logic/empty_operator.rb new file mode 100644 index 000000000..44ab38c40 --- /dev/null +++ b/app/models/logic/empty_operator.rb @@ -0,0 +1,7 @@ +class Logic::EmptyOperator < Logic::BinaryOperator + def to_s = "empty operator" + + def type = :empty + + def errors(_stable_ids = nil) = ['empty'] +end diff --git a/app/models/logic/greater_than.rb b/app/models/logic/greater_than.rb new file mode 100644 index 000000000..2ba94af0f --- /dev/null +++ b/app/models/logic/greater_than.rb @@ -0,0 +1,3 @@ +class Logic::GreaterThan < Logic::BinaryOperator + def operation = :> +end diff --git a/app/models/logic/greater_than_eq.rb b/app/models/logic/greater_than_eq.rb new file mode 100644 index 000000000..d452bceef --- /dev/null +++ b/app/models/logic/greater_than_eq.rb @@ -0,0 +1,3 @@ +class Logic::GreaterThanEq < Logic::BinaryOperator + def operation = :>= +end diff --git a/app/models/logic/less_than.rb b/app/models/logic/less_than.rb new file mode 100644 index 000000000..b39282ee7 --- /dev/null +++ b/app/models/logic/less_than.rb @@ -0,0 +1,3 @@ +class Logic::LessThan < Logic::BinaryOperator + def operation = :< +end diff --git a/app/models/logic/less_than_eq.rb b/app/models/logic/less_than_eq.rb new file mode 100644 index 000000000..79e4c7308 --- /dev/null +++ b/app/models/logic/less_than_eq.rb @@ -0,0 +1,3 @@ +class Logic::LessThanEq < Logic::BinaryOperator + def operation = :<= +end diff --git a/spec/models/logic/binary_operator_spec.rb b/spec/models/logic/binary_operator_spec.rb new file mode 100644 index 000000000..de145514c --- /dev/null +++ b/spec/models/logic/binary_operator_spec.rb @@ -0,0 +1,52 @@ +include Logic + +describe Logic::BinaryOperator do + let(:two_greater_than_one) { greater_than(constant(2), constant(1))} + + describe '#type' do + it { expect(two_greater_than_one.type).to eq(:boolean) } + end + + describe '#to_s' do + it { expect(two_greater_than_one.to_s).to eq('(2 > 1)') } + end + + describe '#==' do + it { expect(two_greater_than_one).to eq(greater_than(constant(2), constant(1))) } + it { expect(two_greater_than_one).not_to eq(greater_than(constant(1), constant(2))) } + end + + describe '#errors' do + it { expect(greater_than(constant(1), constant(true)).errors).to eq(['les types sont incompatibles : (1 > true)']) } + end +end + +describe Logic::GreaterThan do + it 'computes' do + expect(greater_than(constant(1), constant(1)).compute).to be(false) + expect(greater_than(constant(2), constant(1)).compute).to be(true) + end +end + +describe Logic::GreaterThanEq do + it 'computes' do + expect(greater_than_eq(constant(0), constant(1)).compute).to be(false) + expect(greater_than_eq(constant(1), constant(1)).compute).to be(true) + expect(greater_than_eq(constant(2), constant(1)).compute).to be(true) + end +end + +describe Logic::LessThan do + it 'computes' do + expect(less_than(constant(1), constant(1)).compute).to be(false) + expect(less_than(constant(1), constant(2)).compute).to be(true) + end +end + +describe Logic::LessThanEq do + it 'computes' do + expect(less_than_eq(constant(0), constant(1)).compute).to be(true) + expect(less_than_eq(constant(1), constant(1)).compute).to be(true) + expect(less_than_eq(constant(2), constant(1)).compute).to be(false) + end +end diff --git a/spec/models/logic_spec.rb b/spec/models/logic_spec.rb index 43a017a4f..abd5fcc41 100644 --- a/spec/models/logic_spec.rb +++ b/spec/models/logic_spec.rb @@ -6,5 +6,7 @@ describe Logic do expect(Logic.from_json(constant(1).to_json)).to eq(constant(1)) expect(Logic.from_h(empty.to_h)).to eq(empty) + + expect(Logic.from_h(greater_than(constant(1), constant(2)).to_h)).to eq(greater_than(constant(1), constant(2))) end end