Current section
Files
Jump to
Current section
Files
lib/instructions_runner.ex
defmodule MarsExplorer.InstructionsRunner do
@moduledoc """
Module responsible for running the exploration instructions
"""
use Agent
alias MarsExplorer.{HighlandGrid, ExplorationsController, Exploration}
@doc """
Run a set of exploration instructions
## Example
iex> instructions = [{:grid, %{north: 5, east: 5}}, {:place, %{north: 0, east: 0, direction: :north}}, [:move, :move]]
[{:grid, %{north: 5, east: 5}}, {:place, %{north: 0, east: 0, direction: :north}}, [:move, :move]]
iex> MarsExplorer.InstructionsRunner.run instructions
[
%MarsExplorer.Exploration{
probe: %MarsExplorer.Probe{
north: 2,
east: 0,
direction: :north
},
grid: %MarsExplorer.HighlandGrid{
north_limit: 5,
east_limit: 5
}
}
]
"""
@spec run([
{:grid, %{north: integer(), east: integer()}}
| {:place, Exploration.placement()}
| [:move | :turn_left | :turn_right]
]) :: [Exploration.t()]
def run([{:grid, grid} | rest]) do
grid = HighlandGrid.build(grid)
ExplorationsController.set_grid(grid)
run(rest)
end
def run([{:place, placement} | rest]) do
grid = ExplorationsController.get_grid()
if grid do
case Exploration.place(grid, placement) do
{:ok, exploration} ->
ExplorationsController.set_running_exploration(exploration)
run(rest, exploration)
{:error, :invalid_placement} ->
run(rest)
end
else
run(rest)
end
end
def run([_instruction | rest]), do: run(rest)
def run([]), do: nil
defp run([{:invalid, _instruction} | rest], exploration), do: run(rest, exploration)
defp run([instructions | rest], exploration) when is_list(instructions) do
new_exploration = execute_movements(instructions, exploration)
ExplorationsController.update_running_exploration(new_exploration)
run(rest, new_exploration)
end
defp run([{:place, _placement} | _rest] = instructions, exploration) do
ExplorationsController.update_running_exploration(exploration)
run(instructions)
end
defp run([], exploration) do
ExplorationsController.update_running_exploration(exploration)
ExplorationsController.get_running_exploration()
|> ExplorationsController.add_exploration_to_explorations_list()
explorations = ExplorationsController.get_explorations()
ExplorationsController.clean_explorations()
explorations
end
defp execute_movements([:move | rest], exploration) do
new_exploration =
exploration
|> Exploration.move()
|> case do
{:ok, exploration} -> exploration
{:error, :at_grid_limit} -> exploration
end
ExplorationsController.update_running_exploration(new_exploration)
execute_movements(rest, new_exploration)
end
defp execute_movements([:turn_left | rest], exploration) do
{:ok, new_exploration} = exploration |> Exploration.turn_left()
ExplorationsController.update_running_exploration(new_exploration)
execute_movements(rest, new_exploration)
end
defp execute_movements([:turn_right | rest], exploration) do
{:ok, new_exploration} = exploration |> Exploration.turn_right()
ExplorationsController.update_running_exploration(new_exploration)
execute_movements(rest, new_exploration)
end
defp execute_movements([], exploration) do
ExplorationsController.update_running_exploration(exploration)
exploration
end
end