%% ---------------------------------------------------------------------------
%% @doc pp_dungeon.erl

%% @author  hjh
%% @email  hejiahua@163.com
%% @since  2017-02-14
%% @deprecated 副本协议处理
%% ---------------------------------------------------------------------------
-module(pp_dungeon).
-export([handle/3]).

-include("server.hrl").
-include("dungeon.hrl").
-include("scene.hrl").
-include("common.hrl").
-include("def_module.hrl").
-include("def_fun.hrl").
-include("def_daily.hrl").
-include("errcode.hrl").
-include("def_vip.hrl").
-include("figure.hrl").
-include("rec_event.hrl").
-include("def_goods.hrl").
-include("exp_dun_drop.hrl").
-include("dun_guard.hrl").
-include("relationship.hrl").
-include("dungeon_pet.hrl").
-include("vip.hrl").
-include("pet.hrl").
-include("god_dun.hrl").

%% --------------------------------------------
%% @doc 扫荡相关协议入口
%% 1.61022 通用扫荡
%% 2.61028 材料副本批量扫荡
%% 3.61072 幻光副本扫荡
%% 4.61096 宝宝副本扫荡
%% --------------------------------------------

%% 进入副本
handle(61001, Player, [DunId, Type]) ->
    lib_dungeon:enter_dungeon(Player, DunId, Type);

%% 主动退出副本
handle(61002, Player, []) ->
    ?PRINT("RoleId:~p ~n", [Player#player_status.id]),
    lib_dungeon:active_quit(Player);

%% 通用结算界面
handle(61003, Player, []) ->
    #player_status{id = RoleId, copy_id = CopyId} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true -> mod_dungeon:push_settlement(CopyId, RoleId);
        false -> skip
    end;

%% 副本信息
handle(61004, Player, []) ->
    case lib_dungeon:is_on_dungeon(Player) of
        true -> mod_dungeon:send_dungeon_info(Player#player_status.copy_id, Player#player_status.id, node());
        false -> skip
    end;

%% 助战次数
handle(61011, #player_status{id = RoleId} = Player, [DunId]) ->
    Dun = data_dungeon:get_dun(DunId),
    if
        not is_record(Dun, dun_cfg) -> HelpCount = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_HELP, DunId);
        true ->
            CountType = lib_dungeon_api:get_daily_help_type(Dun#dun_cfg.type, DunId),
            HelpType = ?MOD_DUNGEON_HELP,
            % = case Dun#dungeon.type of
            %     ?DUNGEON_TYPE_EQUIP ->
            %         ?MOD_DUNGEON_HELP_AWARD;
            %     _ ->
            %         ?MOD_DUNGEON_HELP
            % end,
            HelpCount = lib_daily:get_count(RoleId, ?MOD_DUNGEON, HelpType, CountType)
    end,
    MaxHelpCount = lib_dungeon:get_max_help_count(Dun),
    LeftCount = max(MaxHelpCount - HelpCount, 0),
    {ok, BinData} = pt_610:write(61011, [LeftCount, DunId]),
    lib_server_send:send_to_sid(Player#player_status.sid, BinData);


%% 退出副本时间
handle(61018, Player, []) ->
    #player_status{id = RoleId, copy_id = CopyId} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true -> mod_dungeon:send_flow_quit_time(CopyId, RoleId, node());
        false -> skip
    end;

% 获取副本状态信息
handle(61020, #player_status{dungeon_record = undefined} = Player, Args) ->
    NewPlayer = lib_dungeon:load_dungeon_record(Player),
    handle(61020, NewPlayer, Args),
    {ok, NewPlayer};

% 获取副本状态信息
handle(61020, Player, [DunType]) ->
    #player_status{dungeon_record = Rec, id = RoleId} = Player,
    DataList = lib_dungeon:create_dungeon_infos(Rec, DunType),
    lib_dungeon:get_dungeon_data(RoleId, DataList, DunType, {lib_dungeon, send_dungeon_info, []});

% 购买副本次数
handle(61021, Player, [DunId, Count]) when Count > 0 ->
    case data_dungeon:get_dun(DunId) of
        #dun_cfg{buy_count_cost = [_|_] = BuyCost, type = DunType} ->
            #player_status{id = RoleId, vip_status = #vip_status{lv = VipLv}} = Player,
            CountType = lib_dungeon_api:get_daily_buy_type(DunType, DunId),
            % {_VipType, _VipLv} = lib_vip_api:get_valid_vip_lv(Player),
            VipBuyCount = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_BUY, CountType),
            case lib_dungeon:calc_buy_count_cost(BuyCost, VipBuyCount, Count, VipLv) of
                [] ->
                    lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61021, [?ERRCODE(err610_buy_count_error), DunId, VipBuyCount]);
                false ->
                    lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61021, [?ERRCODE(err610_buy_vip_error), DunId, 0]);
                Cost ->
                    case lib_goods_api:cost_object_list_with_check(Player, Cost,  dungeon_count_buy_cost, integer_to_list(DunId)) of
                        {true, NewPlayer0,_} ->
                            NewVipBuyCount = VipBuyCount + Count,
                            lib_daily:set_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_BUY, CountType, NewVipBuyCount),
                            lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61021, [?SUCCESS, DunId, NewVipBuyCount]),
                            {ok, NewPlayer0};
                        _ ->
                            lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61021, [?ERRCODE(err610_buy_cost_error), DunId, VipBuyCount])
                    end
            end;
        _ ->
            lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61021, [?ERRCODE(err610_buy_count_error), DunId, 0])
    end;

% ########### 扫荡 ##############
handle(61022, #player_status{dungeon_record = undefined} = Player, Args) ->
    NewPlayer = lib_dungeon:load_dungeon_record(Player),
    case handle(61022, NewPlayer, Args) of
        {ok, NewPlayer1} ->
            {ok, NewPlayer1};
        _ ->
            {ok, NewPlayer}
    end;
% ########### 扫荡 ##############
handle(61022, Player, [DunId, SweepNum, CostType]) ->
    #player_status{id = RoleId, sid = Sid, figure = Figure} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            Code = ?ERRCODE(err610_had_on_dungeon), RewardsList = [], CustomRewards = [], NewPlayer = Player;
        _ ->
            case lib_dungeon_sweep:check_sweep(Player, DunId, SweepNum, CostType) of
                {false, Code} ->
                    RewardsList = [], CustomRewards = [], NewPlayer = Player;
                {ok, RewardsList0, Costs} ->
                    Rewards = lists:flatten(RewardsList0),
                    DunType = data_dungeon:get_dun_type(DunId),
                    case lib_dungeon_api:get_custom_act_reward_times(DunType, DunId, Figure#figure.lv) of
                        Times when Times > 1 ->
                            Rewards1 = [{TGoodsType, TGoodsId, TGoodsNum*Times}||{TGoodsType, TGoodsId, TGoodsNum}<-Rewards],
                            CustomRewards = [{TGoodsType1, TGoodsId1, TGoodsNum1*max(1, Times-1)}||{TGoodsType1, TGoodsId1, TGoodsNum1}<-Rewards];
                        _ ->
                            Rewards1 = Rewards, CustomRewards = []
                    end,
                    case lib_goods_api:can_give_goods(Player, Rewards1) of
                        true ->
                            #dun_cfg{id = DunId, type = DunType, count_cond = CountCondition} = data_dungeon:get_dun(DunId),
                            {Code, CostPlayer1} =
                             if CostType == 1 ->
                                    Mark = lists:concat([DunId, "-", SweepNum]),
                                    case lib_goods_api:cost_object_list_with_check(Player, Costs, dungeon_count_sweep_cost, Mark) of
                                        {true, CostPlayer, _} ->
                                            {?SUCCESS, CostPlayer};
                                        _ ->
                                            {?ERRCODE(goods_not_enough), Player}
                                    end;
                                true ->
                                    {?SUCCESS, Player}
                            end,
                            case Code == ?SUCCESS of
                                true ->
                                    RewardsList = Rewards,
                                    TmpPlayer = lib_goods_api:send_reward(CostPlayer1, Rewards1, dungeon_count_sweep_rewards, DunType);
                                _ ->
                                    RewardsList = [],
                                    TmpPlayer = CostPlayer1
                            end,
                            %% 基础次数更新
                            if CostType == 1 ->
                                    case Costs of
                                    [{GoodsType, _, _}|_] -> ok;
                                    _ -> GoodsType = ?TYPE_BGOLD
                                    end,
                                   lib_dungeon:dungeon_buy_count_plus(CountCondition, GoodsType, DunId, DunType, RoleId, SweepNum);
                                true ->
                                    lib_dungeon:dungeon_count_plus(CountCondition, DunId, DunType, RoleId, SweepNum),
                                    lib_counter:plus_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId, SweepNum),
                                    lib_daily:plus_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunId, SweepNum)
                            end,
                            %% 其他扫荡次数更新
                            lib_dungeon_distribute:handle_sweep_count_plus(DunType, DunId, RoleId, SweepNum),

                            %% 触发
                            SweepDunIds = lib_dungeon_distribute:get_sweep_duns(DunType, DunId, SweepNum),
                            TriggerPlayer = lib_dungeon_sweep:sweep_dungeon_trigger(TmpPlayer, DunType, SweepDunIds),
                            %% 翻牌
                            TmpNewPlayer1 = lib_dungeon_distribute:start_dun_flop(TriggerPlayer, DunType, DunId),
                            custom_act_mobilize:finish_dungeon(RoleId, DunType, DunId),
                            NewPlayer = TmpNewPlayer1;
                        _ ->
                            Code = ?ERRCODE(err150_no_cell),
                            RewardsList = [],
                            NewPlayer = Player
                    end
            end
    end,
    WaveId = lib_dungeon_distribute:get_sweep_wave(NewPlayer, DunId, SweepNum, CostType),
    lib_server_send:send_to_sid(Sid, pt_610, 61022,
     [Code, DunId, RewardsList, CustomRewards, ?DUN_RESULT_TYPE_SUCCESS, ?DUN_RESULT_SUBTYPE_NO, WaveId, [{?DUN_PASS_TIME, 0}]]),
    {ok, NewPlayer};

% ########### 获取副本是否可用 ##############
% handle(61024, Player, []) ->
%     AllTypes = data_dungeon:get_types(),
%     F = fun
%         (Type) ->
%             {_DunId, Res} = lib_dungeon:get_recommend_dun(Player, Type),
%             {Type, Res}
%     end,
%     List = [F(T) || T <- AllTypes],
%     {ok, BinData} = pt_610:write(61024, [List]),
%     lib_server_send:send_to_sid(Player#player_status.sid, BinData);

%% 爬塔副本每日奖励领取
handle(61025, Player, _) ->
    lib_dungeon_tower:get_tower_daily_reward(Player);

% 材料副本批量扫荡 0免费扫荡|1全部扫荡
handle(61028, Player, [DunType, Type]) ->
    lib_dungeon_sweep:batch_sweep(Player, DunType, Type);

% 讨伐副本伤害输出
handle(61029, Player, _) ->
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #player_status{copy_id = CopyId, dungeon = #status_dungeon{dun_id = DunId}} = Player,
            case lib_dungeon:is_cluster_dungeon_by_dun_id(DunId) of
                    true ->
                        clusters_node:apply_cast(mod_dungeon, get_mon_hurt_info, [CopyId, Player#player_status.sid, node()]);
                    _ ->
                        mod_dungeon:get_mon_hurt_info(CopyId, Player#player_status.sid, node())
            end;
        _ ->
            lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61029, [[]])
    end;

%% 守卫信标-复活信息
handle(61031, Player, []) ->
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #player_status{dungeon = Dungeon = #status_dungeon{dun_id = DunId}} = Player,
            case data_dungeon:get_dun_type(DunId) of
                ?DUNGEON_TYPE_GUARD ->
                    #status_dungeon{
                        dead_time = DeadTime, revive_count = CommonDunCount
                        ,cost_revive_count = CostReviveCount
                    } = Dungeon,
                    Cd = data_dun_guard:get_revive_cd(CommonDunCount+1),
                    NextTime = DeadTime + Cd,
                    ReviveInfo = [{1, CostReviveCount+1, 0}, {9, CommonDunCount+1, NextTime}],
                    % ?ERR("61031 ~p ~p", [DeadTime, ReviveInfo]),
                    lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61031, [ReviveInfo]);
                _ ->
                    lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61031, [[]])
            end;
        _ ->
            lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61031, [[]])
    end;

%% 星辰副本-章节信息
handle(61032, Player, _) ->
    lib_dungeon_galaxy:get_chapter_info(Player);

%% 星辰副本-领取章节奖励
handle(61033, Player, [ChapterId, StarNum]) ->
    lib_dungeon_galaxy:galaxy_chapter_reward(Player, ChapterId, StarNum);

%% 星辰副本-进入下一章节
handle(61034, Player, _) ->
    lib_dungeon_galaxy:enter_next_chapter(Player);


% ########### 经验副本里程碑奖励 ############
handle(61045, Player, [DunId, WaveId]) ->
    #player_status{id = RoleId, sid = Sid, exp_dun_achieve = ExpDunAchieve, dungeon_record = DungeonRecs} = Player,
    case lists:keyfind({DunId, WaveId}, 1, ExpDunAchieve) of
        {_, 0} ->
            case data_dun_exp:get_achieve(WaveId) of
                FirstReward = [_|_] ->
                    DunRec = maps:get(DunId, DungeonRecs, []),
                    case lists:keyfind(?DUNGEON_REC_MAX_SCORE, 1, DunRec) of
                        {_, MaxScore} -> ok;
                        _             -> MaxScore = 0
                    end,
                    if WaveId =< MaxScore ->
                            DunType = data_dungeon:get_dun_type(DunId),
                            NewPlayer = lib_goods_api:send_reward(Player, FirstReward, exp_dun_achieve, DunType),
                            NewExpDunAchieve = lists:keystore({DunId, WaveId}, 1, ExpDunAchieve, {{DunId, WaveId}, 1}),
                            lib_dungeon_exp:db_update_exp_dun_achieve(RoleId, [{{DunId, WaveId}, 1}]),
                            {ok, Bin1} = pt_610:write(61045, [?SUCCESS]),
                            {ok, Bin2} = pt_610:write(61046, [DunId, [{WaveId, 1}]]),
                            lib_server_send:send_to_sid(Sid, <<Bin1/binary, Bin2/binary>>),
                            % SQL = io_lib:format(?SQL_EXP_DUN_REPLACE, [lists:concat(["(", ulists:list_to_string([RoleId, DunId, WaveId, 1], ","), ")"])]),
                            % db:execute(SQL),
                            {ok, NewPlayer#player_status{exp_dun_achieve = NewExpDunAchieve}};
                        true ->
                            lib_server_send:send_to_sid(Sid, pt_610, 61045, [?ERRCODE(args_error)]),
                            ok
                    end;
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_610, 61045, [?ERRCODE(data_error)]),
                    ok
            end;
        {_, 1} ->
            lib_server_send:send_to_sid(Sid, pt_610, 61045, [?ERRCODE(reward_is_got)]),
            ok;
        _ ->
            ok
    end;

%% 翻牌
handle(61047, Player, [Pos]) ->
    lib_dungeon_flop:dun_flop(Pos, Player);

%% 水晶宝藏稀有展示
handle(61048, Player, []) ->
    lib_dungeon_flop:rare_reward_info(Player);


%% 经验副本里程碑信息
handle(61049, Player, []) ->
    lib_dungeon_exp:get_achieve_info(Player);

%% 放置经验奖励查看&领取
handle(61050, Player, [Type = 0, _]) ->
    #player_status{sid = Sid, figure = #figure{lv = RoleLv}} = Player,
    OpenLv = data_module:get_module_open_lv(?MOD_DUNGEON, ?EXP_DROP_1),
    if
        RoleLv < OpenLv ->
            lib_server_send:send_to_sid(Sid, pt_610, 61050, [?FAIL, Type, 0, []]);
        true ->
            exp_dun_drop_api:query_exp_drop_reward_info(Player#player_status.id, Type)
    end;
handle(61050, Player, [Type = 1, _Arg]) ->
    #player_status{sid = Sid, figure = #figure{lv = RoleLv}} = Player,
    OpenLv = data_module:get_module_open_lv(?MOD_DUNGEON, ?EXP_DROP_1),
    if
        RoleLv < OpenLv ->
            lib_server_send:send_to_sid(Sid, pt_610, 61050, [?FAIL, Type, 0, []]);
        true ->
            % Hours = lib_pet_api:pet_life_skill_about_exp_drop_sum_time(Player),
            UpdateArgs = [{?MOD_PET, 0}],
            exp_dun_drop_api:get_exp_drop_reward(Player#player_status.id, Type, UpdateArgs)
            % exp_dun_drop_api:get_exp_drop_reward(Player#player_status.id, Type)
    end;

%% 快速挂机奖励领取
handle(61050, #player_status{sid = Sid, figure = #figure{lv = RoleLv}} = Player, [_Type = 2, Arg]) ->
    OpenLv = data_module:get_module_open_lv(?MOD_DUNGEON, ?EXP_DROP_2),
    if RoleLv >= OpenLv ->
            fast_exp_drop:get_fast_drop_reward(Player, Arg);
            % exp_dun_drop_api:get_fast_exp_drop_reward(Player#player_status.id, Arg);
        true ->
            lib_server_send:send_to_sid(Sid, pt_610, 61050, [?FAIL, _Type, 0, []])
    end;

%% 快速挂机信息查询
handle(61051, Player, _) ->
    #player_status{id = RoleId, sid = Sid, exp_dun_drop = ExpDunDrop} = Player,
    case ExpDunDrop of
        #role_exp_dun_drop{fast_drop_time = Time} -> ok;
        _ -> Time = 0
    end,
    MaxCount = fast_exp_drop:get_fast_drop_max_count(Player),
    DropedCount = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_EXP_DUN_FAST_DROP),
    lib_server_send:send_to_sid(Sid, pt_610, 61051, [MaxCount, DropedCount, Time]),
    ok;

%% 放置经验信息查询
handle(61052, Player, _) ->
    #player_status{id = RoleId, exp_dun_drop = ExpDunDrop} = Player,
    Now = utime:unixtime(),
    {LastTime, TimeLast, NewTimeLast} = exp_dun_drop_api:get_cache_time_last(ExpDunDrop, Now),
    exp_dun_drop_api:get_exp_dun_drop_info(RoleId, {Now, TimeLast, LastTime, NewTimeLast}),
    ok;

handle(61053, Player, _) ->
    #player_status{sid = Sid} = Player,
    ExpRatio = lib_player:get_exp_drop_ratio(Player),
    lib_server_send:send_to_sid(Sid, pt_610, 61053, [ExpRatio]),
    ok;

handle(61054, Player, [PageSize, PageNo]) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    exp_dun_wave_rank:get_wave_rank(RoleId, Sid, {PageSize, PageNo}),
    ok;

handle(61055, Player, []) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    exp_dun_wave_rank:get_top_wave_rank(RoleId, Sid),
    ok;

% ########### 获取评分信息 ###############
handle(61065, Player, [DunId]) ->
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #player_status{copy_id = CopyId, id = RoleId} = Player,
            mod_dungeon:get_dun_score_info(CopyId, RoleId, node());
        _ ->
            #player_status{sid = Sid, dungeon_record = DunRecs} = Player,
            DunRec = maps:get(DunId, DunRecs, []),
            case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, DunRec) of
                {_, ScoreL} when is_list(ScoreL) -> ScoreL;
                _ -> ScoreL = []
            end,
            case lists:keyfind(?DUNGEON_REC_DATA_1, 1, DunRec) of
                {_, Lv} -> ok;
                _       -> Lv = Player#player_status.figure#figure.lv
            end,
            case data_dungeon_grade:get_dungeon_grade(DunId, Lv) of
                #dungeon_grade{condition = Cons} -> ok;
                _ -> Cons = []
            end,
            ScoreL1 = lists:foldl(fun({ConfigId, _, _}, Acc) ->
                case lists:member(ConfigId, ScoreL) of
                    true -> [{ConfigId, ?DUN_SCORE_FINISH}|Acc];
                    _    -> [{ConfigId, ?DUN_SCORE_UNFIN}|Acc]
                end
             end, [], Cons),
            lib_server_send:send_to_sid(Sid, pt_610, 61065, [DunId, ScoreL1])
    end;

% ########### 批量扫荡展示界面 ############
handle(61066, Player, [DunType]) ->
    lib_dungeon_sweep:sweep_show_calc(DunType, Player);

% ############# 水晶(翻牌) ###############
%% Index 1免费|2额外一次|3全部
handle(61068, Player, [DunType, Index]) ->
    lib_dungeon_flop:dun_batch_flop(DunType, Index, Player);

handle(61069, Player, [DunId]) ->
    #player_status{id = RoleId, copy_id = CopyId} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #player_status{dungeon = #status_dungeon{dun_id = DunId}} = Player,
            case lib_dungeon:is_cluster_dungeon_by_dun_id(DunId) of
                true ->
                    clusters_node:apply_cast(mod_dungeon, get_mon_kill_info, [CopyId, {RoleId, node()}]);
                _ ->
                    mod_dungeon:get_mon_kill_info(CopyId, {RoleId, node()})
            end;
        false -> skip
    end;

handle(61070, Player, [DunId]) ->
    #player_status{id = RoleId, sid = Sid, copy_id = CopyId, dungeon_record = AllDunRecs} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            case lib_dungeon:is_cluster_dungeon_by_dun_id(DunId) of
                true ->
                    clusters_node:apply_cast(mod_dungeon, get_dun_rating_info, [CopyId, {RoleId, node()}]);
                _ ->
                    mod_dungeon:get_dun_rating_info(CopyId, {RoleId, node()})
            end;
        false ->
            DunRec = maps:get(DunId, AllDunRecs, []),
            case lists:keyfind(?DUNGEON_REC_RATING, 1, DunRec) of
                {_, RoleMaxRating} -> ok;
                _ -> RoleMaxRating = 0
            end,
            lib_server_send:send_to_sid(Sid, pt_610, 61070, [DunId, RoleMaxRating, 0])
    end;

%% 幻光副本
handle(61071, Player, _) ->
    #player_status{sid = Sid, id = RoleId, dungeon_record = DunRecs, role_dun_visus = RoleDunVisus} = Player,
    DunIds = data_dungeon:get_ids_by_type(?DUNGEON_TYPE_VISUS),
    {DailyPassCountList, DailySweepCountList} = lib_dungeon_visus:get_daily_count_list(DunIds),
    DailyPassCountList1 = lib_daily:get_count(RoleId, DailyPassCountList),
    DailySweepCountList1 = lib_counter:get_count(RoleId, DailySweepCountList),
    DailyPassCountList2 = [{DunIdX, CountX} || {{_, _, DunIdX}, CountX} <- DailyPassCountList1],
    DailySweepCountList2 = [{DunIdX1, SweepSignX1} || {{_, _, DunIdX1}, SweepSignX1} <- DailySweepCountList1],
    Data = lists:foldl(fun({DunId, Count}, Acc) ->
        DunRec = maps:get(DunId, DunRecs, []),
        case lists:keyfind(?DUNGEON_REC_MAX_SCORE, 1, DunRec) of
            {_, DunMaxWave} -> ok;
            _  -> DunMaxWave = 0
        end,
        case lists:keyfind(DunId, 1, RoleDunVisus) of
            {_, SweepWaves, Time, _} ->
                case utime:is_today_four(Time) of
                    true -> SweepWaves1 = SweepWaves;
                    _    -> SweepWaves1 = []
                end;
            _ -> SweepWaves1 = []
        end,
        %% 此标识为章节(副本id)奖励状态
        SweepSignX2 =
        case lib_dungeon_visus:check_dun_all_wave_pass(DunId, DunRec) of
            true ->
                case lists:keyfind(DunId, 1, DailySweepCountList2) of
                    {_, SweepSign} -> ?IF(SweepSign == 0, 1, 2);
                    _ -> 0
                end;
            _ -> 0
        end,
        Waves1 = lists:filter(fun(WaveId) -> not lists:member(WaveId, SweepWaves1) end, lists:seq(1, Count)),
        AllSweepWaves = Waves1 ++ SweepWaves1,
        [{DunId, DunMaxWave, SweepSignX2, AllSweepWaves}|Acc]
    end, [], DailyPassCountList2),
    {HighestDunId, HighestWave} = lib_dungeon_visus:get_last_highest_wave(RoleDunVisus),
    lib_server_send:send_to_sid(Sid, pt_610, 61071, [HighestDunId, HighestWave, Data]),
    ok;

handle(61072, Player, _) ->
    Res =
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #player_status{dungeon = #status_dungeon{dun_id = DunId}} = Player,
            case data_dungeon:get_dun(DunId) of
                #dun_cfg{type = DunType} when DunType == ?DUNGEON_TYPE_VISUS ->
                    false;
                _ ->
                    true
            end;
        _ ->
            true
    end,
    if
        Res == false ->
            lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61072, [?ERRCODE(err610_on_dungeon_cannot_operate), [], []]);
        true ->
            #player_status{id = RoleId, dungeon_record = DunRecs} = Player,
            DunIds = data_dungeon:get_ids_by_type(?DUNGEON_TYPE_VISUS),
            DunWaveRecs = lists:foldl(fun(DunId, Acc) ->
                DunRec = maps:get(DunId, DunRecs, []),
                case lists:keyfind(?DUNGEON_REC_MAX_SCORE, 1, DunRec) of
                    {_, MaxWave} -> MaxWave;
                    _            -> MaxWave = 0
                end,
                [{DunId, MaxWave}|Acc]
            end, [], DunIds),
            DunIdCountList = [{?MOD_DUNGEON, ?MOD_DUNGEON_PASS_LV, DunIdX} || DunIdX <- DunIds],
            DailyCountList1 = lib_daily:get_count(RoleId, DunIdCountList),
            DailyCountList2 = [{DunIdX1, DailyCount} || {{_, _, DunIdX1}, DailyCount} <- DailyCountList1],
            NewPlayer = lib_dungeon_visus:visus_dun_sweep(Player, DunWaveRecs, DailyCountList2),
            lib_activitycalen_api:role_success_end_activity(RoleId,?MOD_DUNGEON,?DUNGEON_TYPE_VISUS,1),
            {ok, NewPlayer}
    end;

%% 宠物副本里程碑奖励信息
handle(61073, Player, []) ->
    #player_status{sid = Sid, role_dun_pet = RoleDunPet} = Player,
    #role_dun_pet{reward_status = RewardStatus} = RoleDunPet,
    lib_server_send:send_to_sid(Sid, pt_610, 61073, [RewardStatus]),
    {ok, Player};

%% 领取宠物副本里程碑奖励(废弃)
handle(61074, Player, [_DunId]) ->
    % {ok, NewPlayer} = lib_dungeon_pet:receive_milestone_reward(Player, DunId),
    {ok, Player};

%% 宠物副本-全服排行
handle(61075, Player, [Type]) ->
    mod_dun_pet_rank:get_score_rank(Player#player_status.id, Type),
    {ok, Player};

%% 宠物副本-获取前后3名排行信息
handle(61076, Player, []) ->
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            mod_dun_pet_rank:get_real_time_score_rank(Player#player_status.id);
        _ -> %% TODO
            mod_dun_pet_rank:get_real_time_score_rank(Player#player_status.id)
    end,
    {ok, Player};

%% 宠物副本-获取场景内所有buff球信息
handle(61077, Player, []) ->
    lib_dungeon_pet:get_all_buff(Player),
    {ok, Player};

%% 宠物副本-触发buff球
handle(61078, Player, [BuffId, X, Y]) ->
    lib_dungeon_pet:pick_buff(Player, BuffId, X, Y),
    {ok, Player};

%% 宠物副本-查询副本日次数
handle(61084, Player, []) ->
    CountType = lib_dungeon_api:get_daily_buy_type(?DUNGEON_TYPE_PET, 12001),
    VipBuyCount = lib_daily:get_count(Player#player_status.id, ?MOD_DUNGEON, ?MOD_DUNGEON_BUY, CountType),
    case lib_daily:get_count(Player#player_status.id, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, ?DUNGEON_TYPE_PET) of
        Count when is_integer(Count) -> skip;
        _ -> Count = 0
    end,
    LimitCount = data_dungeon_pet:get_dun_pet_kv_cfg(daily_enter_count),
    LeftCount = max(VipBuyCount + LimitCount - Count, 0),
    lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61084, [LeftCount]),
    {ok, Player};


%% 守卫信标里程碑信息
handle(61081, Player, [DunId]) when DunId =/= 0 ->
    #player_status{sid = Sid, role_dun_guard = RoleDunGuard} = Player,
    WaveAchieve = data_dun_guard:get_dun_all_achieve_wave(DunId),
    DunWaves = lists:foldl(fun(Wave, Acc) ->
        case lists:keyfind({DunId, Wave}, 1, RoleDunGuard) of
            {_, WaveStatus} ->
                [{DunId, Wave, WaveStatus}|Acc];
            _ ->
                Acc
        end
    end, [], WaveAchieve),
    {ok, Bin} = pt_610:write(61081, [DunWaves]),
    lib_server_send:send_to_sid(Sid, Bin),
    ok;
handle(61081, Player, [_]) ->
    #player_status{sid = Sid, role_dun_guard = RoleDunGuard} = Player,
    DunIds = data_dungeon:get_ids_by_type(?DUNGEON_TYPE_GUARD),
    AllDunWaves = lists:foldl(fun(DunId, Acc) ->
        WaveAchieve = data_dun_guard:get_dun_all_achieve_wave(DunId),
        DunWaves = lists:foldl(fun(Wave, Acc1) ->
            case lists:keyfind({DunId, Wave}, 1, RoleDunGuard) of
                {_, WaveStatus} ->
                    [{DunId, Wave, WaveStatus}|Acc1];
                _ ->
                    Acc1
            end
        end, [], WaveAchieve),
        lists:append(DunWaves, Acc)
     end, [], DunIds),
    {ok, Bin} = pt_610:write(61081, [AllDunWaves]),
    lib_server_send:send_to_sid(Sid, Bin),
    ok;


handle(61082, Player, [DunId, Wave]) ->
    #player_status{id = RoleId, sid = Sid, role_dun_guard = RoleDunGuard} = Player,
    case lists:keyfind({DunId, Wave}, 1, RoleDunGuard) of
        {_, ?ACHIEVING} ->
            case data_dun_guard:get_achieve(DunId, Wave) of
                #base_dun_guard_achieve{rewards = Rewards} ->
                    NewPlayer0 = lib_goods_api:send_reward(Player, Rewards, dun_guard_achieve),
                    lib_server_send:send_to_sid(Sid, pt_610, 61082, [?SUCCESS, DunId, Wave]),
                    NewRoleDunGuard = lists:keystore({DunId, Wave}, 1, RoleDunGuard, {{DunId, Wave}, ?HAVE_REWARDED}),
                    db:execute(?REPLACE_INTO_ROLE_DUN_ACHIEVE, [RoleId, DunId, Wave, ?HAVE_REWARDED]),
                    NewPlayer = NewPlayer0#player_status{role_dun_guard = NewRoleDunGuard},
                    {ok, NewPlayer};
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_610, 61082, [?ERRCODE(data_error), DunId, Wave]),
                    ok
            end;
        {_, ?HAVE_REWARDED} ->
            lib_server_send:send_to_sid(Sid, pt_610, 61082, [?ERRCODE(reward_is_got), DunId, Wave]);
        _ ->
            lib_server_send:send_to_sid(Sid, pt_610, 61082, [?ERRCODE(err610_tower_dun_rewarded), DunId, Wave]),
            ok
    end;

%% 幻光副本-领取章节奖励
handle(61087, Player, [DunId]) ->
    #player_status{id = RoleId, sid = Sid, dungeon_record = DunRecs} = Player,
    DunRec = maps:get(DunId, DunRecs, []),
    IsPass = lib_dungeon_visus:check_dun_all_wave_pass(DunId, DunRec),
    if
        not IsPass ->
            lib_server_send:send_to_sid(Sid, pt_610, 61087, [?ERRCODE(err610_have_not_pass), DunId, 0]);
        true ->
            DunSweepSign = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUN_SWEEP_SIGN, DunId),
            if
                DunSweepSign == 0 -> %% 可领
                    lib_dungeon_visus:send_dun_achieve_rewards(Player, DunId);
                    % lib_server_send:send_to_sid(Sid, pt_610, 61087, [?SUCCESS]),
                true -> %% 已领
                    lib_server_send:send_to_sid(Sid, pt_610, 61087, [?ERRCODE(err610_have_sweeped), DunId, 0])
            end
    end;

%% 获取积分排行榜
handle(61088, Player, [0|_]) ->
    #player_status{id = RoleId} = Player,
    Score = lib_week:get_count(RoleId, ?MOD_DUNGEON, ?MOD_GOD_DUN_SCORE, ?DUNGEON_TYPE_GOD),
    god_dun_rank_local:get_score_rank(RoleId, Score),
    ok;

handle(61088, Player, [1|_]) ->
    #player_status{id = RoleId, figure = #figure{name = Name}} = Player,
    ServerId = config:get_server_id(),
    ZoneId = czone_api:env_get_zone_id(),
    ZoneId =/= undefined andalso begin
     Score = lib_week:get_count(RoleId, ?MOD_DUNGEON, ?MOD_GOD_DUN_SCORE, ?DUNGEON_TYPE_GOD),
     clusters_node:apply_cast(gen_server, cast, [god_dun_rank_mgr, {get_god_dun_score_rank, RoleId, Name, ServerId, ZoneId, Score}])
    end,
    ok;

%% 唤神副本积分商城
handle(61090, Player, _) ->
    lib_role_god_dun:get_role_god_shop(Player);

%% 唤神副本积分商城兑换
handle(61091, Player, [ShopId, Num]) ->
    case lib_role_god_dun:god_shop_exchange(Player, ShopId, Num) of
        {false, Errcode} ->
            lib_server_send:send_to_sid(Player#player_status.sid, pt_610, 61091, [Errcode, ShopId, Num]),
            ok;
        {true, NewPlayer} ->
            {ok, NewPlayer}
    end;


handle(61092, Player, [Wave]) ->
    #player_status{sid = Sid, copy_id = CopyId} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            gen_server:cast(CopyId, {get_god_dun_role_wave_score, Sid, Wave}),
            ok;
        _ ->
            lib_server_send:send_to_sid(Sid, pt_610, 61092, [0])
    end;

handle(61093, Player, [Wave]) ->
    #player_status{id = RoleId, copy_id = CopyId, dungeon = Dungeon,
        figure = #figure{name = Name, profile_photo_id = PhotoId}} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #status_dungeon{dun_id = DunId} = Dungeon,
            case data_dungeon:get_dun(DunId) of
                #dun_cfg{type = DunType} when DunType == ?DUNGEON_TYPE_GOD ->
                    ZoneId = czone_api:env_get_zone_id(),
                    ServerId = config:get_server_id(),
                    ServNum = config:get_server_num(),
                    ZoneId =/= undefined andalso gen_server:cast(CopyId, {get_god_dun_score, RoleId, Name, PhotoId, ZoneId, ServerId, ServNum, Wave}),
                    ok;
                _ ->
                    skip
            end;
        _ ->
            ok
    end;

%% 宝宝副本-放置塔
handle(61094, _Player, [_MonId]) ->
    % case lib_dungeon:is_on_dungeon(Player) of
    %     true ->
    %        lib_dungeon_child:create_tower(Player, MonId);
    %    _ ->
    %        ignore
    % end,
    ok;

%% 宝宝副本-清除放塔cd
handle(61095, _Player, [_MonId]) ->
    ok;
    % case lib_dungeon:is_on_dungeon(Player) of
    %     true ->
    %         % NewPlayer = lib_dungeon_child:clean_tower_cd(Player, MonId),
    %         {ok, Player};
    %     _ ->
    %         {ok, Player}
    % end;

%% 宝宝副本-扫荡副本
handle(61096, Player, []) ->
    NewPlayer = lib_dungeon_child:sweep_dun_child(Player),
    {ok, NewPlayer};

%% 宠物副本-日奖励查询/领取
handle(61098, Player, [Type]) ->
    case Type of
        1 ->
            mod_dun_pet_rank:get_daily_reward_status(Player#player_status.id);
        2 ->
            mod_dun_pet_rank:receive_daily_reward(Player#player_status.id);
        _ ->
            ok
    end,
    {ok, Player};

%% 宠物副本-是否首次进入
handle(61099, Player, [DunId]) ->
    #player_status{id = RoleId} = Player,
    Count   = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_FIRTS_ENTER, DunId),
    IsFirst =
    case Count > 0 of
        true -> 1;
        _    -> 0
    end,
    lib_server_send:send_to_uid(RoleId, pt_610, 61099, [DunId, IsFirst]),
    {ok, Player};

%% 宠物副本-助战宠物选择
handle(61101, Player, [DunId, PetList, IsEnter]) ->
    #player_status{sid = Sid, status_pet = StatusPet,
        dungeon = StatusDun
    } = Player,
    IsOnDunPet = case data_dungeon:get_dun_type(StatusDun#status_dungeon.dun_id) of
                     ?DUNGEON_TYPE_PET -> true;
                     _ -> false
                 end,
    case lib_dungeon:is_on_dungeon(Player) of
        %% 宠物副本中禁止切换助战宠物
        true when IsOnDunPet ->
            lib_server_send:send_to_sid(Sid, pt_611, 61101,
                [?ERRCODE(err610_cannot_choose_pet_on_dungeon), 0, [], 0]
            );
        _ ->
            %% 判断选择上限
            LimitFollow = case data_dungeon_pet:get_dun_pet_cfg(DunId) of
                              #dun_pet_next_dun_cfg{follow_num = TNum} -> TNum;
                              _ -> 0
                          end,
            CheckList = [
                {param, PetList, LimitFollow}, {check_same_slot, PetList}, {check_dun, DunId},
                {has_pet, PetList, StatusPet#status_pet.pets, StatusPet#status_pet.follow_pet}
            ],
            %% 如果选择列表为空，则不携带协战宠物，不需要判断检测
            case erlang:length(PetList) of
                0 ->
                    case lib_dungeon_pet:check_follow_pet([{check_dun, DunId}]) of
                        true ->
                            lib_dungeon_pet:choose_pet_assist(Player, DunId, PetList, IsEnter);
                        {false, Err} ->
                            lib_server_send:send_to_sid(Sid, pt_611, 61101, [Err, 0, [], 0])
                    end;
                _ ->
                    case lib_dungeon_pet:check_follow_pet(CheckList) of
                        true ->
                            lib_dungeon_pet:choose_pet_assist(Player, DunId, PetList, IsEnter);
                        {false, Err} ->
                            lib_server_send:send_to_sid(Sid, pt_611, 61101, [Err, 0, [], 0])
                    end
            end
    end;

%% 查询上次选择的助战宠物
handle(61102, Player, []) ->
    lib_dungeon_pet:get_pet_last_choose(Player);

%% 选择掉落奖励
handle(61112, Player, [DunId, Index]) ->
    #player_status{sid = Sid, dungeon = StatusDun} = Player,
    #status_dungeon{dun_id = NowDunId} = StatusDun,
    IsOnDunPet = case data_dungeon:get_dun_type(NowDunId) of
                     ?DUNGEON_TYPE_PET -> true;
                     _ -> false
                 end,
    case lib_dungeon:is_on_dungeon(Player) of
        %% 宠物副本中禁止选择奖励
        true when IsOnDunPet ->
            lib_server_send:send_to_sid(Sid, pt_611, 61112,
	            [?ERRCODE(err610_cannot_choose_reward_on_dungeon), 0, 0]
            );
        _ ->
            lib_dungeon_pet:choose_drop_reward(Player, DunId, Index)
    end;

%% 上次选择的掉落奖励
handle(61113, Player, []) ->
    lib_dungeon_pet:get_reward_last_choose(Player);

handle(61103, Player, []) ->
    #player_status{sid = Sid, dungeon = StatusDun, copy_id = CopyId} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            #status_dungeon{dun_id = DunId} = StatusDun,
            case data_dungeon:get_dun_type(DunId) of
                ?DUNGEON_TYPE_GUARD ->
                    clusters_node:apply_cast(mod_dungeon, dispatch_dun_event, [CopyId, {'quick_pass_next_dun', node(), Sid}]);
                    % mod_dungeon:dispatch_dun_event(CopyId, {'quick_pass_next_dun', Sid});
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_611, 61103, [?FAIL, 0])
            end;
        _ ->
            lib_server_send:send_to_sid(Sid, pt_611, 61103, [?FAIL, 0])
    end;

handle(61104, Player, []) ->
    #player_status{sid = Sid} = Player,
    Node = node(),
    guard_dun_assist_local:get_assist_rank(Node, Sid),
    ok;

handle(61105, Player, [DunId]) ->
    #player_status{sid = Sid} = Player,
    Node = node(),
    clusters_node:apply_cast(guard_dun_assist_mgr, get_guard_dun_pass_log, [Node, Sid, DunId]),
    ok;

handle(61106, Player, [DunId]) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    Count = lib_counter:get_count(RoleId, ?MOD_DUN_MULTI, 3, DunId),
    if Count > 0 ->
            lib_server_send:send_to_sid(Sid, pt_611, 61106, [?ERRCODE(reward_is_got), DunId]);
        true ->
            Node = node(),
            clusters_node:apply_cast(guard_dun_assist_mgr, get_guard_dun_pass_reward, [Node, RoleId, DunId])
    end,
    ok;

handle(61108, Player, [DunId]) ->
    #player_status{id = RoleId} = Player,
    Node = node(),
    if DunId == 0 ->
            AllDunIds = data_dungeon:get_ids_by_type(?DUNGEON_TYPE_GUARD),
            CountList = lib_counter:get_count(RoleId, [{?MOD_DUN_MULTI, 3, DunIdX} || DunIdX <- AllDunIds]),
            CountList1 = [{DunIdX1, CountX} || {{_, _, DunIdX1}, CountX} <- CountList],
            clusters_node:apply_cast(guard_dun_assist_mgr, query_guard_dun_pass_reward, [Node, RoleId, CountList1]);
        true ->
            Count = lib_counter:get_count(RoleId, ?MOD_DUN_MULTI, 2, DunId),
            CountList1 = [{DunId, Count}],
            clusters_node:apply_cast(guard_dun_assist_mgr, query_guard_dun_pass_reward, [Node, RoleId, CountList1])
    end,
    ok;

handle(61109, Player, [Msg]) ->
    #player_status{id = RoleId, sid = Sid, copy_id = CopyId, dungeon = StatusDun} = Player,
    if not is_list(Msg) ->
            lib_server_send:send_to_sid(Sid, pt_611, 61109, [?FAIL, #figure{}, Msg]);
        true ->
            case lib_dungeon:is_on_dungeon(Player) of
                true ->
                    #status_dungeon{dun_id = DunId} = StatusDun,
                    DunType = data_dungeon:get_dun_type(DunId),
                    if DunType == ?DUNGEON_TYPE_GUARD ->
                            Now = utime:unixtime(),
                            Ret =
                            case erlang:get(guard_team_chat_cd) of
                                undefined -> true;
                                LastTime  -> Now - LastTime >= 3
                            end,
                            if Ret == true ->
                                    mod_dungeon:dispatch_dun_event(CopyId, {'team_chat', Sid, RoleId, node(), Msg}),
                                    erlang:put(guard_team_chat_cd, Now);
                                true ->
                                    lib_server_send:send_to_sid(Sid, pt_611, 61109, [?ERRCODE(err610_is_cd), #figure{}, Msg])
                            end;
                        true ->
                            lib_server_send:send_to_sid(Sid, pt_611, 61109, [?FAIL, #figure{}, Msg])
                    end;
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_611, 61109, [?FAIL, #figure{}, Msg])
            end
    end,
    ok;

handle(61115, Player, []) ->
    #player_status{sid = Sid, id = RoleId, figure = #figure{vip = VipLv}} = Player,
    VipDunIds = data_dungeon:get_ids_by_type(?DUNGEON_TYPE_VIP),
    PriVal = lib_vip_api:get_vip_privilege(Player, ?VIP_DUN_SWEEP, 1),
    IsOnDungeon = lib_dungeon:is_on_dungeon(Player),
    if
        PriVal == 0 ->
            lib_server_send:send_to_sid(Sid, pt_611, 61115, [?ERRCODE(vip_limit), []]);
        IsOnDungeon ->
            lib_server_send:send_to_sid(Sid, pt_611, 61115, [?ERRCODE(err610_on_dungeon), []]);
        true ->
            AccessDunIds = lists:foldl(fun(DunId, Acc) ->
                case data_dungeon:get_dun(DunId) of
                    #dun_cfg{condition = Condition} ->
                        case lists:keyfind(vip, 1, Condition) of
                            {_, VipLimit} when VipLv >= VipLimit ->
                                [DunId|Acc];
                            _ -> Acc
                        end;
                    _ -> Acc
                end
             end, [], VipDunIds),
            CountDunIds = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, AccessDunIds),
            case lists:filter(fun({_, Count}) -> Count > 0 end, CountDunIds) of
                FilterDunIds = [_|_] ->
                    FilterDunIds1 = [DunIdX || {DunIdX, _} <- FilterDunIds],
                    {Rewards, FilterDunIds2} = lib_dungeon_vip:calc_sweep_rewards(Player, FilterDunIds1),
                    case Rewards of
                        [_|_] ->
                            Rewards1 = lib_goods_util:merge_same_goods(Rewards),
                            NewPlayer = lib_goods_api:send_reward(Player, Rewards1, dungeon_count_sweep_rewards, ?DUNGEON_TYPE_VIP),
                            lists:map(fun(DunIdX1) ->
                                lib_daily:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, DunIdX1),
                                lib_daily:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunIdX1),
                                lib_counter:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_SUCCESS, DunIdX1)
                             end, FilterDunIds2),
                            DunType = ?DUNGEON_TYPE_VIP,
                            DunCountList = [{DunIdX2, 1} || DunIdX2 <- FilterDunIds2],
                            lib_server_send:send_to_sid(Sid, pt_611, 61115, [?SUCCESS, Rewards1]),
                            {ok, NewPlayer1} = lib_dungeon_flop:start_batch_dun_flop(NewPlayer, DunType, DunCountList),
                            {ok, NewPlayer1};
                        _ ->
                            lib_server_send:send_to_sid(Sid, pt_611, 61115, [?ERRCODE(err610_dun_have_all_sweeped), []])
                    end;
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_611, 61115, [?ERRCODE(err610_today_not_pass), []])
            end
    end;

handle(61116, Player, [Start, Len]) ->
    #player_status{id = RoleId, sid = Sid, dungeon_record = DungeonRecs} = Player,
    if DungeonRecs == undefined ->
            NewPlayer = lib_dungeon:load_dungeon_record(Player);
        true ->
            NewPlayer = Player
    end,
    DunIds = data_tower_dun:get_all_diffcult_dun(),
    #player_status{dungeon_record = NewDungeonRecs} = NewPlayer,
    AllStar = lists:foldl(fun(DunId, AccStar) ->
        DunRecs = maps:get(DunId, NewDungeonRecs, []),
        case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, DunRecs) of
            {_, StarList} ->
                AccStar + length(StarList);
            _ -> AccStar
        end
    end, 0, DunIds),
    tower_dun_rank:get_tower_dun_rank(RoleId, Sid, Start, Len, AllStar),
    {ok, NewPlayer};

handle(61117, Player, [Start, Len]) ->
    #player_status{id = RoleId, sid = Sid, dungeon_record = DungeonRecs} = Player,
    if DungeonRecs == undefined ->
            NewPlayer = lib_dungeon:load_dungeon_record(Player);
        true ->
            NewPlayer = Player
    end,
    #player_status{dungeon_record = NewDungeonRecs} = NewPlayer,
    DunIds = data_dungeon:get_ids_by_type(?DUNGEON_TYPE_VISUS),
    {MaxDunId, MaxDunScore} = lists:foldl(fun(DunId, {AccDun, AccWave}) ->
        DunRecs = maps:get(DunId, NewDungeonRecs, []),
        case lists:keyfind(?DUNGEON_REC_MAX_SCORE, 1, DunRecs) of
            {_, MaxScore} ->
                if DunId > AccDun -> {DunId, MaxScore};
                    true -> {AccDun, AccWave}
                end;
            _ -> {AccDun, AccWave}
        end
    end, {0, 0}, DunIds),
    visus_dun_rank:get_visus_dun_rank(RoleId, Sid, Start, Len, {MaxDunId, MaxDunScore}),
    {ok, NewPlayer};

handle(61118, Player, []) ->
    #player_status{sid = Sid, tower_dun_star = TowerStarData} = Player,
    DataList = maps:to_list(TowerStarData),
    lib_server_send:send_to_sid(Sid, pt_611, 61118, [DataList]),
    ok;

handle(61119, Player, [Index]) ->
    #player_status{id = RoleId, sid = Sid, tower_dun_star = TowerStarData} = Player,
    State = maps:get(Index, TowerStarData, 0),
    if
        State == 0 ->
            lib_server_send:send_to_sid(Sid, pt_611, 61119, [?ERRCODE(err610_star_not_access), Index]);
        State == 2 ->
            lib_server_send:send_to_sid(Sid, pt_611, 61119, [?ERRCODE(reward_is_got), Index]);
        State == 1 ->
            case data_tower_dun:get_star_reward(Index) of
                {_Star, Rewards} ->
                    NewPlayer = lib_goods_api:send_reward(Player, Rewards, tower_star_reward),
                    NewTowerStarData = maps:put(Index, 2, TowerStarData),
                    lib_dungeon_tower:update_tower_star_data(RoleId, Index, 2),
                    NewPlayer1 = NewPlayer#player_status{tower_dun_star = NewTowerStarData},
                    lib_server_send:send_to_sid(Sid, pt_611, 61119, [?SUCCESS, Index]),
                    {ok, NewPlayer1};
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_611, 61119, [?FAIL, Index])
            end;
        true ->
            lib_server_send:send_to_sid(Sid, pt_611, 61119, [?FAIL, Index])
    end;

%% 爬塔困难副本获取恢复次数信息
handle(61121, Player, []) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    % lib_dungeon_tower:refresh_dun_count_state(RoleId),
    DungeonType = ?DUNGEON_TYPE_TOWER,
    CfgCount  = data_dungeon_special:get(DungeonType, guard_harddun_num),
    AftCount  = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, DungeonType),
    ResetTime = lib_counter:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUN_RESET_TIME, DungeonType),
    lib_server_send:send_to_sid(Sid, pt_611, 61121, [max(0, CfgCount - AftCount), ResetTime]),
    ok;

%% 宠物副本-查询扫荡奖励
handle(61123, Player, [DunId]) ->
    lib_dungeon_pet:get_sweep_reward(Player, DunId),
    ok;

%% 宠物副本-领取扫荡奖励
handle(61122, Player, [DunId]) ->
    {ok, NewPlayer} = lib_dungeon_pet:sweep_dungeon_pet(Player, DunId),
    {ok, NewPlayer};

%% 玩家落地+开场特效播放完
handle(61124, Player, _) ->
    #player_status{sid = Sid, copy_id = CopyId} = Player,
    case lib_dungeon:is_on_dungeon(Player) of
        true ->
            mod_dungeon:animation_notice(CopyId, Sid);
        false ->
            lib_server_send:send_to_sid(Sid, pt_611, 61124, [0, 0, 0, 0, 0, 0, 0, ?FAIL])
    end;

%% 新主线副本扫荡
handle(61125, Player, [DunId]) ->
    #player_status{id = RoleId, sid = Sid, dungeon_record = DunRecs} = Player,
    DunRec = maps:get(DunId, DunRecs, []),
    case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, DunRec) of
        {_, ScoreEventIds} ->
            Score = length(ScoreEventIds);
        _ -> Score = 0
    end,
    #dun_cfg{count_cond = CountCond, base_reward = BaseRewards} = data_dungeon:get_dun(DunId),
    if Score >= 3 ->
            case lists:keyfind(?DUN_COUNT_COND_DAILY, 1, CountCond) of
                {_, MaxNum} -> ok;
                _ -> MaxNum = 0
            end,
            CountType = lib_dungeon_api:get_daily_count_type(?DUNGEON_TYPE_MAIN_LINE, DunId),
            Count = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, CountType),
            if
                Count < MaxNum ->
                    BaseRewards1 = lib_goods_util:merge_same_goods(BaseRewards),
                    Player1 = lib_goods_api:send_reward(Player, BaseRewards, main_line_dun_sweep),
                    lib_daily:increment(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, CountType),
                    lib_server_send:send_to_sid(Sid, pt_611, 61125, [?SUCCESS, DunId, BaseRewards1]),
                    lib_activitycalen_api:success_finish_dungeon(RoleId, ?MOD_DUNGEON, ?DUNGEON_TYPE_MAIN_LINE, DunId),
                    lib_task_api:fin_dun_enter(RoleId,DunId),
                    {ok, Player1};
                true -> %% Count >= MaxNum
                    lib_server_send:send_to_sid(Sid, pt_611, 61125, [?ERRCODE(err610_challen_count_limit), DunId, []]),
                    ok
            end;
        true ->
            lib_server_send:send_to_sid(Sid, pt_611, 61125, [?ERRCODE(err610_not_sweep), DunId, []]),
            ok
    end;

handle(61126, Player, []) ->
    #player_status{id = RoleId, sid = Sid, dungeon_record = DunRecs} = Player,
    {ChangeCounts, Rewards} =
    lists:foldl(fun(DunId, {AccCount, AccRewards}) ->
        DunRec = maps:get(DunId, DunRecs, []),
        case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, DunRec) of
            {_, ScoreEventIds} ->
                Score = length(ScoreEventIds);
            _ -> Score = 0
        end,
        #dun_cfg{count_cond = CountCond, base_reward = BaseRewards} = data_dungeon:get_dun(DunId),
        if Score >= 3 ->
                case lists:keyfind(?DUN_COUNT_COND_DAILY, 1, CountCond) of
                    {_, MaxNum} -> ok;
                    _ -> MaxNum = 0
                end,
                CountType = lib_dungeon_api:get_daily_count_type(?DUNGEON_TYPE_MAIN_LINE, DunId),
                Count = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, CountType),
                if
                    Count < MaxNum ->
                        AccCount1   = [{{?MOD_DUNGEON, ?MOD_DUNGEON_ENTER, CountType}, MaxNum}|AccCount],
                        DunRewards  = [{GoodsType, GoodsId, round(MaxNum-Count)*GoodsNum} || {GoodsType, GoodsId, GoodsNum} <- BaseRewards],
                        % DunRewards1 = lib_goods_util:merge_same_goods(DunRewards),
                        lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_DUNGEON, ?DUNGEON_TYPE_MAIN_LINE, max(0, MaxNum-Count)),
                        AccRewards1 = [{DunId, DunRewards}|AccRewards],
                        {AccCount1, AccRewards1};
                    true ->
                        {AccCount, AccRewards}
                end;
            true -> {AccCount, AccRewards}
        end
    end, {[], []}, data_dungeon:get_ids_by_type(?DUNGEON_TYPE_MAIN_LINE)),
    Rewards1 = lists:flatten([DunRewardsX || {_DunIdX, DunRewardsX} <- Rewards]),
    Player1 = lib_goods_api:send_reward(Player, Rewards1, main_line_dun_sweep),
    lib_daily:set_count(RoleId, ChangeCounts),
    {ok, BinData} = pt_611:write(61126, [?SUCCESS, Rewards]),
    lib_server_send:send_to_sid(Sid, BinData),
    {ok, Player1};

handle(61127, Player, [DunId]) ->
    #player_status{sid = Sid, id = RoleId, dungeon_record = AllDunRecs} = Player,
    DunCfg = data_dungeon:get_dun(DunId),
    if
        not is_record(DunCfg, dun_cfg) ->
            lib_server_send:send_to_sid(Sid, pt_611, 61127, [?FAIL, DunId]),
            ok;
        true ->
            DunRec = maps:get(DunId, AllDunRecs, []),
            case lists:keyfind(?DUNGEON_REC_DATA, 1, DunRec) of
                {_, RewardState} ->
                    if RewardState =/= 0 ->
                            lib_server_send:send_to_sid(Sid, pt_611, 61127, [?ERRCODE(reward_is_got), DunId]),
                            ok;
                        true ->
                            #dun_cfg{first_reward = FirstReward} = DunCfg,
                            Player1 = lib_goods_api:send_reward(Player, FirstReward, dun_score_rewards),
                            AllDunRecs1 = lib_dungeon_main_line:get_dun_score_rewards(RoleId, AllDunRecs, DunRec, DunId),
                            Player2 = Player1#player_status{dungeon_record = AllDunRecs1},
                            lib_server_send:send_to_sid(Sid, pt_611, 61127, [?SUCCESS, DunId]),
                            {ok, Player2}
                    end;
                _ ->
                    case lists:keyfind(?DUNGEON_REC_MAX_STARS, 1, DunRec) of
                        {_, ScoreEventIds} -> ok;
                        _ -> ScoreEventIds = []
                    end,
                    MaxScore = length(ScoreEventIds),
                    if MaxScore < 3 ->
                            lib_server_send:send_to_sid(Sid, pt_611, 61127, [?ERRCODE(err610_dun_score_need_max), DunId]),
                            ok;
                        true ->
                            #dun_cfg{first_reward = FirstReward} = DunCfg,
                            Player1 = lib_goods_api:send_reward(Player, FirstReward, dun_score_rewards),
                            AllDunRecs1 = lib_dungeon_main_line:get_dun_score_rewards(RoleId, AllDunRecs, DunRec, DunId),
                            Player2 = Player1#player_status{dungeon_record = AllDunRecs1},
                            lib_server_send:send_to_sid(Sid, pt_611, 61127, [?SUCCESS, DunId]),
                            {ok, Player2}
                    end
            end
    end;

%% 爬塔副本今日是否已扫荡
handle(61128, Player, []) ->
    #player_status{id = RoleId, sid = Sid} = Player,
    DunType = ?DUNGEON_TYPE_TOWER,
    SweepSign = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUN_SWEEP_SIGN, DunType),
    lib_server_send:send_to_sid(Sid, pt_611, 61128, [SweepSign]),
    ok;

%% 爬塔副本今日扫荡
handle(61129, Player, []) ->
    #player_status{id = RoleId, sid = Sid, dungeon = StatusDungeon} = Player,
    DunType = ?DUNGEON_TYPE_TOWER,
    SweepSign = lib_daily:get_count(RoleId, ?MOD_DUNGEON, ?MOD_DUN_SWEEP_SIGN, DunType),
    if SweepSign == 0 ->
            #status_dungeon{dun_data = DunData} = StatusDungeon,
            case lists:keyfind(?DUNGEON_TYPE_TOWER, 1, DunData) of
                {_, MaxDunIds} -> ok;
                _ -> MaxDunIds = []
            end,
            case lib_dungeon_tower:get_sweep_dun(RoleId, DunType, MaxDunIds) of
                SweepDunIds = [_|_] ->
                    %% 日常
                    lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_DUNGEON, 4),
                    lib_dungeon_tower:sweep_tower_dun(Player, SweepDunIds);
                _ ->
                    lib_server_send:send_to_sid(Sid, pt_611, 61129, [?ERRCODE(err610_have_not_pass)]),
                    ok
            end;
        true ->
            lib_server_send:send_to_sid(Sid, pt_611, 61129, [?ERRCODE(err610_have_sweeped)]),
            ok
    end;

handle(61130, Player, []) ->
    lib_dungeon_exp:sweep_exp_dun(Player);

handle(_Cmd, _Player, _Data) ->
    {error, atom_to_list(?MODULE) ++ " no match"}.
