%%%-------------------------------------------------------------------
%%% @author liushl
%%% @doc
%%%     又是一个装备培养系统
%%% @end
%%%-------------------------------------------------------------------
-module(warsoul_logic).
-author("liushl").

-include("goods.hrl").
-include("server.hrl").
-include("def_goods.hrl").
-include("errcode.hrl").
-include("figure.hrl").
-include("warsoul.hrl").
-include("def_module.hrl").
-include("common.hrl").
-include("custom_act.hrl").
-include("rush_rank.hrl").
%% API
-export([
    login/1,                    %% 登陆初始化
    collect_goods/2,            %% 收集到战魂了
    decompose_return_stuff/2    %% 分解返还材料
]).

%% 玩家协议处理
-export([
    warsoul_wear/3,             %% 上阵
    warsoul_off/2,              %% 下阵
    warsoul_strength/4,         %% 强化
    warsoul_strength_back/3,    %% 强化回退
    warsoul_decompose/3,        %% 战魂分解
    warsoul_evolution/4,        %% 进化升星
    get_collect_info/1,         %% 图鉴
    get_collect_award/1,        %% 领取收集奖励
    unlock_pos/2,                %% 解锁位置
    calc_war_soul_on/1
]).

%% @doc 登陆初始化
login(Player) ->
    %% 加载收集信息
    SQL = io_lib:format(<<"SELECT goods_id FROM role_war_soul_collect WHERE role_id=~p">>, [Player#player_status.id]),
    AllCollect = db:get_all(SQL),
    WarSoul = #role_war_soul{
        collect         = lists:flatten(AllCollect)
    },
    %% 加载其他数据
    SQL2 = io_lib:format(<<"SELECT pos_list,collect_award FROM role_war_soul WHERE role_id=~p">>, [Player#player_status.id]),
    WarSoul1 =
    case db:get_row(SQL2) of
        [PosBin, CollectAward] ->
            WarSoul#role_war_soul{pos_list = util:bitstring_to_term(PosBin), collect_award = CollectAward};
        _ ->
            WarSoul
    end,
    %% 计算当前阵型
    Player1 = warsoul_api:update_warsoul_array(Player#player_status{role_war_soul = WarSoul1}),
    Player2 = warsoul_api:include_warsoul_attr(Player1),
    Player2.

%% @doc 获得物品时/进化时
%% 收集到战魂了
collect_goods(Player, []) ->
    Player;
collect_goods(Player, [{_, TypeId, _}|T]) ->
    collect_goods(Player, [{TypeId, 1}|T]);
collect_goods(Player, [{TypeId, _}|T]) ->
    case data_warsoul:get_war_soul_info(TypeId) of
        #base_war_soul_info{} ->
            NewPlayer = when_get_new_warsoul(Player, TypeId),
            collect_goods(NewPlayer, T);
        _ ->
            collect_goods(Player, T)
    end;
collect_goods(Player, [_|T]) ->
    collect_goods(Player, T).

when_get_new_warsoul(Player, GoodsId) ->
    #player_status{role_war_soul = RoleWarSoul, id = RoleId, figure = #figure{name = Name}} = Player,
    #role_war_soul{collect = Collect} = RoleWarSoul,
    case lists:member(GoodsId, Collect) of
        true  ->
            Player;
        false ->
            NewCollect = [GoodsId|Collect],
            NewRoleWarSoul = RoleWarSoul#role_war_soul{collect = NewCollect},
            SQL = io_lib:format(<<"REPLACE INTO role_war_soul_collect(role_id,goods_id) VALUES(~p,~p)">>, [RoleId, GoodsId]),
            goods_transaction:add_sql(SQL),
            lib_server_send:send_to_sid(Player#player_status.sid, pt_143, 14306, [GoodsId]),
            lib_log_api:log_war_soul_handbook(
                [RoleId, Name, GoodsId, length(NewCollect), utime:unixtime()]
            ),
            Player2 = Player#player_status{role_war_soul = NewRoleWarSoul},
            NewPlayer = custom_act_sellswords_resupply:warsoul_evolution(Player2, GoodsId),
            NewPlayer
    end.

%% @doc 分解返还材料
decompose_return_stuff(#goods{type = ?GOODS_TYPE_WAR_SOUL} = Goods, List) ->
    calc_return_stuff(Goods) ++ List;
decompose_return_stuff(_, List) -> List.

calc_return_stuff(#goods{color = Color} = Goods) ->
    Strength = warsoul_api:get_warsoul_strength_lv(Goods),
    Stuff = calc_strength_stuff(Color, Strength, []),
    lib_goods_util:merge_same_goods(Stuff).

calc_strength_stuff(_Color, 0, List) -> List;
calc_strength_stuff(Color, Lv, List) ->
    case data_warsoul:get_war_soul_strength(Color, Lv) of
        #base_war_soul_strength{cost = Cost} ->
            calc_strength_stuff(Color, Lv - 1, Cost ++ List);
        _ ->
            List
    end.

%%---------------------------------------------------------------------
%% @doc 上阵:同一类型的只能上阵一个
%%---------------------------------------------------------------------
warsoul_wear_check(Player, Pos, GoodsId) ->
    case common_check(GoodsId, ?GOODS_LOC_WAR_SOUL_BAG) of
        {false, Err} -> {false, Err};
        {ok, FromGoods, EquipConfig} ->
            RoleWarSoul   = Player#player_status.role_war_soul,
            IsCellOpen    = lists:member(Pos, RoleWarSoul#role_war_soul.pos_list),
            OldExistGoods = lib_goods_util:get_goods_by_cell(?GOODS_LOC_WAR_SOUL_EQUIP, Pos),
            AllWarSoul    = warsoul_api:get_all_warsoul_list(),
            IsSame        = check_any_same_type(AllWarSoul, FromGoods, OldExistGoods),
            if
                not (FromGoods#goods.subtype =:= ?GOODS_WARSOUL_EQUIPMENT) -> {false, ?ERRCODE(err143_cannot_wear)};
                not IsCellOpen -> {false, ?ERRCODE(err143_err143_pos_lock)};
                IsSame -> {false, ?ERRCODE(err143_same_warsoul)};
                true ->
                    {ok, FromGoods, EquipConfig, OldExistGoods}
            end
    end.

%% 战魂上阵
warsoul_wear(Player, Pos, GoodsId) ->
    case warsoul_wear_check(Player, Pos, GoodsId) of
        {false, Err} -> {false, Err};
        {ok, FromGoods, EquipConfig, OldExistGoods} ->
            %% 穿戴强制绑定
            goods_logic:put_goods_on(FromGoods, ?GOODS_LOC_WAR_SOUL_BAG, ?GOODS_LOC_WAR_SOUL_EQUIP, Pos, OldExistGoods),

            %% 如果有旧装备，则需要取消旧技能
            case is_record(OldExistGoods, goods) of
                true  ->
                    OldGoods = OldExistGoods#goods.goods_id,
                    case data_warsoul:get_war_soul_info(OldExistGoods#goods.goods_id) of
                        #base_war_soul_info{skill = DeleteSkill} ->
                            lib_skill_api:divide_passive_skill(DeleteSkill) =/= [] andalso
                                mod_scene_agent:update(Player, [{delete_passive_skill, DeleteSkill}]);
                        _ ->
                            ok
                    end;
                false ->
                    OldGoods = 0
            end,
            %% 上阵新技能
            #base_war_soul_info{skill = AddSkill} = EquipConfig,
            lib_skill_api:divide_passive_skill(AddSkill) =/= [] andalso
                mod_scene_agent:update(Player, [{passive_skill, AddSkill}]),
            %% 刷新一下阵型
            Player1 = warsoul_api:update_warsoul_array(Player),
            %% 刷新一下战力
            Player2 = warsoul_api:update_warsoul_power(Player1),
            #player_status{id = RoleId, figure = Figure} = Player2,
            {ColorList, SumStrenLv, SumStar} = calc_war_soul_on(RoleId),
            lib_achievement_api:war_soul_on_event(Player2, ColorList),
            lib_achievement_api:war_soul_up_event(Player2, SumStrenLv),
            lib_achievement_api:war_soul_star_event(Player2, SumStar),
            %% ssr战魂
            % F = fun(WarSoul, TSum) ->
            %    case WarSoul of
            %        {Color, Num} when Color >= 4 -> TSum + Num;
            %        _ -> TSum
            %    end end,
            % Sum = lists:foldl(F, 0, ColorList),
            % {ok, Player3} = lib_seven_days_goal:do_finish_task(Player2, ?MOD_WARSOUL, 1, Sum, true),
            #player_status{role_war_soul = NewRoleWarSoul} = Player2,
            #role_war_soul{attr = FinalAttr, extra_power = ExtraPower} = NewRoleWarSoul,
            Power = calc_attr_power(Player2, FinalAttr),
            SumPower = Power + ExtraPower,
            {ok, Player3} = lib_seven_days_goal:do_finish_task(Player2, ?MOD_WARSOUL, 1, SumPower, true),
            lib_log_api:log_war_soul_equip(
                [RoleId, Figure#figure.name, Pos, OldGoods, FromGoods#goods.goods_id, utime:unixtime()]
            ),
            ta_agent_fire:warsoul_equip(Player3, [1, Pos, OldGoods, EquipConfig, Player]),
            {ok, Player3}
    end.

calc_attr_power(Player, AttrList) ->
    Power = lib_player_attr:calc_attr_list_power(Player, AttrList),
    Power.

%% 判断是否上阵同类型的战魂
check_any_same_type(AllWarSoul, FromGoods, OldExistGoods) ->
    WearType = warsoul_api:get_warsoul_type(FromGoods),
    case is_record(OldExistGoods, goods) of
        true  ->
            case warsoul_api:get_warsoul_type(OldExistGoods) =:= WearType of
                true  ->
                    %% 是替换同类型的战魂，则认为没有冲突
                    false;
                false ->
                    lists:any(
                        fun(GoodsInfo) ->
                            warsoul_api:get_warsoul_type(GoodsInfo) =:= WearType
                        end, AllWarSoul
                    )
            end;
        false ->
            lists:any(
                fun(GoodsInfo) ->
                    warsoul_api:get_warsoul_type(GoodsInfo) =:= WearType
                end, AllWarSoul
            )
    end.

%% 判断阵位是否开启
check_cell_open(Player, Cell) ->
    CellCfg = data_warsoul:get_war_soul_unlock(Cell),
    check_cell_open_do(Player, CellCfg).
check_cell_open_do(_Player, []) -> true;
check_cell_open_do(Player, [{lv, Lv}|T]) ->
    case Player#player_status.figure#figure.lv >= Lv of
        true  -> check_cell_open_do(Player, T);
        false -> false
    end;
check_cell_open_do(Player, [{dun, DunId}|T]) ->
    DunFinish = lib_dungeon_api:check_ever_finish(Player#player_status.id, DunId),
    case DunFinish of
        true  -> check_cell_open_do(Player, T);
        false -> false
    end;
check_cell_open_do(_Player, _) -> false.
%%---------------------------------------------------------------------
%% @doc 下阵
%%---------------------------------------------------------------------
warsoul_off_check(_Player, GoodsId) ->
    case common_check(GoodsId, ?GOODS_LOC_WAR_SOUL_EQUIP) of
        {false, Err} -> {false, Err};
        {ok, FromGoods, _EquipConfig} ->
            CellNum = lib_goods_util:get_null_cell_num(?GOODS_LOC_WAR_SOUL_BAG),
            if
                CellNum =< 0 -> {false, ?ERRCODE(err143_warsoul_no_cell)};
                true ->
                    {ok, FromGoods}
            end
    end.
warsoul_off(Player, GoodsId) ->
    case warsoul_off_check(Player, GoodsId) of
        {false, Err} -> {false, Err};
        {ok, FromGoods} ->
            goods_logic:take_goods_off(FromGoods, ?GOODS_LOC_WAR_SOUL_BAG),
            case data_warsoul:get_war_soul_info(FromGoods#goods.goods_id) of
                #base_war_soul_info{skill = DeleteSkill} ->
                    lib_skill_api:divide_passive_skill(DeleteSkill) =/= [] andalso
                        mod_scene_agent:update(Player, [{delete_passive_skill, DeleteSkill}]);
                _ ->
                    ok
            end,
            %% 刷新一下阵型
            Player1 = warsoul_api:update_warsoul_array(Player),

            Player2 = warsoul_api:update_warsoul_power(Player1),

            {ColorList, SumStrenLv, SumStar} = calc_war_soul_on(Player#player_status.id),
            lib_achievement_api:war_soul_on_event(Player2, ColorList),
            lib_achievement_api:war_soul_up_event(Player2, SumStrenLv),
            lib_achievement_api:war_soul_star_event(Player2, SumStar),

            #player_status{role_war_soul = NewRoleWarSoul} = Player2,
            #role_war_soul{attr = FinalAttr, extra_power = ExtraPower} = NewRoleWarSoul,
            Power = calc_attr_power(Player2, FinalAttr),
            SumPower = Power + ExtraPower,
            {ok, Player3} = lib_seven_days_goal:do_finish_task(Player2, ?MOD_WARSOUL, 1, SumPower, true),

            {ok, Player3}
    end.

%%---------------------------------------------------------------------
%% @doc 强化
%%---------------------------------------------------------------------
warsoul_strength_check(Player, GoodsId, Location, Count) ->
    case common_check(GoodsId, Location) of
        {false, Err} -> {false, Err};
        {ok, GoodsInfo, EquipConfig} ->
            Lv = goods_extra_data:extra_data_get(GoodsInfo, ?GOODS_OTHER_KEY_WARSOUL_LV, 0),
            StrengthConfig = data_warsoul:get_war_soul_strength(GoodsInfo#goods.color, Lv + 1),
            #base_war_soul_info{strength_limit = Max} = EquipConfig,
            if
                not (GoodsInfo#goods.subtype =:= ?GOODS_WARSOUL_EQUIPMENT) -> {false, ?ERRCODE(err143_cannot_strength)};
                Lv >= Max -> {false, ?ERRCODE(err143_warsoul_max_lv)};
                not is_record(StrengthConfig, base_war_soul_strength) -> {false, ?ERRCODE(err143_warsoul_max_lv)};
                true ->
                    case calc_strength_cost(Player, Max, GoodsInfo#goods.color, Lv, 0, Count, []) of
                        {true, NextLv, Cost} ->
                            {ok, GoodsInfo, Cost, Lv, NextLv};
                        {false, Err} ->
                            {false, Err}
                    end
            end
    end.

%% 计算连续强化需要的材料
%% 达到满级了
calc_strength_cost(_Player, Max, _Color, Max, _Count, _MaxCount, TotalCost) ->
    {true, Max, TotalCost};
%% 强化5次了
calc_strength_cost(_Player, _Max, _Color, Lv, MaxCount, MaxCount, TotalCost) ->
    {true, Lv, TotalCost};
%% 升一级
calc_strength_cost(Player, Max, Color, Lv, Count, MaxCount, CostTemp) ->
    NextLv = Lv + 1,
    case data_warsoul:get_war_soul_strength(Color, NextLv) of
        #base_war_soul_strength{cost = Cost} ->
            TotalCost = lib_goods_util:merge_same_goods(CostTemp ++ Cost),
            case lib_goods_api:check_object_list(Player, TotalCost) of
                true  ->
                    calc_strength_cost(Player, Max, Color, NextLv, Count + 1, MaxCount, TotalCost);
                {false, _Error} when Count > 0 ->
                    %% 可以强化Count次，Count+1次的时候材料不足，那就允许强化到Lv
                    {true, Lv, CostTemp};
                {false, Error} ->
                    %% 一次都强化不了，直接返回错误
                    {false, Error}
            end;
        _ when Count > 0 ->
            %% 强化count次后找不到配置，应该是强化到满级了
            {true, Lv, CostTemp};
        _ ->
            %% 一次都强化不了，说明当前就是满级
            {false, ?ERRCODE(err143_warsoul_max_lv)}
    end.
%% 强化战魂
warsoul_strength(Player, GoodsId, Location, Count) ->
    case warsoul_strength_check(Player, GoodsId, Location, Count) of
        {false, Err} -> {false, Err};
        {ok, GoodsInfo, Cost, OldLv, NextLv} ->
            case lib_goods_api:cost_object_list(Player, Cost, warsoul_strength, "") of
                {false, Err, _} -> {false, Err};
                {true, Player1} ->
                    HistoryLv = goods_extra_data:extra_data_get(GoodsInfo, ?GOODS_OTHER_KEY_WARSOUL_HIS_LV, 0),
                    NewGoodsInfo = goods_extra_data:extra_data_update(GoodsInfo, [{?GOODS_OTHER_KEY_WARSOUL_LV, NextLv}]),
                    case NextLv > HistoryLv of
                        true ->
                            NewGoodsInfo1 = goods_extra_data:extra_data_update(NewGoodsInfo, [{?GOODS_OTHER_KEY_WARSOUL_HIS_LV, NextLv}]);
                        _ ->
                            NewGoodsInfo1 = NewGoodsInfo
                    end,
                    goods_logic:update_goods_info_extra([NewGoodsInfo1]),
                    Player2 = warsoul_api:update_warsoul_power(Player1),
                    #player_status{id = RoleId, figure = #figure{name = Name}
                        , role_war_soul = NewRoleWarSoul} = Player2,
                    
                    %% 强化达到整10，给一个传闻
                    CheckLv = NextLv div 10,
                    GoodsInfo#goods.color >= ?ORANGE
                        andalso (CheckLv > (OldLv div 10))
                        andalso lib_chat:send_TV({all}, ?MOD_WARSOUL, 1,
                        [Name, RoleId, GoodsInfo#goods.goods_id, CheckLv * 10]),
                    
                    lib_log_api:log_war_soul_strength(
                        [RoleId, Name, GoodsInfo#goods.id, GoodsInfo#goods.goods_id, util:term_to_bitstring(Cost),
                        lib_goods_api:get_currency(Player, ?GOODS_ID_WARSOUL),
                        lib_goods_api:get_currency(Player2, ?GOODS_ID_WARSOUL),
                        NextLv, utime:unixtime()]
                        ),
                    {_, SumStrenLv, _} = calc_war_soul_on(Player#player_status.id),
                    lib_achievement_api:war_soul_up_event(Player2, SumStrenLv),
                    %% 大于历史最高才触发
                    NextLv > HistoryLv andalso
                    custom_act_mobilize:update_mobilize_task(Player2, warsoul, max(0, NextLv - OldLv)),
                    lib_task_api:warsoul_strength(Player2,NextLv),
                    #role_war_soul{attr = FinalAttr, extra_power = ExtraPower} = NewRoleWarSoul,
                    Power = calc_attr_power(Player2, FinalAttr),
                    SumPower = Power + ExtraPower,
                    {ok, Player3} = lib_seven_days_goal:do_finish_task(Player2, ?MOD_WARSOUL, 1, SumPower, true),
                    {ok, Player3, NextLv}
            end
    end.

%% 升级回退
warsoul_strength_back(Player, GoodsId, Location) ->
    case common_check(GoodsId, Location) of
        {ok, GoodsInfo, _EquipmentConfig} ->
            Return = calc_return_stuff(GoodsInfo),
            case Return =/= [] of
                true  ->
                    NewGoodsInfo = goods_extra_data:extra_data_update(GoodsInfo, [{?GOODS_OTHER_KEY_WARSOUL_LV, 0}]),
                    goods_logic:update_goods_info_extra([NewGoodsInfo]),
                    Player1 = lib_goods_api:send_reward(Player, Return, warsoul_evolution),
                    Player2 = case Location =:= ?GOODS_LOC_WAR_SOUL_EQUIP of
                        true  ->
                            warsoul_api:update_warsoul_power(Player1);
                        false ->
                            Player1
                    end,
                    #player_status{id = RoleId, figure = #figure{name = Name}} = Player,
                    lib_log_api:log_war_soul_strength(
                        [RoleId, Name, GoodsInfo#goods.id, GoodsInfo#goods.goods_id, util:term_to_bitstring(Return),
                            lib_goods_api:get_currency(Player, ?GOODS_ID_WARSOUL),
                            lib_goods_api:get_currency(Player2, ?GOODS_ID_WARSOUL),
                            0, utime:unixtime()]
                    ),
                    {_, SumStrenLv, _} = calc_war_soul_on(Player#player_status.id),
                    lib_achievement_api:war_soul_up_event(Player2, SumStrenLv),
                    {ok, Player2};
                false ->
                    {false, ?ERRCODE(err143_nothing_to_back)}
            end;
        {false, Err} -> {false, Err}
    end.
%%---------------------------------------------------------------------
%% @doc 战魂分解
%%---------------------------------------------------------------------
warsoul_decompose(Player, Cost, GiveList) ->
    #player_status{id = RoleId, figure = #figure{name = Name}} = Player,
    lib_log_api:log_war_soul_del(
        [RoleId, Name, util:term_to_bitstring(Cost), util:term_to_bitstring(GiveList),
        lib_goods_api:get_currency(Player, ?GOODS_ID_WARSOUL), utime:unixtime()]
    ),
    ok.
%%---------------------------------------------------------------------
%% @doc 进化升星
%%---------------------------------------------------------------------
check_warsoul_evolution(_Player, MainGoodsId, Location, GoodsIds) ->
    case common_check(MainGoodsId, Location) of
        {ok, GoodsInfo, _WarSoulConfig} ->
            case data_warsoul:get_war_soul_evolution(GoodsInfo#goods.goods_id) of
                #base_war_soul_evolution{
                    base_cost = BaseCost,
                    extra_cost = ExtraCost,
                    to_goods_id = TargetGoodsId
                } ->
                    case data_warsoul:get_war_soul_info(TargetGoodsId) of
                        #base_war_soul_info{} = TargetWarSoul ->
                            %% 将物品对象id转为#goods{}
                            {CostList, Return} = format_goods(GoodsIds),
                            case check_cost_list(BaseCost ++ ExtraCost, CostList) of
                                true ->
                                    {true, TargetWarSoul, GoodsInfo, [{One, 1}||One <- CostList], Return};
                                {false, Error} ->
                                    {false, Error}
                            end;
                        _ ->
                            {false, ?MISSING_CONFIG}
                    end;
                _ ->
                    {false, ?ERRCODE(err143_cannot_evolution)}
            end;
        _ ->
            {false, ?ERRCODE(err150_no_goods)}
    end.

%% 战魂进化
warsoul_evolution(Player, MainGoodsId, Location, GoodsIds) ->
    case check_warsoul_evolution(Player, MainGoodsId, Location, GoodsIds) of
        {false, Err} ->
            {false, Err};
        {true, TargetWarSoul, FromGoods, CostList, Return} ->
            #base_war_soul_info{goods_id = TargetGoodsId, skill = AddSkill} = TargetWarSoul,
            NewGoodsInfo = lib_goods_util:get_new_goods(data_goods_type:get(TargetGoodsId)),
            NewGoodsInfo1 = NewGoodsInfo#goods{
                id = FromGoods#goods.id,
                player_id = FromGoods#goods.player_id,
                location = FromGoods#goods.location,
                cell = FromGoods#goods.cell,
                num = 1
            },
            %% 保留强化等级
            StrengthLv = warsoul_api:get_warsoul_strength_lv(FromGoods),
            NewGoodsInfo2 =
                case StrengthLv > 0 of
                    true  ->
                        goods_extra_data:extra_data_update(NewGoodsInfo1, [{?GOODS_OTHER_KEY_WARSOUL_LV, StrengthLv}]);
                    false ->
                        NewGoodsInfo1
                end,
            %% 消耗材料进化物品
            case goods_logic:update_goods_info([NewGoodsInfo2], CostList, warsoul_evolution) of
                {ok, _} ->
                    #player_status{id = RoleId, figure = #figure{name = Name}} = Player,
                    %% 更新场景的技能
                    %% 上阵新技能
                    lib_skill_api:divide_passive_skill(AddSkill) =/= [] andalso
                        mod_scene_agent:update(Player, [{passive_skill, AddSkill}]),
                    %% 返还材料
                    Player1 = case Return =/= [] of
                        true  -> lib_goods_api:send_reward(Player, Return, warsoul_evolution);
                        false -> Player
                    end,
                    lib_chat:send_TV({all}, ?MOD_WARSOUL, 2,
                        [Name, RoleId, FromGoods#goods.goods_id, TargetGoodsId]),
                    %% 判断图鉴收集
                    Player2 = when_get_new_warsoul(Player1, TargetGoodsId),

                    Player3 = warsoul_api:update_warsoul_power(Player2),
                    LogCost = [CostId || {#goods{goods_id = CostId}, _} <- CostList],
                    lib_log_api:log_war_soul_evolution(
                        [RoleId, Name, FromGoods#goods.id, FromGoods#goods.goods_id, TargetGoodsId,
                        util:term_to_bitstring(LogCost), util:term_to_bitstring(Return), utime:unixtime()]
                    ),
                    {_ColorList, _, SumStar} = calc_war_soul_on(Player#player_status.id),
                    lib_achievement_api:war_soul_up_event(Player3, SumStar),
                    #player_status{role_war_soul = NewRoleWarSoul} = Player3,
                    #role_war_soul{attr = FinalAttr, extra_power = ExtraPower} = NewRoleWarSoul,
                    Power = calc_attr_power(Player3, FinalAttr),
                    SumPower = Power + ExtraPower,
                    {ok, Player4} = lib_seven_days_goal:do_finish_task(Player3, ?MOD_WARSOUL, 1, SumPower, true),

                    ta_agent_fire:warsoul_equip(Player4, [2, NewGoodsInfo2#goods.cell, FromGoods#goods.goods_id, TargetWarSoul, Player]),
                    {ok, Player4};
                _ ->
                    {false, 0}
            end
    end.

%% 先判断固定消耗/后判断非固消耗
%% 将前端发过来的消耗列表减去配置，如果为空，则检查通过
check_cost_list([], []) ->
    true;
check_cost_list([], _) ->
    %% 需求材料满足条件，但是还有剩下的，也认为不符合条件
    {false, ?ERRCODE(err143_evolution_stuff_error)};
check_cost_list([{NeedNum, NeedGoods}|T], GoodsList) ->
    case del_goods(NeedNum, NeedGoods, GoodsList, []) of
        {false, Error} ->
            {false, Error};
        LeftGoodsList ->
            check_cost_list(T, LeftGoodsList)
    end.

%% 将符合要求的物品从原列表中删除
del_goods(0, _GoodsIds, CheckGoodsList, LeftGoodsList) ->
    %% 需要的物品是够的，则初步可以，返回剩下的材料
    CheckGoodsList ++ LeftGoodsList;
del_goods(_Num, _GoodsIds, [], _LeftGoodsList) ->
    %% 遍历一遍后，需要的材料不够，则直接结束检查
    {false, ?ERRCODE(err143_evolution_less_stuff)};
del_goods(Num, GoodsIds, [#goods{goods_id = GoodsId} = Goods|T], LeftGoodsList) ->
    case lists:member(GoodsId, GoodsIds) of
        true  ->
            del_goods(Num - 1, GoodsIds, T, LeftGoodsList);
        false ->
            del_goods(Num, GoodsIds, T, [Goods|LeftGoodsList])
    end.

format_goods(GoodsIds) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    lists:foldl(
        fun(Id, {Temp, TempReturn}) ->
            case lib_goods_api:get_goods_info(GoodsStatus, Id, ?GOODS_LOC_WAR_SOUL_BAG) of
                #goods{} = GoodsInfo ->

                    {[GoodsInfo|Temp], calc_return_stuff(GoodsInfo) ++ TempReturn};
                _ ->
                    {Temp, TempReturn}
            end
        end, {[], []}, GoodsIds
    ).

%%---------------------------------------------------------------------
%% @doc 图鉴
%%---------------------------------------------------------------------
%% 图鉴信息
get_collect_info(Player) ->
    #player_status{
        role_war_soul = #role_war_soul{collect = Collect, collect_award = CollectAward}
    } = Player,
    [CollectAward, Collect].

%% 领取收集奖励
get_collect_award(Player) ->
    #player_status{role_war_soul = RoleWarSoul, id = RoleId} = Player,
    #role_war_soul{collect = Collect, collect_award = CollectAward} = RoleWarSoul,
    CollectNum = length(Collect),
    case get_next_lv(CollectAward, data_warsoul:get_all_war_soul_collect()) of
        false ->
            {false, ?ERRCODE(err143_collect_max)};
        NextLv when NextLv > CollectNum ->
            {false, ?ERRCODE(err143_collect_condition)};
        NextLv ->
            NewRoleWarSoul = RoleWarSoul#role_war_soul{collect_award = NextLv},
            db_save_role_warsoul(RoleId, NewRoleWarSoul),
            Player1 = Player#player_status{role_war_soul = NewRoleWarSoul},
            Award = data_warsoul:get_war_soul_collect(NextLv),
            Player2 = lib_goods_api:send_reward(Player1, Award, warsoul_collect_award),
            {true, Player2, NextLv}
    end.

get_next_lv(NowLv, [Lv|_]) when Lv > NowLv -> Lv;
get_next_lv(NowLv, [_|T]) -> get_next_lv(NowLv, T);
get_next_lv(_NowLv, []) -> false.

%%---------------------------------------------------------------------
%% @doc 解锁位置
%%---------------------------------------------------------------------
unlock_pos(Player, Pos) ->
    #player_status{role_war_soul = RoleWarSoul, id = RoleId} = Player,
    #role_war_soul{pos_list = PosList} = RoleWarSoul,
    IsCellOpen    = check_cell_open(Player, Pos),
    AlreadyUnlock = lists:member(Pos, PosList),
    MaxPos        = data_warsoul:get_max_pos(),
    if
        Pos > MaxPos -> {false, 0};
        AlreadyUnlock -> {false, ?ERRCODE(err143_err143_pos_unlock)};
        not IsCellOpen -> {false, ?ERRCODE(err143_pos_not_open)};
        true ->
            NewRoleWarSoul = RoleWarSoul#role_war_soul{pos_list = [Pos|PosList]},
            db_save_role_warsoul(RoleId, NewRoleWarSoul),
            NewPlayer = Player#player_status{role_war_soul = NewRoleWarSoul},
            {ok, NewPlayer}
    end.
%%---------------------------------------------------------------------
%% @doc Internal Function
%%---------------------------------------------------------------------
common_check(GoodsId, Location) ->
    case lib_goods_api:get_goods_info(GoodsId, Location) of
        #goods{goods_id = GoodsTypeId} = GoodsInfo ->
            case data_warsoul:get_war_soul_info(GoodsTypeId) of
                #base_war_soul_info{} = EquipmentConfig ->
                    {ok, GoodsInfo, EquipmentConfig};
                _ ->
                    {false, ?MISSING_CONFIG}
            end;
        _ ->
            {false, ?ERRCODE(err152_not_exist)}
    end.

db_save_role_warsoul(RoleId, RoleWarSoul) ->
    #role_war_soul{collect_award = CollectAward, pos_list = PosList} = RoleWarSoul,
    SQL = io_lib:format(<<"REPLACE INTO role_war_soul(`role_id`,`pos_list`,`collect_award`) VALUES(~p,'~ts',~p)">>,
        [RoleId, util:term_to_bitstring(PosList), CollectAward]),
    db:execute(SQL).

%% 计算上阵xx个xx品质战魂
%% return - { [{color, Num}...], SumStrenLv, SumStar }
calc_war_soul_on(RoleId) ->
    GoodsStatus = lib_goods_do:get_goods_status(),
    List = lib_goods_util:get_goods_list(RoleId, ?GOODS_LOC_WAR_SOUL_EQUIP, GoodsStatus#goods_status.dict),
    F = fun(#goods{goods_id = GoodsTypeId, color = Color} = GoodsInfo, {TList, TSumLv, TSumStar}) ->
        Lv = warsoul_api:get_warsoul_strength_lv(GoodsInfo),
        case data_warsoul:get_war_soul_info(GoodsTypeId) of
            #base_war_soul_info{star = Star} -> ok;
            _ -> Star = 0
        end,
        TList1 = case lists:keyfind(Color, 1, TList) of
                     {_, Num} -> lists:keystore(Color, 1, TList, {Color, Num + 1});
                     _ -> lists:keystore(Color, 1, TList, {Color, 1})
                 end,
        {TList1, TSumLv + Lv, TSumStar + Star}
        end,
    lists:foldl(F, {[], 0, 0}, List).