103 lines
4.0 KiB
Erlang
103 lines
4.0 KiB
Erlang
%%%-------------------------------------------------------------------
|
|
%%% @author aresei
|
|
%%% @copyright (C) 2023, <COMPANY>
|
|
%%% @doc
|
|
%%%
|
|
%%% @end
|
|
%%% Created : 26. 7月 2023 10:40
|
|
%%%-------------------------------------------------------------------
|
|
-module(mnesia_totalizator).
|
|
-author("aresei").
|
|
-include("iot.hrl").
|
|
-include_lib("stdlib/include/qlc.hrl").
|
|
|
|
-define(TAB_NAME, totalizator).
|
|
|
|
%% API
|
|
-export([create_table/0]).
|
|
-export([increment_success/2, increment_fail/2, delete/2, table_size/0, query/2]).
|
|
|
|
create_table() ->
|
|
%% id生成器
|
|
mnesia:create_table(?TAB_NAME, [
|
|
{attributes, record_info(fields, totalizator)},
|
|
{record_name, totalizator},
|
|
{disc_copies, [node()]},
|
|
{type, ordered_set}
|
|
]).
|
|
|
|
-spec query(SceneIds :: [integer()], Dates :: [calendar:date()]) -> [map()].
|
|
query(SceneIds, Dates) when is_list(SceneIds), is_list(Dates) ->
|
|
lists:map(fun(Date) ->
|
|
Scenes = lists:map(fun(SceneId) ->
|
|
Key = {SceneId, Date},
|
|
case mnesia:dirty_read(?TAB_NAME, Key) of
|
|
[R | _] ->
|
|
to_map(R);
|
|
[] ->
|
|
#{<<"scene_id">> => SceneId, <<"success_num">> => 0, <<"fail_num">> => 0}
|
|
end
|
|
end, SceneIds),
|
|
#{<<"date">> => format_date(Date), <<"scenes">> => Scenes}
|
|
end, Dates).
|
|
|
|
-spec increment_success(SceneId :: integer(), IncNum :: integer()) -> ok | {error, Reason :: any()}.
|
|
increment_success(SceneId, IncNum) when is_integer(SceneId), is_integer(IncNum) ->
|
|
increment(SceneId, success, IncNum).
|
|
|
|
-spec increment_fail(SceneId :: integer(), IncNum :: integer()) -> ok | {error, Reason :: any()}.
|
|
increment_fail(SceneId, IncNum) when is_integer(SceneId), is_integer(IncNum) ->
|
|
increment(SceneId, fail, IncNum).
|
|
|
|
-spec increment(SceneId :: integer(), Type :: atom(), IncNum :: integer()) -> ok | {error, Reason :: any()}.
|
|
increment(SceneId, Type, IncNum) when is_integer(SceneId), is_integer(IncNum), is_atom(Type) ->
|
|
{Date, _} = calendar:local_time(),
|
|
Key = {SceneId, Date},
|
|
Fun = fun() ->
|
|
case mnesia:read(?TAB_NAME, Key) of
|
|
[R = #totalizator{option = Option = #option{success_num = SuccessNum, fail_num = FailNum}} | _] ->
|
|
NOption = case Type of
|
|
success ->
|
|
Option#option{success_num = SuccessNum + IncNum};
|
|
fail ->
|
|
Option#option{fail_num = FailNum + IncNum}
|
|
end,
|
|
NR = R#totalizator{option = NOption},
|
|
mnesia:write(?TAB_NAME, NR, write);
|
|
[] ->
|
|
Option = case Type of
|
|
success ->
|
|
#option{success_num = IncNum};
|
|
fail ->
|
|
#option{fail_num = IncNum}
|
|
end,
|
|
R = #totalizator{key = Key, scene_id = SceneId, date = Date, option = Option},
|
|
mnesia:write(?TAB_NAME, R, write)
|
|
end
|
|
end,
|
|
|
|
case mnesia:transaction(Fun) of
|
|
{atomic, ok} ->
|
|
ok;
|
|
{aborted, Reason} ->
|
|
{error, Reason}
|
|
end.
|
|
|
|
-spec delete(SceneId :: integer(), Date :: calendar:date()) -> ok | {error, Reason :: any()}.
|
|
delete(SceneId, Date) when is_integer(SceneId), is_tuple(Date) ->
|
|
case mnesia:transaction(fun() -> mnesia:delete(?TAB_NAME, {SceneId, Date}, write) end) of
|
|
{atomic, ok} ->
|
|
ok;
|
|
{aborted, Reason} ->
|
|
{error, Reason}
|
|
end.
|
|
|
|
-spec table_size() -> integer().
|
|
table_size() ->
|
|
mnesia:table_info(?TAB_NAME, size).
|
|
|
|
to_map(#totalizator{scene_id = SceneId, option = #option{success_num = SuccessNum, fail_num = FailNum}}) ->
|
|
#{<<"scene_id">> => SceneId, <<"success_num">> => SuccessNum, <<"fail_num">> => FailNum}.
|
|
|
|
format_date({Year, Month, Day}) ->
|
|
iolist_to_binary(io_lib:format("~b-~2..0b-~2..0b", [Year, Month, Day])). |