Current section
Files
Jump to
Current section
Files
lib/portal.ex
defmodule Portal do
use Application
# See http://elixir-lang.org/docs/stable/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec
children = [worker(Portal.Door, [])]
# See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :simple_one_for_one, name: Portal.Supervisor]
Supervisor.start_link(children, opts)
end
@doc """
Shoots a new door with the given `color`.
"""
def shoot(color) do
Supervisor.start_child(Portal.Supervisor, [color])
end
defstruct [:left, :right]
@doc """
Starts transfering `data` from `left` to `right`.
"""
def transfer(left, right, data) do
for item <- data do
Portal.Door.push(left, item)
end
%Portal{left: left, right: right}
end
@doc """
Pushes data to the right in the given `portal`.
"""
def push_right(portal) do
push(portal, :left, :right)
end
@doc """
Pushes data to the left in the given `portal`.
"""
def push_left(portal) do
push(portal, :right, :left)
end
defp push(portal, source, target) do
# See if we can pop data from source. If so, push the
# popped data to the target. Otherwise, do nothing.
case Map.get(portal, source) |> Portal.Door.pop do
:error -> :ok
{:ok, h} -> Portal.Door.push(Map.get(portal, target), h)
end
# Let's return the portal itself
portal
end
end
defimpl Inspect, for: Portal do
def inspect(%Portal{left: left, right: right}, _) do
left_door = inspect(left)
right_door = inspect(right)
left_data = inspect(Enum.reverse(Portal.Door.get(left)))
right_data = inspect(Portal.Door.get(right))
max = max(String.length(left_door), String.length(left_data))
"""
#Portal<
#{String.rjust(left_door, max)} <=> #{right_door}
#{String.rjust(left_data, max)} <=> #{right_data}
>
"""
end
end