Current section

Files

Jump to
nop_elixir lib nop element premise.ex
Raw

lib/nop/element/premise.ex

defmodule NOP.Element.Premise do
use GenServer
use NOP.Element.LogicElement
def start_link(premise_name, fbe, fbe_attr, operator, operand) do
state = init_state(premise_name, fbe, fbe_attr, operator, operand)
state = init_condition_list(state)
state = reset_statistics_to_state(state)
#{:ok, pid} = GenServer.start_link(__MODULE__, state, name: String.to_atom(premise_name))
{:ok, pid} = GenServer.start_link(__MODULE__, state)
#Link premise to FBE
GenServer.cast(fbe, {:link_premise, fbe_attr, pid, :left, premise_name})
{:ok, pid}
end
def start_link(premise_name, fbe_left, fbe_left_attr, operator, fbe_right, fbe_right_attr) do
state = init_state(premise_name, fbe_left, fbe_left_attr, operator, fbe_right, fbe_right_attr)
state = init_condition_list(state)
state = reset_statistics_to_state(state)
#{:ok, pid} = GenServer.start_link(__MODULE__, state, name: String.to_atom(premise_name))
{:ok, pid} = GenServer.start_link(__MODULE__, state)
#Link premise to FBE (left)
GenServer.cast(fbe_left, {:link_premise, fbe_left_attr, pid, :left, premise_name})
#Link premise to FBE (right)
GenServer.cast(fbe_right, {:link_premise, fbe_right_attr, pid, :right, premise_name})
{:ok, pid}
end
def init(state) do
{:ok, state}
end
def handle_cast({:notify, side, _, fbe_attr, new_value, fbe_name}, state) do
premise_name = get_name(state)
Logger.debug("Premise #{premise_name} notified by modification of FBE attribute #{fbe_name}.#{fbe_attr} to value #{new_value} on the #{side} side")
premise = get_premise_from_state(state)
beg_time = get_timestamp()
state = update_assert(state, side, premise, new_value)
end_time = get_timestamp()
state = add_statistics_to_state(state, diff_between_timestamp(beg_time, end_time))
{:noreply, state}
end
defp init_state(premise_name, fbe_left, fbe_left_attr, operator, fbe_right, fbe_right_attr) do
state = %{:name => premise_name}
#Get initial value
left_value = GenServer.call(fbe_left, {:get_attr, fbe_left_attr}, :infinity)
right_value = GenServer.call(fbe_right, {:get_attr, fbe_right_attr}, :infinity)
#Assert initial value based on attribute value
result = assert_value(premise_name, left_value, operator, right_value)
#Set the premise
premise_attrs = premise_to_map(fbe_left, fbe_left_attr, left_value, operator, fbe_right, fbe_right_attr, right_value)
#Update state
state = set_premise_to_state(state, premise_attrs)
set_result_to_state(state, result)
end
defp init_state(premise_name, fbe, fbe_attr, operator, operand) do
state = %{:name => premise_name}
#Get initial value
attr_value = GenServer.call(fbe, {:get_attr, fbe_attr})
#Assert initial value based on attribute value
result = assert_value(premise_name, attr_value, operator, operand)
#Set the premise
premise_attrs = premise_to_map(fbe, fbe_attr, attr_value, operator, operand)
#Update state
state = set_premise_to_state(state, premise_attrs)
set_result_to_state(state, result)
end
defp premise_to_map(fbe, fbe_attr, last_value, operator, operand) do
{fbe, fbe_attr, last_value, operator, operand}
end
defp premise_to_map(fbe_left, fbe_left_attr, left_value, operator, fbe_right, fbe_right_attr, right_value) do
{fbe_left, fbe_left_attr, left_value, operator, fbe_right, fbe_right_attr, right_value}
end
# Operators -----------------------------
defp assert(left, :EQ, right) do
left == right
end
defp assert(left, :NE, right) do
left != right
end
defp assert(left, :GT, right) do
left > right
end
defp assert(left, :GE, right) do
left >= right
end
defp assert(left, :LT, right) do
left < right
end
defp assert(left, :LE, right) do
left <= right
end
defp assert(_, _, _) do
false
end
# Operators -----------------------------
defp assert_value(premise_name, left_value, operator, right_value) do
result = assert(left_value, operator, right_value)
Logger.debug("Assert premise #{premise_name} (#{left_value} #{operator} #{right_value}) ? = #{result}")
result
end
defp get_premise_from_state(state) do
Map.get(state, :premise)
end
defp set_premise_to_state(state, premise_attrs) do
Map.put(state, :premise, premise_attrs)
end
defp update_assert(state, :left, {fbe, fbe_attr, _, operator, operand}, new_value) do
name = get_name(state)
old_result = get_result_from_state(state)
result = assert_value(name, new_value, operator, operand)
if old_result != result do
notify_conditions(state, result, name)
end
premise = premise_to_map(fbe, fbe_attr, new_value, operator, operand)
state = set_premise_to_state(state, premise)
set_result_to_state(state, result)
end
defp update_assert(state, :left, {fbe_left, fbe_left_attr, _, operator, fbe_right, fbe_right_attr, right_value}, new_value) do
name = get_name(state)
old_result = get_result_from_state(state)
result = assert_value(name, new_value, operator, right_value)
if old_result != result do
notify_conditions(state, result, name)
end
premise = premise_to_map(fbe_left, fbe_left_attr, new_value, operator, fbe_right, fbe_right_attr, right_value)
state = set_premise_to_state(state, premise)
set_result_to_state(state, result)
end
defp update_assert(state, :right, {fbe_left, fbe_left_attr, left_value, operator, fbe_right, fbe_right_attr, _}, new_value) do
name = get_name(state)
old_result = get_result_from_state(state)
result = assert_value(name, left_value, operator, new_value)
if old_result != result do
notify_conditions(state, result, name)
end
premise = premise_to_map(fbe_left, fbe_left_attr, left_value, operator, fbe_right, fbe_right_attr, new_value)
state = set_premise_to_state(state, premise)
set_result_to_state(state, result)
end
defp update_my_state(_state, _name, _element_name, _values, _old_result) do
true
end
end