Current section
Files
Jump to
Current section
Files
lib/rollex/evaluator.ex
defmodule Rollex.Evaluator do
@moduledoc false
@spec evaluate(Rollex.tokens() | {:error, error :: String.t()}) :: Rollex.rollResult()
def evaluate({:error, _error_msg} = input) do
input
end
def evaluate({:ok, tokenized_input}) do
evaluate(tokenized_input)
end
def evaluate(tokenized_input) do
rolled_input = _calculate_dice_results(tokenized_input)
rolled_input
|> Rollex.PrattParser.evaluate_expression()
|> _build_evaluator_output(rolled_input)
end
def histogram(tokenized_input) do
tokenized_input
|> _histogram_dice()
|> Rollex.PrattParser.evaluate_expression()
|> _build_histogram_output(tokenized_input)
end
defp _calculate_dice_results(input, output \\ [])
defp _calculate_dice_results([], output), do: Enum.reverse(output)
defp _calculate_dice_results([%{is_dice: true} = token | tail], output) do
_calculate_dice_results(tail, [Rollex.Dice.roll(token) | output])
end
defp _calculate_dice_results([token | tail], output) do
_calculate_dice_results(tail, [token | output])
end
defp _histogram_dice(input, effort \\ 0, output \\ [])
defp _histogram_dice([], _effort, output), do: Enum.reverse(output)
defp _histogram_dice([%name{} = token | tail], effort, output) do
try do
Protocol.assert_impl!(Rollex.Histogram, name)
{histogram, this_effort} = Rollex.Histogram.evaluate(token, effort)
_histogram_dice(tail, effort + this_effort, [
%Rollex.Tokens.Histogram{histogram: histogram} | output
])
rescue
ArgumentError ->
_histogram_dice(tail, effort, [token | output])
end
end
defp _build_evaluator_output({:error, errors}, _full_tokenized_input) do
{:error, errors}
end
defp _build_evaluator_output({:error, errors, _}, _full_tokenized_input) do
{:error, errors}
end
defp _build_evaluator_output({:ok, final_total, [%Rollex.Tokens.End{}]}, full_tokenized_input) do
{:ok, %{totals: final_total, tokens: full_tokenized_input}}
end
defp _build_evaluator_output(
{:ok, _final_total, [%Rollex.Tokens.RightParenthesis{} | _rest_of_input]},
_full_tokenized_input
) do
{:error, "Missing opening parenthesis"}
end
defp _build_evaluator_output(
{:ok, _final_total, [%Rollex.Tokens.LeftParenthesis{} | _rest_of_input]},
_full_tokenized_input
) do
{:error, "Missing closing parenthesis"}
end
defp _build_evaluator_output({:ok, _final_total, _tokens}, _full_tokenized_input) do
{:error, "Unable to complete calculation"}
end
defp _build_histogram_output({:ok, result, _}, full_tokenized_input) do
{:ok, %{histogram: Map.get(result, :histogram, %{}), tokens: full_tokenized_input}}
end
defp _build_histogram_output({:error, msg, _}, _full_tokenized_input), do: {:error, msg}
end