WIP: Add formatter and some other stuff
This commit is contained in:
parent
d70f5bb389
commit
6a8c4fe1e1
@ -1048,37 +1048,3 @@ do_grids_mess_sig2(Request = #{"grids" := 1,
|
||||
wxDialog:destroy(Dialog);
|
||||
do_grids_mess_sig2(BadRequest, _) ->
|
||||
tell("Bad request: ~tp", [BadRequest]).
|
||||
|
||||
|
||||
|
||||
|
||||
%%% Helpers
|
||||
|
||||
|
||||
price_to_string(Pucks) ->
|
||||
Gaju = 1_000_000_000_000_000_000,
|
||||
H = integer_to_list(Pucks div Gaju),
|
||||
R = Pucks rem Gaju,
|
||||
case string:strip(lists:flatten(io_lib:format("~18..0w", [R])), right, $0) of
|
||||
[] -> H;
|
||||
T -> string:join([H, T], ".")
|
||||
end.
|
||||
|
||||
string_to_price(String) ->
|
||||
case string:split(String, ".") of
|
||||
[H] -> join_price(H, "0");
|
||||
[H, T] -> join_price(H, T);
|
||||
_ -> {error, bad_price}
|
||||
end.
|
||||
|
||||
join_price(H, T) ->
|
||||
try
|
||||
Parts = [H, string:pad(T, 18, trailing, $0)],
|
||||
Price = list_to_integer(unicode:characters_to_list(Parts)),
|
||||
case Price < 0 of
|
||||
false -> {ok, Price};
|
||||
true -> {error, negative_price}
|
||||
end
|
||||
catch
|
||||
error:R -> {error, R}
|
||||
end.
|
||||
|
||||
279
src/gd_lib.erl
Normal file
279
src/gd_lib.erl
Normal file
@ -0,0 +1,279 @@
|
||||
%%% @doc
|
||||
%%% GajuDesk Helper Functions
|
||||
%%% @end
|
||||
|
||||
-module(gd_lib).
|
||||
|
||||
-export([format_price/1, format_price/3, format_price/4, % read_price/1,
|
||||
price_to_string/1, string_to_price/1,
|
||||
is_int/1]).
|
||||
|
||||
|
||||
format_price(Pucks) ->
|
||||
format_price(gaju, {west, $,, 3},Pucks).
|
||||
|
||||
|
||||
format_price(puck, {west, Separator, Period}, Pucks) ->
|
||||
western_format(Separator, Period, Pucks);
|
||||
format_price(gaju, {west, Separator = $., Period}, Pucks) ->
|
||||
western_format(Separator, $,, Period, all, Pucks);
|
||||
format_price(gaju, {west, Separator, Period}, Pucks) ->
|
||||
western_format(Separator, $., Period, all, Pucks);
|
||||
format_price(Unit, jp, Pucks) ->
|
||||
jp_format(Unit, all, Pucks).
|
||||
|
||||
|
||||
|
||||
-spec format_price(Unit, Style, Precision, Pucks) -> Serialized
|
||||
when Unit :: gaju | puck,
|
||||
Style :: jp | jp_pucks | {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.
|
||||
%%
|
||||
%% Consider, for example, a few input and output pairs:
|
||||
%% ```
|
||||
%% format_price({$,, 3}, 3, 123456789123456789123456789) ->
|
||||
%% "木123,456,789.123".
|
||||
%%
|
||||
%% format_price({$,, 3}, 6, 123456789123456789123456789) ->
|
||||
%% "木123,456,789.123,456"
|
||||
%%
|
||||
%% format_price({$,, 3}, all, 123456789123456789123456789) ->
|
||||
%% "木123.456.789,123.456.789.123.456.789"
|
||||
%%
|
||||
%% format_price({$_, 4}, 10, 123456789123456789123456789) ->
|
||||
%% "木1_2345_6789.1234_5678_91"
|
||||
%%
|
||||
%% format_price(jp, 3, 123456789123456789123456789) ->
|
||||
%% "1億2345万6789木12京3000兆本"
|
||||
%%
|
||||
%% format_price(jp, 6, 123456789123456789123456789) ->
|
||||
%% "1億2345万6789木12京3456兆本"
|
||||
%%
|
||||
%% format_price(jp, 0, 123456789123456789123456789) ->
|
||||
%% "1億2345万6789木"
|
||||
%%
|
||||
%% format_price(jp_pucks, all, 123456789123456789123456789) ->
|
||||
%% "123秭4567垓8912京3456兆7891億2345万6789本"
|
||||
%% '''
|
||||
|
||||
|
||||
format_price(puck, {west, Separator, Period}, _, Pucks) ->
|
||||
western_format(Separator, Period, Pucks);
|
||||
format_price(gaju, {west, Separator = $., Period}, Precision, Pucks) ->
|
||||
western_format(Separator, $,, Period, Precision, Pucks);
|
||||
format_price(gaju, {west, Separator, Period}, Precision, Pucks) ->
|
||||
western_format(Separator, $., Period, Precision, Pucks);
|
||||
format_price(Unit, jp, Precision, Pucks) ->
|
||||
jp_format(Unit, Precision, Pucks).
|
||||
|
||||
|
||||
|
||||
|
||||
western_format(Separator, Period, Pucks) ->
|
||||
P = lists:reverse(integer_to_list(Pucks)),
|
||||
[puck_mark() | separate(Separator, Period, P)].
|
||||
|
||||
|
||||
western_format(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) ->
|
||||
G = lists:reverse(integer_to_list(Pucks div one_gaju())),
|
||||
H = [gaju_mark() | separate(Separator, Period, G)],
|
||||
case decimal_pucks(Precision, Pucks rem one_gaju()) of
|
||||
{"", ""} ->
|
||||
H;
|
||||
{P, E} ->
|
||||
T = lists:reverse(separate(Separator, Period, P)),
|
||||
lists:flatten([H, Break, T, E])
|
||||
end.
|
||||
|
||||
decimal_pucks(_, 0) ->
|
||||
{"", ""};
|
||||
decimal_pucks(all, Pucks) ->
|
||||
RTrailing = lists:reverse(integer_to_list(Pucks)),
|
||||
{lists:reverse(lists:dropwhile(fun(C) -> C =:= $0 end, RTrailing)), ""};
|
||||
decimal_pucks(Precision, Pucks) ->
|
||||
{Significant, Rest} = lists:split(min(Precision, 18), integer_to_list(Pucks)),
|
||||
RTrailing = lists:reverse(Significant),
|
||||
Trailing = lists:reverse(lists:dropwhile(fun(C) -> C =:= $0 end, RTrailing)),
|
||||
case lists:all(fun(C) -> C =:= $0 end, Rest) of
|
||||
true -> {Trailing, ""};
|
||||
false -> {Trailing, "..."}
|
||||
end.
|
||||
|
||||
separate(_, _, "") ->
|
||||
"";
|
||||
separate(S, P, G) ->
|
||||
separate(S, P, 1, G, []).
|
||||
|
||||
separate(_, _, _, [H], A) ->
|
||||
[H | A];
|
||||
separate(S, P, P, [H | T], A) ->
|
||||
separate(S, P, 1, T, [S, H | A]);
|
||||
separate(S, P, N, [H | T], A) ->
|
||||
separate(S, P, N + 1, T, [H | A]).
|
||||
|
||||
|
||||
jp_format(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) ->
|
||||
P = lists:reverse(integer_to_list(Pucks)),
|
||||
case lists:all(fun(C) -> C =:= $0 end, P) of
|
||||
false -> rank(puck_mark(), P);
|
||||
true -> [$0, puck_mark()]
|
||||
end;
|
||||
jp_format(puck, Precision, Pucks) ->
|
||||
Digits = min(Precision, 18),
|
||||
P = lists:reverse(integer_to_list(Pucks)),
|
||||
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,
|
||||
case lists:all(fun(C) -> C =:= $0 end, PuckingString) of
|
||||
false -> rank(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]) ->
|
||||
[P4, Symbol];
|
||||
rank(Symbol, [P4, P3]) ->
|
||||
[P3, P4, Symbol];
|
||||
rank(Symbol, [P4, P3, P2]) ->
|
||||
[P2, P3, P4, Symbol].
|
||||
|
||||
jp_ranks() ->
|
||||
% "万億兆京垓秭穣溝澗正載極".
|
||||
"ABCDEFG".
|
||||
|
||||
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) ->
|
||||
A;
|
||||
rank(_, [$0, $0, $0], A) ->
|
||||
A;
|
||||
rank(_, [$0, $0], A) ->
|
||||
A;
|
||||
rank(_, [$0], A) ->
|
||||
A;
|
||||
rank(_, [], A) ->
|
||||
A;
|
||||
rank([RH | _], [P4, $0, $0, $0], A) ->
|
||||
[P4, RH | A];
|
||||
rank([RH | _], [P4, $0, $0], A) ->
|
||||
[P4, RH | A];
|
||||
rank([RH | _], [P4, $0], A) ->
|
||||
[P4, RH | A];
|
||||
rank([RH | _], [P4], A) ->
|
||||
[P4, RH | A];
|
||||
rank([RH | _], [P4, P3, $0, $0], A) ->
|
||||
[P3, P4, RH | A];
|
||||
rank([RH | _], [P4, P3, $0], A) ->
|
||||
[P3, P4, RH | A];
|
||||
rank([RH | _], [P4, P3], A) ->
|
||||
[P3, P4, RH | A];
|
||||
rank([RH | _], [P4, P3, P2, $0], A) ->
|
||||
[P2, P3, P4, RH | A];
|
||||
rank([RH | _], [P4, P3, P2], A) ->
|
||||
[P2, P3, P4, RH | A];
|
||||
rank([RH | _], [P4, P3, P2, P1], A) ->
|
||||
[P1, P2, P3, P4, RH | A].
|
||||
|
||||
|
||||
gaju_mark() -> $G.
|
||||
|
||||
puck_mark() -> $P.
|
||||
|
||||
one_gaju() -> 1_000_000_000_000_000_000.
|
||||
|
||||
|
||||
-spec price_to_string(Pucks) -> Gajus
|
||||
when Pucks :: integer(),
|
||||
Gajus :: string().
|
||||
%% @doc
|
||||
%% A simplified formatting function that converts an integer value in Pucks to a string representation
|
||||
%% in Gajus. Useful for formatting generic output for UI elements
|
||||
|
||||
price_to_string(Pucks) ->
|
||||
Gaju = 1_000_000_000_000_000_000,
|
||||
H = integer_to_list(Pucks div Gaju),
|
||||
R = Pucks rem Gaju,
|
||||
case string:strip(lists:flatten(io_lib:format("~18..0w", [R])), right, $0) of
|
||||
[] -> H;
|
||||
T -> string:join([H, T], ".")
|
||||
end.
|
||||
|
||||
|
||||
-spec string_to_price(Gajus) -> Pucks
|
||||
when Gajus :: string(),
|
||||
Pucks :: integer().
|
||||
%% @doc
|
||||
%% A simplified formatting function that converts a Gaju value represented as a string to an
|
||||
%% integer value in Pucks.
|
||||
|
||||
string_to_price(String) ->
|
||||
case string:split(String, ".") of
|
||||
[H] -> join_price(H, "0");
|
||||
[H, T] -> join_price(H, T);
|
||||
_ -> {error, bad_price}
|
||||
end.
|
||||
|
||||
join_price(H, T) ->
|
||||
try
|
||||
Parts = [H, string:pad(T, 18, trailing, $0)],
|
||||
Price = list_to_integer(unicode:characters_to_list(Parts)),
|
||||
case Price < 0 of
|
||||
false -> {ok, Price};
|
||||
true -> {error, negative_price}
|
||||
end
|
||||
catch
|
||||
error:R -> {error, R}
|
||||
end.
|
||||
|
||||
|
||||
-spec is_int(string()) -> boolean().
|
||||
%% @doc
|
||||
%% A simple boolean check over whether every character in a string is part of an integer value
|
||||
%% without the trashy `try .. catch' way.
|
||||
|
||||
is_int(S) ->
|
||||
lists:all(fun(C) -> $0 =< C andalso C =< $9 end, S).
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
-include_lib("wx/include/wx.hrl").
|
||||
-include("$zx_include/zx_logger.hrl").
|
||||
-include("gd.hrl").
|
||||
|
||||
-record(s,
|
||||
{frame = none :: none | wx:wx_object(),
|
||||
@ -232,7 +233,7 @@ done(#s{frame = Frame, caller = Caller,
|
||||
case clean_spend(TX) of
|
||||
{ok, CleanTX} ->
|
||||
|
||||
|
||||
end,
|
||||
Result =
|
||||
case wxTextCtrl:getValue(NameTx) of
|
||||
"" ->
|
||||
@ -246,10 +247,12 @@ done(#s{frame = Frame, caller = Caller,
|
||||
ok = wxFrame:destroy(Frame),
|
||||
zxw_modal:done(Caller, Result).
|
||||
|
||||
clean_spend(TX) ->
|
||||
clean_spend(TX, []).
|
||||
|
||||
clean_spend(#spend_tx{recipient_id = ""}) ->
|
||||
ok;
|
||||
clean_spend( TX = #spend_tx{amount = S}) when is_list(S) ->
|
||||
clean_spend(TX = #spend_tx{recipient_id = ""}, Errors) ->
|
||||
clean_spend(TX#spend_tx{recipient_id = none}, [recipient_id | Errors]);
|
||||
clean_spend(TX = #spend_tx{amount = S}, Errors) when is_list(S) ->
|
||||
case string_to_price(S) of
|
||||
{ok, Amount} -> clean_spend(TX#spend_tx{amount = Amount});
|
||||
{error, _} -> ok
|
||||
@ -270,5 +273,3 @@ clean_spend(TX) ->
|
||||
{ok, CleanTX}.
|
||||
|
||||
|
||||
is_int(S) ->
|
||||
lists:all(fun(C) -> $0 =< C andalso C =< $9 end, S).
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user