Packages

Accomplice is a library for grouping members of a list with a respect to a number of constraints.

Current section

Files

Jump to
accomplice lib accomplice_helpers.ex
Raw

lib/accomplice_helpers.ex

defmodule Accomplice.Helpers do
@moduledoc false
@doc false
@spec validate_options(map()) :: map() | {:error, atom()}
def validate_options(%{minimum: min, ideal: ideal, maximum: max} = options) do
cond do
min < 1 || max < 1 || ideal < 1 -> {:error, :size_constraint_below_one}
min > max -> {:error, :minimum_above_maximum}
ideal < min || ideal > max -> {:error, :ideal_not_between_min_and_max}
true -> options
end
end
def validate_options(%{minimum: min, maximum: max} = options) do
cond do
min < 1 || max < 1 -> {:error, :size_constraint_below_one}
min > max -> {:error, :minimum_above_maximum}
true -> options
end
end
def validate_options(options) when is_map(options), do: {:error, :missing_size_constraint}
def validate_options(_), do: {:error, :options_is_not_map}
@doc false
@spec pop(list(any())) :: {any(), list(any())} | {nil, list(any())}
def pop([]), do: {nil, []}
def pop([head | tail]), do: {head, tail}
@type actions :: nonempty_list(:add | :complete) | :impossible
@doc false
@spec create_actions(list(list(any())), list(any()), map()) :: actions
def create_actions(current_group, ungrouped, %{minimum: minimum, ideal: ideal, maximum: maximum}) do
current_group_length = length(current_group)
cond do
current_group_length < minimum ->
# when the current_group's length is less than the minimum constraint,
# our only option is to add en element. If there are no elements to add,
# then we have no legal action and so return the :impossible atom
case ungrouped do
[] -> :impossible
ungrouped -> add_actions(ungrouped)
end
current_group_length == maximum ->
# when the current_group's length is equal to the maximum constraint,
# our only option is to complete the group.
[:complete]
current_group_length < ideal ->
# when the current group's length is less than the ideal, we first want
# to try adding an element, then we'll try completing the group since we
# know that we're at least at the minimum length.
add_actions(ungrouped) ++ [:complete]
current_group_length == ideal ->
# when the current group's length is at ideal, we first want to try completing
# the group, then try adding the elements, since we know that we're below the
# maximum current_group length.
[:complete | add_actions(ungrouped)]
end
end
@spec add_actions(list(any())) :: list({:add, any()})
defp add_actions([]), do: []
defp add_actions(ungrouped) do
for _ <- 1..length(ungrouped), do: :add
end
end