Packages
islands_grid
0.1.1
0.1.46
0.1.45
0.1.44
0.1.43
0.1.42
0.1.41
0.1.40
0.1.39
0.1.38
0.1.37
0.1.36
0.1.35
0.1.34
0.1.33
0.1.32
0.1.31
0.1.30
0.1.29
0.1.28
0.1.27
0.1.26
0.1.25
0.1.24
0.1.23
0.1.22
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
A grid (map of maps) and functions for the Game of Islands.
Current section
Files
Jump to
Current section
Files
lib/islands/grid.ex
# ┌───────────────────────────────────────────────────────────────────────┐
# │ Inspired by the book "Functional Web Development" by Lance Halvorsen. │
# └───────────────────────────────────────────────────────────────────────┘
defmodule Islands.Grid do
use PersistConfig
@book_ref Application.get_env(@app, :book_ref)
@moduledoc """
Creates a `grid` struct for the _Game of Islands_.
Convenience module for client applications.
Converts a board or guesses struct to a grid (map of maps).
Also converts a grid to a list of maps.
\n##### #{@book_ref}
"""
import Enum, only: [reduce: 3]
alias __MODULE__.Tile
alias IO.ANSI.Plus, as: ANSI
alias Islands.{Board, Coord, Guesses, Island}
@type t :: %{Coord.row() => %{Coord.col() => atom}}
@board_range Application.get_env(@app, :board_range)
@doc """
Returns an "empty" grid.
"""
@spec new() :: t
def new() do
for row <- @board_range, into: %{} do
{row, for(col <- @board_range, into: %{}, do: {col, nil})}
end
end
@doc """
Converts a board or guesses struct to a grid.
"""
@spec new(Board.t() | Guesses.t()) :: t
def new(board_or_guesses)
def new(%Board{islands: islands, misses: misses}) do
islands
|> Map.values()
|> reduce(new(), fn %Island{type: type, coords: coords, hits: hits}, grid ->
grid
|> update(coords, type)
|> update(hits, :"#{type}_hit")
end)
|> update(misses, :board_miss)
end
def new(%Guesses{hits: hits, misses: misses}),
do: new() |> update(hits, :hit) |> update(misses, :miss)
@doc """
Converts a grid to a list of maps.
"""
@spec to_maps(t, (atom -> ANSI.ansidata())) :: [map]
def to_maps(%{} = grid, fun \\ &Tile.new/1) when is_function(fun, 1) do
for {row_num, row_map} <- grid do
[
{"row", row_num}
| for({col_num, cell_val} <- row_map, do: {col_num, fun.(cell_val)})
]
|> Map.new()
end
end
## Private functions
@spec update(t, Island.coords(), atom) :: t
defp update(grid, coords, value) do
coords
|> MapSet.to_list()
|> reduce(grid, fn %Coord{row: row, col: col}, grid ->
put_in(grid[row][col], value)
end)
end
end