%%%===================================================================
%%% @author zmh
%%% @doc 灵能系统
%%% @end
%%%===================================================================
-module(lib_role_nucleon).
-include("server.hrl").
-include("predefine.hrl").
-include("scene.hrl").
-include("goods.hrl").
-include("def_goods.hrl").
-include("role_nucleon.hrl").
-include("def_module.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("common.hrl").
-include("errcode.hrl").
-include("figure.hrl").
-include("skill.hrl").
-include("rec_offline.hrl").
-compile(export_all).

-export([
	login/1,                %%登陆
	get_pane_info/1,        %%获取抽奖面板数据
	equip_armor/2,          %%穿
	resolve_armor/2,        %%分解
	nucleon_pos_lv_up/4,    %%槽位升级
	nucleon_pos_grade_up/2,
	armor_grade_up/3,        %%装甲突破
	do_nucleon_rock/3,       %%抽奖
	nucleon_section_up/2,    %%觉醒
	nucleon_recast_attr/2,   %%洗练
	get_nucleon_attr/1,
	count_nucleon_attr/1,
	handle_event/2,
	get_nucleon_lv/1,		 %% 获得灵能等级
	zero_time/1,             %%凌晨
	get_skills/1,            %%技能汇总
	get_nucleon_passive_skill/1, %%获得被动技能
	check_have_learn_skill/2,
	calc_power/3,
	nucleon_exchange_goods/3,
	charge_power/1
	]).

handle_event(Status, #event_callback{type_id = ?EVENT_ZERO_CLOCK}) ->
    NStatus = zero_time(Status),
    {ok, NStatus};
handle_event(Status, _) ->
    {ok, Status}.

%%上线
login(Status)->
	#player_status{id=RoleID,figure=Figure}=Status,
	NucleonHoles = load_nucleon_hole(RoleID),
	RoleNucleon = case db:get_row(io_lib:format(?SQL_ROLE_NUCLEON_GET,[RoleID])) of
		[Lv,Exp,ONormal,NTime,NFirst,NState,OSpecial,STime,SFirst,EState,OReTime]->
			{Normal,Special,ReTime} = case utime:is_today(OReTime) of
				true->
					{ONormal,OSpecial,OReTime};
				_->
					{0,0,utime:unixtime()}
			end,
			#role_nucleon{
				lv=Lv,exp=Exp,holes=NucleonHoles,
				normal=Normal,ntime=NTime,
				nfirst=NFirst,nstate=util:to_term(NState),
				special=Special,stime=STime,
				sfirst=SFirst,estate=util:to_term(EState),
				rtime=ReTime};
		_->
			#role_nucleon{holes=NucleonHoles,rtime=utime:unixtime()}
	end,
	NRoleNucleon = fix_rule_state(RoleNucleon),
	NFigure = Figure#figure{nucleon_lv=NRoleNucleon#role_nucleon.lv},
	Status0 = Status#player_status{role_nucleon=NRoleNucleon,figure=NFigure},
	Status1 = count_equip_attr(Status0),
	NStatus = count_nucleon_attr(Status1),
	NStatus.

load_nucleon_hole(RoleID)->
	Sql = io_lib:format(?SQL_PLAYER_NUCLEON_GET, [RoleID]),
	case db:get_all(Sql) of
		[] ->
			init_nucleon_hole([4,5,6,7],[]);
        Holes0 when is_list(Holes0) ->
            Holes1 = make_nucleon_hole(Holes0,[]),
            fix_nucleon_hole(Holes1,[4,5,6,7]);
        _ ->
        	init_nucleon_hole([4,5,6,7],[])
    end.

init_nucleon_hole([],Holes)->
	Holes;
init_nucleon_hole([H|T],Holes)->
	Hole = #nucleon_hole{
		pos = H,
		grade = 1,
		lv = 1
	},
	init_nucleon_hole(T,[Hole|Holes]).

%%数据拼接
make_nucleon_hole([],NucleonHoles)->
	NucleonHoles;
make_nucleon_hole([[Pos,Grade,Lv,Exp,SkillId,SkillLv,SecLv,Attrs0]|T],NucleonHoles)->
	Attrs = util:to_term(Attrs0),
	Hole = #nucleon_hole{
		pos = Pos,
		grade = Grade,
		lv = Lv,
		exp = Exp,
		skill = SkillId,
		skill_lv = SkillLv,
		sec_lv = SecLv,
		attrs = Attrs
	},
	make_nucleon_hole(T,[Hole|NucleonHoles]).

fix_nucleon_hole(Holes,[])->
	Holes;
fix_nucleon_hole(Holes,[H|T])->
	case lists:keymember(H,#nucleon_hole.pos,Holes) of
		true->
			fix_nucleon_hole(Holes,T);
		_->
			#nucleon_recast_base{
				attrs  = Attrs
			}=data_nucleon:nucleon_recast(max(H-?MODIY_VALUE,1),1),
			Hole = #nucleon_hole{
				pos = H,
				grade = 1,
				lv = 1,
				attrs = Attrs
			},
			fix_nucleon_hole([Hole|Holes],T)
	end.

calc_power(Status, AttrPower, BaseAttr) ->
	case Status#player_status.role_nucleon of
		#role_nucleon{attrs = Attrs} = RoleNucleon ->
			Skills = get_skills(Status),
            RoleLv = Status#player_status.figure#figure.lv,
			{_SKillAttr,SPower}  = lib_skill_attr:get_passive_skill_attr_and_power(Skills, RoleLv),
			PartialAttr = attr_conv:to_attr_record(Attrs),
			Power = lib_player_attr:calc_attr_power_partial(AttrPower, BaseAttr, PartialAttr) + SPower,
			{Status#player_status{role_nucleon = RoleNucleon#role_nucleon{power = Power}}, SPower};
		_ ->
			{Status, 0}
	end.

get_nucleon_power(Player) ->
	case Player#player_status.role_nucleon of
		#role_nucleon{power = Power} -> Power;
		_ -> 0
	end.

%%充能
charge_power(Status)->
	#player_status{
		id=RoleID,
		role_nucleon=RoleNucleon
	}=Status,
	#role_nucleon{
		lv = Lv,
		exp = Exp
	}=RoleNucleon,
	NextLv = Lv+1,
	Config = data_nucleon:nucleon_title(NextLv),
	CKList = [
    	{check_open,Status},
    	{check_max_title,Config},
    	{check_exp,Exp,Config}
    ],
    case util:check_lists(?MODULE,CKList) of
        true->
        	#nucleon_title_base{
        		cost = Cost,
        		exp  = Max,
        		rate = Rate
        	}=Config,
        	[NExp,NStatus0,Reports] = do_charge(Exp,Max,Cost,Rate,Status,[]),
        	case Reports /= [] of
        		true->
        			NRoleNucleon = RoleNucleon#role_nucleon{exp=NExp},
        			NStatus = NStatus0#player_status{role_nucleon=NRoleNucleon},
        			save_role_nucleon(RoleID,NRoleNucleon),
        			{ok,[Reports,NStatus]};
        		_->
        			{false,?GOODS_NOT_ENOUGH}
        	end;
        {false,Err}->
        	{false,Err}
    end.

do_charge(Exp,Max,_Cost,_Rate,NStatus,Reports) when Exp>=Max->
	[Max,NStatus,Reports];
do_charge(Exp,Max,Cost,Rate,Status,Reports)->
	case lib_goods_api:cost_object_list_with_check(Status, Cost, role_nucleon, ["nucleon charge power"]) of
        {true,NStatus,_}->
            case urand:rand(1,10000)=<Rate of
            	true->
            		Add = 2*data_nucleon:get(nucleon_charge),
            		do_charge(Exp+Add,Max,Cost,Rate,NStatus,[{1,Add}|Reports]);
            	_->
            		Add = data_nucleon:get(nucleon_charge),
            		do_charge(Exp+Add,Max,Cost,Rate,NStatus,[{0,Add}|Reports])
            end;
		{false,_Err,_}->
    		[Exp,Status,Reports]
    end.

%%激活阶位
active_nucleon_title(Status)->
	#player_status{
		id=RoleID,
		figure = Figure,
		role_nucleon=RoleNucleon
	}=Status,
	#role_nucleon{
		lv = Lv,
		exp = Exp
	}=RoleNucleon,
	NextLv = Lv+1,
	Config = data_nucleon:nucleon_title(NextLv),
	CKList = [
    	{check_open,Status},
    	{check_max_title,Config},
    	{check_active_title,Status,Exp,Config}
    ],
    case util:check_lists(?MODULE,CKList) of
        true->
        	NRoleNucleon = RoleNucleon#role_nucleon{lv=NextLv,exp=0},
        	NStatus = Status#player_status{role_nucleon=NRoleNucleon,figure=Figure#figure{nucleon_lv=NextLv}},
        	save_role_nucleon(RoleID,NRoleNucleon),
        	lib_log_api:log_nucleon_lv(RoleID,Figure#figure.name,Lv,NextLv),
        	{ok,[NextLv,NStatus]};
        {false,Err}->
        	{false,Err}
    end.

%%穿装甲
equip_armor(Uid,Status)->
	#player_status{
		id=RoleID,
		figure=Figure
	}=Status,
	#figure{name=RName}=Figure,
    GoodsStatus = lib_goods_do:get_goods_status(),
    #goods_status{dict = Dict} = GoodsStatus,
    LocBag = ?GOODS_LOC_ARMOR_BAG,
    LocEquip = ?GOODS_LOC_ARMOR_EQUIP,
    InGoodsInfo = lib_goods_util:get_goods(Uid,Dict,LocBag), %%需要穿戴的道具
    case InGoodsInfo of
        #goods{subtype=Pos,goods_id=IGoods,color = NewColor}->
        	skip;
        _->
            Pos = 0,IGoods=0,NewColor = 0
    end,
    OutGoodsInfo = lib_role_nucleon:get_equip_bypos(Pos,GoodsStatus),
    case OutGoodsInfo of
        #goods{goods_id=OGoods, color = OldColor}->
        	skip;
        _->
            OGoods=0, OldColor = 0
    end,
    CKList = [
    	{check_open,Status},
    	{check_goods,InGoodsInfo}
    ],
    case util:check_lists(?MODULE,CKList) of
        true->
            F = fun() ->
                ok = lib_goods_dict:start_dict(),
	            case is_record(OutGoodsInfo, goods) of
	                true ->
	                    [_NewOutGoodsInfo, GoodsStatus1]  = goods_logic:change_goods_location(OutGoodsInfo, LocBag, 0, GoodsStatus),
	                    [_NewInGoodsInfo, NewGoodsStatus1] = goods_logic:change_goods_location(InGoodsInfo, LocEquip, Pos, GoodsStatus1);
	                false ->
	                    [_NewInGoodsInfo, NewGoodsStatus1] = goods_logic:change_goods_location(InGoodsInfo, LocEquip, Pos, GoodsStatus)
	            end,
	            #goods_status{
	                dict = Dict0
	            } = NewGoodsStatus1,
	            {NewGoodsDict, GoodsL0} = lib_goods_dict:handle_dict_and_notify(Dict0),
	            NewGoodsStatus2 = NewGoodsStatus1#goods_status{
	                dict = NewGoodsDict
	            },
	            {ok,NewGoodsStatus2,GoodsL0}
	        end,
	        case goods_transaction:transaction(F) of
            	{ok,NewGoodsStatus,GoodsL}->
		            lib_goods_do:set_goods_status(NewGoodsStatus),
		            lib_goods_api:notify_client_num(RoleID, [InGoodsInfo#goods{num=0}]),
		            lib_goods_api:notify_client(RoleID, GoodsL, nucleon_equip),

		            NStatus1 = active_hole(InGoodsInfo,Status),
					NStatus = count_equip_attr(NStatus1),

		            handle_achievement(NStatus),
					lib_log_api:log_nucleon_equip(RoleID,RName,0,Pos,OGoods,IGoods),
		            %% 数据上报
		            #role_nucleon{holes = NucleonHoles} = NStatus#player_status.role_nucleon,
		            NucHole = lists:keyfind(Pos,#nucleon_hole.pos,NucleonHoles),
		            case NucHole of
			            #nucleon_hole{lv = LevelPos}-> skip;
			            _ ->  LevelPos = 0
		            end,
		            case data_nucleon:nucleon_equip(OGoods) of
			            #nucleon_equip_base{star = OldStar} -> ok;
						_ -> OldStar = 0
		            end,
		            case data_nucleon:nucleon_equip(IGoods) of
			            #nucleon_equip_base{star = NewStar} -> ok;
			            _ -> NewStar = 0
		            end,
		            OptionName = case OGoods of
									 0 -> "穿戴";
									 _ -> "替换"
		                         end,
		            UpInfo = [Pos, LevelPos, OptionName, OGoods, IGoods, OldColor, NewColor,
			            OldStar, NewStar],
		            {ok,NStatus, UpInfo};
		        _Reason->
                    ?INFO("~p ~p mod_goods equip_armor:~p", [?MODULE, ?LINE, _Reason]),
                    {false,?ERRCODE(fail)}
            end;
        {false,Err}->
            {false,Err}
    end.

handle_achievement(Player) ->
	GoodsStatus = lib_goods_do:get_goods_status(),
	GoodList = lib_goods_util:get_goods_list(
		Player#player_status.id, ?GOODS_LOC_ARMOR_EQUIP, GoodsStatus#goods_status.dict
	),
	F = fun(#goods{color = Color}, TList) ->
		case lists:keyfind(Color, 1, TList) of
			{_, Num} -> lists:keystore(Color, 1, TList, {Color, Num + 1});
			_ -> lists:keystore(Color, 1, TList, {Color, 1})
		end end,
	SuitList = lists:foldl(F, [], GoodList),
	lib_achievement_api:nucleon_suit_event(Player, SuitList),
	ok.

%%灵能装甲 分解
resolve_armor(UidList,Status)->
	#player_status{
		id=RoleID,
		figure=#figure{name=Name}
	}=Status,
	GoodsStatus = lib_goods_do:get_goods_status(),
    #goods_status{dict = BagDicts} = GoodsStatus,
	LocBag = ?GOODS_LOC_ARMOR_BAG,
	NucleonDict   = lib_goods_util:get_location_goods(BagDicts, LocBag),
	Datas  = dict:to_list(NucleonDict),
    NewGoodsList = fix_resolve(Datas,UidList,[]),
    case length(NewGoodsList)>=1 of
        true->
            F = fun() ->
                ok = lib_goods_dict:start_dict(),
                {ok, NGoodsStatus0} = goods_del:delete_goods_list(GoodsStatus, NewGoodsList),
                {Dict, GoodsL}  = lib_goods_dict:handle_dict_and_notify(NGoodsStatus0#goods_status.dict),
                NGoodsStatus1 = NGoodsStatus0#goods_status{dict = Dict},
                {ok, NGoodsStatus1, GoodsL}
            end,
            case goods_transaction:transaction(F) of
                {ok, NGoodsStatus,UpdateGoodsList} ->
                    lib_goods_api:notify_client(RoleID, UpdateGoodsList, nucleon_equip),
                    lib_goods_do:set_goods_status(NGoodsStatus),
                    [Gain0,Cost] = calc_resolve_gain(UpdateGoodsList,[],[]),
					% lib_goods_api:log_cost(RoleID,nucleon_resolve,Cost),
					Gain = util:combine_list(Gain0,1),
					Produce = #produce{type=nucleon_resolve,reward=Gain},
					lib_goods_api:send_reward_with_mail(Status, Produce, ?MOD_NUCLEON),
					lib_log_api:log_nucleon_resolve(RoleID,Name,Gain,Cost),
	        		{ok,Gain};
                _Reason->
                    ?INFO("~p ~p mod_goods nucleon_equip:~p", [?MODULE, ?LINE, _Reason]),
                    {false,?ERRCODE(err139_reslove_fail)}
            end;
        _->
            {false,?ERRCODE(err139_reslove_fail)}
    end.


%%灵能槽位升级
nucleon_pos_lv_up(AutoBuy,AutoLv,Pos,Status)->
	#player_status{
		id = RoleID,
		figure = #figure{name=Name},
		role_nucleon = RoleNucleon
	}=Status,
	#role_nucleon{holes=NucleonHoles}=RoleNucleon,
	NucHole = lists:keyfind(Pos,#nucleon_hole.pos,NucleonHoles),
	case NucHole of
		#nucleon_hole{lv=PosLv}->
			skip;
		_->
			PosLv = 0
	end,
	Config = data_nucleon:nucleon_lv(PosLv),

	GoodsStatus = lib_goods_do:get_goods_status(),
    GoodsInfo = lib_role_nucleon:get_equip_bypos(Pos,GoodsStatus),

	CKList=[
		{check_open,Status},
		{check_pos_actived,NucHole},
		{check_cfg,Config,nucleon_lv_base},
		{check_pos,Pos},
		{check_pos_max_lved,Config},
		{check_pos_grade_limit,NucHole,Config},
		{check_goods_equip,GoodsInfo}
	],
	case util:check_lists(?MODULE,CKList) of
		true->
			#nucleon_hole{exp=PosExp}=NucHole,
			#nucleon_lv_base{cost=Cost,exp=Max,grade=Grade,next=NextLv}=Config,
			#nucleon_lv_base{grade=NextGrade} = data_nucleon:nucleon_lv(NextLv),
			[NPosLv,NPosExp,NCost,NStatus] = case NextGrade =:= Grade of
				true -> %%允许升级
					do_nucleon_pos_lv_up(PosLv,NextLv,PosExp,Max,Cost,AutoLv,AutoBuy,Status,[]);
				_->
					do_nucleon_pos_lv_up(PosLv,PosLv,PosExp,Max,Cost,AutoLv,AutoBuy,Status,[])
			end,
    		NewNucHole = NucHole#nucleon_hole{lv=NPosLv,exp=NPosExp},
    		NewNucleonHoles = lists:keystore(Pos,#nucleon_hole.pos,NucleonHoles,NewNucHole),
    		NewRoleNucleon = RoleNucleon#role_nucleon{holes=NewNucleonHoles},
    		save_role_nucleon_hole(RoleID,NewNucHole),

    		NStatus0 = NStatus#player_status{role_nucleon=NewRoleNucleon},
    		NewStatus = case NPosLv == PosLv of
    			true->
    				NStatus0;
    			_->
		    		NStatus1 = lib_role_nucleon:count_equip_attr(NStatus0),
					NStatus2 = lib_role_nucleon:count_nucleon_attr(NStatus1),
					NStatus3 = lib_player:count_player_attribute(NStatus2,?MOD_NUCLEON),
		            lib_player:send_attribute_change_notify(NStatus3, ?NOTIFY_ATTR),
				    custom_act_mobilize:update_mobilize_task(NStatus3, nucleonup, NPosLv-PosLv, false),
		            NStatus3
		    end,
		    lib_log_api:log_nucleon_equip_upgrade(RoleID,Name,Pos,PosLv,PosExp,NPosLv,NPosExp,util:combine_list(NCost,1)),
    		{ok,NPosLv,NPosExp,NewStatus};
        {false,Err}->
        	{false,Err}
	end.


do_nucleon_pos_lv_up(PosLv,PosLv,Max,Max,_Cost,_AutoLv,_AutoBuy,NStatus,Costs) ->
	[PosLv,Max,Costs,NStatus];
do_nucleon_pos_lv_up(PosLv,PosLv,PosExp,Max,Cost,AutoLv,AutoBuy,Status,Costs)->
	Res = case AutoBuy>0 of
        true->%%自动购买
            lib_goods_api:cost_objects_with_auto_buy(Status, Cost, nucleon_equip, ["nucleon equip lv"]);
        _->
            lib_goods_api:cost_object_list_with_check(Status, Cost, nucleon_equip, ["nucleon equip lv"])
    end,
    case Res of
        {true,NStatus,_}->
        	NExp = min(PosExp+10,Max),
        	case AutoLv>0 of
        		true->
					do_nucleon_pos_lv_up(PosLv,PosLv,NExp,Max,Cost,AutoLv,AutoBuy,NStatus,Cost++Costs);
				_->
					[PosLv,NExp,Cost++Costs,NStatus]
			end;
    	{false,_Err,_}->
    		[PosLv,PosExp,Costs,Status]
    end;
do_nucleon_pos_lv_up(PosLv,NextLv,PosExp,Max,Cost,AutoLv,AutoBuy,Status,Costs)->
	Res = case AutoBuy>0 of
        true->%%自动购买
            lib_goods_api:cost_objects_with_auto_buy(Status, Cost, nucleon_equip, ["nucleon equip lv"]);
        _->
            lib_goods_api:cost_object_list_with_check(Status, Cost, nucleon_equip, ["nucleon equip lv"])
    end,
    case Res of
        {true,NStatus,_}->
        	NExp = min(PosExp+10,Max),
        	case NExp>= Max of
        		true->
        			[NextLv,0,Cost++Costs,NStatus];
        		_->
        			case AutoLv>0 of
        				true->
        					do_nucleon_pos_lv_up(PosLv,NextLv,NExp,Max,Cost,AutoLv,AutoBuy,NStatus,Cost++Costs);
        				_->
        					[PosLv,NExp,Cost++Costs,NStatus]
        			end
        	end;
    	{false,_Err,_}->
    		[PosLv,PosExp,Costs,Status]
    end.




%%槽位突破
nucleon_pos_grade_up(Pos,Status)->
	#player_status{
		id = RoleID,
		role_nucleon = RoleNucleon
	}=Status,
	#role_nucleon{holes=NucleonHoles}=RoleNucleon,
	NucHole = lists:keyfind(Pos,#nucleon_hole.pos,NucleonHoles),
	case NucHole of
		#nucleon_hole{lv=PosLv}->
			skip;
		_->
			PosLv = 0
	end,
	Config = data_nucleon:nucleon_lv(PosLv),
	CKList=[
		{check_open,Status},
		{check_pos_actived,NucHole},
		{check_cfg,Config,nucleon_lv_base},
		{check_pos,Pos},
		{check_pos_max_lv,Config,NucHole},
		{check_pos_grade_up,Config},
		{check_pos_attr,Pos,Config,NucHole}
	],
	case util:check_lists(?MODULE,CKList) of
		true->
			#nucleon_lv_base{next=NextLv}=Config,
			#nucleon_lv_base{grade=NextGrade} = data_nucleon:nucleon_lv(NextLv),
    		NewNucHole = NucHole#nucleon_hole{lv=NextLv,exp=0,grade=NextGrade},
    		NewNucleonHoles = lists:keystore(Pos,#nucleon_hole.pos,NucleonHoles,NewNucHole),
    		NRoleNucleon = RoleNucleon#role_nucleon{holes=NewNucleonHoles},
    		save_role_nucleon_hole(RoleID,NewNucHole),
    		NStatus = Status#player_status{role_nucleon=NRoleNucleon},
    		{ok,NextGrade,NextLv,NStatus};
        {false,Err}->
        	{false,Err}
	end.


%%装甲进化
armor_grade_up(Uid,Loc,Status)->
	#player_status{
		id=RoleID,
		figure = #figure{name=Name},
		role_nucleon = RoleNucleon
	}=Status,
	GoodsStatus = lib_goods_do:get_goods_status(),

    #goods_status{dict = BagDicts} = GoodsStatus,
	GoodsInfo = lib_goods_util:get_goods(Uid,BagDicts,Loc),

	LocBag    = ?GOODS_LOC_ARMOR_BAG,

	CKList=[
		{check_goods,GoodsInfo},
		{check_grade,GoodsInfo}
	],
	case util:check_lists(?MODULE,CKList) of
		true->
            #goods{
                goods_id = ItemID
            } = GoodsInfo,
            #nucleon_equip_base{
            	cost=Cost,
            	next=Next
            }=data_nucleon:nucleon_equip(ItemID),
            #ets_goods_type{color=Color}=data_goods_type:get(Next),

            Dict   = lib_goods_util:get_location_goods(BagDicts, LocBag),
			Datas  = dict:to_list(Dict),
            EquipCost = filter_grade_up(Datas,Uid,Cost,[]),
            % ?INFO("-------:~p~n",[{Uid,Cost,length(Datas),Datas}]),
            % ?INFO("---------:~p~n",[EquipCost]),
			GoodsStatus0 = lib_goods_do:get_goods_status(),
			NGoodsInfo = GoodsInfo#goods{goods_id=Next,color=Color},
			F = fun() ->
                ok = lib_goods_dict:start_dict(),
                {ok, GoodsStatus0} = goods_del:delete_goods_list(GoodsStatus0, EquipCost),
                NGoodsStatus1 = goods_logic:change_goods_info(NGoodsInfo, GoodsStatus0),
                {NewDict, GoodsL}  = lib_goods_dict:handle_dict_and_notify(NGoodsStatus1#goods_status.dict),
                NGoodsStatus2 = NGoodsStatus1#goods_status{dict = NewDict},
                {ok, NGoodsStatus2,GoodsL}
            end,
            case length(EquipCost)>0 of
            	true->
		            case goods_transaction:transaction(F) of
		                {ok, NGoodsStatus,UpdateGoodsList} ->
		                    lib_goods_api:notify_client(RoleID, UpdateGoodsList, nucleon_equip),
		                    lib_goods_do:set_goods_status(NGoodsStatus),
		                    case Loc of
		                    	?GOODS_LOC_ARMOR_EQUIP->
				                    Status1 = active_hole(NGoodsInfo,Status),
				                    NStatus = count_equip_attr(Status1);
				                _->
				                	NStatus = Status
				            end,
		    				lib_chat:send_TV({all}, ?MOD_NUCLEON, 2, [Name,RoleID,ItemID,Next]),
		    				lib_log_api:log_nucleon_equip_evo(RoleID,Name,ItemID,Next,EquipCost,Uid),
			                %% 数据上报
			                #role_nucleon{holes = NucleonHoles} = RoleNucleon,
			                Pos = GoodsInfo#goods.subtype,
			                NucHole = lists:keyfind(Pos,#nucleon_hole.pos,NucleonHoles),
			                case NucHole of
				                #nucleon_hole{lv = LevelPos}-> skip;
				                _ ->  LevelPos = 0
			                end,
			                case data_nucleon:nucleon_equip(ItemID) of
				                #nucleon_equip_base{star = OldStar} -> ok;
				                _ -> OldStar = 0
			                end,
			                case data_nucleon:nucleon_equip(Next) of
				                #nucleon_equip_base{star = NewStar} -> ok;
				                _ -> NewStar = 0
			                end,
			                case data_goods_type:get(ItemID) of
								#ets_goods_type{color = OldColor} -> ok;
								_ -> OldColor = 0
			                end,
			                case data_goods_type:get(Next) of
				                #ets_goods_type{color = NewColor} -> ok;
				                _ -> NewColor = 0
			                end,
			                case Loc == ?GOODS_LOC_ARMOR_EQUIP of
								true ->
									UpInfo =  [Pos, LevelPos, "进化", ItemID, Next, OldColor, NewColor,
										OldStar, NewStar];
								_ ->
									UpInfo = []
			                end,
		    				{ok,Next,NStatus,UpInfo};
		                _Reason->
		                    ?INFO("~p ~p mod_goods nucleon_equip:~p", [?MODULE, ?LINE, _Reason]),
		                    {false,?ERRCODE(goods_not_enough)}
		            end;
		        _->
		        	{false,?ERRCODE(goods_not_enough)}
		    end;
        {false,Err}->
        	{false,Err}
    end.

%觉醒
nucleon_section_up(Pos,Status)->
	#player_status{
		id=RoleID,
		figure=#figure{name=Name},
		role_nucleon=RoleNucleon
	}=Status,
	#role_nucleon{holes=NucleonHoles}=RoleNucleon,
   	NucHole = lists:keyfind(Pos,#nucleon_hole.pos,NucleonHoles),
	case NucHole of
		#nucleon_hole{sec_lv=SecLv}->
			skip;
		_->
			SecLv = 0
	end,

	GoodsStatus = lib_goods_do:get_goods_status(),
    GoodsInfo = lib_role_nucleon:get_equip_bypos(Pos,GoodsStatus),

    CKList=[
    	{check_open,Status},
		{check_section,Pos,SecLv},
		{check_pos,Pos},
		{check_goods_equip,GoodsInfo},
		{check_goods_equip_color,Pos,GoodsInfo}
	],
	case util:check_lists(?MODULE,CKList) of
		true->
		    #nucleon_section_base{
		        cost=Cost,
		        skill=Skill,
		        next=Next
		    } = data_nucleon:nucleon_section(max(Pos-?MODIY_VALUE,1),SecLv),
		    case data_nucleon:nucleon_section(max(Pos-?MODIY_VALUE,1),Next) of
		    	#nucleon_section_base{skill=NSkill}->
		    		ignore;
		    	_->
		    		NSkill = Skill
		    end,
		    case lib_goods_api:cost_object_list_with_check(Status, Cost, nucleon_section_up, ["nucleon section up"]) of
                {true,Status0,_}->
    				NewNucHole0 = NucHole#nucleon_hole{sec_lv=Next},
    				NewNucHole  = active_hole_skill(RoleID,Pos,NSkill,NewNucHole0),
    				NewNucleonHoles = lists:keystore(Pos,#nucleon_hole.pos,NucleonHoles,NewNucHole),
    				NRoleNucleon = RoleNucleon#role_nucleon{holes=NewNucleonHoles},
    				NStatus      = Status0#player_status{role_nucleon=NRoleNucleon},
    				case lists:keyfind(Pos,1,data_nucleon:get(pos_name)) of
    					{_,PName}->
    						skip;
    					_->
    						PName = <<>>
    				end,
    				lib_chat:send_TV({all}, ?MOD_NUCLEON, 5, [Name,RoleID,PName,Next]),
    				lib_log_api:log_nucleon_section(RoleID,Name,Pos,Next,Cost),
    				save_role_nucleon_hole(RoleID,NewNucHole),
	                handle_awaken_achievement(NStatus, NewNucleonHoles),
                    [{_GoodsType, _GoodsId, GoodsNum}] = Cost,
    				{ok,Pos,Next,GoodsNum,NStatus};
		    	{false,Err,_}->
            		{false,Err}
            end;
		{false,Err}->
			{false,Err}
	end.

handle_awaken_achievement(Status, NucleonHoles) ->
	F = fun(#nucleon_hole{sec_lv = AwakenLv}, TSumLv) ->
				AwakenLv + TSumLv;
			(_, TSumLv) -> TSumLv
	end,
	SumLv = lists:foldl(F, 0, NucleonHoles),
	lib_achievement_api:nucleon_awaken_event(Status, SumLv),
	ok.

%%洗练
nucleon_recast_attr(Pos,Status)->
	#player_status{
		id=RoleID,
		role_nucleon=RoleNucleon
	}=Status,
	#role_nucleon{holes=NucleonHoles}=RoleNucleon,
   	NucHole = lists:keyfind(Pos,#nucleon_hole.pos,NucleonHoles),
	case NucHole of
		#nucleon_hole{grade=Grade,attrs=Attrs}->
			skip;
		_->
			Grade = 0,Attrs=[]
	end,
	Config = data_nucleon:nucleon_recast(max(Pos-?MODIY_VALUE,1),Grade),
    CKList=[
    	{check_cfg,Config,nucleon_recast_base},
    	{check_attr_max,Attrs,Config#nucleon_recast_base.maxs}
	],
	case util:check_lists(?MODULE,CKList) of
		true->
			#nucleon_recast_base{
				maxs=MaxList,
				adds=AddList,
				cost=Cost
			}=Config,
			[NewAttrs,Reports] = do_nucleon_recast_attr(Attrs,MaxList,AddList,[]),
			Times = lib_pet_api:pet_life_skill_about_nucleon_wash_free(Status),
			HasFreeTimes = case Times > 0 of
				               true -> case lib_daily:get_count(RoleID, ?MOD_NUCLEON, 1) of
					                       Count when is_integer(Count), Count =:= 0 -> true;
					                       _ -> false
				                       end;
				               _ -> false
			               end,
			case HasFreeTimes of
				true ->
					NewNucHole = NucHole#nucleon_hole{attrs=NewAttrs},
					NewNucleonHoles = lists:keystore(Pos,#nucleon_hole.pos,NucleonHoles,NewNucHole),
					NRoleNucleon = RoleNucleon#role_nucleon{holes=NewNucleonHoles},
					save_role_nucleon_hole(RoleID,NewNucHole),
					NStatus = Status#player_status{role_nucleon=NRoleNucleon},
					lib_daily:increment(RoleID, ?MOD_NUCLEON, 1),
					lib_server_send:send_to_uid(RoleID, pt_139, 13914, [0]),
					{ok,Reports,NewAttrs,NStatus};
				_ ->
					case lib_goods_api:cost_object_list_with_check(Status, Cost, nucleon_exchange, ["nucleon exchange"]) of
						{true,NStatus0,_}->
							NewNucHole = NucHole#nucleon_hole{attrs=NewAttrs},
							NewNucleonHoles = lists:keystore(Pos,#nucleon_hole.pos,NucleonHoles,NewNucHole),
							NRoleNucleon = RoleNucleon#role_nucleon{holes=NewNucleonHoles},
							save_role_nucleon_hole(RoleID,NewNucHole),
							NStatus = NStatus0#player_status{role_nucleon=NRoleNucleon},
							{ok,Reports,NewAttrs,NStatus};
						{false,Err,_}->
							{false,Err}
					end
			end;
        {false,Err}->
        	{false,Err}
    end.


do_nucleon_recast_attr(Attrs,_MaxList,[],Reports)->
	[Attrs,Reports];
do_nucleon_recast_attr(Attrs,MaxList,[{K,AddMax}|T],Reports)->
	case lists:keyfind(K,1,MaxList) of
		{_,Max}->
			skip;
		_->
			Max = 0
	end,
	Add = urand:rand(1,AddMax),
	case lists:keyfind(K,1,Attrs) of
		{_,CurV}->
			skip;
		_->
			CurV = 0
	end,
	case CurV<Max andalso Max>0 of
		true->
			NewV = min(CurV+Add,Max),
			do_nucleon_recast_attr(lists:keystore(K,1,Attrs,{K,NewV}),MaxList,T,[{K,Add}|Reports]);
		_->
			do_nucleon_recast_attr(Attrs,MaxList,T,Reports)
	end.



%%校正一下 隐藏规则  防止策划更新新的规则
fix_rule_state(RoleNucleon)->
	#role_nucleon{
		nstate = NState0,
		estate = EState0
	}=RoleNucleon,
	#pool_base{rule=Rule0}=data_nucleon:get_pool(1),
	#pool_base{rule=Rule1}=data_nucleon:get_pool(2),
	NState = fix_state(NState0,Rule0),
	EState = fix_state(EState0,Rule1),
	RoleNucleon#role_nucleon{nstate=NState,estate=EState}.

fix_state(State,[])->
	State;
fix_state(State,[{A,_}|Rules])->
	NState = case lists:keyfind(A,1,State) of
		{A,_}->
			State;
		_->
			[{A,0}|State]
	end,
	fix_state(NState,Rules).

%%获得被动技能
get_nucleon_passive_skill(Status)->
	Skills = get_skills(Status),
	lib_skill:divide_passive_skill(Skills).

%%技能汇总
get_skills(Status)->
	#player_status{role_nucleon=RoleNucleon}=Status,
	#role_nucleon{holes=NucleonHoles}=RoleNucleon,
	do_get_skills(NucleonHoles,[]).
do_get_skills([],Skills)->
	Skills;
do_get_skills([H|T],OSkills)->
	#nucleon_hole{
		pos=Pos,
		sec_lv=SecLv
	}=H,
	case data_nucleon:nucleon_section(max(Pos-?MODIY_VALUE,1),SecLv) of
		#nucleon_section_base{skill=Skills,sec_skill=SecSkills}->
			NSkills = OSkills++Skills++SecSkills,
			do_get_skills(T,NSkills);
		_->
			do_get_skills(T,OSkills)
	end.

check_have_learn_skill(Status,SkillID)->
	Skills = get_skills(Status),
	case lists:keyfind(SkillID,1,Skills) of
		{_,_}->
			true;
		_->
			false
	end.


%%获得抽奖面板信息
get_pane_info(RoleNucleon)->
	#role_nucleon{
		normal = N,   %%普通已抽免费次数
		ntime  = Nt,  %%上次免费抽时间
		nfirst = Nf,  %%普通首次
		nstate = Ns,  %%免费抽奖情况
		special = S,  %%付费已抽免费次数
		stime  = St,  %%上次付费已抽免费次数
		sfirst = Sf,  %%付费首次
		estate = Es   %%付费抽奖情况
	}=RoleNucleon,
	% Now = utime:unixtime(),
	{Times1,Nremain} = get_times(1,N,Nt,0),
	{Times2,Sremain} = get_times(2,S,St,0),
	Infos = [{1,Nf,Times1,Nremain,Ns},{2,Sf,Times2,Sremain,Es}],
	Infos.


%%获得可抽奖次数
get_times(Type,Num,Ltime,_Now)->
	#pool_base{free=Max,open=Open,cd=Cd}=data_nucleon:get_pool(Type),
	case util:get_open_day()=<Open of
		true->
			{max(0,Max-Num),Ltime+Cd};
		_-> %%免费有效期之外
			{0,0}
	end.

%%抽奖操作
do_nucleon_rock(Type,OpTy,Status)->
	#player_status{
		figure=#figure{lv=RoleLv},
		role_nucleon=RoleNucleon
	}=Status,
	case check_op_cd(Type,OpTy,RoleNucleon) of
		{false,Err}->
			{false,Err};
		_->
			case OpTy=<1 of
				true->%%单抽
					nucleon_rock(Type,RoleLv,RoleNucleon);
				_->
					serise_nucleon_rock(Type,RoleLv,RoleNucleon,10,[])
			end
	end.

%%2017 07 21 不错ＣＤ　次数检测
check_op_cd(_,_,_)->
	true.


serise_nucleon_rock(_Type,_RoleLv,RoleNucleon,0,Awards)->
	case length(Awards)=<0 of
		true->
			{false,?ERRCODE(err139_pool_empty)};
		_->
			{ok,Awards,RoleNucleon}
	end;
serise_nucleon_rock(Type,RoleLv,RoleNucleon,Num,Awards)->
	case nucleon_rock(Type,RoleLv,RoleNucleon) of
		{ok,Award0,NRoleNucleon}->
			serise_nucleon_rock(Type,RoleLv,NRoleNucleon,Num-1,Award0++Awards);
		_->
			serise_nucleon_rock(Type,RoleLv,RoleNucleon,Num-1,Awards)
	end.

%%抽奖
nucleon_rock(Type,RoleLv,RoleNucleon) when Type=<1->
	#role_nucleon{
		nfirst = Nf,  %%普通首次
		nstate = Ns   %%抽奖情况
	}=RoleNucleon,
	{IsUpdate,Pools} = calc_pool(Type,Nf,RoleLv,Ns),
    case length(Pools)>=1 of
        true->
        	AwardID = urand:rand_with_weight(Pools),
        	NewState = after_rock(IsUpdate,Type,AwardID,Ns),
        	NRoleNucleon = RoleNucleon#role_nucleon{nfirst=1,nstate=NewState},
        	{ok,[AwardID],NRoleNucleon};
		_->
            {false,?ERRCODE(err139_pool_empty)}
    end;
nucleon_rock(Type,RoleLv,RoleNucleon)->
	#role_nucleon{
		sfirst = Sf,  %%付费首次
		estate = Es   %%抽奖情况
	}=RoleNucleon,
	{IsUpdate,Pools} = calc_pool(Type,Sf,RoleLv,Es),
    case length(Pools)>=1 of
        true->
        	AwardID = urand:rand_with_weight(Pools),
        	NewState = after_rock(IsUpdate,Type,AwardID,Es),
        	NRoleNucleon = RoleNucleon#role_nucleon{sfirst=1,estate=NewState},
        	{ok,[AwardID],NRoleNucleon};
		_->
            {false,?ERRCODE(err139_pool_empty)}
    end.


%%计算实际奖池内道具 符合等级  符合首次
calc_pool(Type,IsF,Lv,State)->
	#pool_base{
		rule=Rule,
		first=F
	}=data_nucleon:get_pool(Type),
	OriAll = data_nucleon:nucleon_pool(Type),
	Pools0 = case IsF=<0 of
		true-> %%首次大酬宾
			filter_pool(OriAll,F,Lv);
		_->
			filter_pool(OriAll,0,Lv)
	end,
	%%必现道具存在的情况下 奖池优先
	[MPools,ResPools] = filter_rule_pool(Rule,State,Pools0),
	case length(MPools)>0 of
		true->
			{1,MPools};
		_->
			{0,ResPools}
	end.

%%初步筛选符合首次和等级的
filter_pool(OriAll,F,Lv)->
	filter_pool(OriAll,F,Lv,[]).
filter_pool([],_,_,ResAll)->
	ResAll;
filter_pool([{W,T}|OriAll],F,Lv,ResAll)->
	#nucleon_award_base{
		color=St,
		lv=Slv
	}=data_nucleon:nucleon_award(T),
	case F>0 of
		true->%%说明首次 只给符合这个条件的
			case St==F andalso Slv=<Lv of
				true->
					filter_pool(OriAll,F,Lv,[{W,T}|ResAll]);
				_->
					filter_pool(OriAll,F,Lv,ResAll)
			end;
		_->%%不是首次  等级符合就可以
			case Slv=<Lv of
				true->
					filter_pool(OriAll,F,Lv,[{W,T}|ResAll]);
				_->
					filter_pool(OriAll,F,Lv,ResAll)
			end
	end.

%%进一步筛选符合轮次必现规则的道具
filter_rule_pool(Rule,State,Pools)->
	filter_rule_pool(Rule,State,Pools,[],[]).
filter_rule_pool(_Rule,_State,[],MPools,ResPools)->
	[MPools,ResPools];
filter_rule_pool(Rule,State,[{W,T}|Pools],MPools,ResPools)->
	Color = case data_nucleon:nucleon_award(T) of
		#nucleon_award_base{color=Nt}->
			Nt;
		_->
			0
	end,
	case lists:keyfind(Color,1,Rule) of
		{Color,Aim}->%%存在规则
			case lists:keyfind(Color,1,State) of
				{Color,CAim} when CAim+1>=Aim ->%%满足规则 必出 0次开始计数 当前9 下一次就是必现次数
					filter_rule_pool(Rule,State,Pools,[{W,T}|MPools],ResPools);
				{Color,Nu} when Nu<Aim-> %%存在规则 且出现过 又不满足轮次 不给 20170721 给！！
					filter_rule_pool(Rule,State,Pools,MPools,[{W,T}|ResPools]);
				_->%%有规则 但是还没记录
					filter_rule_pool(Rule,State,Pools,MPools,[{W,T}|ResPools])
			end;
		_->%%无规则
			filter_rule_pool(Rule,State,Pools,MPools,[{W,T}|ResPools])
	end.

%%计算消耗
calc_cost(Type,OpTy,RoleNucleon)->
	#role_nucleon{
		normal = N,
		ntime  = Nt,
		special = S,
		stime  = St
	} = RoleNucleon,
	Free = case Type=<1 of
		true->
			N;
		_->
			S
	end,
	LTime = case Type=<1 of
		true->
			Nt;
		_->
			St
	end,
	#pool_base{
		free=Max,
		open=Open,
		cd=Cd,
		one=One,
		cost=Cost,
		pay=Pay,
		ten=Ten
	}=data_nucleon:get_pool(Type),
	Now = utime:unixtime(),
	case OpTy =<1 of
		true->%%单抽 免费检测
			case util:get_open_day()=<Open of
				true->%%免费期内 看是否有免费次数和cd是否合法
					case Free<Max andalso (LTime+Cd-Now)=<0 of
						true->
							NRoleNucleon = case Type =<1 of
								true->
									RoleNucleon#role_nucleon{normal=Free+1,ntime=Now};
								_->
									RoleNucleon#role_nucleon{special=Free+1,stime=Now}
							end,
							{0,One,NRoleNucleon}; %%免费
						_->
							{Cost,One,RoleNucleon}
					end;
				_-> %%免费有效期之外
					{Cost,One,RoleNucleon}
			end;
		_->
			{Pay,Ten,RoleNucleon}
	end.

%%修正新的状态记录 7.17 改为指定次数必现  期间随机出现的统计不清零
after_rock(IsUpdate,Type,AwardID,State)->
	#pool_base{rule=Rules}=data_nucleon:get_pool(Type),
	Color = case data_nucleon:nucleon_award(AwardID) of
		#nucleon_award_base{color=Nt}->
			Nt;
		_->
			0
	end,
	after_sub_rock(IsUpdate,Rules,Color,State).

after_sub_rock(_,[],_,State)->
	State;
after_sub_rock(IsUpdate,[{A,N}|Rules],Color,State)->
	NState = case lists:keyfind(A,1,State) of
		{A,CurN} ->
			case A == Color of %%出现规则中道具
				true->
					case IsUpdate>=1 of
						true-> %%必现期间出现 且达到峰值 要重置
							case (CurN+1)>=N of
								true->
									lists:keyreplace(A,1,State,{A,0});
								_->
									lists:keyreplace(A,1,State,{A,min(CurN+1,N)})
							end;
						_->
							lists:keyreplace(A,1,State,{A,min(CurN+1,N)})
					end;
				_->
					lists:keyreplace(A,1,State,{A,min(CurN+1,N)})
			end;
		_->
			lists:keystore(A,1,State,{A,1})
	end,
	after_sub_rock(IsUpdate,Rules,Color,NState).


%%激活孔位新的技能  升级
active_hole_skill(RoleID,Pos,Skill,NucHole)->
	#nucleon_hole{skill=OSkill,skill_lv=OldLv}=NucHole,
	case Skill of
		[{SkillId,Lv}]->
			case OSkill =:= SkillId of
				true when OldLv >= Lv ->
					NucHole;
				_->
					{ok,Bin} = pt_139:write(13913,[Pos,SkillId,Lv]),
					lib_server_send:send_to_uid(RoleID,Bin),
					NucHole#nucleon_hole{skill=SkillId,skill_lv=Lv}
			end;
		_->
			NucHole
	end.


%%计算分解所得
calc_resolve_gain([],Gain,Cost)->
	[Gain,Cost];
calc_resolve_gain([GoodsInfo|GoodsList],Gain,Cost)->
	#goods{id=Uid,goods_id=ItemID}=GoodsInfo,
	#nucleon_equip_base{resolve = Resolve}=data_nucleon:nucleon_equip(ItemID),
	calc_resolve_gain(GoodsList,Resolve++Gain,[{Uid,ItemID}|Cost]).

%%技能激活
active_hole(GoodsInfo,Status)->
	#goods{color=Color,subtype=Pos}=GoodsInfo,
	#player_status{
		id=RoleID,
		role_nucleon=RoleNucleon,
		figure = #figure{name=Name}
	}=Status,
	#role_nucleon{holes=Holes}=RoleNucleon,
	NucHole = lists:keyfind(Pos,#nucleon_hole.pos,Holes),
	case NucHole of
		#nucleon_hole{skill=Skill} when Skill>0-> %%已激活
			Status;
		#nucleon_hole{}->
			case data_nucleon:active_hole(max(Pos-?MODIY_VALUE,1),Color) of
				{Skill,Lv} when Skill>0->   %%有效技能
					NNucHole = NucHole#nucleon_hole{skill=Skill,skill_lv=Lv},
					NHoles = lists:keystore(Pos,#nucleon_hole.pos,Holes,NNucHole),
					NRoleNucleon = RoleNucleon#role_nucleon{holes=NHoles},
					{ok,Bin} = pt_139:write(13913,[Pos,Skill,Lv]),
					lib_server_send:send_to_uid(RoleID,Bin),
					NewStatus = Status#player_status{role_nucleon=NRoleNucleon},
					#skill{name=SName} = data_skill:get(Skill,Lv),
					lib_chat:send_TV({all}, ?MOD_NUCLEON, 3, [Name,RoleID,SName]),
					%lib_skill:update_other_active_skills(NewStatus);
					save_role_nucleon_hole(RoleID,NNucHole),
					lib_log_api:log_nucleon_section(RoleID,Name,Pos,1,[]),
					NewStatus;
				_->%%无效技能
					Status
			end;
		_->
			Status
	end.

%%灵能道具兑换
nucleon_exchange_goods(Status,SortID,Num)->
	#player_status{id=RoleID,figure=#figure{name=RName}}=Status,
	CKList=[
    	{check_sort,SortID}
	],
	case util:check_lists(?MODULE,CKList) of
		true->
			{GainID,Cost} = data_nucleon:get_nucleon_exchange(SortID),
			Gain = [{?TYPE_GOODS,GainID,Num}],
			NCost = [{K,T,V*Num}||{K,T,V}<-Cost],
			case lib_goods_api:cost_object_list_with_check(Status, NCost, nucleon_exchange, ["nucleon exchange"]) of
                {true,NStatus,_}->
                    Produce = #produce{type=nucleon_exchange,reward=Gain},
                    lib_goods_api:send_reward_with_mail(RoleID, Produce, ?MOD_NUCLEON),
                    lib_log_api:log_nucleon_exchange(RoleID,RName,Gain,NCost),
                    {ok,NStatus};
				{false,Err,_}->
            		{false,Err}
            end;
        {false,Err}->
        	{false,Err}
    end.

%%数据持久化
save_role_nucleon(RoleID,RoleNucleon)->
	#role_nucleon{
		lv = Lv,
		exp = Exp,
		normal = Normal,
		ntime = NTime,
		nfirst = NFirst,
		nstate = ONState,
		special = Special,
		stime = STime,
		sfirst = SFirst,
		estate = OEState,
		rtime = ReTime
	}=RoleNucleon,
	NState = util:term_to_string(ONState),
	EState = util:term_to_string(OEState),
	db:execute(io_lib:format(?SQL_ROLE_NUCLEON_REPLACE,[RoleID,Lv,Exp,Normal,NTime,NFirst,NState,Special,STime,SFirst,EState,ReTime])).

%%数据持久化
save_role_nucleon_hole(RoleID,NucleonHole)->
	#nucleon_hole{
		pos   = Pos,       %%部位
		grade = Grade,       %%部位阶位
		lv    = Lv,       %%部位等级
		exp   = Exp,       %%=部位经验
		attrs = Attrs0,      %%部位属性
		skill = Skill,       %%技能
		skill_lv  = SkillLv,	 %%技能等级
		sec_lv    = SecLv	 %%觉醒等级
	}=NucleonHole,
	Attrs = util:term_to_string(Attrs0),
	db:execute(io_lib:format(?SQL_PLAYER_NUCLEON_REPLACE,[RoleID,Pos,Grade,Lv,Exp,Skill,SkillLv,SecLv,Attrs])).


%%校正 抽出元宝消费
fix_cost(Status,Cost)->
	fix_cost(Status,Cost,0,[]).

fix_cost(Status,[],Gold,Cost)->
	#player_status{bgold=BGold}=Status,
	case BGold>=Gold of
		true->
			[{bgold,Gold}|Cost];
		_ when BGold=<0->
			[{gold,Gold}|Cost];
		_->
			[{bgold,BGold},{gold,Gold-BGold}|Cost]
	end;
fix_cost(Status,[C|Cost],Gold,NCost)->
	case C of
		{gold,N}->
			fix_cost(Status,Cost,Gold+N,NCost);
		_->
			fix_cost(Status,Cost,Gold,[C|NCost])
	end.

%%凌晨
zero_time(Status)->
	#player_status{sid=Sid,role_nucleon=RoleNucleon}=Status,
	NRoleNucleon=RoleNucleon#role_nucleon{
		normal = 0,
		special = 0,
		rtime = utime:unixtime()
	},
	NStatus=Status#player_status{role_nucleon=NRoleNucleon},
	Infos = lib_role_nucleon:get_pane_info(NRoleNucleon),
	{ok,Bin}=pt_139:write(13910,[Infos]),
	lib_server_send:send_to_sid(Sid,Bin),
	NStatus.

check({check_attr_max,Attrs,Maxs})->
	case check_all_attr_max(Attrs,Maxs) of
		false->
			true;
		_->
			{false,?ERRCODE(err139_all_attr_max_reached)}
	end;
check({check_pos_actived,NucHole})->
	case NucHole of
		#nucleon_hole{}->
			true;
		_->
			?ERRCODE(missing_config)
	end;
check({check_pos_attr,Pos,Config,NucHole})->
	#nucleon_lv_base{grade=Grade}=Config,
	#nucleon_hole{attrs=Attrs}=NucHole,
	#nucleon_recast_base{
		maxs=Maxs
	}=data_nucleon:nucleon_recast(max(Pos-?MODIY_VALUE,1),Grade),
	case check_max_attr(Attrs,Maxs) of
		true->
			true;
		_->
			{false,?ERRCODE(err139_need_attr_max)}
	end;
check({check_pos_max_lved,Config})->
	#nucleon_lv_base{next=Next}=Config,
	case Next>0 of
		true->
			true;
		_->
			{false,?ERRCODE(err139_max_lv_reached)}
	end;
check({check_pos_grade_limit,NucHole,Config})->
	#nucleon_lv_base{next=Next,exp=Max,grade=CGrade}=Config,
	#nucleon_hole{exp=CExp}=NucHole,
	case data_nucleon:nucleon_lv(Next) of
		#nucleon_lv_base{grade=CGrade}->
			true;
		_ when CExp<Max->
			true;
		_->
			{false,?ERRCODE(err139_need_up_grade)}
	end;
check({check_pos_max_lv,Config,NucHole})->
	#nucleon_hole{exp=CurExp}=NucHole,
	#nucleon_lv_base{next=Next,exp=Max}=Config,
	case Next>0 of
		true->
			case CurExp>=Max of
				true->
					true;
				_->
					{false,?ERRCODE(err139_need_more_exp)}
			end;
		_->
			{false,?ERRCODE(err139_max_lv_reached)}
	end;
check({check_pos_grade_up,Config})->
	#nucleon_lv_base{next=Next,grade=CGrade}=Config,
	case data_nucleon:nucleon_lv(Next) of
		#nucleon_lv_base{grade=NGrade} when NGrade /= CGrade ->
			true;
		_->
			{false,?ERRCODE(err139_need_up_lv)}
	end;
check({check_cfg,Config,Atom})->
	case is_record(Config,Atom) of
		true->
			true;
		_->
			{false,?ERRCODE(missing_config)}
	end;
check({check_max_title,Config})->
	case Config of
		#nucleon_title_base{}->
			true;
		_->
			{false,?ERRCODE(err139_max_title_reached)}
	end;
check({check_exp,Exp,Config})->
	#nucleon_title_base{exp=Max}=Config,
	case Exp<Max of
		true->
			true;
		_->
			{false,?ERRCODE(err139_need_active_next)}
	end;
check({check_active_title,Status,Exp,Config})->
	#nucleon_title_base{exp=Max,dungeon=DunID}=Config,
	case Exp>=Max of
		true->
			case lib_dungeon_api:check_ever_finish(Status,DunID) of
				true->
					true;
				_->
					{false,?ERRCODE(err139_need_finish_dun)}
			end;
		_->
			{false,?ERRCODE(err139_need_more_power)}
	end;
check({check_sort,SortID})->
	case data_nucleon:get_nucleon_exchange(SortID) of
		[]->
			{false,?ERRCODE(missing_config)};
		_->
			true
	end;
check({check_pos,Pos})->
	case lists:member(Pos,[4,5,6,7]) of
		true->
			true;
		_->
			{false,?ERRCODE(args_error)}
	end;
check({check_open,Lv}) when is_integer(Lv)->
	case Lv >= lib_module:get_open_lv(?MOD_NUCLEON) of
		true->
			true;
		_->
			{false,?ERRCODE(err139_sys_not_open)}
	end;
check({check_open,Status})->
	case lib_module:is_open(Status,?MOD_NUCLEON) of
		true->
			true;
		_->
			{false,?ERRCODE(err139_sys_not_open)}
	end;
check({check_goods,GoodsInfo})->
	case is_record(GoodsInfo,goods) of
		true->
			true;
		_->
			{false,?ERRCODE(err139_goods_not_exist)}
	end;
check({check_goods_equip,GoodsInfo})->
	case is_record(GoodsInfo,goods) of
		true->
			true;
		_->
			{false,?ERRCODE(err139_need_equip_goods)}
	end;
check({check_goods_equip_color,Pos,GoodsInfo})->
	#goods{color=Color}=GoodsInfo,
	case data_nucleon:active_hole(max(Pos-?MODIY_VALUE,1),Color) of
		{_,_}->
			true;
		_->
			{false,?ERRCODE(err139_need_equip_higher_goods)}

	end;
check({check_grade,GoodsInfo})->
	#goods{goods_id=ItemID}=GoodsInfo,
	case data_nucleon:nucleon_equip(ItemID) of
		#nucleon_equip_base{next=N} when N>0 ->
			true;
		_->
			{false,?ERRCODE(err139_max_grade_reached)}
	end;
check({check_section,Pos,MSec})->
	case data_nucleon:nucleon_section(max(Pos-?MODIY_VALUE,1),MSec) of
		#nucleon_section_base{next=Next} when Next=<0->
		    {false,?ERRCODE(err139_section_max_reached)};
		#nucleon_section_base{}->
			true;
		_->
			{false,?ERRCODE(missing_config)}
	end.

count_nucleon_attr(Status)->
    #player_status{role_nucleon=RoleNucleon, figure = #figure{lv = RoleLv}}=Status,
    #role_nucleon{
    	lv = Lv,
    	holes = NucleonHoles,
    	armor_attr = ArmorAttr
    }=RoleNucleon,
    case data_nucleon:nucleon_title(Lv) of
    	#nucleon_title_base{attrs=Attrs0}->
    		skip;
    	_->
    		Attrs0 = []
    end,
    Attrs1 = calc_sec_attrs(NucleonHoles,[]),
    Skills = get_skills(Status),
    {SkillAttr,_} = lib_skill_attr:get_passive_skill_attr_and_power(Skills, RoleLv),
    Attrs = util:combine_list(Attrs0++Attrs1++ArmorAttr++SkillAttr),
    NRoleNucleon = RoleNucleon#role_nucleon{attrs=Attrs},
    Status#player_status{role_nucleon=NRoleNucleon}.

get_nucleon_lv(Player) ->
	case Player of
		#player_status{role_nucleon = #role_nucleon{lv = Lv}} ->
			Lv;
		_ ->
			0
	end.

%%属性获取
get_nucleon_attr(Status)->
	#player_status{
		role_nucleon=RoleNucleon
	}=Status,
	case RoleNucleon of
		#role_nucleon{attrs=Attrs}->
			Attrs;
		_->
			Attrs = []
	end,
	Attrs.

%%计算觉醒属性
calc_sec_attrs([],Attrs)->
	Attrs;
calc_sec_attrs([#nucleon_hole{pos=Pos,sec_lv=Lv,skill=Skill,attrs=RandAttrs}|T],Attrs)->
	case data_nucleon:nucleon_section(max(Pos-?MODIY_VALUE,1),Lv) of
		#nucleon_section_base{attrs=Attrs0} ->
			case Skill>0 of
				true->
					calc_sec_attrs(T,Attrs0++Attrs++RandAttrs);
				_->
					calc_sec_attrs(T,Attrs++RandAttrs)
			end;
		_->
			calc_sec_attrs(T,Attrs)
	end.

%%计算装备属性
count_equip_attr(Status)->
	#player_status{role_nucleon=RoleNucleon, off = StatusOff}=Status,
	case StatusOff#status_off.goods_status of
		undefined ->
			GoodsStatus = lib_goods_do:get_goods_status(),
			AllEquips = get_all_equips(GoodsStatus);
		GoodsStatus ->
			AllEquips = get_all_equips(GoodsStatus)
	end,
	#role_nucleon{holes=NucleonHoles}=RoleNucleon,
	Attrs = calc_equips_attrs(AllEquips,NucleonHoles,[]),
	NRoleNucleon = RoleNucleon#role_nucleon{armor_attr=Attrs},
	Status#player_status{role_nucleon=NRoleNucleon}.

calc_equips_attrs([],_NucleonHoles,Attrs)->
	util:combine_list(Attrs);
calc_equips_attrs([H|T],NucleonHoles,Attrs)->
	#goods{goods_id = ItemID,subtype=Pos}=H,
	case lists:keyfind(Pos,#nucleon_hole.pos,NucleonHoles) of
		#nucleon_hole{lv=Lv,attrs=Attrs2}->
			%%等级属性
			Attr1 = case data_nucleon:nucleon_equip(ItemID) of
				#nucleon_equip_base{attrs=Attr0}->
					[{K,V+A*Lv}||{K,V,A}<-Attr0];
				_->
					[]
			end,
			calc_equips_attrs(T,NucleonHoles,Attr1++Attrs2++Attrs);
		_->
			calc_equips_attrs(T,NucleonHoles,Attrs)
	end.


%%通过位置找道具
get_equip_bypos(Pos,GoodsStatus)->
	AllEquips = get_all_equips(GoodsStatus),
	lists:keyfind(Pos,#goods.cell,AllEquips).


%%获取所有装甲
get_all_equips(GoodsStatus)->
	#goods_status{dict = Dict} = GoodsStatus,
	NucleonDict   = lib_goods_util:get_location_goods(Dict, ?GOODS_LOC_ARMOR_EQUIP),
	Datas  = dict:to_list(NucleonDict),
	Equips = [V||{_K,V}<-Datas],
	Equips.

%%校正
fix_resolve([],_UidList,NGoodsInfoList)->
    NGoodsInfoList;
fix_resolve([{Id,H}|T],UidList,NGoodsInfoList)->
    case H of
        #goods{type=?GOODS_TYPE_X3}->
            case lists:member(Id,UidList) of
                true->
                    fix_resolve(T,UidList,[{H,1}|NGoodsInfoList]);
                _->
                    fix_resolve(T,UidList,NGoodsInfoList)
            end;
        _->
            fix_resolve(T,UidList,NGoodsInfoList)
    end.

%%突破消耗矫正
filter_grade_up(_Datas,_Uid,[],NGoodsInfoList)->
	NGoodsInfoList;
filter_grade_up(Datas,Uid,[{_,GType,Num}|T],NGoodsInfoList)->
	EatList = filter_eat(Datas,Uid,GType,Num,[]),
    case length(EatList)>=Num of
    	true->
    		filter_grade_up(Datas,Uid,T,EatList++NGoodsInfoList);
        _->
            []
    end.

filter_eat([],_Uid,_GType,_Num,EatList)->
	EatList;
filter_eat(_Datas,_Uid,_GType,Num,EatList) when Num=<0->
	EatList;
filter_eat([{Id,H}|T],Uid,GType,Num,EatList)->
	case Id /= Uid andalso H#goods.goods_id =:= GType of
		true->
			filter_eat(T,Uid,GType,Num-1,[{H,1}|EatList]);
		_->
			filter_eat(T,Uid,GType,Num,EatList)
	end.



%%计算一键消耗
calc_quick_cost(_,_,Need,_Status,NCost) when Need=<0->
	{Need,NCost};
calc_quick_cost(_,[],Need,_Status,NCost)->
	{Need,NCost};
calc_quick_cost(Auto,[H|Cost],Need,Status,NCost) when Auto=<0->
	Per = data_nucleon:get(nucleon_equip_value),
	case H of
		{?TYPE_GOODS,T,_V}->
			case lib_goods_api:get_goods_num(Status,[T]) of
				[{_,Has}|_] when Has>0->
					case Has*Per>=Need of
						true->
							calc_quick_cost(Auto,Cost,0,Status,[{?TYPE_GOODS,T,util:ceil(Need/Per)}|NCost]);
						_->
							calc_quick_cost(Auto,Cost,Need-Has*Per,Status,[{?TYPE_GOODS,T,Has}|NCost])
					end;
				_->
					calc_quick_cost(Auto,Cost,Need,Status,NCost)
			end;
		_->%%不支持其他类型
			calc_quick_cost(Auto,Cost,Need,Status,NCost)
	end;
calc_quick_cost(Auto,[H|Tail],Need,Status,NCost)->
	Per = data_nucleon:get(nucleon_equip_value),
	case H of
		{?TYPE_GOODS,T,_V}->
			{0,[{?TYPE_GOODS,T,util:ceil(Need/Per)}|NCost]};
		_->
			calc_quick_cost(Auto,Tail,Need,Status,NCost)
	end.


check_max_attr([],_Maxs)->
	false;
check_max_attr([{K,V}|T],Maxs)->
	case lists:keyfind(K,1,Maxs) of
		{_,M} when V>=M->
			true;
		_->
			check_max_attr(T,Maxs)
	end.

check_all_attr_max(_Attrs,[])->
	true;
check_all_attr_max(Attrs,[{K,Max}|T])->
	case lists:keyfind(K,1,Attrs) of
		{_,CurV} when CurV>=Max->
			check_all_attr_max(Attrs,T);
		_->
			false
	end.
