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