Current section
Files
Jump to
Current section
Files
lib/say_number.ex
defmodule SayNumber do
@moduledoc """
Main module to handle spelling of a number.
"""
alias SayNumber.Patcher.Indonesian, as: IDPatcher
@doc """
Say number, supply an integer and locale,
get the pronounciable words. Currently supported locale:
* English (default)
* Indonesian Language (Bahasa Indonesia)
Current `number` limit is: `999_999_999_999_999`
Returns a string.
## Examples
iex> SayNumber.spell(1899)
"One thousand eight hundred ninety nine"
iex> SayNumber.spell(91_000, "id")
"Sembilan puluh satu ribu"
"""
def spell(number, locale \\ "en") do
Gettext.put_locale(SayNumber.Gettext, locale)
IO.puts(Gettext.get_locale(SayNumber.Gettext))
IO.puts("**** 2")
number
|> do_spell()
|> patch_by_locale(locale)
|> String.capitalize()
end
defp do_spell(n) when n >= 1_000_000_000_000_000,
do: raise(Gettext.gettext(SayNumber.Gettext, "Too large number"))
defp do_spell(0), do: Gettext.gettext(SayNumber.Gettext, "zero")
defp do_spell(1), do: Gettext.gettext(SayNumber.Gettext, "one")
defp do_spell(2), do: Gettext.gettext(SayNumber.Gettext, "two")
defp do_spell(3), do: Gettext.gettext(SayNumber.Gettext, "three")
defp do_spell(4), do: Gettext.gettext(SayNumber.Gettext, "four")
defp do_spell(5), do: Gettext.gettext(SayNumber.Gettext, "five")
defp do_spell(6), do: Gettext.gettext(SayNumber.Gettext, "six")
defp do_spell(7), do: Gettext.gettext(SayNumber.Gettext, "seven")
defp do_spell(8), do: Gettext.gettext(SayNumber.Gettext, "eight")
defp do_spell(9), do: Gettext.gettext(SayNumber.Gettext, "nine")
defp do_spell(10), do: Gettext.gettext(SayNumber.Gettext, "ten")
defp do_spell(11), do: Gettext.gettext(SayNumber.Gettext, "eleven")
defp do_spell(12), do: Gettext.gettext(SayNumber.Gettext, "twelve")
defp do_spell(13), do: Gettext.gettext(SayNumber.Gettext, "thirteen")
defp do_spell(14), do: Gettext.gettext(SayNumber.Gettext, "fourteen")
defp do_spell(15), do: Gettext.gettext(SayNumber.Gettext, "fifteen")
defp do_spell(16), do: Gettext.gettext(SayNumber.Gettext, "sixteen")
defp do_spell(17), do: Gettext.gettext(SayNumber.Gettext, "seventeen")
defp do_spell(18), do: Gettext.gettext(SayNumber.Gettext, "eighteen")
defp do_spell(19), do: Gettext.gettext(SayNumber.Gettext, "nineteen")
defp do_spell(20), do: Gettext.gettext(SayNumber.Gettext, "twenty")
defp do_spell(30), do: Gettext.gettext(SayNumber.Gettext, "thirty")
defp do_spell(40), do: Gettext.gettext(SayNumber.Gettext, "forty")
defp do_spell(50), do: Gettext.gettext(SayNumber.Gettext, "fifty")
defp do_spell(60), do: Gettext.gettext(SayNumber.Gettext, "sixty")
defp do_spell(70), do: Gettext.gettext(SayNumber.Gettext, "seventy")
defp do_spell(80), do: Gettext.gettext(SayNumber.Gettext, "eighty")
defp do_spell(90), do: Gettext.gettext(SayNumber.Gettext, "ninety")
# Below hundred.
defp do_spell(n) when n < 100 do
multiple_of_tens = div(n, 10) * 10
remaining = n - multiple_of_tens
construct_string(multiple_of_tens, "", remaining)
end
# Below thousand.
defp do_spell(n) when n < 1000 do
multiple_of_hundreds = div(n, 100)
remaining = rem(n, 100)
construct_string(
multiple_of_hundreds,
Gettext.gettext(SayNumber.Gettext, "hundred"),
remaining
)
end
# Below million.
defp do_spell(n) when n < 1_000_000 do
multiple_of_hundreds = div(n, 1000)
remaining = rem(n, 1000)
construct_string(
multiple_of_hundreds,
Gettext.gettext(SayNumber.Gettext, "thousand"),
remaining
)
end
# Below billion.
defp do_spell(n) when n < 1_000_000_000 do
multiple_of_hundreds = div(n, 1_000_000)
remaining = rem(n, 1_000_000)
construct_string(
multiple_of_hundreds,
Gettext.gettext(SayNumber.Gettext, "million"),
remaining
)
end
# Below trillion.
defp do_spell(n) when n < 1_000_000_000_000 do
multiple_of_hundreds = div(n, 1_000_000_000)
remaining = rem(n, 1_000_000_000)
construct_string(
multiple_of_hundreds,
Gettext.gettext(SayNumber.Gettext, "billion"),
remaining
)
end
# Below quadrillion.
defp do_spell(n) when n < 1_000_000_000_000_000 do
multiple_of_hundreds = div(n, 1_000_000_000_000)
remaining = rem(n, 1_000_000_000_000)
construct_string(
multiple_of_hundreds,
Gettext.gettext(SayNumber.Gettext, "trillion"),
remaining
)
end
# Need to write this method in order to prevent infinite loop for 200, 3000, etc.
# Directly append the number of base with the base itself.
defp construct_string(number_of_base, base, 0) do
[do_spell(number_of_base), base]
|> Enum.join(" ")
end
defp construct_string(number_of_base, base, remaining) do
[do_spell(number_of_base), base, do_spell(remaining)]
|> Enum.reject(&(&1 == ""))
|> Enum.join(" ")
end
defp patch_by_locale(string, locale) do
if locale == "id" do
IDPatcher.perform(string)
else
string
end
end
end