%% ---------------------------------------
%% desc         :超级富豪
%% module       :lib_mono_poly.erl
%% author       :hh
%% time         :20/08/25
%% ---------------------------------------


-module(custom_act_mono_poly).

-include("server.hrl").
-include("custom_act.hrl").
-include("mono_poly.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("def_fun.hrl").
-include("errcode.hrl").
-include("common.hrl").
-include("def_module.hrl").
-include("figure.hrl").
-include("def_goods.hrl").

-export([
    handle_event/2,
    check/1
    ]).

-export([
    role_monopoly_info/3
    ,dice_action/3
    ,dice_reissue/2
    ,get_round_reward/3

    ,gm_reset_monopoly/2
    ]).


%% 登录判断跨天
handle_event(Player, #event_callback{type_id = ?EVENT_LOGIN_CAST}) ->
    check_daily_mono_poly_update(Player#player_status.id, ?EVENT_LOGIN_CAST),
    {ok, Player};

%% 充值更新数据
handle_event(Player, #event_callback{type_id = ?EVENT_RECHARGE, data = #callback_recharge_data{gold = Gold}}) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_MONOPOLY) of
        [ActInfo = #act_info{key = {_, SubType}}|_] ->
            update_role_monopoly(RoleId, ActInfo, Gold),
            role_monopoly_info(RoleId, Sid, SubType),
            {ok, Player};
        _ -> %% 活动未开
            {ok, Player}
    end;

%% 在线跨天
handle_event(Player, #event_callback{type_id = ?EVENT_ZERO_CLOCK}) ->
    #player_status{id = RoleId} = Player,
    check_daily_mono_poly_update(RoleId, ?EVENT_ZERO_CLOCK),
    {ok, Player};

handle_event(Player, _) ->
    {ok, Player}.

%% 人物进程执行
check_daily_mono_poly_update(RoleId, EventType) ->
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_MONOPOLY) of
        [ActInfo = #act_info{stime = StartTime}|_] ->
            CustomActData = #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(ActInfo),
            case ActData of
                #role_mono_poly{time = Time} ->
                    IsToday = utime:is_today(Time),
                    if Time =/= 0 andalso (not IsToday) ->
                            NewActData = daily_refresh_role_mono_poly(ActData, StartTime),
                            if EventType == ?EVENT_LOGIN_CAST ->
                                    ?IF(NewActData =/= ActData, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData}), skip);
                                true -> %% 在线跨天的不更新数据库
                                    lib_custom_act_data:put_custom_data(CustomActData#custom_act_data{act_data = NewActData})
                            end;
                        true -> %% 未有数据或已跨天
                            skip
                    end;
                _ -> %% 暂时未有数据
                    skip
            end;
        _ -> %% 活动未开
            skip
    end.

update_role_monopoly(RoleId, ActInfo, Gold) ->
    CustomActData = #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(ActInfo),
    case ActData of
        #role_mono_poly{} ->
            NewActData1 = update_role_charge_info(ActData, Gold);
        _ ->
            NewActData = init_role_monopoly(),
            NewActData1 = update_role_charge_info(NewActData, Gold)
    end,
    ?IF(ActData =/= NewActData1, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData1}), skip),
    ok.

init_role_monopoly() ->
    LuckyPool = init_luck_pool(),
    Now = utime:unixtime(),
    #role_mono_poly{
        round = 1,
        lucky_pool = LuckyPool,
        time = Now
    }.

%% Index可能重复
init_luck_pool() ->
    CfgPools = data_mono_poly:get_luckycard_weight(),
    LuckTypePools = filter_luck_pool(CfgPools),
    CfgN = data_mono_poly:get_kv(luckycard_pool),
    Pools = init_luck_pool_do(LuckTypePools, CfgN, []),
    [{Index, 0} || Index <- Pools].

filter_luck_pool(CfgPools) ->
    lists:foldl(fun({Weight, Index, Type}, Acc) -> 
        case lists:keyfind(Type, 1, Acc) of
            {_, TypeAcc} ->
                lists:keystore(Type, 1, Acc, {Type, [{Weight, Index}|TypeAcc]});
            _ ->
                lists:keystore(Type, 1, Acc, {Type, [{Weight, Index}]})
        end 
    end, [], CfgPools).

init_luck_pool_do(_LuckTypePools, [], Acc) ->
    Acc;
init_luck_pool_do(LuckTypePools, [{Type, N}|Rest], Acc) ->
    case lists:keyfind(Type, 1, LuckTypePools) of
        {_, Pool} ->
            RandPool = urand:list_rand_by_weight(Pool, N, false),
            % ?ERR("~p ~p", [Type, RandPool]),
            init_luck_pool_do(LuckTypePools, Rest, RandPool ++ Acc);
        _ ->
            init_luck_pool_do(LuckTypePools, Rest, Acc)
    end.

%% 跨天刷新日常次数
daily_refresh_role_mono_poly(ActData, ActStartTime) ->
    %% 计算今日可补签次数
    NewActData = check_reissue_init(ActData, ActStartTime),
    %% 今日已获取金骰子&普通骰子次数更新,累充更新,今日已投掷次数更新
    NewActData#role_mono_poly{
        total_gold = 0,
        normal_get = 0,
        gold_get = 0,
        dice_count = 0,
        gold_dice_count = 0,
        time = utime:unixtime()
    }.

update_role_charge_info(ActData, Gold) ->
    #role_mono_poly{
        total_gold = OldTotal
    } = ActData,
    CountAdds = calc_pass_lv(OldTotal, Gold),
    NewActData = update_charge_count(CountAdds, ActData),
    Now = utime:unixtime(),
    NewActData#role_mono_poly{total_gold = OldTotal + Gold, time = Now}.

calc_pass_lv(OldTotal, Gold) ->
    NormalLv = data_mono_poly:get_kv(normal_dice_level),
    GoldLv   = data_mono_poly:get_kv(gold_dice_level),
    CountAdds = calc_pass_lv_do({normal_count, NormalLv}, OldTotal, round(OldTotal+Gold), []),
    calc_pass_lv_do({gold_count, GoldLv}, OldTotal, round(OldTotal+Gold), CountAdds).

calc_pass_lv_do({_Type, []}, _, _, Acc) -> Acc;
calc_pass_lv_do({Type, [CfgLv|Rest]}, OldTotal, NewTotal, Acc) ->
    if
        OldTotal < CfgLv andalso NewTotal >= CfgLv ->
            case lists:keyfind(Type, 1, Acc) of
                {_, Count} ->
                    NewAcc = lists:keystore(Type, 1, Acc, {Type, Count+1}),
                    calc_pass_lv_do({Type, Rest}, OldTotal, NewTotal, NewAcc);
                _ ->
                    NewAcc = lists:keystore(Type, 1, Acc, {Type, 1}),
                    calc_pass_lv_do({Type, Rest}, OldTotal, NewTotal, NewAcc)
            end;
        true ->
            calc_pass_lv_do({Type, Rest}, OldTotal, NewTotal, Acc)
    end.

update_charge_count([], ActData) -> 
    ActData;
update_charge_count([{normal_count, AddCount}|Rest], ActData) ->
    #role_mono_poly{normal_count = NormalCount, normal_get = NormalGet} = ActData,
    NewActData = ActData#role_mono_poly{normal_count = round(NormalCount+AddCount), normal_get = NormalGet+AddCount},
    update_charge_count(Rest, NewActData);
update_charge_count([{gold_count, AddCount}|Rest], ActData) ->
    #role_mono_poly{gold_count = GoldCount, gold_get = GoldGet} = ActData,
    NewActData = ActData#role_mono_poly{gold_count = round(GoldCount+AddCount), gold_get = GoldGet+AddCount},
    update_charge_count(Rest, NewActData);
update_charge_count([_|Rest], ActData) ->
    update_charge_count(Rest, ActData).


%% 超级富豪信息
role_monopoly_info(RoleId, Sid, SubType) ->
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_MONOPOLY) of
        [ActInfo = #act_info{stime = Stime}|_] ->
            #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(ActInfo),
                case ActData of
                    #role_mono_poly{} ->
                        NewActData = check_luck_pool_init(ActData),
                        ?IF(NewActData =/= ActData, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData}), skip),
                        % ?ERR("~p", [ActData]),
                        {ok, BinData} = pack_role_mono_poly_info(SubType, NewActData),
                        lib_server_send:send_to_sid(Sid, BinData);
                    _ ->
                        ActData1 = #role_mono_poly{},
                        ActData2 = check_luck_pool_init(ActData1),
                        ActData3 = check_reissue_init(ActData2, Stime),
                        ?IF(ActData3 =/= ActData1, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = ActData3}), skip),
                        {ok, BinData} = pack_role_mono_poly_info(SubType, ActData3),
                        % {ok, BinData} = pt_332:write(33228, [SubType, 0, 0, 0, 0, 0, 0, 0, 0, [], [], []]),
                        lib_server_send:send_to_sid(Sid, BinData)
                end;
        _ ->    
            {ok, BinData} = pt_332:write(33228, [SubType, 0, 0, 0, 0, 0, 0, 0, 0, 0, [], [], []]),
            lib_server_send:send_to_sid(Sid, BinData)
    end.

check_luck_pool_init(ActData) ->
    % ?ERR("~p", [ActData]),
    case ActData of
        #role_mono_poly{lucky_pool = []} ->
            NewLuckyPool = init_luck_pool(),
            ActData#role_mono_poly{round = 1, lucky_pool = NewLuckyPool};
        _ ->
            ActData
    end.

check_reissue_init(ActData, ActStartTime) ->
    #role_mono_poly{
        normal_count = NormalCount,
        reissue_count = _OldReissueCount
    } = ActData,
    Now = utime:unixtime(),
    LastDays = max(0, utime:day_span(ActStartTime, Now) - 1),
    NormalLvCfg = data_mono_poly:get_kv(normal_dice_level),
    GoldLvCfg   = data_mono_poly:get_kv(gold_dice_level),
    Limit = length(NormalLvCfg) + length(GoldLvCfg),
    %% 计算今日可补签次数
    TodayReissueCount = max(0, LastDays*Limit - NormalCount),
    NewReissueCount   = TodayReissueCount,
    ActData#role_mono_poly{
        reissue_count = NewReissueCount
    }.

%% 掷骰子
dice_action(Player, SubType, DiceType) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    CheckL = [
        {act_is_open, [SubType]},
        {count_check, [SubType, DiceType]},
        {dice_index_check, [SubType]}
    ],
    case util:check_lists(?MODULE, CheckL) of
        true ->
            #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_MONOPOLY, SubType),
            {NewActData, PassDice, DiceList} = dice_action_do(ActData, DiceType),
            Rewards = dice_rewards(DiceList),
            NewPlayer = lib_goods_api:send_reward(Player, Rewards, monopoly_dice),
            % ?ERR("~p ~p ~p", [NewActData, PassDice, DiceList]),
            ?IF(NewActData =/= ActData, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData}), skip),
            {ok, BinData} = pack_dice_info(?SUCCESS, SubType, PassDice, DiceList),
            lib_server_send:send_to_sid(Sid, BinData),
            {ok, NewPlayer};
        {false, Errcode} -> %?ERR("~p", [Errcode]),
            {ok, BinData} = pt_332:write(33229, [Errcode, SubType, 0, []]),
            lib_server_send:send_to_sid(Sid, BinData),
            ok
    end.

%% 补签
dice_reissue(Player, SubType) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    CheckL = [
        {act_is_open, [SubType]},
        {reissue_count_check, [SubType]}
    ],
    case util:check_lists(?MODULE, CheckL) of
        true ->
            #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_MONOPOLY, SubType),
            Cost = calc_reissue_cost(ActData),
            case lib_goods_api:cost_object_list_with_check(Player, Cost, reissue_cost, "") of
                {true, NewPlayer, _} ->
                    NewActData = dice_reissue_do(ActData),
                    ?IF(NewActData =/= ActData, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData}), skip),
                    {ok, BinData} = pt_332:write(33230, [?SUCCESS, SubType]),
                    lib_server_send:send_to_sid(Sid, BinData),
                    {ok, NewPlayer};
                {false, Errcode, _} ->
                    {ok, BinData} = pt_332:write(33230, [Errcode, SubType]),
                    lib_server_send:send_to_sid(Sid, BinData)
            end;
            % ?ERR("~p", [NewActData]),
        {false, Errcode} ->
            {ok, BinData} = pt_332:write(33230, [Errcode, SubType]),
            lib_server_send:send_to_sid(Sid, BinData),
            ok
    end.

calc_reissue_cost(ActData) ->
    #role_mono_poly{reissue_use = UseCount} = ActData,
    NewUseCount = UseCount+1,
    MaxCount = data_mono_poly:get_max_count(),
    Price = if NewUseCount >= MaxCount ->
            data_mono_poly:get_reissue_price(MaxCount);
        true ->
            data_mono_poly:get_reissue_price(NewUseCount)
    end,
    [{?TYPE_GOLD, 0, Price}].

%% 领取圈数奖励
get_round_reward(Player, SubType, Round) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    CheckL = [
        {act_is_open, [SubType]},
        {round_reward_check, [SubType, Round]}
    ],
    case util:check_lists(?MODULE, CheckL) of
        true ->
            #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_MONOPOLY, SubType),
            {NewPlayer, NewActData} = get_round_rewards_do(Player, ActData, SubType, Round),
            ?IF(NewActData =/= ActData, lib_custom_act_data:save_custom_data(RoleId, CustomActData#custom_act_data{act_data = NewActData}), skip),
            {ok, BinData} = pt_332:write(33231, [?SUCCESS, SubType, Round]),
            lib_server_send:send_to_sid(Sid, BinData),
            {ok, NewPlayer};
        {false, Errcode} ->
            {ok, BinData} = pt_332:write(33231, [Errcode, SubType, Round]),
            lib_server_send:send_to_sid(Sid, BinData),
            ok
    end.

dice_action_do(ActData, DiceType) ->
    #role_mono_poly{
        dice_count = DiceCount,         %% 今日普通骰子已投掷次数
        gold_dice_count = GoldDiceCount,%% 今日金骰子已投掷次数
        % normal_count = NormalCount,     %% 已获普通次数
        normal_use = NormalUse,         %% 已使用普通次数
        % gold_count = GoldCount,         %% 已获高级次数
        gold_use = GoldUse,             %% 已使用高级次数
        round = Round,                  %% 当前圈数
        dice_index = DiceIndex,         %% 当前停留格子编号
        lucky_pool = LuckyPool,         %% 幸运奖池 [{奖励index, status}]
        circle_dice_list = DiceStatus,  %% 当前圈数状态 [{格子index, 奖励列表, 幸运池索引}]
        round_rewards = RoundRewards    %% [{圈数,奖励领取状态}]
    } = ActData,

    %% 随机本次骰子点
    RandDice = get_this_dice_result(DiceType, DiceCount, GoldDiceCount),
    % ?ERR("this time dice ~p", [RandDice]),
    %% 计算本次经过的点数对应的奖励
    {DiceAddList, NewLuckyPool, SpecialEvent} = calc_pass_dice_rewards(Round, DiceIndex, LuckyPool, DiceStatus, RandDice),
    
    %% 更新点数和圈数状态
    {NewRound, NewDiceIndex, NewNormalUse, NewGoldUse, DiceAddList1, NewLuckyPool1} =
     update_round_dice_with_spec(DiceType, Round, DiceIndex, NormalUse, GoldUse, RandDice, NewLuckyPool, DiceStatus, SpecialEvent),

    %% 更新已投掷次数
    {NewDiceCount, NewGoldDiceCount} = update_dice_count(DiceType, DiceCount, GoldDiceCount),
    
    NewDiceStatus = lists:append([DiceAddList, DiceAddList1, DiceStatus]),    
    
    %% 检查是否达到终点,更新圈数奖励状态
    NewRoundRewards = check_round_rewards(NewRound, NewDiceIndex, RoundRewards),

    %% 检查珍稀奖池是否抽完,更新珍稀奖池
    NewLuckyPool2 = check_luck_pool_reward(NewLuckyPool1),
    
    %% 检查是否重置圈数状态
    {ResetRound, ResetDiceIndex, NewDiceStatus1} = check_reset_dice_round(NewRound, NewDiceIndex, NewDiceStatus),
    % ?ERR("~p ~p ~p", [ResetRound, ResetDiceIndex, NewDiceIndex]),
    NewActData = ActData#role_mono_poly{
        dice_count = NewDiceCount,
        gold_dice_count = NewGoldDiceCount,
        normal_use = NewNormalUse,
        gold_use = NewGoldUse,
        round = ResetRound,
        dice_index = ResetDiceIndex,
        lucky_pool = NewLuckyPool2,
        circle_dice_list = NewDiceStatus1,
        round_rewards = NewRoundRewards,
        time = utime:unixtime()
    },
    {NewActData, RandDice, DiceAddList ++ DiceAddList1}.

%% 补签操作
dice_reissue_do(ActData) ->
    #role_mono_poly{normal_count = NormalCount, reissue_count = ReissueCount, reissue_use = ReissueUse} = ActData,
    NewReissueUse = ReissueUse + 1,
    NewNormalCount = NormalCount + 1,
    NewReissueCount = max(0, ReissueCount - 1),
    ActData#role_mono_poly{
        normal_count = NewNormalCount,
        reissue_count = NewReissueCount,
        reissue_use  = NewReissueUse,
        time = utime:unixtime()
    }.

%% 圈数奖励领取
 get_round_rewards_do(Player, ActData, SubType, Round) ->
    #player_status{figure = #figure{name = RoleName}} = Player,
    #role_mono_poly{round_rewards = RoundRewards} = ActData,
    NewRoundRewards = lists:keystore(Round, 1, RoundRewards, {Round, ?ROUND_REWARDS_2}),
    NewActData = ActData#role_mono_poly{
        round_rewards = NewRoundRewards, 
        time = utime:unixtime()
    },
    Rewards   = data_mono_poly:get_one_round_rewards(?CUSTOM_ACT_TYPE_MONOPOLY, SubType, Round),
    % ?ERR("~p ~p", [Round, Rewards]),
    NewPlayer = lib_goods_api:send_reward(Player, Rewards, monopoly_round_reward),
    case Rewards of
        [{_, GoodsId, Num}|_] ->
            lib_chat:send_TV({all}, ?MOD_AC_CUSTOM, 5, [RoleName, GoodsId, Num]);
        _ ->
            skip
    end,
    {NewPlayer, NewActData}.

dice_rewards(DiceList) ->
    lists:foldl(fun({_Dice, Rewards, _LuckIndex}, Acc) -> 
        Rewards ++ Acc
    end, [], DiceList).

get_this_dice_result(DiceType, DiceCount, GoldDiceCount) ->
    MaxCount = data_mono_poly:get_max_dice_count(DiceType),
    Count = ?IF(DiceType == ?NORMAL_DICE, DiceCount, GoldDiceCount),
    NewCount = Count+1,
    WeightList =
    if NewCount >= MaxCount ->
            data_mono_poly:get_dice_weight(DiceType, MaxCount);
        true ->
            data_mono_poly:get_dice_weight(DiceType, NewCount)
    end,
    NewWeightList =
    if
        DiceType == ?NORMAL_DICE ->
            WeightList;
        true -> %% 金骰子必出4~6点
            lists:filter(fun({_Weight, Dice}) -> Dice >= 4 end, WeightList)
    end,
    % ?ERR("~p ~p", [WeightList, NewWeightList]),
    urand:rand_with_weight(NewWeightList).

% {格子index, 奖励列表, 幸运池索引}
calc_pass_dice_rewards(Round, DiceIndex, LuckyPool, DiceStatus, Dice) ->
    PassDices = lists:seq(DiceIndex+1, DiceIndex+Dice),
    % ?ERR("pass dices ~p", [PassDices]),
    MaxPassDice = lists:max(PassDices),
    SmallWeights = data_mono_poly:get_small_weight(),
    {DiceAddList, NewLuckyPool, Special} =
     lists:foldl(fun(PassDice, {TempDiceAddList, TempLuckPool, TempSpecial}) -> 
        Type = data_mono_poly:get_lattice_type(Round, PassDice),
        if 
            PassDice >= MaxPassDice -> %% 最后一格
                if
                    Type == ?NORMAL_BOX orelse Type == ?LUCKY_BOX ->
                        case check_dice_index_have_rewarded(DiceStatus, PassDice) of
                            false ->
                                {Rewards, LuckIndex, NewTempLuckPool} = calc_dice_reward(Type, SmallWeights, TempLuckPool),
                                {[{PassDice, Rewards, LuckIndex}|TempDiceAddList], NewTempLuckPool, TempSpecial};
                            _ ->
                                {TempDiceAddList, TempLuckPool, TempSpecial}
                        end;
                    Type == ?ANOTHER_CHANCE orelse Type == ?BACKWARD_3 orelse Type == ?BACKWARD_1
                     orelse Type == ?DIRECT_END ->
                        {TempDiceAddList, TempLuckPool, [{PassDice, Type}|TempSpecial]};
                    true ->
                        {TempDiceAddList, TempLuckPool, TempSpecial}
                end;
            true -> %% 经过的格子
                if 
                    Type == ?NORMAL_BOX orelse Type == ?LUCKY_BOX ->
                        case check_dice_index_have_rewarded(DiceStatus, PassDice) of
                            false ->
                                {Rewards, LuckIndex, NewTempLuckPool} = calc_dice_reward(Type, SmallWeights, TempLuckPool),
                                {[{PassDice, Rewards, LuckIndex}|TempDiceAddList], NewTempLuckPool, TempSpecial};
                            _ ->
                                {TempDiceAddList, TempLuckPool, TempSpecial}
                        end;
                    true ->
                        {TempDiceAddList, TempLuckPool, TempSpecial}
                end
        end
    end, {[], LuckyPool, []}, PassDices),
    {DiceAddList, NewLuckyPool, Special}.

%% 该格子是否领取过奖励
check_dice_index_have_rewarded(DiceStatus, PassDice) ->
    case lists:keyfind(PassDice, 1, DiceStatus) of
        {_, _, _} ->
            true;
        _ ->
            false
    end.

calc_dice_reward(_Type = ?NORMAL_BOX, RewardWeights, _LuckyPool) ->
    RandIndex = urand:rand_with_weight(RewardWeights),
    #base_mono_smallbox{rewards = Rewards} = data_mono_poly:get_smallbox_reward(RandIndex),
    {Rewards, 0, _LuckyPool};
calc_dice_reward(_Type = ?LUCKY_BOX, _RewardWeights, LuckyPool) ->
    case lists:filter(fun({_LuckIndex, Status}) -> 
        Status == ?LUCK_ACCESS
    end, LuckyPool) of
        FilterPool = [_|_] ->
            WeightPool = 
            [begin 
                #base_mono_luckycard{weight = Weight} = data_mono_poly:get_luckycard_rewards(Index1), 
                {Weight, Index1} 
            end || {Index1, _} <- FilterPool],
            Index = urand:rand_with_weight(WeightPool),
            #base_mono_luckycard{rewards = Rewards} = data_mono_poly:get_luckycard_rewards(Index),
            NewLuckyPool = update_luck_pool(Index, LuckyPool);
        _ ->
            Rewards = [], Index = 0, NewLuckyPool = LuckyPool
    end,
    {Rewards, Index, NewLuckyPool}.

%% 因为是可能重复的,因此不使用lists:keystore
update_luck_pool(Index, LuckyPool) ->
    update_luck_pool_do(Index, LuckyPool, []).

update_luck_pool_do(_Index, [], PrevPool) -> 
    PrevPool;
update_luck_pool_do(Index, [{Index, ?LUCK_ACCESS}|Rest], PrevPool) ->
    PrevPool ++ [{Index, ?LUCK_NOT_ACCESS}|Rest];
update_luck_pool_do(Index, [{LuckIndex, Access}|Rest], PrevPool) ->
    update_luck_pool_do(Index, Rest, [{LuckIndex, Access}|PrevPool]).

%% 根据投掷类型判断普通投掷次数和金骰子投掷次数
update_round_dice_with_spec(DiceType, Round, DiceIndex, NormalUse, GoldUse, Dice, LuckyPool, _DiceStatus, []) ->
    MaxIndex = data_mono_poly:get_round_max_index(Round),
    NewDiceIndex = min(MaxIndex, DiceIndex+Dice),
    % ?ERR("~p ~p ~p ~p", [NewDiceIndex, MaxIndex, DiceIndex, Dice]),
    {NewNormalUse, NewGoldUse} = ?IF(DiceType == ?NORMAL_DICE, {NormalUse+1, GoldUse}, {NormalUse, GoldUse+1}),
    % ?ERR("~p ~p", [NewNormalUse, NewGoldUse]),
    {Round, NewDiceIndex, NewNormalUse, NewGoldUse, [], LuckyPool};

update_round_dice_with_spec(DiceType, Round, DiceIndex, NormalUse, GoldUse, Dice, LuckyPool, _DiceStatus, [{_, ?ANOTHER_CHANCE}|_]) ->
    MaxIndex = data_mono_poly:get_round_max_index(Round),
    NewDiceIndex = min(MaxIndex, DiceIndex+Dice),
    {NewNormalUse, NewGoldUse} = ?IF(DiceType == ?NORMAL_DICE, {NormalUse, GoldUse}, {max(0, NormalUse-1), GoldUse+1}),
    {Round, NewDiceIndex, NewNormalUse, NewGoldUse, [], LuckyPool};

update_round_dice_with_spec(DiceType, Round, DiceIndex, NormalUse, GoldUse, Dice, LuckyPool, _DiceStatus, [{_, ?BACKWARD_3}|_]) ->
    ?ERR("~p", [DiceIndex+Dice-3]),
    {NewNormalUse, NewGoldUse} = ?IF(DiceType == ?NORMAL_DICE, {NormalUse+1, GoldUse}, {NormalUse, GoldUse+1}),
    {Round, max(0, DiceIndex+Dice-3), NewNormalUse, NewGoldUse, [], LuckyPool};

update_round_dice_with_spec(DiceType, Round, DiceIndex, NormalUse, GoldUse, Dice, LuckyPool, _DiceStatus, [{_, ?BACKWARD_1}|_]) ->
    ?ERR("~p", [DiceIndex+Dice-1]),
    {NewNormalUse, NewGoldUse} = ?IF(DiceType == ?NORMAL_DICE, {NormalUse+1, GoldUse}, {NormalUse, GoldUse+1}),
    {Round, max(0, DiceIndex+Dice-1), NewNormalUse, NewGoldUse, [], LuckyPool};

update_round_dice_with_spec(DiceType, Round, DiceIndex, NormalUse, GoldUse, Dice, LuckyPool, DiceStatus, [{_, ?DIRECT_END}|_]) ->
    MaxIndex = data_mono_poly:get_round_max_index(Round),
    StartDice = DiceIndex+Dice,
    DirectPassDice = MaxIndex - StartDice,
    {NewNormalUse, NewGoldUse} = ?IF(DiceType == ?NORMAL_DICE, {NormalUse+1, GoldUse}, {NormalUse, GoldUse+1}),
    {DiceAddList, NewLuckyPool, _SpecialEvent} = calc_pass_dice_rewards(Round, StartDice, LuckyPool, DiceStatus, DirectPassDice),
    {Round, MaxIndex, NewNormalUse, NewGoldUse, DiceAddList, NewLuckyPool}.

check_round_rewards(Round, DiceIndex, RoundRewards) ->
    MaxIndex = data_mono_poly:get_round_max_index(Round),
    NewRoundRewards =
    if
        DiceIndex >= MaxIndex ->
            lists:keystore(Round, 1, RoundRewards, {Round, ?ROUND_REWARDS_1});
        true ->
            RoundRewards
    end,
    NewRoundRewards.

check_luck_pool_reward(LuckyPool) ->
    case lists:any(fun({_Index, Status}) -> 
        Status == ?LUCK_ACCESS
    end, LuckyPool) of
        true ->
            LuckyPool;
        _ ->
            init_luck_pool()
    end.

check_reset_dice_round(Round, DiceIndex, DiceStatus) ->
    MaxIndex = data_mono_poly:get_round_max_index(Round),
    MaxRound = data_mono_poly:get_max_round(),
    if
        DiceIndex >= MaxIndex ->
            NewRound = Round + 1,
            if NewRound > MaxRound ->
                    {Round, DiceIndex, DiceStatus};
                true ->
                    {NewRound, 0, []}
            end;
        true ->
            {Round, DiceIndex, DiceStatus}
    end.

update_dice_count(?NORMAL_DICE, DiceCount, GoldDiceCount) ->
    {DiceCount+1, GoldDiceCount};
update_dice_count(?GOLD_DICE, DiceCount, GoldDiceCount) ->
    {DiceCount, GoldDiceCount+1}.

pack_dice_info(Errcode, SubType, PassDice, DiceList) ->
    pt_332:write(33229, [Errcode, SubType, PassDice, DiceList]).

pack_role_mono_poly_info(SubType, ActData) ->
    #role_mono_poly{
        total_gold = TodayGold,
        normal_get = DailyNormal,         %% 今日已获得普通骰子次数
        gold_get = DailyGold,             %% 今日已获得金骰子次数
        normal_count = NormalCount,       %% 已获普通次数
        normal_use = NormalUse,           %% 已使用普通次数
        gold_count = GoldCount,           %% 已获高级次数
        gold_use = GoldUse,               %% 已使用高级次数
        round = Round,
        dice_index = DiceIndex,
        lucky_pool = LuckyPool,
        circle_dice_list = CircleDiceList,  %% 当前圈数状态 [{格子index, 奖励列表, 幸运池索引}]
        round_rewards = RoundRewards,     %% [{圈数,奖励领取状态}]
        reissue_count = ReissueCount,
        reissue_use = ReissueUse
    } = ActData,
    %% 
    RestNormalCount = max(0, NormalCount - NormalUse),
    RestGoldCount = max(0, GoldCount - GoldUse),
    RestReissueCount = ReissueCount,
    pt_332:write(33228, [SubType, Round, DiceIndex, RestNormalCount, RestGoldCount, DailyNormal, DailyGold, RestReissueCount, ReissueUse, TodayGold, LuckyPool, CircleDiceList, RoundRewards]).

gm_reset_monopoly(Player, 1) ->
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_MONOPOLY) of
        [ActInfo = #act_info{}|_] ->
            #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(ActInfo),
                case ActData of
                    #role_mono_poly{} ->
                        NewActData = ActData#role_mono_poly{
                            time = utime:unixtime(),               %% 操作最后时间
                            normal_use = 0,         %% 已使用普通次数
                            gold_use = 0           %% 已使用高级次数
                        },
                        lib_custom_act_data:save_custom_data(Player#player_status.id, CustomActData#custom_act_data{act_data = NewActData}),
                        ok;
                    _ ->
                        ok
                end;
        _ ->
            ok
    end;
gm_reset_monopoly(Player, 2) ->
    case lib_custom_act_api:get_open_custom_act_infos(?CUSTOM_ACT_TYPE_MONOPOLY) of
        [ActInfo = #act_info{}|_] ->
            #custom_act_data{act_data = ActData} = CustomActData = lib_custom_act_data:custom_act_data(ActInfo),
                case ActData of
                    #role_mono_poly{} ->
                        NewActData = check_luck_pool_init(#role_mono_poly{}),
                        lib_custom_act_data:save_custom_data(Player#player_status.id, CustomActData#custom_act_data{act_data = NewActData}),
                        ok;
                    _ ->
                        ok
                end;
        _ ->
            ok
    end.    

%% 活动开启检查
check({act_is_open, [SubType]}) ->
    case lib_custom_act_util:get_custom_act_open_info(?CUSTOM_ACT_TYPE_MONOPOLY, SubType) of
        #act_info{} ->
            true;
        _ ->
            {false, ?ERRCODE(err331_act_closed)}
    end;

%% 剩余次数检查
check({count_check, [SubType, DiceType]}) ->
    #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_MONOPOLY, SubType),
    case ActData of
        #role_mono_poly{
            normal_count = NormalCount,     %% 已获普通次数
            normal_use = NormalUse,         %% 已使用普通次数
            gold_count = GoldCount,         %% 已获高级次数
            gold_use = GoldUse              %% 已使用高级次数
        } ->
            if DiceType == ?NORMAL_DICE ->
                    RestCount = NormalCount - NormalUse,
                    if RestCount =< 0 ->
                            {false, ?ERRCODE(err331_dice_count_limit)};
                        true ->
                            true
                    end;
                DiceType == ?GOLD_DICE ->
                    RestCount = GoldCount - GoldUse,
                    if RestCount =< 0 ->
                            {false, ?ERRCODE(err331_dice_count_limit)};
                        true ->
                            true
                    end;
                true ->
                    {false, ?ERRCODE(err331_dice_type_error)}
            end;
        _ ->
            {false, ?ERRCODE(err331_have_not_dice_count)}
    end;

%% 剩余补签次数检查
check({reissue_count_check, [SubType]}) ->
    #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_MONOPOLY, SubType),
    case ActData of
        #role_mono_poly{reissue_count = ReissueCount} ->
            if
                ReissueCount =< 0 ->
                    {false, ?ERRCODE(err331_reissue_count_limit)};
                true ->
                    true
            end;
        _ ->
            {false, ?ERRCODE(err331_have_not_dice_count)}
    end;

%% 圈数完成检查
check({dice_index_check, [SubType]}) ->
    #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_MONOPOLY, SubType),
    case ActData of
        #role_mono_poly{round = Round, dice_index = DiceIndex} ->
            MaxRound = data_mono_poly:get_max_round(),
            MaxIndex = data_mono_poly:get_round_max_index(Round),
            if
                Round >= MaxRound andalso DiceIndex >= MaxIndex ->
                    {false, ?ERRCODE(err331_max_round)};
                true ->
                    true
            end;
        _ ->
            {false, ?ERRCODE(err331_have_not_dice_count)}
    end;

%% 圈数奖励检查
check({round_reward_check, [SubType, Round]}) ->
    #custom_act_data{act_data = ActData} = lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_MONOPOLY, SubType),
    case ActData of
        #role_mono_poly{round_rewards = RoundRewards} ->
            case lists:keyfind(Round, 1, RoundRewards) of
                {_, ?ROUND_REWARDS_1} ->
                    case data_mono_poly:get_one_round_rewards(?CUSTOM_ACT_TYPE_MONOPOLY, SubType, Round) of
                        [_|_] ->
                            true;
                        _ ->
                            {false, ?ERRCODE(err331_round_data_error)}
                    end;
                {_, ?ROUND_REWARDS_2} ->
                    {false, ?ERRCODE(err331_round_rewarded)};
                _ ->
                    {false, ?ERRCODE(err331_round_not_fin)}
            end;
        _ ->
            {false, ?ERRCODE(err331_have_not_dice_count)}
    end;
check(_) ->
    {false, ?FAIL}.
