defmodule Holidefs.Definition do
@moduledoc """
A definition is a set of rules for the holiday events in
the year.
"""
alias Holidefs.Definition
alias Holidefs.Definition.Rule
defstruct [:code, :name, rules: []]
@type t :: %Definition{
code: atom,
name: String.t(),
rules: [Holidefs.Definition.Rule.t()]
}
@doc """
Returns the path for the given locale definition file.
"""
@spec file_path(atom, Path.t()) :: binary
def file_path(code, path \\ path()), do: Path.join(path, "#{code}.yaml")
@doc """
Returns the path where all the locale definitions are saved.
"""
@spec path() :: Path.t()
def path() do
Path.join(:code.priv_dir(:holidefs), "/calendars/definitions")
end
@doc """
Loads the definition for a locale code and name.
If any definition rule is invalid, a `RuntimeError` will be raised
"""
@spec load!(atom, String.t()) :: t
def load!(code, name) do
{:ok, file_data} =
code
|> file_path()
|> to_charlist()
|> YamlElixir.read_from_file()
rules =
file_data
|> Map.get("months")
|> Enum.flat_map(fn {month, rules} ->
for rule <- rules, do: Rule.build(code, month, rule)
end)
%Definition{
code: code,
name: name,
rules: rules
}
end
@doc """
Returns the list of regions from the definition.
"""
@spec get_regions(t) :: [String.t()]
def get_regions(%Definition{} = definition) do
definition
|> Map.get(:rules)
|> Stream.flat_map(&Map.get(&1, :regions))
|> Stream.uniq()
|> Enum.sort()
end
end