diff --git a/src/hz_format.erl b/src/hz_format.erl index cb723f2..a516fb2 100644 --- a/src/hz_format.erl +++ b/src/hz_format.erl @@ -4,109 +4,167 @@ -module(hz_format). --export([price/1, price/3, price/4, % read_price/1, +-export([price/1, price/2, price/3, price/4, % read_price/1, price_to_string/1, string_to_price/1]). +-spec price(Pucks) -> Formatted + when Pucks :: integer(), + Formatted :: string(). +%% @doc +%% A convenience formatting function. +%% @equiv price(us, Pucks). price(Pucks) -> - price(gaju, {west, $,, 3},Pucks). + price(us, Pucks). -price(puck, {west, Separator, Period}, Pucks) -> - western_format(Separator, Period, Pucks); -price(gaju, {west, Separator = $., Period}, Pucks) -> - western_format(Separator, $,, Period, all, Pucks); -price(gaju, {west, Separator, Period}, Pucks) -> - western_format(Separator, $., Period, all, Pucks); +-spec price(Style, Pucks) -> Formatted + when Style :: us | ch | jp | {Separator, Period}, + Separator :: $, | $. | $_, + Period :: 3 | 4, + Pucks :: integer(), + Formatted :: string(). +%% @doc +%% A convenient formatting function. +%% @equiv price(gaju, Style, Pucks). + +price(Style, Pucks) -> + price(gaju, Style, Pucks). + + +-spec price(Unit, Style, Pucks) -> Formatted + when Unit :: gaju | puck, + Style :: us | ch | jp | {Separator, Period}, + Separator :: $, | $. | $_, + Period :: 3 | 4, + Pucks :: integer(), + Formatted :: string(). +%% @doc +%% A simplified format function covering the most common formats desired. +%% +%% ``` + +price(gaju, us, Pucks) -> + wetsern($,, $., 3, all, Pucks); +price(puck, us, Pucks) -> + wetsern($,, 3, Pucks); +price(gaju, ch, Pucks) -> + wetsern($., $,, 3, all, Pucks); +price(puck, ch, Pucks) -> + wetsern($,, 3, Pucks); price(Unit, jp, Pucks) -> - jp_format(Unit, all, Pucks). + jp(Unit, all, Pucks); +price(gaju, {$., Period}, Pucks) -> + wetsern($., $,, Period, all, Pucks); +price(gaju, {Separator, Period}, Pucks) -> + wetsern(Separator, $., Period, all, Pucks); +price(puck, {Separator, Period}, Pucks) -> + wetsern(Separator, Period, Pucks). -spec price(Unit, Style, Precision, Pucks) -> Serialized when Unit :: gaju | puck, - Style :: jp | jp_pucks | {Separator, Period}, + Style :: us | ch | jp | {Separator, Period}, Precision :: all | 0..18, Separator :: $, | $. | $_, Period :: 3 | 4, Pucks :: integer(), Serialized :: string(). %% @doc -%% A formatting function that accepts a price value in pucks as an integer, and outputs a string -%% formatted in the desired way. +%% A flexible, if annoyingly complex, formatting function. %% -%% Consider, for example, a few input and output pairs: %% ``` -%% price({$,, 3}, 3, 123456789123456789123456789) -> +%% price(gaju, us, 3, 123456789123456789123456789) -> +%% "木123,456,789.123...". +%% +%% price(gaju, ch, 3, 123456789123456789123456789) -> +%% "木123.456.789,123...". +%% +%% price(gaju, us, 3, 123456789123000000000000000) -> %% "木123,456,789.123". %% -%% price({$,, 3}, 6, 123456789123456789123456789) -> -%% "木123,456,789.123,456" +%% price(gaju, {$,, 3}, 3, 123456789123456789123456789) -> +%% "木123,456,789.123...". %% -%% price({$,, 3}, all, 123456789123456789123456789) -> +%% price(gaju, {$,, 3}, 6, 123456789123000000000000000) -> +%% "木123,456,789.123" +%% +%% price(gaju, {$., 3}, all, 123456789123456789123456789) -> %% "木123.456.789,123.456.789.123.456.789" %% -%% price({$_, 4}, 10, 123456789123456789123456789) -> -%% "木1_2345_6789.1234_5678_91" +%% price(gaju, {$_, 4}, 10, 123456789123456789123456789) -> +%% "木1_2345_6789.1234_5678_91..." %% -%% price(jp, 3, 123456789123456789123456789) -> -%% "1億2345万6789木12京3000兆本" +%% price(gaju, jp, 3, 123456789123456789123456789) -> +%% "1億2345万6789木 12京3000兆本" %% -%% price(jp, 6, 123456789123456789123456789) -> -%% "1億2345万6789木12京3456兆本" +%% price(gaju, jp, 6, 123456789123456789123456789) -> +%% "1億2345万6789木 12京3456兆本" %% -%% price(jp, 0, 123456789123456789123456789) -> +%% price(gaju, jp, 0, 123456789123456789123456789) -> %% "1億2345万6789木" %% -%% price(jp_pucks, all, 123456789123456789123456789) -> +%% price(puck, jp, all, 123456789123456789123456789) -> %% "123秭4567垓8912京3456兆7891億2345万6789本" %% ''' - -price(puck, {west, Separator, Period}, _, Pucks) -> - western_format(Separator, Period, Pucks); -price(gaju, {west, Separator = $., Period}, Precision, Pucks) -> - western_format(Separator, $,, Period, Precision, Pucks); -price(gaju, {west, Separator, Period}, Precision, Pucks) -> - western_format(Separator, $., Period, Precision, Pucks); -price(Unit, jp, Precision, Pucks) -> - jp_format(Unit, Precision, Pucks). +price(gaju, us, Precision, Pucks) -> + wetsern($,, $., 3, Precision, Pucks); +price(gaju, ch, Precision, Pucks) -> + wetsern($., $,, 3, Precision, Pucks); +price(gaju, jp, Precision, Pucks) -> + jp(gaju, Precision, Pucks); +price(gaju, {$., Period}, Precision, Pucks) -> + wetsern($., $,, Period, Precision, Pucks); +price(gaju, {Separator, Period}, Precision, Pucks) -> + wetsern(Separator, $., Period, Precision, Pucks); +price(puck, us, _, Pucks) -> + wetsern($,, 3, Pucks); +price(puck, ch, _, Pucks) -> + wetsern($., 3, Pucks); +price(puck, jp, _, Pucks) -> + jp(puck, all, Pucks); +price(puck, {Separator, Period}, _, Pucks) -> + wetsern(Separator, Period, Pucks). -western_format(Separator, Period, Pucks) -> +wetsern(Separator, Period, Pucks) -> P = lists:reverse(integer_to_list(Pucks)), [puck_mark() | separate(Separator, Period, P)]. -western_format(Separator, _, Period, 0, Pucks) -> +wetsern(Separator, _, Period, 0, Pucks) -> G = lists:reverse(integer_to_list(Pucks div one_gaju())), [gaju_mark() | separate(Separator, Period, G)]; -western_format(Separator, Break, Period, Precision, Pucks) -> +wetsern(Separator, Break, Period, Precision, Pucks) -> SP = integer_to_list(Pucks), Length = length(SP), Over18 = Length > 18, NoPucks = (Pucks rem one_gaju()) =:= 0, case {Over18, NoPucks} of {true, true} -> - Gs = lists:reverse(lists:sublist(Length - 18, SP)), + Gs = lists:reverse(lists:sublist(SP, Length - 18)), [gaju_mark() | separate(Separator, Period, Gs)]; {true, false} -> - {GChars, PChars} = lists:split(18, SP), - H = [gaju_mark() | separate(Separator, Period, lists:reverse(GChars))], - {P, E} = decimal_pucks(Precision, PChars), + {PChars, GChars} = lists:split(18, lists:reverse(SP)), + H = [gaju_mark() | separate(Separator, Period, GChars)], + {P, E} = decimal_pucks(Precision, lists:reverse(PChars)), T = lists:reverse(separate(Separator, Period, P)), lists:flatten([H, Break, T, E]); {false, true} -> [gaju_mark(), $0]; {false, false} -> + PChars = lists:flatten(string:pad(SP, 18, leading, $0)), {P, E} = decimal_pucks(Precision, PChars), T = lists:reverse(separate(Separator, Period, P)), lists:flatten([gaju_mark(), $0, Break, T, E]) end. decimal_pucks(all, PChars) -> + io:format("decimal_pucks: PChars: ~p~n", [PChars]), RTrailing = lists:reverse(PChars), {lists:reverse(lists:dropwhile(fun(C) -> C =:= $0 end, RTrailing)), ""}; decimal_pucks(Precision, PChars) -> @@ -131,101 +189,99 @@ separate(S, P, N, [H | T], A) -> separate(S, P, N + 1, T, [H | A]). -jp_format(gaju, 0, Pucks) -> +jp(gaju, 0, Pucks) -> G = lists:reverse(integer_to_list(Pucks div one_gaju())), - rank(gaju_mark(), G); -jp_format(gaju, all, Pucks) -> - H = jp_format(gaju, 0, Pucks), - T = jp_format(puck, all, Pucks rem one_gaju()), - H ++ T; -jp_format(gaju, Precision, Pucks) -> - H = jp_format(gaju, 0, Pucks), - T = jp_format(puck, Precision, Pucks rem one_gaju()), - H ++ T; -jp_format(puck, all, Pucks) -> + rank4(gaju_mark(), G); +jp(gaju, all, Pucks) -> + H = jp(gaju, 0, Pucks), + T = jp(puck, all, Pucks rem one_gaju()), + lists:flatten([H, " ", T]); +jp(gaju, Precision, Pucks) -> + H = jp(gaju, 0, Pucks), + T = jp(puck, Precision, Pucks rem one_gaju()), + lists:flatten([H, " ", T]); +jp(puck, all, Pucks) -> P = lists:reverse(integer_to_list(Pucks)), case lists:all(fun(C) -> C =:= $0 end, P) of - false -> rank(puck_mark(), P); + false -> rank4(puck_mark(), P); true -> [$0, puck_mark()] end; -jp_format(puck, Precision, Pucks) -> +jp(puck, Precision, Pucks) -> Digits = min(Precision, 18), - P = lists:reverse(integer_to_list(Pucks)), - case length(P) > Digits of + P = lists:flatten(string:pad(integer_to_list(Pucks), 18, leading, $0)), + case length(P) < Digits of true -> [$0, puck_mark()]; false -> - Significant = lists:nthtail(Digits, P), - Filler = tuple_to_list(erlang:make_tuple(Digits, $0)), - PuckingString = Filler ++ Significant, + PuckingString = lists:flatten(string:pad(lists:reverse(lists:sublist(P, Digits)), 18, leading, $0)), case lists:all(fun(C) -> C =:= $0 end, PuckingString) of - false -> rank(puck_mark(), PuckingString); + false -> rank4(puck_mark(), PuckingString); true -> [$0, puck_mark()] end end. -rank(Symbol, [$0, $0, $0, $0 | PT]) -> - rank(jp_ranks(), PT, [Symbol]); -rank(Symbol, [P4, $0, $0, $0 | PT]) -> - rank(jp_ranks(), PT, [P4, Symbol]); -rank(Symbol, [P4, P3, $0, $0 | PT]) -> - rank(jp_ranks(), PT, [P3, P4, Symbol]); -rank(Symbol, [P4, P3, P2, $0 | PT]) -> - rank(jp_ranks(), PT, [P2, P3, P4, Symbol]); -rank(Symbol, [P4, P3, P2, P1 | PT]) -> - rank(jp_ranks(), PT, [P1, P2, P3, P4, Symbol]); -rank(Symbol, [P4]) -> +rank4(Symbol, [$0, $0, $0, $0 | PT]) -> + rank4(ranks(jp), PT, [Symbol]); +rank4(Symbol, [P4, $0, $0, $0 | PT]) -> + rank4(ranks(jp), PT, [P4, Symbol]); +rank4(Symbol, [P4, P3, $0, $0 | PT]) -> + rank4(ranks(jp), PT, [P3, P4, Symbol]); +rank4(Symbol, [P4, P3, P2, $0 | PT]) -> + rank4(ranks(jp), PT, [P2, P3, P4, Symbol]); +rank4(Symbol, [P4, P3, P2, P1 | PT]) -> + rank4(ranks(jp), PT, [P1, P2, P3, P4, Symbol]); +rank4(Symbol, [P4]) -> [P4, Symbol]; -rank(Symbol, [P4, P3]) -> +rank4(Symbol, [P4, P3]) -> [P3, P4, Symbol]; -rank(Symbol, [P4, P3, P2]) -> +rank4(Symbol, [P4, P3, P2]) -> [P2, P3, P4, Symbol]. -jp_ranks() -> - "万億兆京垓秭穣溝澗正載極". - -rank([_ | RT], [$0, $0, $0, $0 | PT], A) -> - rank(RT, PT, A); -rank([RH | RT], [P4, $0, $0, $0 | PT], A) -> - rank(RT, PT, [P4, RH | A]); -rank([RH | RT], [P4, P3, $0, $0 | PT], A) -> - rank(RT, PT, [P3, P4, RH | A]); -rank([RH | RT], [P4, P3, P2, $0 | PT], A) -> - rank(RT, PT, [P2, P3, P4, RH | A]); -rank([RH | RT], [P4, P3, P2, P1 | PT], A) -> - rank(RT, PT, [P1, P2, P3, P4, RH | A]); -rank(_, [$0, $0, $0, $0], A) -> +rank4([_ | RT], [$0, $0, $0, $0 | PT], A) -> + rank4(RT, PT, A); +rank4([RH | RT], [P4, $0, $0, $0 | PT], A) -> + rank4(RT, PT, [P4, RH | A]); +rank4([RH | RT], [P4, P3, $0, $0 | PT], A) -> + rank4(RT, PT, [P3, P4, RH | A]); +rank4([RH | RT], [P4, P3, P2, $0 | PT], A) -> + rank4(RT, PT, [P2, P3, P4, RH | A]); +rank4([RH | RT], [P4, P3, P2, P1 | PT], A) -> + rank4(RT, PT, [P1, P2, P3, P4, RH | A]); +rank4(_, [$0, $0, $0, $0], A) -> A; -rank(_, [$0, $0, $0], A) -> +rank4(_, [$0, $0, $0], A) -> A; -rank(_, [$0, $0], A) -> +rank4(_, [$0, $0], A) -> A; -rank(_, [$0], A) -> +rank4(_, [$0], A) -> A; -rank(_, [], A) -> +rank4(_, [], A) -> A; -rank([RH | _], [P4, $0, $0, $0], A) -> +rank4([RH | _], [P4, $0, $0, $0], A) -> [P4, RH | A]; -rank([RH | _], [P4, $0, $0], A) -> +rank4([RH | _], [P4, $0, $0], A) -> [P4, RH | A]; -rank([RH | _], [P4, $0], A) -> +rank4([RH | _], [P4, $0], A) -> [P4, RH | A]; -rank([RH | _], [P4], A) -> +rank4([RH | _], [P4], A) -> [P4, RH | A]; -rank([RH | _], [P4, P3, $0, $0], A) -> +rank4([RH | _], [P4, P3, $0, $0], A) -> [P3, P4, RH | A]; -rank([RH | _], [P4, P3, $0], A) -> +rank4([RH | _], [P4, P3, $0], A) -> [P3, P4, RH | A]; -rank([RH | _], [P4, P3], A) -> +rank4([RH | _], [P4, P3], A) -> [P3, P4, RH | A]; -rank([RH | _], [P4, P3, P2, $0], A) -> +rank4([RH | _], [P4, P3, P2, $0], A) -> [P2, P3, P4, RH | A]; -rank([RH | _], [P4, P3, P2], A) -> +rank4([RH | _], [P4, P3, P2], A) -> [P2, P3, P4, RH | A]; -rank([RH | _], [P4, P3, P2, P1], A) -> +rank4([RH | _], [P4, P3, P2, P1], A) -> [P1, P2, P3, P4, RH | A]. +ranks(jp) -> + "万億兆京垓秭穣溝澗正載極". + gaju_mark() -> $木.