This repository has been archived on 2022-07-11. You can view files and clone it, but cannot push or open issues or pull requests.
dandhelper.ex/Dice.ex

67 lines
1.7 KiB
Elixir

defmodule DiceMacro do
defmacro for_every_value(name, todo) do
quote do
def unquote(name)(d) do
Enum.reduce(d.values, 0, unquote(todo))
end
end
end
end
defmodule Dice do
@moduledoc """
`Dice` is a structure that contain a constant or a random value
"""
defstruct values: [[]]
# note: when implement `Enum` instead of is_list ?
@doc """
Returns: `Dice` struct having every values specified in parameter
"""
def new(values) when is_list(values) do
%Dice{values: values}
end
@doc """
Returns: `Dice` struct parsed from a string "nDf" or "n"
"""
def new(str) when is_bitstring(str) do
cond do
str =~ ~r/\d+d\d+/i ->
cap = Regex.named_captures(~r/(?<nb>\d+)d(?<faces>\d+)/i, str)
nb = String.to_integer(cap["nb"])
faces = String.to_integer(cap["faces"])
new(Enum.map(1..nb, fn(_) ->
Enum.to_list(1..faces)
end))
str =~ ~r/\d+/ ->
new([[String.to_integer(str)]])
end
end
@doc """
Returns: `Dice` negated (every values in the `Dice` are negated)
"""
def neg(d) do
%Dice{values: Enum.map(d.values, fn(arr) ->
Enum.map(arr, &(-(&1)))
end)}
end
require DiceMacro
DiceMacro.for_every_value(:test, fn(r, l) -> l + Enum.random(r) end)
DiceMacro.for_every_value(:max, fn(r, l) -> l + Enum.max(r) end)
DiceMacro.for_every_value(:min, fn(r, l) -> l + Enum.min(r) end)
DiceMacro.for_every_value(:mean, fn(r, l) -> l + (Enum.min(r) + Enum.max(r)) / 2 end)
def to_string(d) do
cond do
Enum.count(d.values) == 1 and Enum.count(List.first(d.values)) == 1 ->
"#{List.first(List.first(d.values))}"
true ->
"#{Enum.count(d.values)}D#{Enum.count(List.first(d.values))}"
end
end
end