defmodule Retex.Node.Test do @moduledoc """ Test node. If we reached that node, means that we are checking that a value is matching a specific condition. If this is the case, we activate this node and pass the token down to the beta network. """ defstruct class: nil, id: nil @type t :: %Retex.Node.Test{} def new(class, id), do: %__MODULE__{class: class, id: id} defimpl Retex.Protocol.Activation do def activate( %Retex.Node.Test{class: [_operator, "$" <> _variable = var]} = neighbor, %Retex{activations: _activations} = rete, %{value: value} = wme, bindings, tokens ) do rete |> Retex.create_activation(neighbor, wme) |> Retex.add_token(neighbor, wme, Map.merge(bindings, %{var => value}), tokens) |> Retex.continue_traversal(Map.merge(bindings, %{var => value}), neighbor, wme) end def activate( %Retex.Node.Test{class: [:in, value]} = neighbor, %Retex{activations: _activations} = rete, wme, bindings, tokens ) do if Enum.member?(value, wme.value) do rete |> Retex.create_activation(neighbor, wme) |> Retex.add_token(neighbor, wme, bindings, tokens) |> Retex.continue_traversal(bindings, neighbor, wme) else Retex.stop_traversal(rete, %{}) end end def activate( %Retex.Node.Test{class: [operator, value]} = neighbor, %Retex{activations: _activations} = rete, wme, bindings, tokens ) do if apply(Kernel, operator, [wme.value, value]) do rete |> Retex.create_activation(neighbor, wme) |> Retex.add_token(neighbor, wme, bindings, tokens) |> Retex.continue_traversal(bindings, neighbor, wme) else Retex.stop_traversal(rete, %{}) end end @spec active?(%{id: any}, Retex.t()) :: boolean() def active?(%{id: id}, %Retex{activations: activations}) do Enum.any?(Map.get(activations, id, [])) end end end