lib/rollex/utilities.ex

defmodule Rollex.Utilities do
  defguard is_arithmetic_total?(key) when key != :successes and key != :histogram

  @float_precision 4

  @type merge_operation :: (operation :: atom, left :: number, right :: number -> number)

  @doc """
  Merges two sets of dice roll results into one
  """
  @spec merge(
          left :: map,
          right :: map,
          merge_operation
        ) :: map
  def merge(%{histogram: histogram} = h, %{arithmetic: number}, merge_op) do
    %{h | histogram: Rollex.Distribution.translate_histogram(histogram, number, merge_op)}
  end

  def merge(%{arithmetic: number}, %{histogram: histogram} = h, merge_op) do
    %{h | histogram: Rollex.Distribution.translate_histogram(histogram, number, merge_op)}
  end

  def merge(%{histogram: left}, %{histogram: right} = h, _merge_op) do
    %{h | histogram: Rollex.Distribution.zip_histograms(left, right)}
  end

  def merge(left, right, merge_op) do
    Map.merge(left, right, merge_op)
  end

  @doc """
  Conveniently parses a float from a string known to contain a number, with rounding
  """
  def simple_float_parse(""), do: 1.0

  def simple_float_parse(input) when is_binary(input) do
    {value, _} = Float.parse(input)
    maybe_int = round(value)

    if maybe_int == value do
      maybe_int
    else
      Float.round(value, @float_precision)
    end
  end

  @doc """
  Conveniently parses an integer from a string known to contain a number
  """
  def simple_integer_parse(""), do: 1

  def simple_integer_parse(input) when is_binary(input) do
    {value, _} = Integer.parse(input)
    value
  end
end