defmodule Faker do @moduledoc """ Main module to start application with some helper functions. """ @doc """ Starts Faker with default locale. """ @spec start() :: :ok def start do :application.start(:faker) end @doc """ Starts Faker with `lang` locale. """ @spec start(atom) :: :ok def start(lang) when is_atom(lang) do :application.start(:faker) locale(lang) :ok end @doc """ Internal function to format string. It replaces `"#"` to random number and `"?"` to random Latin letter. """ @spec format(String.t()) :: String.t() def format(str) when is_binary(str) do format(str, "") end defp format(<<"#"::utf8, tail::binary>>, acc) do format(tail, <>) end defp format(<<"?"::utf8, tail::binary>>, acc) do format(tail, <>) end defp format(<>, acc) do format(tail, <>) end defp format("", acc) do acc end @alphabet ~c"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" defp letter do Enum.at(@alphabet, random_between(0, Enum.count(@alphabet) - 1)) end @doc """ Returns application locale ready for module construct. """ @spec mlocale() :: String.t() def mlocale do Faker.country() |> mlocale() end defp mlocale(nil) do mlocale("") end defp mlocale(suffix) do Faker.locale() |> to_string() |> String.capitalize() |> Kernel.<>(suffix) end @doc """ Returns application locale. """ @spec locale() :: atom def locale do Application.get_env(:faker, :locale) end @doc """ Returns application country. """ @spec country() :: atom def country do Application.get_env(:faker, :country) end @doc """ Sets application locale. """ @spec locale(atom) :: :ok def locale(lang) when is_atom(lang) do Application.put_env(:faker, :locale, lang) end @doc """ Returns a random float in the value range 0.0 =< x < 1.0. ## Examples iex> is_float(random_uniform()) true """ @spec random_uniform() :: float def random_uniform() do Application.get_env(:faker, :random_module).random_uniform() end @doc """ Returns a (pseudo) random number as an integer between the range intervals. ## Examples iex> random_between(3, 7) in [3, 4, 5, 6, 7] true """ @spec random_between(integer, integer) :: integer def random_between(left, right) do Application.get_env(:faker, :random_module).random_between(left, right) end @doc """ Returns a random bytes. """ @spec random_bytes(pos_integer) :: binary def random_bytes(total) do Application.get_env(:faker, :random_module).random_bytes(total) end @doc """ Returns a shuffled enum. """ @spec shuffle(Enum.t()) :: list() def shuffle(enum) do Application.get_env(:faker, :random_module).shuffle(enum) end defmacro localize(function) do quote do def unquote(function)() do caller = unquote(__CALLER__.module) fn_impl = unquote(function) fn_args = [] fallback = Module.concat(caller, En) [Faker.mlocale(), EnUs] |> Stream.map(&Module.concat(caller, &1)) |> Enum.find(fallback, &function_exported?(&1, fn_impl, 0)) |> apply(fn_impl, fn_args) end end end defmacro sampler(name, data) do count = Enum.count(data) mapped_data = data |> Enum.with_index() |> Enum.into(%{}, fn {k, v} -> {v, k} end) |> Macro.escape() quote do def unquote(name)() do unquote(mapped_data) |> Map.get(Faker.random_between(0, unquote(count - 1))) end end end defmacro samplerp(name, data) do count = Enum.count(data) mapped_data = data |> Enum.with_index() |> Enum.into(%{}, fn {k, v} -> {v, k} end) |> Macro.escape() quote do defp unquote(name)() do unquote(mapped_data) |> Map.get(Faker.random_between(0, unquote(count - 1))) end end end end