%%%-----------------------------------
%%% @Module  : lib_daily
%%% @Author  : xyao
%%% @Email   : jiexiaowen@gmail.com
%%% @Created : 2010.05.08
%%% @Description: 每天记录器
%%%-----------------------------------
-module(lib_daily).

-include("daily.hrl").
-include("common.hrl").
-include("predefine.hrl").
-export([
         online/1,
         get_all/2,
         get_count/2,  %% 列表获取计数
         get_count/3,
         get_count/4,
         set_count/2,
         set_count/4,
         set_count/5,

         increment/3,  %%加一操作
         increment/4,

         decrement/3,   %%减一操作
         decrement/4,
         cut_count/5,


         plus_count/2,   %%列表追加
         plus_count/4,
         plus_count/5,



         get_refresh_time/4,
         set_refresh_time/4,
         lessthan_limit/3,
         lessthan_limit/4,
         get_count_limit/2,
         get_count_limit/3,
         is_clear/4,
         update_count_db/7,
         get_count_and_other_from_db/4,
         get_count_and_other_from_db/5,
         get_count_and_refresh_time_from_db/4,
         get_config/3,
         get_clock/3

        ,set_count_offline/4    %%第三方和离线操作
        ,set_count_offline/5
        ,get_count_offline/2
        ,get_count_offline/3
        ,get_count_offline/4
        ,increment_offline/3
        ,increment_offline/4
        ,decrement_offline/3
        ,decrement_offline/4
        ,plus_count_offline/4
        ,plus_count_offline/5
        ]).

-export([
    new/1,
    get/4,
    get/5
]).

%% 上线操作
online(RoleId) ->
    reload(RoleId).

%% 获取整个记录器
get(RoleId, Module, SubModule, Type) ->
    NowTime = utime:unixtime(),
    get(RoleId, Module, SubModule, Type, NowTime).
get(RoleId, Module, SubModule, Type, NowTime) ->
    {Res, Clock} = get_clock(Module, SubModule, Type),
    if
        Res=/= true ->
            #ets_daily{id={Module, SubModule, Type}, count = 99999};
        Clock =:= ?TWELVE ->
            Data = get_all(RoleId, ?TWELVE),
            RD =  lists:keyfind({Module, SubModule, Type}, #ets_daily.id, Data),
            do_get(NowTime, RD, 0);
        true ->
            Data = get_all(RoleId, ?FOUR),
            RD = lists:keyfind({Module, SubModule, Type}, #ets_daily.id, Data),
            do_get(NowTime, RD, ?FOUR)
    end.

%% 使用时间戳判断是否同一天，判断数据是否还有效
do_get(NowTime, EtsDaily, Clock) ->
    case EtsDaily of
        false ->
            false;
        #ets_daily{refresh_time = Time} ->
            case utime:is_logic_same_day(NowTime, Time, Clock) of
                true -> %% 同一天
                    EtsDaily;
                false when Clock =:= ?FOUR ->
                    OpenTime = util:get_open_time(),
                    %% OpenTime 为开服日零点时间戳
                    case NowTime - OpenTime > 2 * ?ONE_DAY_SECONDS of
                        true  ->    % 已经超过2个普通自然日（排除开服首日，避免每次都做完整时间计算）
                            false;
                        false ->
                            %% 逻辑上的开服第一天结束时间
                            {OpenDate, _} = utime:unixtime_to_localtime(OpenTime),
                            NextDate = utime:get_before_day(OpenDate, 1, 1),
                            NextLogicDateTime = {NextDate, {?FOUR, 0, 0}},
                            FirstDayEnd = utime:unixtime(NextLogicDateTime),
                            case NowTime < FirstDayEnd of
                                true  -> %% 开服第一天不清理日常(针对0点到4点之间开的服)
                                    EtsDaily;
                                false ->
                                    false
                            end
                    end;
                false ->
                    false
            end
    end.

%% 取玩家的整个记录
get_all(RoleId, ?TWELVE) ->
    Data =  get(?DAILY_KEY(?TWELVE)),
    case Data =:= undefined of
        true -> TwelveData = reload(RoleId, ?TWELVE);
        false -> TwelveData = Data
    end,
    TwelveData;
get_all(RoleId, ?FOUR) ->
    Data =  get(?DAILY_KEY(?FOUR)),
    case Data =:= undefined of
        true -> FourData = reload(RoleId, ?FOUR);
        false -> FourData = Data
    end,
    FourData.

%% 获取数量
get_count(RoleId, List) ->
    lists:map(
      fun({Module, SubModule, Type} = Id) ->
              Count = get_count(RoleId, Module, SubModule, Type),
              {Id, Count}
      end, List).

%% 获取数量
get_count(RoleId, Module, Type) ->
    get_count(RoleId, Module, ?DEFAULT_SUB_MODULE, Type).

get_count(RoleId, Module, SubModule, TypeList) when is_list(TypeList) ->
    F = fun(Type, Acc) -> Acc ++ [{Type, get_count(RoleId, Module, SubModule, Type)}] end,
    lists:foldl(F, [], TypeList);

%% 获取数量
get_count(RoleId, Module, SubModule, Type) ->
    case lib_daily:get(RoleId, Module, SubModule, Type) of
        false -> 0;
        RD -> RD#ets_daily.count
    end.

%% 设置数量
set_count(RoleId, List) ->
    Now = utime:unixtime(),
    F = fun
        ({ {Module, SubModule, Type}, Count}, {FOUR, TWELVE}) ->
            Daily = case lib_daily:get(RoleId, Module, SubModule, Type, Now) of
                false ->
                    new([Module, SubModule, Type, Count]);
                RD ->
                    RD#ets_daily{count = Count}
            end,
            Daily2 = Daily#ets_daily{refresh_time = Now},
            case get_clock(Module, SubModule, Type) of
                {_Res, ?TWELVE} ->
                    {FOUR, [Daily2 | TWELVE]};
                _ ->
                    {[Daily2 | FOUR], TWELVE}
            end
    end,
    {FourData, TwelveData} = lists:foldl(F, {[], []}, List),
    do_save_batch(RoleId, FourData, ?FOUR),
    do_save_batch(RoleId, TwelveData, ?TWELVE).


set_count(RoleId, Module, Type, Count) ->
    set_count(RoleId, Module, ?DEFAULT_SUB_MODULE, Type, Count).

set_count(RoleId, Module, SubModule, Type, Count) ->
    Now = utime:unixtime(),
    case lib_daily:get(RoleId, Module, SubModule, Type, Now) of
        false ->
            Daily = new([Module, SubModule, Type, Count]),
            save(RoleId, Daily#ets_daily{refresh_time = Now});
        RD ->
            save(RoleId, RD#ets_daily{count = Count, refresh_time = Now})
    end.

%% 加一操作
increment(RoleId, Module, Type) ->
    increment(RoleId, Module, ?DEFAULT_SUB_MODULE, Type).

%% 加一操作
increment(RoleId, Module, SubModule, Type) ->
    plus_count(RoleId, Module, SubModule, Type, 1).

%% 追加数量
plus_count(RoleId, List) ->
    Now = utime:unixtime(),
    F = fun
        ({ {Module, SubModule, Type}, Count}, {FOUR, TWELVE}) ->
            Daily = case lib_daily:get(RoleId, Module, SubModule, Type, Now) of
                false ->
                    new([Module, SubModule, Type, Count]);
                RD ->
                    RD#ets_daily{count = RD#ets_daily.count + Count}
            end,
            Daily2 = Daily#ets_daily{refresh_time = Now},
            case get_clock(Module, SubModule, Type) of
                {_Res, ?TWELVE} ->
                    {FOUR, [Daily2 | TWELVE]};
                _ ->
                    {[Daily2 | FOUR], TWELVE}
            end
    end,
    {FourData, TwelveData} = lists:foldl(F, {[], []}, List),
    do_save_batch(RoleId, FourData, ?FOUR),
    do_save_batch(RoleId, TwelveData, ?TWELVE).


%% 追加数量
plus_count(RoleId, Module, Type, Count) ->
    plus_count(RoleId, Module, ?DEFAULT_SUB_MODULE, Type, Count).
%% 追加数量
plus_count(RoleId, Module, SubModule, Type, Count) ->
    Now = utime:unixtime(),
    case lib_daily:get(RoleId, Module, SubModule, Type, Now) of
        false ->
            Daily = new([Module, SubModule, Type,  Count, ?DEFAULT_OTHER]),
            save(RoleId, Daily#ets_daily{refresh_time = Now});
        RD = #ets_daily{count = OldCount} ->
            Daily = RD#ets_daily{count = OldCount + Count, refresh_time = Now},
            save(RoleId, Daily)
    end.

%% 扣除数量
cut_count(RoleId, Module, SubModule, Type, Count) ->
    Now = utime:unixtime(),
    case lib_daily:get(RoleId, Module, SubModule, Type, Now) of
        false ->
            Daily = new([Module, SubModule, Type,  0, ?DEFAULT_OTHER]),
            save(RoleId, Daily#ets_daily{refresh_time = Now});
        RD = #ets_daily{count = OldCount} ->
            Daily = RD#ets_daily{count = OldCount - Count, refresh_time = Now},
            save(RoleId, Daily)
    end.

%% 获取刷新时间
get_refresh_time(RoleId, Module, SubModule, Type) ->
    case lib_daily:get(RoleId, Module, SubModule, Type) of
        false -> 0;
        RD -> RD#ets_daily.refresh_time
    end.

%% 更新刷新时间
set_refresh_time(RoleId, Module, SubModule, Type) ->
    Now = utime:unixtime(),
    case lib_daily:get(RoleId, Module, SubModule, Type, Now) of
        false ->
            Daily = new([Module, SubModule, Type, 0]),
            save(RoleId, Daily#ets_daily{refresh_time = Now});
        RD ->
            save(RoleId, RD#ets_daily{refresh_time = Now})
    end.

new([Module, SubModule, Type, Count]) ->
    new([Module, SubModule, Type, Count, ?DEFAULT_OTHER]);
new([Module, SubModule, Type, Count, Other]) ->
    #ets_daily{
        id              = {Module, SubModule, Type}
        ,count          = Count
        ,other          = Other
        ,refresh_time   = utime:unixtime()
    }.

save(RoleId, RoleDaily) ->
    {ModuleId, SubModuleId, TypeId} = RoleDaily#ets_daily.id,
    {_Res, Clock} = get_clock(ModuleId, SubModuleId, TypeId),
    if
        Clock==?TWELVE ->
            do_save(RoleId, RoleDaily, ?TWELVE);
        true ->
            do_save(RoleId, RoleDaily, ?FOUR)
    end.

do_save(RoleId, RoleDaily, ?TWELVE) ->
    #ets_daily{
        id = {ModuleId, SubModuleId, TypeId}, refresh_time = NowTime
        ,count = Count, other = Other
    } = RoleDaily,
    Data = get_all(RoleId, ?TWELVE),
    Data1 = [RoleDaily] ++ lists:keydelete(RoleDaily#ets_daily.id, #ets_daily.id, Data),
    put(?DAILY_KEY(?TWELVE), Data1),
    SqlData = [
        RoleId, ModuleId, SubModuleId, TypeId, Count
        ,util:term_to_bitstring(Other), NowTime
    ],
    db:execute(io_lib:format(?sql_daily_role_upd, SqlData));

do_save(RoleId, RoleDaily, ?FOUR) ->
    #ets_daily{
        id = {ModuleId, SubModuleId, TypeId}, refresh_time = NowTime
        ,count = Count, other = Other
    } = RoleDaily,
    Data = get_all(RoleId, ?FOUR),
    Data1 = [RoleDaily] ++ lists:keydelete(RoleDaily#ets_daily.id, #ets_daily.id, Data),
    put(?DAILY_KEY(?FOUR), Data1),
    SqlData = [
        RoleId, ModuleId, SubModuleId, TypeId, Count
        ,util:term_to_bitstring(Other), NowTime
    ],
    db:execute(io_lib:format(?sql_daily_four_role_upd, SqlData)).

%% 同时保存多个记录
do_save_batch(_RoleId, [], _) -> ok;
do_save_batch(RoleId, DailyList, ?TWELVE) ->
    F = fun
        (#ets_daily{id = Id}) ->
            lists:keyfind(Id, #ets_daily.id, DailyList) =:= false
    end,
    Data = get_all(RoleId, ?TWELVE),
    Data1 = DailyList ++ lists:filter(F, Data),
    put(?DAILY_KEY(?TWELVE), Data1),
    ValueStr = ulists:list_to_string([io_lib:format("(~p,~p,~p,~p,~p, '~ts', ~p)", [RoleId, ModuleId, SubModuleId, TypeId, Count, util:term_to_bitstring(Other), NowTime]) || #ets_daily{id = {ModuleId, SubModuleId, TypeId}, count = Count, other = Other, refresh_time = NowTime} <- DailyList], ","),
    SQL = io_lib:format(?sql_daily_role_upd_batch, [ValueStr]),
    db:execute(SQL);

do_save_batch(RoleId, DailyList, ?FOUR) ->
    F = fun
        (#ets_daily{id = Id}) ->
            lists:keyfind(Id, #ets_daily.id, DailyList) =:= false
    end,
    Data = get_all(RoleId, ?FOUR),
    Data1 = DailyList ++ lists:filter(F, Data),
    put(?DAILY_KEY(?FOUR), Data1),
    ValueStr = ulists:list_to_string([io_lib:format("(~p,~p,~p,~p,~p, '~ts', ~p)", [RoleId, ModuleId, SubModuleId, TypeId, Count, util:term_to_bitstring(Other), NowTime]) || #ets_daily{id = {ModuleId, SubModuleId, TypeId}, count = Count, other = Other, refresh_time = NowTime} <- DailyList], ","),
    SQL = io_lib:format(?sql_daily_four_role_upd_batch, [ValueStr]),
    db:execute(SQL).

%% 所有数据重载
reload(RoleId) ->
    D1 = reload(RoleId, ?TWELVE),
    D2 = reload(RoleId, ?FOUR),
    {D1, D2}.

reload(RoleId, Clock) ->
    case Clock of
        ?TWELVE ->
            erase(?DAILY_KEY(?TWELVE)),
            List1 = db:get_all(io_lib:format(?sql_daily_role_sel_all, [RoleId])),
            D1 = to_dict(List1, []),
            put(?DAILY_KEY(?TWELVE), D1),
            D1;
        ?FOUR ->
            erase(?DAILY_KEY(?FOUR)),
            List2 = db:get_all(io_lib:format(?sql_daily_four_role_sel_all, [RoleId])),
            D2 = to_dict(List2, []),
            put(?DAILY_KEY(?FOUR), D2),
            D2
    end.

%% 获取次数上限
get_count_limit(Module, Type) ->
    get_count_limit(Module, ?DEFAULT_SUB_MODULE, Type).

%% 获取次数上限
get_count_limit(Module, SubModule, Type) ->
    case get_config(Module, SubModule, Type) of
        [] -> 0;
        #base_daily{limit = Limit} -> Limit
    end.

%% 判断未超过限制次数
%% @return true未超过|false超过
lessthan_limit(RoleId, Module, Type) ->
    lessthan_limit(RoleId, Module, ?DEFAULT_SUB_MODULE, Type).

%% 未超过限制次数
%% @return [{type, boolean}]
lessthan_limit(RoleId, Module, SubModule, TypeList) when is_list(TypeList) ->
    F = fun(Type, Acc) -> Acc ++ [{Type, lessthan_limit(RoleId, Module, SubModule, Type)}] end,
    lists:foldl(F, [], TypeList);

%% 未超过限制次数
%% @return true未超过|false超过
lessthan_limit(RoleId, Module, SubModule, Type) ->
    %% 后台缺失配置的情况下，直接返回超过次数
    Limit = get_count_limit(Module, SubModule, Type),
    Count = case lib_daily:get(RoleId, Module, SubModule, Type) of
                false -> 0;
                RD -> RD#ets_daily.count
            end,
    Count<Limit.

%% 是否清理
is_clear(Clock, ModuleId, SubModuleId, TypeId) ->
    case get_config(ModuleId, SubModuleId, TypeId) of
        #base_daily{clock = Clock} -> true;
        _ -> false
    end.

update_count_db(RoleId, ModuleId, SubModuleId, TypeId, Count, Other, Time) ->
    case get_config(ModuleId, SubModuleId, TypeId) of
        #base_daily{clock = ?TWELVE} ->
            db:execute(io_lib:format(?sql_daily_role_upd, [RoleId, ModuleId, SubModuleId, TypeId, Count, util:term_to_bitstring(Other), Time]));
        #base_daily{clock = ?FOUR} ->
            db:execute(io_lib:format(?sql_daily_four_role_upd, [RoleId, ModuleId, SubModuleId, TypeId, Count, util:term_to_bitstring(Other), Time]));
        _ -> error
    end.

%% 获取次数，扩展数据
%% @return {0, 0}
get_count_and_other_from_db(RoleId, ModuleId, SubModuleId, TypeId) ->
    Now = utime:unixtime(),
    get_count_and_other_from_db(RoleId, ModuleId, SubModuleId, TypeId, Now).
get_count_and_other_from_db(RoleId, ModuleId, SubModuleId, TypeId, Now) ->
    {
        Count, _Time, Other
    } = get_count_info_from_db(RoleId, ModuleId, SubModuleId, TypeId, Now),
    {Count, Other}.

%% 获取次数，刷新时间
%% @return {0, 0}
get_count_and_refresh_time_from_db(RoleId, ModuleId, SubModuleId, TypeId) ->
    {Count, Time, _Other} = get_count_info_from_db(RoleId, ModuleId, SubModuleId, TypeId),
    {Count, Time}.

get_count_info_from_db(RoleId, ModuleId, SubModuleId, TypeId) ->
    Now = utime:unixtime(),
    get_count_info_from_db(RoleId, ModuleId, SubModuleId, TypeId, Now).
get_count_info_from_db(RoleId, ModuleId, SubModuleId, TypeId, Now) ->
    SqlData = [RoleId, ModuleId, SubModuleId, TypeId],
    case get_config(ModuleId, SubModuleId, TypeId) of
        #base_daily{clock = ?TWELVE} ->
            Sql = io_lib:format(?sql_daily_role_sel, SqlData),
            case db:get_row(Sql) of
                [] ->
                    {0, 0, []};
                [Count, RefreshTime, Other] ->
                    Data = {Count, RefreshTime, util:bitstring_to_term(Other)},
                    check_time(Now, Data, 0)
            end;
        #base_daily{clock = ?FOUR} ->
            Sql = io_lib:format(?sql_daily_four_role_sel, SqlData),
            case db:get_row(Sql) of
                [] ->
                    {0, 0, []};
                [Count, RefreshTime, Other] ->
                    Data = {Count, RefreshTime, util:bitstring_to_term(Other)},
                    check_time(Now, Data, ?FOUR)
            end;
        _ ->
            {0, 0, []}
    end.

%% 使用时间戳判断是否同一天，判断数据是否还有效
check_time(NowTime, {Count, RefreshTime, Other}, Clock) ->
    case utime:is_logic_same_day(NowTime, RefreshTime, Clock) of
        true -> %% 同一天
            {Count, RefreshTime, Other};
        false ->
            {0, 0, []}
    end.


%% ------------------------- local function -------------------------
to_dict([], D) -> D;
to_dict([[Module, SubModule, Type, Count, Other, Time] | T], D) ->
    to_dict(T, [#ets_daily{id = {Module, SubModule, Type}, count = Count,
                           other = util:bitstring_to_term(Other), refresh_time = Time}|D]).

get_clock(Module, SubModule, Type) ->
    Config = get_config(Module, SubModule, Type),
    case Config of
        [] ->
            {error, ?FOUR};
        #base_daily{clock = Clock} when Clock==?TWELVE orelse Clock==?FOUR->
            {true, Clock};
        #base_daily{clock = Clock} ->
            ?ERR(">>>>> important >>>>> clock config error:~p~n", [{Module, SubModule, Type, Clock}]),
            {error, ?FOUR}
    end.

get_config(Module, SubModule, Type) ->
    case SubModule ==?DEFAULT_SUB_MODULE of
        true -> Config = data_daily:get_id(Module, Type);
        false -> Config = data_daily_extra:get_id(Module, SubModule)
    end,
    case Config of
        [] ->
            %tool:back_trace_to_file(),
            ?ERR(">>>>> important >>>>> missing config:~p~n", [{Module, SubModule, Type}]);
        _ -> skip
    end,
    Config.

%% 减一操作
decrement(RoleId, Module, Type) ->
    decrement(RoleId, Module, ?DEFAULT_SUB_MODULE, Type).

decrement(RoleId, Module, SubModule, Type) ->
    cut_count(RoleId, Module, SubModule, Type, 1).


%% 加一操作
%% 在线时：  同increment一样
%% 不在线时：不在线则直接修改db
increment_offline(RoleId, Module, Type) ->
    increment_offline(RoleId, Module, ?DEFAULT_SUB_MODULE, Type).

%% 加一操作
%% 在线时：  同increment一样
%% 不在线时：不在线则直接修改db
increment_offline(RoleId, Module, SubModule, Type) ->
    plus_count_offline(RoleId, Module, SubModule, Type, 1).


%% 减一操作，不在线则处理离线
decrement_offline(RoleId, Module, Type) ->
    decrement_offline(RoleId, Module, ?DEFAULT_SUB_MODULE, Type).

decrement_offline(RoleId, Module, SubModule, Type) ->
    Pid = misc:get_player_process(RoleId),
    case misc:is_process_alive(Pid) of
        true when Pid =:= self() ->
            decrement(RoleId, Module, SubModule, Type);
        true->
            lib_player:apply_cast(Pid,?APPLY_CAST,?MODULE,decrement,[RoleId, Module, SubModule, Type]);
        _  ->
            Time = utime:unixtime(),
            F = fun() ->
                    {OldCount, Other} = lib_daily:get_count_and_other_from_db(RoleId, Module, SubModule, Type, Time),
                    lib_daily:update_count_db(RoleId, Module, SubModule, Type, max(OldCount-1,0), Other, Time),
                    ok
                end,
            case catch db:transaction(F) of
                ok -> ok;
                Error ->
                    ?ERR("plus_count_offline:~p~n", [Error]),
                    error
            end
    end.

set_count_offline(RoleId, Module, Type, Count) ->
    set_count_offline(RoleId, Module, ?DEFAULT_SUB_MODULE, Type, Count).

set_count_offline(RoleId, Module, SubModule, Type, Count) ->
    Pid = misc:get_player_process(RoleId),
    case misc:is_process_alive(Pid) of
        true when Pid =:= self() ->
            set_count(RoleId, Module, SubModule, Type, Count);
        true ->
            lib_player:apply_cast(Pid,?APPLY_CAST,?MODULE,set_count,[RoleId, Module, SubModule, Type, Count]);
        _  ->
            Time = utime:unixtime(),
            F = fun() ->
                    {_, Other} = lib_daily:get_count_and_other_from_db(RoleId, Module, SubModule, Type, Time),
                    lib_daily:update_count_db(RoleId, Module, SubModule, Type, Count, Other, Time),
                    ok
                end,
            case catch db:transaction(F) of
                ok -> ok;
                Error ->
                    ?ERR("set_count_offline:~p~n", [Error]),
                    error
            end
    end.


%% 追加数量，不在线则处理离线
plus_count_offline(RoleId, Module, Type, Count) ->
    plus_count_offline(RoleId,  Module, ?DEFAULT_SUB_MODULE, Type, Count).

plus_count_offline(RoleId, Module, SubModule, Type, Count) ->
    Pid = misc:get_player_process(RoleId),
    case misc:is_process_alive(Pid) of
        true when Pid =:= self() ->
            plus_count(RoleId, Module, SubModule, Type, Count);
        true->
            lib_player:apply_cast(Pid,?APPLY_CAST,?MODULE,plus_count,[RoleId, Module, SubModule, Type, Count]);
        _  ->
            Time = utime:unixtime(),
            F = fun() ->
                    {OldCount, Other} = lib_daily:get_count_and_other_from_db(RoleId, Module, SubModule, Type, Time),
                    lib_daily:update_count_db(RoleId, Module, SubModule, Type, Count + OldCount, Other, Time),
                    ok
                end,
            case catch db:transaction(F) of
                ok -> ok;
                Error ->
                    ?ERR("plus_count_offline:~p~n", [Error]),
                    error
            end
    end.



%% 获取数量
%% 在线时：  同get_count一样
%% 不在线时：不在线则直接读取db
get_count_offline(RoleId, Module, Type) ->
    get_count_offline(RoleId, Module, ?DEFAULT_SUB_MODULE, Type).

%% 获取数量
%% 在线时：  同get_count一样
%% 不在线时：不在线则直接读取db
get_count_offline(RoleId, Module, SubModule, Type) ->
    Pid = misc:get_player_process(RoleId),
    case misc:is_process_alive(Pid) of
        true  when Pid =:= self()->
            get_count(RoleId, Module, SubModule, Type);
        true ->
            lib_player:apply_call(Pid,?APPLY_CALL,?MODULE,get_count,[RoleId, Module, SubModule, Type]);
        _  ->
            {Count, _Other} = lib_daily:get_count_and_other_from_db(RoleId, Module, SubModule, Type),
            Count
    end.

%% 获取数量(列表形式)
%% 在线时：  同get_count一样
%% 不在线时：不在线则直接读取db
%% RoleId    :: integer() 玩家id
%% List      :: [{Module::integer(), SubModule::integer(), Type::integer()}]
%% @return   :: [{ {Module::integer(), SubModule::integer(), Type::integer()}, Count::integer()}]
get_count_offline(RoleId, List) ->
    Pid = misc:get_player_process(RoleId),
    case misc:is_process_alive(Pid) of
        true  when Pid =:= self() ->
            get_count(RoleId, List);
        true->
            lib_player:apply_call(Pid,?APPLY_CALL,?MODULE,get_count,[RoleId, List]);
        _  ->
            lists:map(
                fun({Module, SubModule, Type} = Id) ->
                    {Count, _Other} = lib_daily:get_count_and_other_from_db(RoleId, Module, SubModule, Type),
                    {Id, Count}
                end, List)
    end.
