%%%-----------------------------------
%%% @Module  : lib_task
%%% @Author  : xyao
%%% @Created : 2010.05.05
%%% @Description: 任务
%%%-----------------------------------
-module(lib_task).
-compile(export_all).

-include("scene.hrl").
-include("common.hrl").
-include("server.hrl").
-include("task.hrl").
-include("figure.hrl").
-include("team.hrl").
-include("errcode.hrl").
-include("predefine.hrl").
-include("def_module.hrl").
-include("goods.hrl").
-include("daily.hrl").
-include("def_fun.hrl").
-include("def_goods.hrl").
-include("guild_labor.hrl").
-include("dungeon.hrl").
-include("local_boss.hrl").

-define(LIMIT_TIME1, 900).
-define(LIMIT_TIME2, 1800).

%% 获取我的任务列表
get_my_task_list(TaskArgs)->
    get_my_task_list(0,TaskArgs).
get_my_task_list(Type,#task_args{id = RoleId, sid=Sid}=TaskArgs) ->
    %% 可接任务
    F = fun(TD, TmpActiveList) ->
        case Type == 0 orelse TD#task.type == Type of
            true ->
                [{TD#task.id, get_tip(active, TD#task.id, TaskArgs)} | TmpActiveList];
            false ->
                TmpActiveList
        end
    end,
    ActiveList  = lists:foldl(F, [], get_active()),
    %% 已接任务
    NowTime = utime:unixtime(),
    F1 = fun(RT, {TL, CL}) ->
                 #role_task{task_id = TaskId, type = TaskType, trigger_time = TriggerTime, mark = Mark} = RT,
                 if
                     Type =/= 0 andalso TaskType =/= Type ->
                        {TL, CL};
                     TaskType == ?TASK_TYPE_CHAPTER ->
                         LimitTime = ?IF(TaskId == 101 orelse TaskId == 102, ?LIMIT_TIME1, ?LIMIT_TIME2),
                         if
                             NowTime > TriggerTime + LimitTime -> %% 大于限时
                                 case is_finish_mark(Mark, TaskArgs) of
                                     false -> {TL, [RT|CL]};
                                     true ->
                                         TipList = get_tip(trigger, TaskId, TaskArgs),
                                         {WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(TipList),
                                         {[{TaskId, TipList, WitchState, NeedNum, NowNum, TriggerTime}|TL], CL}
                                 end;
                             true ->
                                 TipList = get_tip(trigger, TaskId, TaskArgs),
                                 {WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(TipList),
                                 {[{TaskId, TipList, WitchState, NeedNum, NowNum, TriggerTime}|TL], CL}
                         end;
                     true ->
                         TipList = get_tip(trigger, TaskId, TaskArgs),
                         {WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(TipList),
                         {[{TaskId, TipList, WitchState, NeedNum, NowNum, TriggerTime}|TL], CL}
                 end
         end,
    {TriggerList, NeedToDelTask} = lists:foldl(F1, {[], []}, get_trigger()),
    %% 删除需要去掉的限时章节任务
    F2 = fun(RT) ->
                 #role_task{task_id = TaskId, type = TaskType, trigger_time = TriggerTime} = RT,
                 add_log(RoleId, TaskId, TaskType, TriggerTime, 0, 0) %% 完成时间是0就代表过时
         end,
    lists:map(F2, NeedToDelTask),
    {ok, BinData} = pt_300:write(30000, [Type, ActiveList, TriggerList]),
    lib_server_send:send_to_sid(Sid, BinData).

%% 获取任务是否完成
get_task_finish_state(TaskId, TaskArgs)->
    case get_one_trigger(TaskId) of
        false -> ?ERRCODE(err300_no_task_trigger); %% 没接这个任务
        RT -> ?IF(is_finish(RT, TaskArgs), true, ?ERRCODE(err300_task_no_finish))
    end.

%% 获取任务类型
get_task_type(TaskId) ->
    TD = get_data(TaskId),
    ?IF(TD == null, 0, TD#task.type).

%% 升级自动触发任务
lv_up(TaskArgs) ->
    %% 刷新缓存可以优化一下
    refresh_active(TaskArgs),
    case auto_trigger(TaskArgs) of
        true -> skip;
        _ ->
            skip
    end,
    get_my_task_list(0, TaskArgs),
    refresh_npc_ico(TaskArgs).

%% ================================= 登录加载数据 =================================
flush_role_task(TaskArgs) ->
    #task_args{id = Id} = TaskArgs,
    %% 所有已经触发的任务列表
    F1 = fun([Tid, Tt, S ,ES, M, TP, Lv], AllTask) ->
                 case data_task:get(Tid) of
                     null ->
                         del_trigger_from_sql(Id, Tid), %% 移除无效的已接任务
                         AllTask;
                     _ ->
                         Kind = case data_task_condition:get(Tid) of
                                    null -> 0;
                                    TD -> TD#task_condition.kind
                                end,
                         case util:bitstring_to_term(M) of
                             undefined -> AllTask;
                             Mark ->
                                 [#role_task{role_id=Id, lv = Lv, task_id=Tid, trigger_time = Tt,
                                             state = S, end_state = ES, mark = Mark, type=TP, kind = Kind}|AllTask]
                         end
                 end
         end,
    RoleTaskList = db:get_all(io_lib:format("select task_id, trigger_time, state, end_state, mark, type, lv from task_bag where role_id=~w", [Id])),
    RoleTaskListRed = lists:foldl(F1, [], RoleTaskList),
    set_task_bag_list(RoleTaskListRed),

    %% 所有已经完成的任务列表
    F2 = fun([Tid2, Ty2]) ->
                 put_task_log_list(Tid2,#role_task_log{type= Ty2})
         end,
    RoleTaskLogList = db:get_all(io_lib:format("select task_id, type from task_log where role_id=~w", [Id])),
    lists:map(F2,  RoleTaskLogList),
    refresh_active(TaskArgs),

    get_my_task_list(0, TaskArgs),

    %% 自动接取任务
    auto_trigger(TaskArgs),
    auto_finish(TaskArgs),
    login_after(TaskArgs),
    ok.

login_after(TaskArgs) ->
    %%同步转生任务id
    case get_task_bag_id_list_type(?TASK_TYPE_TURN) of
        [#role_task{task_id = TaskId} | _T] ->
            lib_task_event:trigger_after(data_task:get(TaskId), TaskArgs);
        _ -> ok
    end.

%%上线处理已完成的触发任务
handle_refresh_trigger(TaskArgs)->
    RoleTaskList = get_task_bag_id_list(),
    %%纠正配置不匹配任务
    case catch do_refresh_conflict_trigger(RoleTaskList, TaskArgs, []) of
        UpdateList when is_list(UpdateList) ->
            case UpdateList =/= [] of
                true ->
                    refresh_task(TaskArgs);
                false -> ok
            end;
        _Rson ->
            ?ERR("do_refresh_conflict_trigger~p~n",[_Rson])
    end,
    NewRoleTaskList = get_task_bag_id_list(),
    %%自动完成已接取的特殊支线任务和可能离线完成的主线特殊任务(副本)
    case catch do_handle_refresh_trigger(NewRoleTaskList, TaskArgs, []) of
        [] -> ok;
        EventList when is_list(EventList) ->
            lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_STATUS, lib_task_api, cast_handle_refresh_trigger, [EventList]);
        _Reason ->
            Rid = TaskArgs#task_args.id,
            ?ERR("do_handle_refresh_trigger~p:~p~n",[Rid, _Reason])
    end.

%%纠正配置不匹配任务
do_refresh_conflict_trigger([], _TaskArgs, UpdateList) -> UpdateList;
do_refresh_conflict_trigger([RT | T], TaskArgs, UpdateList) ->
    TD = data_task:get(RT#role_task.task_id),
    NewUpdateList = do_conflict_correct(TD, TaskArgs, RT, UpdateList),
    do_refresh_conflict_trigger(T, TaskArgs, NewUpdateList).

%%检测条件
% 等级不匹配：直接清任务
% 任务内容不匹配：替换更新任务
do_conflict_correct(#task{type = Type} = TD, TaskArgs, RT, UpdateList)
    when Type == ?TASK_TYPE_MAIN orelse Type == ?TASK_TYPE_SIDE orelse
         Type == ?TASK_TYPE_TURN orelse Type == ?TASK_TYPE_CHAPTER orelse
         Type == ?TASK_TYPE_NUCLEON ->
    CheckList = [lv, content],
    case check_conflict(CheckList, TaskArgs, TD, RT) of
        {true, Reason, NewRT} ->
            do_conflict_correct_help(Reason, RT, NewRT),
            [1|UpdateList];
        _ -> UpdateList
    end;
do_conflict_correct(_, _TaskArgs, _RT, UpdateList) -> UpdateList.

check_conflict([], _TaskArgs, _TD, _RT) -> true;
check_conflict([lv | T], TaskArgs, TD, RT) ->
    Lv = TaskArgs#task_args.figure#figure.lv,
    case Lv < TD#task.level of
        true -> {true, del, RT};
        false -> check_conflict(T, TaskArgs, TD, RT)
    end;
check_conflict([content | T], TaskArgs, #task{content = Content} = TD, RT) ->
    CfgTaskMark = [content_to_mark(E, TaskArgs)|| E <- Content]
    ++ case TD#task.end_talk of
        0 -> []; %% end_talk = 0则直接提交任务
        _ ->
            [content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc,
            TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs)]
    end,
    Mark = RT#role_task.mark,
    %%检测任务内容冲突(主要存在情况)
    case check_content_conflict(CfgTaskMark, Mark, RT, []) of
        {true, Mark, _NewRT} -> check_conflict(T, TaskArgs, TD, RT);
        {true, _NewMark, NewRT} -> %%与配置有出入,处理
            % ?ERR("do_conflict_trigger~p,~p,~p~n", [TaskArgs#task_args.id, NewMark, Mark]),
            {true, update, NewRT};
        _ -> check_conflict(T, TaskArgs, TD, RT)
    end;
check_conflict([_H | T], TaskArgs, TD, RT) ->
    check_conflict(T, TaskArgs, TD, RT).

check_content_conflict([], [], RT, NewMark) -> {true, NewMark, RT#role_task{mark = NewMark}};
check_content_conflict([], _, RT, NewMark) -> {true, NewMark, RT#role_task{mark = NewMark}};
check_content_conflict([CfgE | CfgT], [ME | MET], RT, NewMark) ->
    [State, _, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, _, PathFind] = CfgE,
    case ME of
        [State, _Finish, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, _Num, _PathFind] -> %%相同不处理
            NewMark1 = NewMark ++ [ME],
            check_content_conflict(CfgT, MET, RT, NewMark1);
        [_, _, ContentType, Id, _, _, _, _, Num, _] -> %% 类型和id相同，保持数量不变，纠正其它信息
            case Num >= NeedNum of
                true ->
                    NewMark1 = NewMark ++ [[State, 1, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, Num, PathFind]];
                false ->
                    FinishState = ?IF(ContentType == ?TASK_CONTENT_END_TALK, 1, 0),
                    NewMark1 = NewMark ++ [[State, FinishState, ContentType, Id, NeedNum, RealSceneId, RealX, RealY, Num, PathFind]]
            end,
            check_content_conflict(CfgT, MET, RT, NewMark1);
        [_, _, _, _, _, _, _, _, _, _] -> %% 纠正所有信息
            NewMark1 = NewMark ++ [CfgE],
            check_content_conflict(CfgT, MET, RT, NewMark1);
        _ -> ok %%异常
    end;
check_content_conflict([CfgE | CfgT], [], RT, NewMark) ->
    NewMark1 = NewMark ++ [CfgE],
    check_content_conflict(CfgT, [], RT, NewMark1).

%%处理冲突的任务
do_conflict_correct_help(update, _OldRT, NewRT) ->
    #role_task{role_id = RId, task_id = TaskId, mark = Mark, end_state = EndState} = NewRT,
    NoFinishState = [EachState || [EachState, 0|_ ] <- Mark],
    if
        NoFinishState == [] -> NewState = EndState;
        true -> NewState = lists:min(NoFinishState)
    end,
    ?IF(NewState == 0, ok, refresh_npc_ico(RId)),
    upd_trigger(RId, TaskId, NewState, Mark),
    put_task_bag_list(NewRT#role_task{write_db = 0, state = NewState}),
    case NewState == EndState of
        true ->
            case lists:last(Mark) of
                [_, 1, ?TASK_CONTENT_END_TALK|_] -> ok;
                _R -> auto_finish_task(RId, TaskId)
            end;
        _ -> ok
    end;
do_conflict_correct_help(del, _OldRT, NewRT) ->
    #role_task{role_id = RId, task_id = TaskId} = NewRT,
    %% 删除缓存
    delete_task_bag_list(TaskId),
    %% 删除数据库
    del_trigger_from_sql(RId, TaskId),
    %% 刷新npc头图标
    refresh_npc_ico(RId),
    ok;
do_conflict_correct_help(_, _OldRT, _NewRT) -> ok.

%%处理已完成的触发支线任务
do_handle_refresh_trigger([], _TaskArgs, EventList) -> EventList;
do_handle_refresh_trigger([#role_task{type = ?TASK_TYPE_SIDE, task_id = TaskId, mark = TaskMark} |T], TaskArgs, OEventList) ->
    EventList = handle_finish_before_trigger(TaskId, TaskMark, TaskArgs, []),
    do_handle_refresh_trigger(T, TaskArgs, OEventList ++ EventList);
do_handle_refresh_trigger([#role_task{type = ?TASK_TYPE_MAIN, task_id = TaskId, mark = [ [_State, 0, ?TASK_CONTENT_DUNGEON|_T1] | _T2 ] = TaskMark } |T], TaskArgs, OEventList) ->
    EventList = handle_finish_before_trigger(TaskId, TaskMark, TaskArgs, []),
    do_handle_refresh_trigger(T, TaskArgs, OEventList ++ EventList);
do_handle_refresh_trigger([_RT |T], TaskArgs, EventList) ->
    do_handle_refresh_trigger(T, TaskArgs, EventList).

%% 刷新任务并发送更新列表
refresh_task(#task_args{id=Id}=TaskArgs) ->
    refresh_active(TaskArgs),
    refresh_npc_ico(Id),
    {ok, BinData} = pt_300:write(30006, []),
    lib_server_send:send_to_uid(Id, BinData).

%% 遍历所有任务看是否可接任务
refresh_active(TaskArgs) ->
    #task_args{figure=#figure{lv=Lv}} = TaskArgs,
    Tids = data_task_lv:get_ids(Lv),
    F = fun(Tid) -> get_data(Tid) end,
    QueryCacheListRed = [F(Tid) || Tid <- Tids, check_task_type(Tid), can_trigger(Tid, TaskArgs) == true],
    set_query_cache_list(QueryCacheListRed).

%% 日常和公会任务不会进入可接缓存
check_task_type(Tid)->
    #task{type = TaskType} = get_data(Tid),
    ?IF(TaskType == ?TASK_TYPE_DAILY orelse TaskType == ?TASK_TYPE_GUILD, false, true).

%% 刷新悬赏任务和公会周任务
refresh_trigger_by_type(TaskArgs, TaskType) ->
    TriggerTasks = get_trigger(),
    F1 = fun(RT, L) -> ?IF(RT#role_task.type =/= TaskType, [RT|L], L) end,
    NewTriggerList0 = lists:foldl(F1, [], TriggerTasks),
    KfDay = data_key_value:get(1030001),
    NewTriggerList  = case util:get_open_day()>= KfDay of
        true->
            fix_task_npc(NewTriggerList0,[],TaskArgs);
        _->
            NewTriggerList0
    end,
    set_task_bag_list(NewTriggerList).

%% 获取任务详细数据
get_data(TaskId) ->
    TD = data_task:get(TaskId),
    ?IF(TD == null, #task{}, TD).

%% 获取玩家能在该Npc接任务或者交任务
get_npc_task_list(NpcId, TaskArgs) ->
    {CanTrigger, Link, UnFinish, Finish} = get_npc_task(NpcId, TaskArgs),
    F1 = fun({Tid,TriTime,ShowTalk}, NS) -> TD = get_data(Tid), {Tid, NS, TD#task.name, TD#task.type,TriTime,ShowTalk} end,
    F2 = fun(TD, NS) -> {TD#task.id, NS, TD#task.name, TD#task.type,0,0} end,
    L1 = [F2(T1, 1) || T1 <- CanTrigger, T1#task.level =< TaskArgs#task_args.figure#figure.lv],
    L2 = [F1(T2, 4) || T2 <- Link],
    L3 = [F1(T3, 2) || T3 <- UnFinish],
    L4 = [F1(T4, 3) || T4 <- Finish],
    L1++L2++L3++L4.

%% 动态控制npc
do_dynamic_npc(TaskArgs, []) -> TaskArgs;
do_dynamic_npc(#task_args{id=Id, npc_info=NpcInfo}=TaskArgs, NpcShow) ->
    NewNpcInfo = lib_npc:change_role_npc_info(Id, NpcInfo, NpcShow),
    lib_player:apply_cast(Id, ?APPLY_CAST_STATUS, lib_npc, update_role_npc_info, [NewNpcInfo]),
    TaskArgs#task_args{npc_info=NewNpcInfo}.

%% 更新场景上npc的任务图标
refresh_npc_ico(#task_args{scene=Scene, sid=Sid, npc_info=NpcInfo}=TaskArgs) ->
    NpcList = lib_npc:get_scene_npc(Scene, NpcInfo),
    F = fun({Id, _, _, _, _, _}) ->
                S = ?IF(Id == 0, 0, get_npc_state(Id, TaskArgs)),
                [Id, S]
        end,
    L = lists:map(F, NpcList),
    {ok, BinData} = pt_120:write(12020, [L]),
    lib_server_send:send_to_sid(Sid, BinData);
refresh_npc_ico(#player_status{} = PS) ->
    TaskArgs = lib_task_api:ps2task_args(PS),
    refresh_npc_ico(TaskArgs);
refresh_npc_ico(PlayerId) ->
    case misc:get_player_process(PlayerId) of
        Pid when is_pid(Pid) -> lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_task, refresh_npc_ico, []);
        _ -> skip
    end.

%% 获取npc任务状态
get_npc_state(NpcId, TaskArgs) ->
    {CanTrigger, Link, UnFinish, Finish} = get_npc_task(NpcId, TaskArgs),
    %% 0表示什么都没有，1表示有可接任务，2表示已接受任务但未完成，3表示有完成任务，4表示有任务相关
    case length(Finish) > 0 of
        true -> 3;
        false ->
            case length(Link)>0 of
                true-> 4;
                false->
                    case length([0 || RT <- CanTrigger, RT#task.level =< TaskArgs#task_args.figure#figure.lv])>0 of
                        true  ->  1;
                        false ->
                            case length(UnFinish)>0 of
                                true -> 2;
                                false -> 0
                            end
                    end
            end
    end.

%% 获取npc任务关联
%%{可接任务，关联，任务未完成，完成任务}
get_npc_task(NpcId, TaskArgs)->
    CanTrigger = [ TS || TS <- get_query_cache_list(), lib_role_task:exchange_npc(TS#task.start_npc) =:= NpcId],
    %% 已经接了的任务处理
    {Link, Unfinish, Finish} = get_npc_other_link_task(NpcId, TaskArgs),
    {CanTrigger, Link, Unfinish, Finish}.

%% 获取已触发任务
get_npc_other_link_task(NpcId, TaskArgs) ->
    get_npc_other_link_task(get_task_bag_id_list(), {[], [], []}, NpcId, TaskArgs).

get_npc_other_link_task([], Result, _, _) -> Result;
get_npc_other_link_task([RT | T], {Link, Unfinish, Finish}, NpcId, TaskArgs) ->
    TD = get_data(RT#role_task.task_id),
    case is_finish(RT, TaskArgs) andalso get_end_npc_id(RT) =:= NpcId of  %% 判断是否完成
        true -> get_npc_other_link_task(T, {Link, Unfinish, Finish++[{RT#role_task.task_id,RT#role_task.trigger_time,filter_show_talk(RT#role_task.mark)}]}, NpcId, TaskArgs);
        false ->
            case task_talk_to_npc(RT, NpcId) of %% 判断是否和NPC对话
                true -> get_npc_other_link_task(T, {Link++[{RT#role_task.task_id,RT#role_task.trigger_time,filter_show_talk(RT#role_task.mark)}], Unfinish, Finish}, NpcId, TaskArgs);
                false ->
                    %% 获取npc未完成
                    case get_start_npc(TD#task.start_npc, TaskArgs#task_args.figure#figure.career) =:= NpcId of %% 判断是否接任务NPC
                        true -> get_npc_other_link_task(T, {Link, Unfinish++[{RT#role_task.task_id,RT#role_task.trigger_time,filter_show_talk(RT#role_task.mark)}], Finish}, NpcId, TaskArgs);
                        false -> get_npc_other_link_task(T, {Link, Unfinish, Finish}, NpcId, TaskArgs)
                    end
            end
    end.

%%过滤对话选项任务的完成TalkId
filter_show_talk([])->
    0;
filter_show_talk([H|T])->
    case H of
        [_, _, ?TASK_CONTENT_CHOOSE_TALK, _NeedId, ShowTalk, _Scene, _X, _Y,_Talk, _PathFind]->
            ShowTalk;
        _->
            filter_show_talk(T)
    end.

%%检查任务的下一内容是否为与某npc的对话
task_talk_to_npc(RT, NpcId)->
    Temp = [0 || [State, Fin, CType, Nid|_] <- RT#role_task.mark, State =:= RT#role_task.state, Fin =:= 0,lib_role_task:exchange_npc(Nid) =:= NpcId,lists:member(CType,[?TASK_CONTENT_TALK,?TASK_CONTENT_CHOOSE_TALK,?TASK_CONTENT_MAILER_RUN])],
    length(Temp)>0.

%% 获取任务对话id
get_npc_task_talk_id(TaskId, NpcId, TaskArgs) ->
    case get_data(TaskId) of
        null -> {none, 0};
        TD ->
            {CanTrigger, Link, UnFinish, Finish} = get_npc_task(NpcId, TaskArgs),
            case {lists:keymember(TaskId, #task.id, CanTrigger), lists:keymember(TaskId,1,Link),
                  lists:keymember(TaskId,1,UnFinish), lists:keymember(TaskId,1,Finish) } of
                {true, _, _, _} -> {start_talk, TD#task.start_talk};    %% 任务触发对话
                {_, true, _, _} ->    %% 关联对话
                    case get_one_trigger(TaskId) of
                        false ->
                            {none, 0};
                        RT ->
                            [Fir|_] = [TalkId || [State,Fin,CType,Nid,TalkId|_] <- RT#role_task.mark,
                                                 State=:= RT#role_task.state, Fin=:=0, lib_role_task:exchange_npc(Nid) =:= NpcId,lists:member(CType,[?TASK_CONTENT_TALK,?TASK_CONTENT_CHOOSE_TALK,?TASK_CONTENT_MAILER_RUN])],
                            {link_talk, Fir}
                    end;
                {_, _, true, _} -> {unfinished_talk, TD#task.unfinished_talk};  %% 未完成对话
                {_, _, _, true} ->   %% 提交任务对话
                    case get_one_trigger(TaskId) of
                        false ->
                            {none, 0};
                        RT ->
                            [Fir|_] = [TalkId || [_,_,?TASK_CONTENT_END_TALK,Nid,TalkId|_] <- RT#role_task.mark, lib_role_task:exchange_npc(Nid) == NpcId],
                            {end_talk, Fir}
                    end;
                _ -> {none, 0}
            end
    end.

%% 获取提示信息
%% 可接任务会有开始npc对话
get_tip(active, TaskId, #task_args{figure=#figure{career=Career}}=TaskArgs) ->
    TD = get_data(TaskId),
    case get_start_npc(TD#task.start_npc, Career) of
        0 -> [];
        StartNpcId ->
            [content_to_mark([0, ?TASK_CONTENT_TALK, StartNpcId, TD#task.start_talk, 0, 0, 0, TD#task.trigger_pathfind], TaskArgs)]
    end;
get_tip(trigger, TaskId, TaskArgs) ->
    RT = get_one_trigger(TaskId),
    [mark_refresh(TaskMark, TaskArgs) || TaskMark <- RT#role_task.mark].

%% 任务阶段内容 转为 任务完成情况记录
%% 任务内容格式：[State(阶段), ContentType(内容类型), Id(任务id), Num(采集或者杀怪的需要数量), ScneId, X, Y, PathFind]
%% 任务内存格式：[State(阶段), IsFinish(是否完成) ContentType(内容类型), Id(任务id), Num(采集或者杀怪的需要数量), ScneId, X, Y, RealNum(收集或者杀怪的完成数量), PathFind]
content_to_mark([State, ContentType, Id, Num, SceneId, X, Y, PathFind], TaskArgs) ->
    content_to_mark([State, ContentType, Id, Num, SceneId, X, Y, PathFind], [],TaskArgs).
content_to_mark([State, ContentType, Id, Num, SceneId, X, Y, PathFind], _Contents, TaskArgs)->
    case ContentType of
        ?TASK_CONTENT_START_TALK ->
            NewId=lib_role_task:exchange_npc(Id),
            {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
            [State, 0, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
        ?TASK_CONTENT_END_TALK ->
            NewId=lib_role_task:exchange_npc(Id),
            {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
            [State, 1, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
        ?TASK_CONTENT_TALK ->
            NewId=lib_role_task:exchange_npc(Id),
            {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
            [State, 0, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
        ?TASK_CONTENT_ITEM ->
            #task_args{id = RoleId, gs_dict = GsDict} = TaskArgs,
            case data_goods_type:get(Id) of
                #ets_goods_type{bag_location = BagLocation} ->
                    GoodsList = lib_goods_util:get_type_goods_list(RoleId, Id, BagLocation, GsDict, 0),
                    TotalNum = lib_goods_util:get_goods_total_num(GoodsList);
                _ ->
                    ?ERR("goods_num err: goods_type_id = ~p err_config", [Id]),
                    TotalNum = 0
            end,
            {Finish, NowNum} = ?IF(TotalNum >= Num, {1, Num}, {0, TotalNum}),
            [State, Finish, ContentType, Id, Num, SceneId, X, Y, NowNum, PathFind];
        ?TASK_CONTENT_MAILER_RUN ->
            NewId=lib_role_task:exchange_npc(Id),
            {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
            [State, 0, ContentType, NewId, Num, RealSceneId, RealX, RealY, 0, PathFind];
        _ ->
            [State, 0, ContentType, Id, Num, SceneId, X, Y, 0, PathFind]
    end;
content_to_mark(_, _Contents, _TaskArgs) -> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0].

%% 异常时刷新
mark_refresh([State, Fin, ContentType, Id, Num, Scene, _X, _Y, Count, PathFind]=Mark, TaskArgs) ->
    if
        Scene == 0 andalso (ContentType == ?TASK_CONTENT_START_TALK orelse
                            ContentType == ?TASK_CONTENT_END_TALK orelse
                            ContentType == ?TASK_CONTENT_TALK) ->
            NewNpc=lib_role_task:exchange_npc(Id),
            {RealSceneId, RealX, RealY} = get_npc_info(NewNpc, TaskArgs#task_args.npc_info),
            [State, Fin, ContentType, NewNpc, Num, RealSceneId, RealX, RealY, Count, PathFind];
        ContentType =:= ?TASK_CONTENT_CHOOSE_TALK ->
            NewNpc = lib_role_task:exchange_npc(Id),
            {RealSceneId, RealX, RealY} = get_npc_info(NewNpc, TaskArgs#task_args.npc_info),
            [State, Fin, ContentType, NewNpc, Num, RealSceneId, RealX, RealY, Count, PathFind];
        true ->
            Mark
    end.

%% 获取奖励
get_award_item(TD, TaskArgs) ->
    SL = get_special_reward_item(TD#task.special_goods_list,  TaskArgs, []),
    F = fun(E, LL) ->
                case E of
                    {?TYPE_GOODS, GoodsTypeId, Num} -> [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|LL];
                    _ -> [E|LL]
                end
        end,
    lists:foldl(F, SL, TD#task.award_list).


%% 获取特殊奖励
get_special_reward_item([], _TaskArgs, Rewards) -> Rewards;
get_special_reward_item([{Career, Sex, GoodsTypeId, Num}|SpecialGoods],  TaskArgs, Rewards) ->
    if
        Career == 0 andalso Sex == 0 ->
            get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
        Career == TaskArgs#task_args.figure#figure.career andalso Sex == 0->
            get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
        Sex == TaskArgs#task_args.figure#figure.sex andalso Career == 0 ->
            get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
        Career == TaskArgs#task_args.figure#figure.career andalso Sex == TaskArgs#task_args.figure#figure.sex ->
            get_special_reward_item(SpecialGoods, TaskArgs, [{?TYPE_BIND_GOODS, GoodsTypeId, Num}|Rewards]);
        true ->
            get_special_reward_item(SpecialGoods, TaskArgs, Rewards)
    end;
get_special_reward_item([_|SpecialGoods], TaskArgs, Rewards) ->
    get_special_reward_item(SpecialGoods, TaskArgs, Rewards).


%% 获取开始npc的id
%% 如果需要判断职业才匹配第2,3
get_start_npc(StartNpc, _) when is_integer(StartNpc) ->
    lib_role_task:exchange_npc(StartNpc);
get_start_npc([], _) -> 0;
get_start_npc([{career, Career, NpcId}|T], RoleCareer) ->
    case Career =:= RoleCareer of
        false -> get_start_npc(T, RoleCareer);
        true -> lib_role_task:exchange_npc(NpcId)
    end.

%%获取当前NPC所在的场景（自动寻路用）
get_npc_info(NpcId, NpcInfo) ->
    case lists:keyfind(NpcId, 1, NpcInfo) of
        {_, _IsShow, Scene, X, Y, _} -> {Scene, X, Y};
        false ->
            case lib_npc:get_npc_info_by_id(NpcId) of
                [] -> {0, 0, 0};
                Npc -> {Npc#ets_npc.scene, Npc#ets_npc.x, Npc#ets_npc.y}
            end
    end.

%%获取当前怪物所在的场景
get_mon_info(MonId) ->
    case mod_scene_mon:lookup(MonId) of
        [] -> {0, 0, 0};
        D -> {D#ets_scene_mon.scene, D#ets_scene_mon.x, D#ets_scene_mon.y}
    end.

%% 指定id任务是否可接
in_active(TaskId) ->
    find_query_cache_exits(TaskId).

get_active() ->
    get_query_cache_list().

get_active(type, Type) ->
    get_query_cache_list_type(Type).

%% 获取已触发任务列表
get_trigger() ->
    get_task_bag_id_list().

%% 获取该阶段任务内容
get_phase(RT)->
    [[State | T] || [State | T] <- RT#role_task.mark, RT#role_task.state =:= State].

%% 获取任务阶段的未完成内容:改成这个任务没有最终完成的
%% get_phase_unfinish(RT)->
%%     [[State, Fin | T] || [State, Fin |T] <- RT#role_task.mark].

get_one_trigger(TaskId) ->
    find_task_bag_list(TaskId).

%% 查看是否领取了指定的任务ID:是:true 否:false
is_trigger_task_id(TaskId) ->
    case find_task_bag_list(TaskId) of
        false -> false;
        _ -> true
    end.

%% 查看是否领取了指定的任务ID:是:true 否:false
is_during_task(TaskId) ->
    case find_task_bag_list(TaskId) of
        #role_task{state=S} when S=<0->
            true;
        _ ->
            false
    end.

%% 只能在任务进程调用
%% 查看是否完成了指定的任务ID:是:true 否:false
is_finish_task_id(TaskId) ->
    case find_task_log_list(TaskId) of
        false -> false;
        _ -> true
    end.

%% 只能在任务进程调用
%% 查看是否完成了多个指定的任务ID:
%% return 已完成的TaskId的Bin形式
%% 是否完成多个任务
%% TaskIds可以是列表形式:[TaskId]
%% TaskIds也可以打包形式(Bin形式):lib_task:pack_task_id([TaskId])
is_finish_task_ids(BinTaskIds) when is_binary(BinTaskIds)->
    TaskIds = unpack_task_id(BinTaskIds),
    FinishIds = is_finish_task_ids(TaskIds),
    pack_task_id(FinishIds);
%% return 已完成的TaskId
is_finish_task_ids(TaskIds) ->
    F = fun(TaskId, TmpList)->
        case find_task_log_list(TaskId) of
            false -> TmpList;
            _ -> [TaskId|TmpList]
        end
    end,
    FinishIds = lists:foldl(F, [], TaskIds),
    FinishIds.

%% 只能在任务进程调用
%% 是否完成对应章节的所有主线任务
is_finish_chapter_all_task(Chapter) ->
    List = data_task:get_ids_by_chapter(Chapter),
    F = fun(TaskId) ->
        is_finish_task_id(TaskId)
    end,
    lists:all(F, List).

%% 获取结束任务的npcid
get_end_npc_id(RT) when is_record(RT, role_task)->
    get_end_npc_id(RT#role_task.mark);

get_end_npc_id(TaskId) when is_integer(TaskId) ->
    case get_one_trigger(TaskId) of
        false -> 0;
        RT -> get_end_npc_id(RT)
    end;
get_end_npc_id([]) -> 0;
get_end_npc_id(Mark) ->
    case lists:last(Mark) of
        [_, _, ?TASK_CONTENT_END_TALK, NpcId|_] -> lib_role_task:exchange_npc(NpcId);
        _ -> 0  %% 这里是异常
    end.

%% ================================= 任务触发检查 =================================
%% 检查是否可以触发任务
can_trigger(TaskId, TaskArgs) ->
    #figure{lv = PlayerLv, career = PlayerCareer, realm = PlayerRealm,
            turn = PlayerTurn, guild_id = PlayerGuilId} = TaskArgs#task_args.figure,
    case find_task_bag_exits(TaskId) of
        true ->
            {false, ?ERRCODE(err300_task_trigger)}; %%已经触发过了
        false ->
            case data_task_condition:get(TaskId) of
                null ->
                    {false, ?ERRCODE(err300_task_config_null)};
                #task_condition{type = TaskType, level = Level, level_max = MaxLevel, realm = Realm,
                                career = Career, turn = Turn, prev = Prev, repeat = Repeat, condition = Condition} = _TD ->
                    if
                        (TaskType ==?TASK_TYPE_DAILY orelse TaskType == ?TASK_TYPE_GUILD) andalso
                        (PlayerLv > MaxLevel orelse PlayerLv < Level)->
                            {false, ?ERRCODE(err300_lv_not_enough)}; %% 等级不足
                        PlayerLv < Level ->
                            {false, ?ERRCODE(err300_lv_not_enough)}; %% 等级不足
                        TaskType == ?TASK_TYPE_GUILD andalso PlayerGuilId == 0 -> %% 没有帮派
                            {false, ?ERRCODE(err300_not_guild)};
                        Realm /=0 andalso PlayerRealm /= Realm ->
                            {false, ?ERRCODE(err300_realm_diff)};  %% 阵营不符合
                        Career /= 0 andalso PlayerCareer /= Career ->
                            {false, ?ERRCODE(err300_career_diff)}; %% 阵营不符合
                        Turn /= 0 andalso PlayerTurn < Turn ->
                            {false, ?ERRCODE(err300_turn_diff)};   %% 转生次数不符合(向下兼容)
                        TaskType == ?TASK_TYPE_TURN andalso PlayerTurn > Turn andalso PlayerTurn > 0 ->
                            {false, ?ERRCODE(err300_turn_diff)};   %% 如果是转生任务 但是玩家的转生次数已经超过了任务的转生次数则不能重复触发
                        true ->
                            case check_prev_task(Prev) of
                                false -> {false, ?ERRCODE(err300_prev_not_fin)}; %% 前置任务未完成
                                true  ->
                                    case check_repeat(TaskId, Repeat) of
                                        false -> {false, ?ERRCODE(err300_fin)};
                                        true ->
                                            case length([1||ConditionItem <- Condition, check_condition(ConditionItem, TaskId, TaskArgs)=:=false]) =:= 0 of
                                                true  -> true;
                                                false -> {false, ?ERRCODE(err300_condition_err)}
                                            end
                                    end
                            end
                    end
            end
    end.

% %% 获取下一等级的任务
% next_lev_list(PS) ->
%     Tids = data_task:get_ids(),
%     F = fun(Tid) -> TD = get_data(Tid), (PS#player_status.figure#figure.lv + 1) =:= TD#task.level end,
%     [XTid || XTid<-Tids, F(XTid)].

%% 是否重复可以接
check_repeat(TaskId, Repeat) ->
    case Repeat =:= 0 of
        true -> find_task_log_exits(TaskId) =/= true;
        false -> true
    end.

%% 前置任务
check_prev_task(PrevId) ->
    case PrevId =:= 0 of
        true  -> true;
        false -> find_task_log_exits(PrevId)
    end.

%% 任务条件建检查
%% 是否完成任务
check_condition({task, TaskId}, _, _) -> find_task_log_exits(TaskId);
%% 是否完成其中之一的任务
check_condition({task_one, TaskList}, _, _) -> lists:any(fun(Tid)-> find_task_log_exits(Tid) end, TaskList);
%% 今天的任务次数是否过多
check_condition({daily_limit, Num}, TaskId, _) ->
    case find_task_log_list(TaskId) of false -> true; RTL   -> RTL#role_task_log.count < Num end;
%%验证开服天数
check_condition({open_day,Day},_,_)->
    OpDay = util:get_open_day(),
    OpDay>=Day;
%% 容错
check_condition(_Other, _, _TaskArgs) -> false.

%% ================================= 触发任务 =================================
%% 自动触发任务
auto_trigger(TaskArgs) ->
    ActiveTasks = get_active(), %% 获取可以接的任务
    do_auto_trigger(TaskArgs,ActiveTasks).
auto_trigger(Type,TaskArgs)->
    ActiveTasks = get_active(type,Type),
    do_auto_trigger(TaskArgs,ActiveTasks).
do_auto_trigger(TaskArgs,ActiveTasks)->
    F = fun(TD, Bool) ->
                case TD#task.start_npc == 0 andalso TD#task.start_talk == 0 of
                    true  -> trigger(TD#task.id, TaskArgs), true;
                    false -> Bool
                end
        end,
    lists:foldl(F, false, ActiveTasks).

%% 手动触发任务
%% return true | {false, Code}
trigger(TaskId, TaskArgs) ->
    %% 注: 给机器人放行逻辑
    IsRobot = lib_robot:is_robot(TaskArgs),
    CanTrigger = case can_trigger(TaskId, TaskArgs) of
        {false, _ErrCode} when IsRobot == true -> true;
        {false, ErrCode} -> {false, ErrCode};
        true -> true
    end,
    case CanTrigger of
        {false, Res} -> {false, Res};
        true ->
            TD = get_data(TaskId),
            TaskMark = [content_to_mark(E, TaskArgs)||E<-TD#task.content]
                ++ case TD#task.end_talk of
                       0 -> []; %% end_talk = 0则直接提交任务
                       _ -> [content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc,
                                              TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs)]
                   end,
            Now = utime:unixtime(),
            add_trigger(TaskArgs#task_args.id, TaskId, Now, 0, TD#task.state,
                        TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
            case handle_finish_before_trigger(TaskId, TaskMark, TaskArgs, []) of
                EventList when is_list(EventList) andalso EventList =/= [] ->
                    lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, lib_task_api, cast_handle_refresh_trigger, [EventList]);
                _ -> ok
            end,
            %% 转生任务接取了要通知其他模块
            ?IF(TD#task.type =/= ?TASK_TYPE_TURN, skip,
                lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, transform, trigger_task, [TD#task.id])),
            get_my_task_list(TD#task.type, TaskArgs),
            refresh_npc_ico(TaskArgs),
            lib_task_event:trigger_after(TD, TaskArgs),
            %lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, ta_agent_fire, task_completed, [Now, [TD#task.id, 1, 0]]),
            true
    end.

%% 有部分支线任务内容在触发时候判断
%% 增加的对应类型,要同步在lib_task_api:make_action_list()增加类型支持
handle_finish_before_trigger(_TaskId, [], _TaskArgs, EventList) -> EventList;
%%转生任务
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_TURN, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_TURN,Id} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%好友数量
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ADD_FRIEND, _Id, Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_ADD_FRIEND, Num, NowNum} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%副本进度
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUN_WAVE, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_DUN_WAVE, Id} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%某个副本
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON, Id} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%副本类型
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON_TYPE, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON_TYPE, Id} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%指定BOSS
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_KILL_BOSS, Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_KILL_BOSS, Id} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备进化
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ERISE, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_ERISE} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备强化
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_STREN, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_STREN} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备附能
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_EMPOWER, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_EMPOWER} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%活跃度
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DAY_ACTIVITY, _Id, _Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_DAY_ACTIVITY} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%副本类型特定经验
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON_EXP, Id, Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON_EXP, Id, Num} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%层级副本类型
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DunId, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DunId} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%动态积分购买
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_SCORE_BUY, Item,_Num, _Scene, ShopId, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_SCORE_BUY, Item, ShopId} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%好友度
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_FRIEND_EXP, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_FRIEND_EXP, NowNum} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%竞技场
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ARENA_TIMES, _Id,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_ARENA_TIMES} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%装备套装
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_EQUIP_SUIT, _Id,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_EQUIP_SUIT} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%进阶系统
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_FOSTER_GRADE, Type} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%预期任务
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_EXPECT_TASK, ExpectTask,_Num, _Scene, _X, _Y, _NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId,?TASK_CONTENT_EXPECT_TASK,ExpectTask}| EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%宝宝同心值
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_CHILD_HEART, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_CHILD_HEART,NowNum} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%战力任务
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_COMBAT, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_COMBAT,NowNum} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%任意主动技能升级次
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ACTIVE_SKILL_LV_TIMES, _Id,_Num, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_ACTIVE_SKILL_LV_TIMES,NowNum} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%指定商定购买技能书
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_SOME_SHOP_BUY_BOOK, ShopId,NeedNum, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_SOME_SHOP_BUY_BOOK,ShopId,NowNum,NeedNum} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
%%任意商定购买技能书
handle_finish_before_trigger(TaskId, [ [_State, 0, ?TASK_CONTENT_ANY_SHOP_BUY_BOOK, _Id,NeedNum, _Scene, _X, _Y, NowNum, _PathFind]|T ], TaskArgs, EventList) ->
    NewEventList = [{TaskId, ?TASK_CONTENT_ANY_SHOP_BUY_BOOK,NowNum,NeedNum} | EventList],
    handle_finish_before_trigger(TaskId, T, TaskArgs, NewEventList);
handle_finish_before_trigger(TaskId, [_|T], TaskArgs, EventList) -> handle_finish_before_trigger(TaskId, T, TaskArgs, EventList).

%% ================================= 完成任务 =================================
%% 自动完成
auto_finish(TaskArgs) when TaskArgs#role_task.type =/= ?TASK_TYPE_SIDE->
     TriggerTasks = get_trigger(),
     F = fun(RT, Bool) ->
             case RT#role_task.state == RT#role_task.end_state of
                true ->
                    case lists:last(RT#role_task.mark) of
                        [_, 1, ?TASK_CONTENT_END_TALK|_] -> Bool;
                        _ ->
                            case finish(RT#role_task.task_id, [], TaskArgs) of
                                {false, _} -> Bool;
                                true -> true;
                                {ok, _} -> true
                            end
                    end;
                false -> Bool
            end
    end,
    case lists:foldl(F, false, TriggerTasks) of
        false -> true;
        true  -> auto_trigger(TaskArgs) %% 这里是个递归，可能会继续触发完成
    end;
auto_finish(_TaskArgs) ->
    true.

%% return true | {false, Code} | {ok, 1}
finish(TaskId, ParamList, TaskArgs) ->
    case is_finish(TaskId, TaskArgs) of
        false ->
            #task{type = Type} = get_data(TaskId),
            if
                ParamList == cost_finish andalso %% 花费完成
                (Type == ?TASK_TYPE_DAILY orelse Type == ?TASK_TYPE_GUILD orelse Type == ?TASK_TYPE_SIDE)->
                    do_normal_finish(TaskId, ParamList, TaskArgs);
                true ->
                    %% ?ERR("error no finish task id:~p~n", [TaskId]),
                    {false, ?ERRCODE(err300_task_no_finish)}
            end;
        true ->
            do_normal_finish(TaskId, ParamList, TaskArgs)
    end.

do_normal_finish(TaskId, ParamList, TaskArgs) ->
    #task_args{id = Id} = TaskArgs,
    TD = get_data(TaskId),
    RT = get_one_trigger(TaskId),
    %% 奖励物品
    if
        TD#task.type == ?TASK_TYPE_DAILY orelse TD#task.type == ?TASK_TYPE_GUILD ->
            Items0 = calc_task_type_reward(TD#task.type, RT#role_task.lv),
            BaseItems = get_award_item(TD, TaskArgs),
            Items = calc_extra_ratio_type_reward(TD#task.type, BaseItems, TaskArgs)++Items0;
        TD#task.type == ?TASK_TYPE_MAIN -> %%计算双倍奖励
            BaseItems = get_award_item(TD, TaskArgs),
            Items = calc_dobule_reward(BaseItems, ParamList);
        true ->
            Items = get_award_item(TD, TaskArgs)
    end,
    LogType = get_log_type(TD#task.type),
    Produce=#produce{
        type=LogType, subtype = TaskId, title=data_language:get(145),
        content=data_language:get(146), reward=Items, show_tips=3,
        remark = lists:concat(["task_id:", TaskId])
    },
    lib_goods_api:send_reward_with_mail(Id, Produce, ?MOD_TASK),
    {ok, BinData} = pt_300:write(30004, [TaskId, 1, Items]),
    lib_server_send:send_to_sid(TaskArgs#task_args.sid, BinData),
    %% 判断特殊类型的任务完成
    if
        TD#task.type == ?TASK_TYPE_DAILY orelse TD#task.type == ?TASK_TYPE_GUILD ->
            finish_task_type(TD#task.type, Id, TaskArgs, RT);
        true ->
            %% 数据库回写
            Time = utime:unixtime(),
            add_log(Id, TaskId, TD#task.type, RT#role_task.trigger_time, Time, 0),
            %% 刷新任务
            refresh_active(TaskArgs),
            %% 完成任务事件
            TalkId = filter_task_talk(RT#role_task.mark),
            lib_task_event:async_finish(Id, TaskId, TalkId),
            case auto_trigger(TaskArgs) of
                true ->
                    get_my_task_list(TD#task.type, TaskArgs),
                    %%主线需要补充更新推送
                    case TD#task.type =:= ?TASK_TYPE_MAIN of
                        true->
                            refresh_npc_ico(TaskArgs);
                        _->
                            skip
                    end,
                    trigger_next_special_task(TD, RT),
                    true;
                _    ->
                    get_my_task_list(TD#task.type, TaskArgs),
                    refresh_npc_ico(TaskArgs),
                    %% check some special task
                    trigger_next_special_task(TD, RT),
                    true
            end
    end.

get_log_type(?TASK_TYPE_DAILY) -> finish_daily_task;
get_log_type(?TASK_TYPE_GUILD) -> finish_guild_task;
get_log_type(_) -> task.

trigger_next_special_task(TD, RT)->
    #task{type = Type, kind = Kind, next = NextTaskId} = TD,
    case Type == ?TASK_TYPE_SIDE andalso NextTaskId > 0 of
        false -> skip;
        true ->
            #role_task{mark = Mark} = RT,
            if
                Kind == ?TASK_KIND_STREN ->
                    lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, lib_task_api, auto_stren_equip, []);
                Kind == ?TASK_KIND_RUNE_DUN ->
                    case get_mark_content_type_num(Mark, ?TASK_CONTENT_DUNGEON_RUNE) of
                        {DunType, DunId} ->
                            lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, lib_task_api, fin_level_dun, [DunType, DunId]);
                        _ -> skip
                    end;
                Kind == ?TASK_KIND_EXP_DUN ->
                    case get_mark_content_type_num(Mark, ?TASK_CONTENT_DUNGEON_EXP) of
                        [] -> skip;
                        {DunType, Exp} -> lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, lib_task_api, fin_dun_exp, [DunType, Exp])
                    end;
                true ->
                    skip
            end
    end.

get_mark_content_type_num([[_, _, ?TASK_CONTENT_DUNGEON_RUNE, DunType, _, _, _, _, RuneDunId, _]|_Mark], ?TASK_CONTENT_DUNGEON_RUNE)-> {DunType, RuneDunId};
get_mark_content_type_num([[_, _, ?TASK_CONTENT_DUNGEON_EXP,  DunType, _, _, _, _, NowExpNum, _]|_Mark], ?TASK_CONTENT_DUNGEON_EXP) -> {DunType, NowExpNum};
get_mark_content_type_num([_H|Mark], ContentType) -> get_mark_content_type_num(Mark, ContentType);
get_mark_content_type_num([], _ContentType)-> [].

%% 完成悬赏和公会周任务
finish_task_type(TaskType, RoleId, TaskArgs, RT)->
    case data_task_lv_dynamic:get_task_type(TaskType) of
        #task_type{count = Count, module_id = ModuleId, counter_id = CounterId} ->
                    % mod_guild:add_growth(RoleId, Figure#figure.guild_id, 1,  finish_guild_task, {task_type, TaskType}),
            FinishCount = lib_daily:get_count(RoleId, ModuleId, CounterId)+1,
            ProduceType = ?IF(TaskType == ?TASK_TYPE_GUILD, finish_guild_task, finish_daily_task),
            lib_daily:increment(RoleId, ModuleId, CounterId),
            %% 数据库回写
            Time = utime:unixtime(),
            LogType = ?IF(lists:member(TaskArgs#task_args.figure#figure.lv, ?DAILY_SPECIAL_LV) andalso TaskType == ?TASK_TYPE_DAILY, 1, TaskType),
            add_log(TaskArgs#task_args.id, RT#role_task.task_id, LogType, RT#role_task.trigger_time, Time, FinishCount),
            %% 完成任务事件
            lib_task_event:async_finish(TaskArgs#task_args.id, RT#role_task.task_id,0),
            case calc_extra_task_type_reward(RT#role_task.task_id, TaskType, FinishCount, RT#role_task.lv) of
                [] -> skip;
                Reward ->
                    Produce=#produce{
                        type=ProduceType, subtype = RT#role_task.task_id, title=data_language:get(145),
                        content=data_language:get(146), reward=Reward, show_tips=3,
                        remark = lists:concat(["task_id:", RT#role_task.task_id])
                    },
                    lib_goods_api:send_reward_with_mail(TaskArgs#task_args.id, Produce, ?MOD_TASK)
                    % lib_goods_api:send_reward_by_id(Reward, ProduceType, RT#role_task.task_id, TaskArgs#task_args.id)
            end,
            TaskType == ?TASK_TYPE_GUILD andalso guild_run_assist:check_run_assist_trigger(TaskArgs#task_args.id),
            if
                FinishCount >= Count ->
                    %% ?ERR("finish task type:~p~n FinishCount:~p~n", [TaskType, FinishCount]),
                    get_my_task_list(TaskType, TaskArgs),
                    refresh_npc_ico(TaskArgs),
                    if
                        TaskType == ?TASK_TYPE_DAILY -> {ok, ?ERRCODE(err300_daily_task_finished)};
                        true -> {ok, ?ERRCODE(err300_guild_task_finished)}
                    end;
                true ->
                    lib_player:apply_cast(RoleId, ?APPLY_CAST_STATUS, ?MODULE, finish_task_type_after, [TaskType]),
                    {ok, ?SUCCESS}
                    % trigger_type_task(TaskType, TaskArgs)
            end;
        _R ->
            ?ERR("error task type:~p~n _R:~p~n", [TaskType, _R]),
            {false, ?FAIL}
    end.

finish_task_type_after(PS, ?TASK_TYPE_DAILY) ->
    TaskArgs  = lib_task_api:ps2task_args(PS),
    case get_task_bag_id_list_type(?TASK_TYPE_DAILY) of
        [] ->
            {_, Code} = trigger_type_task(?TASK_TYPE_DAILY, TaskArgs),
            {ok, Bin} = pt_300:write(30009, [Code]),
            lib_server_send:send_to_uid(TaskArgs#task_args.id, Bin),
            PS;
        _->
            PS
    end;
finish_task_type_after(PS, TaskType) ->
    TaskArgs  = lib_task_api:ps2task_args(PS),
    {_, Code} = trigger_type_task(TaskType, TaskArgs),
    {ok, Bin} = pt_300:write(30009, [Code]),
    lib_server_send:send_to_uid(TaskArgs#task_args.id, Bin),
    PS.

%% 检查扣除物品
%% check_task_cost_goods(TD, RT, ParamList, TaskArgs) ->
%%     #task_args{id = Id, gs_dict = GsDict} = TaskArgs,
%%     %% 删除回收物品
%%     if
%%         TD#task.end_item == [] -> ok;
%%         ParamList == cost_finish -> ok;    %% 特殊任务消耗直接完成不需要扣除物品
%%         true ->
%%             case get_task_cost_goods(TD, RT) of
%%                 [] -> ok;
%%                 [{GoodsId, Num}|_] ->
%%                     case data_goods_type:get(GoodsId) of
%%                         #ets_goods_type{bag_location = BagLocation} ->
%%                             GoodsList = lib_goods_util:get_type_goods_list(Id, GoodsId, BagLocation, GsDict),
%%                             TotalNum = lib_goods_util:get_goods_totalnum(GoodsList),
%%                             if
%%                                 TotalNum >= Num ->
%%                                     lib_player:apply_cast(Id, ?APPLY_CAST_STATUS, lib_goods_api, goods_delete_type_list, [[{GoodsId, Num}], finish_task]),
%%                                     ok;
%%                                 true ->
%%                                     {false, ?ERRCODE(goods_not_enough)}
%%                             end;
%%                         _ ->
%%                             {false, ?ERRCODE(err150_no_goods)}
%%                     end
%%             end
%%     end.

%% 根据任务内容去扣除物品
%% get_task_cost_goods(TD, RT) ->
%%     if
%%         TD#task.type == ?TASK_TYPE_DAILY orelse TD#task.type == ?TASK_TYPE_GUILD ->
%%             #role_task{mark = Mark, kind = _Kind} = RT,
%%             case lists:keyfind(?TASK_CONTENT_ITEM, 3, Mark) of
%%                 false -> [];
%%                 {_State, _, _CType, Id, Num, _SceneId, _X, _Y, _Num, _FindPath} ->
%%                     [{Id, Num}]
%%             end;
%%         true ->
%%             TD#task.end_item
%%     end.

%% 经验双倍奖励
calc_dobule_reward(BaseItems, [{double_type, _}|_T]) ->
    lists:foldl(
    fun ({?TYPE_EXP, GoodsId, Num}, AccList) -> %%经验双倍奖励
            [{?TYPE_EXP, GoodsId, Num * 2} | AccList];
        ({_TypeId, _GoodsId, _Num} = Info, AccList) ->
            [Info| AccList];
        (_, AccList) -> AccList
    end,
    [],
    BaseItems
    );
calc_dobule_reward(BaseItems, _ParamList) -> BaseItems.

%% 赏金任务
calc_task_type_reward(?TASK_TYPE_DAILY, Lv)->
    ExpValue0 = data_exp_base:get(Lv),
    LvExtra = data_award_exp:get_exp_extra(?MOD_TASK,1,Lv),
    [{?TYPE_EXP, ?GOODS_ID_EXP, round(ExpValue0*LvExtra/10000)}];
%% 公会周任务
calc_task_type_reward(?TASK_TYPE_GUILD, Lv) ->
    ExpValue0 = data_exp_base:get(Lv),
    LvExtra = data_award_exp:get_exp_extra(?MOD_TASK,2,Lv),
    [{?TYPE_EXP, ?GOODS_ID_EXP, round(ExpValue0*LvExtra/10000)}];
calc_task_type_reward(_, _) -> [].

%% 计算赏金和公会周任务额外奖励
calc_extra_task_type_reward(TaskId, _TaskType, FinishCount, Lv) ->
    case FinishCount rem 5 of %% 每十次一个
        0 when FinishCount /= 0->
            case data_task_lv_dynamic:get_type_task_dynamic(TaskId, Lv) of
                #task_lv_dynamic_content{extra_reward = ExtraReward} ->
                    case lists:keyfind(FinishCount, 1, ExtraReward) of
                        {_, Rewards} when is_list(Rewards)-> Rewards;
                        _ -> []
                    end;
                _ -> []
            end;
        _ -> []
    end.

%% 计算公会任务的加成奖励
calc_extra_ratio_type_reward(?TASK_TYPE_GUILD, Items, _TaskArgs) ->
    Rewards = lib_goods_api:make_reward_unique(Items),
    Rewards;
calc_extra_ratio_type_reward(?TASK_TYPE_DAILY, Items, TaskArgs) ->
    Rewards = lib_goods_api:make_reward_unique(Items),
    #task_args{figure = #figure{vip_type = _VipType, vip = _VipLv}} = TaskArgs,
    % VipRatio = lib_vip:get_vip_privilege(VipType, VipLv, ?MOD_TASK, 3),
    VipRatio = 0,
    Fun = fun
        ({?TYPE_EXP, GoodTypeId, Num})->
            {?TYPE_EXP, GoodTypeId, trunc(Num * (10000 + VipRatio) / 10000 )};
        (Element) -> Element
    end,
    [Fun(Item) || Item <- Rewards];
calc_extra_ratio_type_reward(_, Items, _) -> Items.

%% 放弃任务
abnegate(TaskId, TaskArgs) ->
    case get_one_trigger(TaskId) of
        false -> Code = 0;
        _RT ->
            %% 删除缓存
            delete_task_bag_list(TaskId),
            %% 删除数据库
            del_trigger_from_sql(TaskArgs#task_args.id, TaskId),
            %% 刷新
            refresh_active(TaskArgs),
            refresh_npc_ico(TaskArgs),
            Code = 1
    end,
    {ok, BinData} = pt_300:write(30005, [Code]),
    lib_server_send:send_to_sid(TaskArgs#task_args.sid, BinData).


%% 有部分任务内容在触发的时候可能就完成了
%% preact_finish(Rid) ->
%%     lists:member(true, [preact_finish(RT, Rid) || RT <- get_task_bag_id_list()]).

%% preact_finish(TaskId, Rid) when is_integer(TaskId) ->
%%     RT = get_one_trigger(TaskId),
%%     case RT of
%%         false -> skip;
%%         _ -> preact_finish(RT, Rid)
%%     end;

%% preact_finish(RT, Rid) ->
%%     lists:member(true, [preact_finish_check([State, Fin | T], Rid) || [State, Fin | T] <- RT#role_task.mark, State =:= RT#role_task.state, Fin =:= 0]).

%% %% 装备武器
%% preact_finish_check([_, 0, equip, _ItemId | _], PS) when is_record(PS, player_status)->
%%     false;

%% %% 加入帮派
%% preact_finish_check([_, 0, join_guild | _], PS) when is_record(PS, player_status)->
%%     false;

%% %% 购买武器
%% preact_finish_check([_, 0, buy_equip, _ItemId | _], _PS) when is_record(_PS, player_status)->
%%     skip;

%% %% 学习技能
%% preact_finish_check([_, 0, learn_skill, _SkillId | _], PS) when is_record(PS, player_status)->
%%     false;

%% %% 收集物品
%% preact_finish_check([_, 0, item, ItemId, _, NowNum | _], PS) when is_record(PS, player_status) ->
%%     Dict = lib_goods_dict:get_player_dict(PS),
%%     Num = lib_goods_util:get_task_goods_num(PS#player_status.id, ItemId, Dict),
%%     case Num >  NowNum of
%%         false -> false;
%%         true -> action(PS#player_status.id, item, [[{ItemId, Num}]])
%%     end;

%% preact_finish_check(_, _) ->
%%     false.

%% 检测任务是否完成
is_finish(TaskId, TaskArgs) when is_integer(TaskId) ->
    case get_one_trigger(TaskId) of
        false -> false;
        RT ->
            IsFinish = is_finish(RT, TaskArgs),
            % ?PRINT("####### is_finish:~p~n", [{TaskArgs#task_args.id, TaskArgs#task_args.figure#figure.lv, TaskArgs#task_args.source, TaskId, IsFinish, lib_robot:is_robot(TaskArgs)}]),
            %% 注: 给机器人放行逻辑
            case {IsFinish, lib_robot:is_robot(TaskArgs)} of
                {false, true} -> true;
                _ -> IsFinish
            end
    end;

is_finish(RT, TaskArgs) when is_record(RT, role_task) ->
    is_finish_mark(RT#role_task.mark, TaskArgs);

is_finish(Mark, TaskArgs) when is_list(Mark) ->
    is_finish_mark(Mark, TaskArgs).

is_finish_mark([], _) -> true;
is_finish_mark([[_, 1|_] | T], TaskArgs) -> is_finish_mark(T, TaskArgs);
is_finish_mark([MK|_T], _TaskArgs) when is_list(MK) -> false;
is_finish_mark([MK|_T], _TaskArgs) -> ?ERR("error task mark:~p~n", [MK]), false.


%% ================================= 任务进度更新 =================================
%% 批量刷新任务过程
action_more(EventList) ->
    [action(TaskId, Rid, Event, ParamList) || {TaskId, Event, ParamList, Rid} <- EventList].

%% 已接所有任务更新判断
action(Rid, Event, ParamList) ->
    case get_task_bag_id_list() of
        []  -> false;
        RTL ->
            Result = [action_one(RT, Rid, Event, ParamList)|| RT<- RTL],
            lists:member(true, Result)
    end.

%% 单个任务更新判断
action(TaskId, Rid, Event, ParamList)->
    case get_one_trigger(TaskId) of
        false -> false;
        RT -> action_one(RT, Rid, Event, ParamList)
    end.

%% 触发任务
%% 如果是减少：
%% 判断：阶段：后退，保持，前进；
%% 变成没有完成状态
action_one(RT, Rid, Event, ParamList) ->
    NowTime = utime:unixtime(),
    #role_task{task_id = TaskId, type = TaskType, trigger_time = TriggerTime} =  RT,
    if
        TaskType == ?TASK_TYPE_CHAPTER ->
            LimitTime = ?IF(TaskId == 101 orelse TaskId == 102, ?LIMIT_TIME1, ?LIMIT_TIME2);
        true -> LimitTime = 0
    end,
    if
        TaskType == ?TASK_TYPE_CHAPTER andalso NowTime > TriggerTime + LimitTime -> %% 限时章节任务,大于限时后不做触发
            false;
        true ->
            F = fun(MarkItem, Update) ->
                        {NewMarkItem, NewUpdate} = content(MarkItem, RT#role_task.state, Event, ParamList),
                        case NewUpdate of
                            true  -> {NewMarkItem, true};
                            false -> {NewMarkItem, Update}
                        end
                end,
            {NewMark, UpdateAble} = lists:mapfoldl(F, false, RT#role_task.mark),
            case UpdateAble of
                false ->
                    false;
                true ->
                    NoFinishState = [EachState || [EachState, 0|_ ] <- NewMark],
                    if
                        NoFinishState == [] -> NewState = RT#role_task.end_state;
                        true -> NewState = lists:min(NoFinishState)
                    end,
                    %% 更新任务记录和任务状态
                    %% 更新数据，但是不更新步骤状态，先缓存,下线的时候再记录数据库
                    NewRT = if
                                RT#role_task.type == ?TASK_TYPE_TURN -> %% 转生任务比较难，默认保存数据
                                    upd_trigger(RT#role_task.role_id, RT#role_task.task_id, NewState, NewMark),
                                    RT#role_task{write_db = 0, state = NewState, mark = NewMark};
                                RT#role_task.state == NewState ->
                                    RT#role_task{write_db = 1, mark = NewMark};
                                true ->
                                    upd_trigger(RT#role_task.role_id, RT#role_task.task_id, NewState, NewMark),
                                    RT#role_task{write_db = 0, state = NewState, mark = NewMark}
                            end,
                    put_task_bag_list(NewRT),
                    ?IF(NewState == RT#role_task.state, ok, refresh_npc_ico(Rid)),
                    % TEST
                    % Ticket = config:get_ticket(),
                    % case Ticket =:= ?INTERNAL_TICKET of
                    %     true -> auto_finish_task(Rid, RT#role_task.task_id);
                    %     false ->skip
                    % end,
                    case NewState == RT#role_task.end_state of
                        true ->
                            case lists:last(NewMark) of
                                [_, 1, ?TASK_CONTENT_END_TALK|_] ->
                                    notify_client_new_mark(RT#role_task.task_id, Rid, NewState, NewMark);
                                _R when TaskType =:= ?TASK_TYPE_NUCLEON ->
                                    notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
                                _R when TaskType =:= ?TASK_TYPE_FOUR ->
                                    notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
                                _R when TaskType =:= ?TASK_TYPE_DAILY ->
                                    notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
                                _R when TaskType =:= ?TASK_TYPE_GUILD ->
                                    notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark);
                                _R when TaskType =/= ?TASK_TYPE_SIDE ->
                                    auto_finish_task(Rid, RT#role_task.task_id);
                                _R ->
                                    notify_client_new_state_mark(RT#role_task.task_id, Rid, NewState, NewMark)
                            end,
                            %lib_player:apply_cast(RT#role_task.role_id, ?APPLY_CAST_STATUS, ta_agent_fire, task_completed,
                            %    [NowTime, [RT#role_task.task_id, 2, NowTime - TriggerTime]]),
                            true;
                        _ ->
                            notify_client_new_mark(RT#role_task.task_id, Rid, NewState, NewMark),
                            true
                    end
            end
    end.

%% 通知客户端刷新任务栏
notify_client_new_mark(TaskId, Rid, NowState, Mark) ->
    {WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(Mark),
    F = fun([EState|_]) -> EState == NowState end,
    {ok, BinData} = pt_300:write(30001, [TaskId, lists:filter(F, Mark), WitchState, NeedNum, NowNum]),
    lib_server_send:send_to_uid(Rid, BinData).

%% 通知客户端刷新任务已完成状态
notify_client_new_state_mark(TaskId, Rid, _NowState, Mark) ->
    {WitchState, NeedNum, NowNum} = get_mon_or_goods_nums(Mark),
    F = fun([_, EState|_T]) -> EState >0 end,
    {ok, BinData} = pt_300:write(30001, [TaskId, lists:filter(F, Mark), WitchState, NeedNum, NowNum]),
    lib_server_send:send_to_uid(Rid, BinData).

get_mon_or_goods_nums([]) -> {0, 0, 0};
get_mon_or_goods_nums([H|Mark])->
    case H of
        [State, _, ContentType, Id, NeedNum, _, _, _, NowNum, _] when
              ContentType == ?TASK_CONTENT_KILL;
              ContentType == ?TASK_CONTENT_DUNGEON;
              ContentType == ?TASK_CONTENT_ITEM;
              ContentType == ?TASK_CONTENT_COLLECT;
              ContentType == ?TASK_CONTENT_GOODS_COMPOSE;
              ContentType == ?TASK_CONTENT_DAY_ACTIVITY;
              ContentType == ?TASK_CONTENT_STREN;
              ContentType == ?TASK_CONTENT_ARENA_TIMES;
              ContentType == ?TASK_CONTENT_COMBAT ->
            if
                ContentType == ?TASK_CONTENT_STREN ->
                    {State, Id, NowNum};
                NeedNum == 0 andalso NowNum == 0 ->
                    get_mon_or_goods_nums(Mark);
                true ->
                    {State, NeedNum, NowNum}
            end;
        _ ->
            get_mon_or_goods_nums(Mark)
    end.

%% 自动完成任务
auto_finish_task(Player, TaskId) when is_record(Player, player_status) ->
    TaskArgs = lib_task_api:ps2task_args(Player),
    %% CellNum  = lib_goods_api:get_cell_num(Player),
    lib_role_task:finish(TaskId, [], TaskArgs),
    ok;
auto_finish_task(PlayerId, TaskId) ->
    case misc:get_player_process(PlayerId) of
        Pid when is_pid(Pid) -> lib_player:apply_cast(Pid, ?APPLY_CAST_STATUS, ?NOT_HAND_OFFLINE, lib_task, auto_finish_task, [TaskId]);
        _ -> skip
    end.

%% 检查物品是否为任务需要 返回所需要的物品ID列表
can_gain_item() ->
    case get_task_bag_id_list() of
        []  -> [];
        RTL ->
            F = fun(RT) ->
                        %% MarkList = get_phase_unfinish(RT),
                        [Id || [_, _, ?TASK_CONTENT_ITEM, Id, Num, _SceneId, _X, _Y, NowNum | _T] <- RT#role_task.mark, NowNum =< Num]
                end,
            List = lists:flatmap(F, RTL),
            List
    end.

%% after_event(Rid) ->
%%     %% TODO 后续事件提前完成检测
%%     case preact_finish(Rid) of
%%         true -> ok;
%%         false ->
%%             %% TODO 通知角色数据更新
%%             refresh_npc_ico(Rid),
%%             {ok, BinData} = pt_300:write(30006, []),
%%             lib_server_send:send_to_uid(Rid, BinData)
%%     end.

%% 兼容可以从完成状态变成没有完成状态
%% 到达某个位置
content([State, 0, ?TASK_CONTENT_ENTER_SCENE, Id, Num, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_ENTER_SCENE, {PlayerScene, PlayerX, PlayerY}) ->
    case Scene == PlayerScene andalso abs(X - PlayerX) < 300 andalso abs(Y - PlayerY) < 300 of
        true  -> {[State, 1, ?TASK_CONTENT_ENTER_SCENE, Id, Num, Scene, X, Y, NowNum, PathFind], true};
        false -> {[State, 0, ?TASK_CONTENT_ENTER_SCENE, Id, Num, Scene, X, Y, NowNum, PathFind], false}
    end;

%% 装备套装中id是 X代, NeedNum是Y件, EqStrenList = [{代,品质,件数}]
content([State, 0, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_EQUIP_SUIT, {id_num_list, SCNList}) ->
    case check_equip_suit_con(SCNList, Series, Color, NeedNum, 0) of
        {false, NowNum} ->
            {[State, 0, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, NowNum, PathFind], false};
        {false, Count} ->
            {[State, 0, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, Count, PathFind], true};
        {true, Count}->
            {[State, 1, ?TASK_CONTENT_EQUIP_SUIT, Series, NeedNum, Color, X, Y, Count, PathFind], true}
    end;

%% 装备强化中id是x级, NeedNum是y件, EqStrenList = [{lv, 件数}]
content([State, 0, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_STREN, {id_num_list, EqStrenList}) ->
    case check_equip_num_con(EqStrenList, Id, NeedNum, 0) of
        {false, NowNum} ->
            {[State, 0, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false};
        {false, Count} ->
            {[State, 0, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, Count, PathFind], true};
        {true, Count}->
            {[State, 1, ?TASK_CONTENT_STREN, Id, NeedNum, Scene, X, Y, Count, PathFind], true}
    end;

%% 装备强化中id是x级, NeedNum是y件, EqStrenList = [{lv, 件数}]
content([State, 0, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_EMPOWER, {id_num_list, EqStrenList}) ->
    case check_equip_num_con(EqStrenList, Id, NeedNum, 0) of
        {false, NowNum} ->
            {[State, 0, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false};
        {false, Count} ->
            {[State, 0, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, Count, PathFind], true};
        {true, Count}->
            {[State, 1, ?TASK_CONTENT_EMPOWER, Id, NeedNum, Scene, X, Y, Count, PathFind], true}
    end;

%% 单次发条密室副本中获得xxx经验
content([State, 0, ?TASK_CONTENT_DUNGEON_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_DUNGEON_EXP, {num, Id, Num}) ->
    %% 密室副本id是副本类型, num是所需要的经验
    case Num >= NeedNum of
        true  -> {[State, 1, ?TASK_CONTENT_DUNGEON_EXP, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        _     -> {[State, 0, ?TASK_CONTENT_DUNGEON_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
    end;

content([State,0,?TASK_CONTENT_DUN_WAVE,Id,NeedNum,Scene,X,Y,NowNum, PathFind],State,?TASK_CONTENT_DUN_WAVE,{num, Id, Num})->
    %%Num是波数
    case Num >= NeedNum of
        true  -> {[State, 1, ?TASK_CONTENT_DUN_WAVE, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        _     -> {[State, 0, ?TASK_CONTENT_DUN_WAVE, Id, NeedNum, Scene, X, Y, max(NowNum,Num), PathFind], true}
    end;

%% 符文之塔的触发
content([State, _Finish, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, Id, PathFind], _State, ?TASK_CONTENT_DUNGEON_RUNE, {id, DunType, DunId}) ->
    case DunId >= DId of
        true  ->
            if
                _Finish == 1 ->
                    {[State, 1, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, DunId, PathFind], false};
                true ->
                    {[State, 1, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, DunId, PathFind], true}
            end;
        _     ->
            {[State, 0, ?TASK_CONTENT_DUNGEON_RUNE, DunType, DId, Scene, X, Y, Id, PathFind], false}
    end;

%% 符文之塔的触发
%% content([ContentState, 1, ?TASK_CONTENT_DUNGEON_RUNE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], _FState, ?TASK_CONTENT_DUNGEON_RUNE, {id, DunId}) ->
%%     case DunId >= Id of
%%         true  -> {[ContentState, 1, ?TASK_CONTENT_DUNGEON_RUNE, Id, NeedNum, Scene, X, Y, DunId, PathFind], false};
%%         _     -> {[ContentState, 1, ?TASK_CONTENT_DUNGEON_RUNE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
%%     end;

%% 公会回收装备(提交x阶y品质及以上品质装备完成任务(id=x阶，NeedNum = y品质)
content([State, 0, ?TASK_CONTENT_GUILD_EQ_RECYCLE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_GUILD_EQ_RECYCLE, {num, Stage, Color}) ->
    case Stage >= Id andalso Color >= NeedNum of
        true  -> {[State, 1, ?TASK_CONTENT_GUILD_EQ_RECYCLE, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        _     -> {[State, 0, ?TASK_CONTENT_GUILD_EQ_RECYCLE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
    end;

%% 吞噬装备(吞噬x阶y品质及以上品质装备完成任务(id=x阶，NeedNum = y品质)
content([State, 0, ?TASK_CONTENT_DEVOUR, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_DEVOUR, {num, Stage, Color}) ->
    case Stage >= Id andalso Color >= NeedNum of
        true  -> {[State, 1, ?TASK_CONTENT_DEVOUR, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        _     -> {[State, 0, ?TASK_CONTENT_DEVOUR, Id, NeedNum, Scene, X, Y, NowNum, PathFind], false}
    end;

%% 装备进化
content([State, 0, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_ERISE, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        Num > NowNum ->
            {[State, 0, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        true ->
            {[State, 0, ?TASK_CONTENT_ERISE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
    end;

%% 竞技场
content([State, 0, ?TASK_CONTENT_ARENA_TIMES, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_ARENA_TIMES, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_ARENA_TIMES, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        true->
            {[State, 0, ?TASK_CONTENT_ARENA_TIMES, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
    end;

%% 战魂升级
content([State, 0, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_WAR_SOUL_LV, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        Num > NowNum ->
            {[State, 0, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        true ->
            {[State, 0, ?TASK_CONTENT_WAR_SOUL_LV, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
    end;

%% 羁绊缔结就行
content([State, 0, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_MATE, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        Num > NowNum ->
            {[State, 0, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        true ->
            {[State, 0, ?TASK_CONTENT_MATE, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
    end;

%% 完成次数就行
content([State, 0, ?TASK_CONTENT_DAY_ACTIVITY, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_DAY_ACTIVITY, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_DAY_ACTIVITY, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        true->
            {[State, 0, ?TASK_CONTENT_DAY_ACTIVITY, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
    end;

%% 完成亲密度就行
content([State, 0, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_FRIEND_EXP, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        Num > NowNum ->
            {[State, 0, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        true ->
            {[State, 0, ?TASK_CONTENT_FRIEND_EXP, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
    end;

%% 完成同心值就行
content([State, 0, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_CHILD_HEART, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        Num > NowNum ->
            {[State, 0, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        true ->
            {[State, 0, ?TASK_CONTENT_CHILD_HEART, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
    end;

%战力任务
content([State, 0, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_COMBAT, {num, Num}) ->
    if
        Num >= NeedNum ->
            {[State, 1, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        Num > NowNum ->
            {[State, 0, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, Num, PathFind], true};
        true ->
            {[State, 0, ?TASK_CONTENT_COMBAT, Id, NeedNum, Scene, X, Y, NowNum, PathFind], true}
    end;

%%选项对话任务
content([State, 0, ?TASK_CONTENT_CHOOSE_TALK, NeedId, NeedNum, Scene, X, Y, _NowNum, PathFind], _, ?TASK_CONTENT_CHOOSE_TALK, {num,Id,TalkId}) ->
    NewNpc = lib_role_task:exchange_npc(NeedId),
    case NewNpc =:= Id of
        true->
             {[State, 1, ?TASK_CONTENT_CHOOSE_TALK, Id, NeedNum, Scene, X, Y, TalkId, PathFind], true};
        _->
            {[State, 0, ?TASK_CONTENT_CHOOSE_TALK, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], false}
    end;


%% 任务对话
content([State, 0, ?TASK_CONTENT_TALK, NeedId, Num, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_TALK, {id, Id}) ->
    NewNpc = lib_role_task:exchange_npc(NeedId),
    case  NewNpc =:= NeedId of
        true->%%无变化
            case NewNpc =:= Id of
                true->
                     {[State, 1, ?TASK_CONTENT_TALK, Id, Num, Scene, X, Y, Num, PathFind], true};
                _->
                    {[State, 0, ?TASK_CONTENT_TALK, Id, Num, Scene, X, Y, _NowNum, PathFind], false}
            end;
        _->
            case NewNpc =:= Id of
                true->
                     {[State, 1, ?TASK_CONTENT_TALK, NewNpc, Num, Scene, X, Y, Num, PathFind], true};
                _->
                     {[State, 0, ?TASK_CONTENT_TALK, NewNpc, Num, Scene, X, Y, _NowNum, PathFind], false}
            end
    end;

%% 个人幻魔处理 数据初始
content([State, 0, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_DUNGEON_TYPE, {init, ?DUNGEON_TYPE_PER_BOSS, Num}) ->
    if Num >=  NeedNum ->
          {[State, 1, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
       Num>NowNum->
          {[State, 0, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, Num, PathFind], true};
       true->
          {[State, 0, ?TASK_CONTENT_DUNGEON_TYPE, ?DUNGEON_TYPE_PER_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], false}
    end;

%% 次元幻魔处理 数据初始
content([State, 0, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_KILL_BOSS, {init, ?MON_REWARD_BOSS, Num}) ->
    if Num >=  NeedNum ->
          {[State, 1, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
       Num>NowNum->
          {[State, 0, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, Num, PathFind], true};
       true->
          {[State, 0, ?TASK_CONTENT_KILL_BOSS, ?MON_REWARD_BOSS, NeedNum, Scene, X, Y, NowNum, PathFind], false}
    end;

%% 进阶 数据初始
content([State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type,  NeedNum, Scene, X, Y, NowNum, PathFind], State, ?TASK_CONTENT_FOSTER_GRADE, {num, Type,  Num}) ->
    if Num >=  NeedNum ->
          {[State, 1, ?TASK_CONTENT_FOSTER_GRADE, Type,  NeedNum, Scene, X, Y, NeedNum, PathFind], true};
       Num>NowNum->
          {[State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type,  NeedNum, Scene, X, Y, Num, PathFind], true};
       true->
          {[State, 0, ?TASK_CONTENT_FOSTER_GRADE, Type,  NeedNum, Scene, X, Y, NowNum, PathFind], false}
    end;

%%指定对话
content([State, 0, ?TASK_CONTENT_TALK, NeedId, TalkId, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_TALK, {id,TalkId,Id}) ->
    NewNpc = lib_role_task:exchange_npc(NeedId),
    case  NewNpc =:= NeedId of
        true->%%无变化
            case NewNpc =:= Id of
                true->
                     {[State, 1, ?TASK_CONTENT_TALK, Id, TalkId, Scene, X, Y, 1, PathFind], true};
                _->
                    {[State, 0, ?TASK_CONTENT_TALK, Id, TalkId, Scene, X, Y, 1, PathFind], false}
            end;
        _->
            case NewNpc =:= Id of
                true->
                     {[State, 1, ?TASK_CONTENT_TALK, NewNpc, TalkId, Scene, X, Y, 1, PathFind], true};
                _->
                     {[State, 0, ?TASK_CONTENT_TALK, NewNpc, TalkId, Scene, X, Y, 1, PathFind], false}
            end
    end;


%% 送信任务
content([State, 0, ?TASK_CONTENT_MAILER_RUN, NeedId, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ?TASK_CONTENT_MAILER_RUN, {id,Id}) ->
    NewNpc = lib_role_task:exchange_npc(NeedId),
    case  NewNpc =:= NeedId of
        true->%%无变化
            case NewNpc =:= Id of
                true->
                     {[State, 1, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
                _->
                    {[State, 0, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, _NowNum, PathFind], false}
            end;
        _->
            case NewNpc =:= Id of
                true->
                     {[State, 1, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
                _->
                     {[State, 0, ?TASK_CONTENT_MAILER_RUN, NewNpc, NeedNum, Scene, X, Y, _NowNum, PathFind], false}
            end
    end;


%% 某个特定的id(特定的副本，特定的活动)
content([State, 0, ContentType, Id, Num, Scene, X, Y, _NowNum, PathFind], State, ContentType, {id, Id}) ->
    {[State, 1, ContentType, Id, Num, Scene, X, Y, Num, PathFind], true};

%% 完成次数就行
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ContentType, {num, Num}) ->
    case NowNum + Num >=  NeedNum of
        true  -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        _     -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum + Num, PathFind], true}
    end;

%% 通用的id和次数
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum, PathFind], State, ContentType, {num, Id, Num}) ->
    case NowNum + Num >=  NeedNum of
        true  -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        _     -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum + Num, PathFind], true}
    end;

%% 列表类型id和次数
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum, PathFind]=H, _Taskstate, ContentType, {id_num_list, IdNumList}) ->
    case lists:keyfind(Id, 1, IdNumList) of
        false -> {H, false};
        {Id, Num} ->
            case NowNum + Num >=  NeedNum of
                true  -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
                _     -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, NowNum + Num, PathFind], true}
            end
    end;

%% 收集物品减少触发状态变成
content([State, _Finsh, ?TASK_CONTENT_ITEM, Id, NeedNum, Scene, X, Y, _NowNum, PathFind]=H, _TaskState, ?TASK_CONTENT_ITEM, {reduce_id_num_list, IdNumList}) ->
    case lists:keyfind(Id, 1, IdNumList) of
        false -> {H, false};
        {Id, _Num, GAllNum} ->
            NewNowNum = min(GAllNum, NeedNum),
            case NewNowNum >=  NeedNum of
                true  -> {[State, 1, ?TASK_CONTENT_ITEM, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
                _     -> {[State, 0, ?TASK_CONTENT_ITEM, Id, NeedNum, Scene, X, Y, NewNowNum, PathFind], true}
            end
    end;

%% 完成次数就行
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ContentType, {value, Num}) ->
    case Num >=  NeedNum of
        true  -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        _     -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
    end;

%% 通用的id和次数
content([State, 0, ContentType, Id, NeedNum, Scene, X, Y, _NowNum, PathFind], State, ContentType, {value, Id, Num}) ->
    case Num >=  NeedNum of
        true  -> {[State, 1, ContentType, Id, NeedNum, Scene, X, Y, NeedNum, PathFind], true};
        _     -> {[State, 0, ContentType, Id, NeedNum, Scene, X, Y, Num, PathFind], true}
    end;

%% 容错
content(MarkItem, _State, _Event, _Args) ->
    {MarkItem, false}.

%% 检查装备的件数和强化数
check_equip_num_con([], _StrenNum, Num, Count)->
    {Count >= Num, Count};
check_equip_num_con(_EqStrenList, _StrenNum, Num, Num)->
    {true, Num};
check_equip_num_con([{StrNum, N}|EqStrenList], StrenNum, Num, Count)->
    if
        StrNum >= StrenNum andalso N >= Num ->
            {true, Num};
        StrNum >= StrenNum ->
            check_equip_num_con(EqStrenList, StrenNum, Num, Count+N);
        true ->
            check_equip_num_con(EqStrenList, StrenNum, Num, Count)
    end.

%%检查套件中装备品质数
check_equip_suit_con([], _Series, _Color, NeedNum, Count)->
    {Count >= NeedNum, Count};
check_equip_suit_con(_SCNList, _Series, _Color, NeedNum, Count) when Count>=NeedNum->
    {true, NeedNum};
check_equip_suit_con([{S,C,N}|SCNList], Series, Color, NeedNum, Count)->
    if
        S =:= Series andalso C>=Color ->
            check_equip_suit_con(SCNList,Series,Color,NeedNum,Count+N);
        true->
            check_equip_suit_con(SCNList,Series,Color,NeedNum,Count)
    end.


% %% 任务失败,算完成了任务一次(超时或者放弃)
% task_fail(PS, RT) ->
%     add_log(PS#player_status.id, RT#role_task.task_id, RT#role_task.type, RT#role_task.trigger_time, utime:unixtime(), 0),
%     refresh_active(PS).

%% ------------------------------
%% 自动完成任务
%% ------------------------------
%% 检测任务是否完成
% auto_finish(TaskId, Id) when is_integer(TaskId) ->
%     case get_one_trigger(TaskId) of
%         false ->
%             Msg = data_task_text:get_auto_finish(1),
%             {ok, BinData} = pt_300:write(30004, [0, Msg, []]),
%             lib_server_send:send_to_uid(Id, BinData),
%             false;
%         RT ->
%             case RT#role_task.state > 0 of
%                 true ->
%                     Msg = data_task_text:get_auto_finish(2),
%                     {ok, BinData} = pt_300:write(30004, [0, Msg, []]),
%                     lib_server_send:send_to_uid(Id, BinData),
%                     false;
%                 false ->
%                     auto_finish(RT, Id)
%             end
%     end;

% auto_finish(RT, Id) when is_record(RT, role_task) ->
%     NewMark = auto_finish_mark(RT#role_task.mark, []),
%     put_task_bag_list(RT#role_task{mark = NewMark, state=RT#role_task.state + 1}),
%     %% 通知客户端刷新任务栏
%     refresh_npc_ico(Id),
%     TipList = get_tip(trigger, RT#role_task.task_id, Id),
%     {ok, BinData} = pt_302:write(30200, [RT#role_task.task_id, TipList]),
%     lib_server_send:send_to_uid(Id, BinData),
%     true.

auto_finish_mark([], NewMark) ->
    NewMark;
auto_finish_mark([MarkItem | T], NewMark) ->
    auto_finish_mark(T, NewMark ++ [auto_check_content(MarkItem)]).

%% 检测任务内容是否完成
auto_check_content([D1, _Finish, kill, D2, Num, _NowNum]) ->
    [D1, 1, kill, D2, Num, Num];

auto_check_content([D1, _Finish, item, D2, Num, _NowNum]) ->
    [D1, 1, item, D2, Num, Num];

auto_check_content([D1, _Finish | D2]) ->
    [D1, 1 | D2];

auto_check_content(Other) ->
    Other.

%% ================================= 进程字段记录 =================================
put_task_log_list(TaskId,TaskInfo) ->
    LogIdList = get_task_log_id_list(),
    case find_task_log_list(TaskId) of
        false ->
            put(log_id_list,[TaskId|LogIdList]),
            put({log, TaskId}, TaskInfo);
        Data ->
            C = Data#role_task_log.count + 1,
            put({log, TaskId}, TaskInfo#role_task_log{count = C})
    end.

find_task_log_list(TaskId) ->
    case get({log, TaskId}) of
        undefined -> false;
        Data -> Data
    end.

%% 已经完成任务的ID列表
get_task_log_id_list() ->
    case get(log_id_list) of
        undefined -> [];
        Data -> Data
    end.

find_task_log_exits(TaskId) ->
    ?IF(find_task_log_list(TaskId) == false, false, true).

delete_task_log_list(TaskId) ->
    erase({log, TaskId}).

get_task_bag_id_list() ->
    get("lib_task_task_bag_id_list").

set_task_bag_list(Data) ->
    put("lib_task_task_bag_id_list", Data).

%% 按type类型
get_task_bag_id_list_type(Type)->
    L = get_task_bag_id_list(),
    [ T || T <- L, T#role_task.type =:= Type].

%% 按TaskId类型
get_task_bag_id_list_task_id(TaskId)->
    L = get_task_bag_id_list(),
    [ T || T <- L, T#role_task.task_id =:= TaskId].

%% 按kind类型
get_task_bag_id_list_kind(Kind)->
    L = get_task_bag_id_list(),
    [ T || T <- L, T#role_task.kind =:= Kind].

put_task_bag_list(TaskInfo) ->
    %% upd_trigger(TaskInfo#role_task.role_id, TaskInfo#role_task.task_id, TaskInfo#role_task.state, TaskInfo#role_task.mark),
    List = lists:keydelete(TaskInfo#role_task.task_id, #role_task.task_id, get_task_bag_id_list()),
    put("lib_task_task_bag_id_list", [TaskInfo|List]).

find_task_bag_list(TaskId) ->
    lists:keyfind(TaskId, #role_task.task_id, get_task_bag_id_list()).

find_task_bag_exits(TaskId) ->
    ?IF(find_task_bag_list(TaskId) == false, false, true).

%% 获取任务接取时间
get_trigger_time(TaskId) ->
    case find_task_bag_list(TaskId) of
        false -> false;
        RT -> RT#role_task.trigger_time
    end.

delete_task_bag_list(TaskId) ->
    put("lib_task_task_bag_id_list", lists:keydelete(TaskId, #role_task.task_id, get_task_bag_id_list())).

get_query_cache_list() ->
    get("lib_task_query_cache_list").

set_query_cache_list(Data) ->
    put("lib_task_query_cache_list", Data).

%% 按类型
get_query_cache_list_type(Type)->
    [ T || T <- get_query_cache_list(), T#task.type =:= Type].

put_query_cache_list(TaskInfo) ->
    List = lists:keydelete(TaskInfo#task.id, 2, get_query_cache_list()),
    List1 = List ++ [TaskInfo],
    put("lib_task_query_cache_list", List1).

find_query_cache_list(TaskId) ->
    lists:keyfind(TaskId, 2, get_query_cache_list()).

find_query_cache_exits(TaskId) ->
    ?IF(find_query_cache_list(TaskId) == false, false, true).

delete_query_cache_list(TaskId) ->
    put("lib_task_query_cache_list", lists:keydelete(TaskId, #task.id, get_query_cache_list())).

%% ================================= db op =================================
%% Type:1 2 3 4需要永久保存的,事物执行task 删除和记录日志操作
add_log(Rid, Tid, Type, TriggerTime, FinishTime, Count) ->
    %% 删除已触发的任务缓存
    delete_task_bag_list(Tid),
    %% 记录任务日志缓存
    put_task_log_list(Tid,#role_task_log{type = Type}),
    %% db操作
    F = fun() ->
                if
                    Type =/= ?TASK_TYPE_MAIN -> skip;
                    true -> db:execute(io_lib:format(<<"update player_state set last_task_id = ~p where id= ~p">>, [Tid, Rid]))
                end,
                if
                    Type == ?TASK_TYPE_MAIN; Type == ?TASK_TYPE_SIDE;
                    Type == ?TASK_TYPE_TURN; Type == ?TASK_TYPE_CHAPTER;
                    Type == ?TASK_TYPE_NUCLEON; Type == ?TASK_TYPE_FOUR->
                        db:execute(lists:concat(["insert into `task_log`(`role_id`,`task_id`,`type`,`trigger_time`,`finish_time`)
                                                   values(",Rid,",",Tid,",",Type,",",TriggerTime,",",FinishTime,")"]));
                    true ->
                        db:execute(lists:concat(["insert into `task_log_clear`(`role_id`, `task_id`, `type`, `trigger_time`, `finish_time`, `count`)
                                          values(",Rid,",",Tid,",",Type,",",TriggerTime,",",FinishTime,",",Count,")"]))
                end,
                db:execute(lists:concat(["delete from `task_bag` where role_id=", Rid, " and task_id=", Tid]))
        end,
    db:transaction(F).

%% 删除完成日志
del_log(Rid, Tid, Type) when Type == ?TASK_TYPE_MAIN; Type == ?TASK_TYPE_SIDE;
                             Type == ?TASK_TYPE_TURN; Type == ?TASK_TYPE_CHAPTER;
                             Type == ?TASK_TYPE_NUCLEON; Type == ?TASK_TYPE_FOUR ->
    db:execute(lists:concat(["delete from `task_log` where role_id=",Rid," and task_id=",Tid]));
del_log(Rid, Tid, _Type) ->
    db:execute(lists:concat(["delete from `task_log_clear` where role_id=",Rid," and task_id=",Tid])).

%% 删除完成日志
del_log_type(Type) when Type == ?TASK_TYPE_FOUR ->
    db:execute(io_lib:format("delete from `task_log` where `type` = ~p", [Type]));
del_log_type(_Type) ->
    ok.

%% 添加触发，新+到任务背包
add_trigger(Rid, Tid, TriggerTime, TaskState, TaskEndState, TaskMark, Type, Kind, RoleLv) ->
    put_task_bag_list(#role_task{role_id = Rid, task_id = Tid, trigger_time = TriggerTime, lv = RoleLv,
                                 state=TaskState, type=Type, kind=Kind, end_state=TaskEndState, mark = TaskMark}),
    delete_query_cache_list(Tid),
    db:execute( io_lib:format(<<"insert into `task_bag`(`role_id`, `task_id`, `trigger_time`, `state`,
                                 `end_state`, `mark`, `type`, `lv`) values(~p,~p,~p,~p,~p,'~s',~p, ~p)">>,
                              [Rid, Tid, TriggerTime, TaskState, TaskEndState, util:term_to_bitstring(TaskMark), Type, RoleLv])).

%% 更新任务记录器
upd_trigger(Rid, Tid, TaskState, TaskMark) ->
    db:execute(io_lib:format(<<"update `task_bag` set state=~p,mark='~s' where role_id=~p and task_id=~p">>, [TaskState, util:term_to_bitstring(TaskMark), Rid, Tid])).

%% 玩家下线更新需要保存数据库的操作
task_offline_up(RoleTaskList)->
    F = fun(TaskInfo, Args) ->
                case TaskInfo#role_task.write_db =/= 1 of
                    true->
                        Args;
                    _->
                        [TaskInfo|Args]
                end
        end,
    Tasks = lists:foldl(F, [], RoleTaskList),
    DbList = format_task_bag([],Tasks),
    Sql = ?SQL_ROLE_TASK_BAG_BATCH,
    batch_save(Sql,DbList),
    ok.

format_task_bag(DbList,[])->
    DbList;
format_task_bag(DbList,[H|T])->
    #role_task{
        role_id = Rid,
        task_id = Tid,
        trigger_time = TriggerTime,
        lv = RoleLv,
        state=TaskState,
        type=Type,
        end_state=TaskEndState,
        mark = TaskMark,
        write_db = IsDb
    }=H,
    case IsDb >= 1 of
        true->
            Data0 = [Rid, Tid, TriggerTime, TaskState, TaskEndState, util:term_to_bitstring(TaskMark), Type, RoleLv],
            Data1 = io_lib:format("(~p,~p,~p,~p,~p,'~ts',~p,~p)", Data0),
            format_task_bag([Data1|DbList],T);
        _->
            format_task_bag(DbList,T)
    end.

batch_save(_Sql,[])->
    ok;
batch_save(Sql,DbList)->
    ArgsString = string:join(DbList, ","),
    SqlN = io_lib:format(Sql, [ArgsString]),
    db:execute(SqlN),
    ok.

%% 删除触发任务
del_trigger_from_sql(Rid, Tid) ->
    db:execute(lists:concat(["delete from `task_bag` where role_id=", Rid, " and task_id=", Tid])).

%% 日常任务清理
daily_clear(Clock, DelaySec)->
    spawn(fun() -> util:multiserver_delay(DelaySec, lib_task, daily_clear, [Clock]) end),
    ok.

%% 每日清理
daily_clear(Clock) ->
    case utime:day_of_week() of
        1 -> %% 周一4点重置公会周任务
            if
                Clock == ?TWELVE -> %% 周一0点清理可清理的任务日志和公会任务
                    skip;
                Clock == ?FOUR -> %% 日常支线任务(悬赏任务)(日清理)
                    del_log_type(?TASK_TYPE_FOUR),
                    db:execute("TRUNCATE TABLE `task_log_clear`"),
                    db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_GUILD]) ),
                    db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_DAILY]) ),
                    db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_FOUR]) );
                true ->
                    skip
            end;
        _ ->
            if
                Clock =/= ?FOUR -> skip;
                true -> %% 日常支线任务(悬赏任务)(日清理)
                    del_log_type(?TASK_TYPE_FOUR),
                    db:execute("TRUNCATE TABLE `task_log_clear`"),
                    db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_GUILD]) ),
                    db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_DAILY]) ),
                    db:execute( io_lib:format("delete from `task_bag` where `type` = ~p", [?TASK_TYPE_FOUR]) )
            end
    end,
    case Clock of
        ?FOUR->
            db:execute("delete from `task_log` where `task_id` = 3070002"),
            db:execute("delete from `task_bag` where `task_id` = 3070002");
        _->
            ignore
    end,
    %% 每个玩家清理
    [gen_server:cast(D#ets_online.pid, {'refresh_and_clear_task', Clock}) || D <- ets:tab2list(?ETS_ONLINE)],
    ?ERR("task_clear_daily ~n", []),
    ok.

%% ================================= 特殊的任务类型触发：悬赏任务和公会任务 =================================
%% return {false, ErrorCode} | {ok, ?SUCCESS}
trigger_type_task(TaskType, TaskArgs)->
    %% 是否已经接取了同类型任务
    case get_task_bag_id_list_type(TaskType) of
        [] ->
            %% 过滤出响应等级的任务
            case filter_task_type_ids(TaskType, TaskArgs) of
                [] ->
                    {false, ?ERRCODE(err300_lv_no_task)};
                TD when TaskType =:= ?TASK_TYPE_DAILY-> %%日常不拼接
                    TaskMark = [content_to_mark(E, TD#task.content, TaskArgs)||E<-TD#task.content],
                    add_trigger(TaskArgs#task_args.id, TD#task.id, utime:unixtime(), 0, TD#task.state,
                                TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
                    get_my_task_list(TaskType, TaskArgs),
                    refresh_npc_ico(TaskArgs),
                    {ok, ?SUCCESS};
                TD->
                    %% npc显示
                    %% TaskArgs1 = do_dynamic_npc(TaskArgs, TD#task.npc_show),
                    TaskMark = [content_to_mark(E, TD#task.content, TaskArgs)||E<-TD#task.content]
                        ++ case TD#task.end_talk of
                               0 -> []; %% end_talk = 0 则直接提交任务
                               _ -> [content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc,
                                                      TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs)]
                           end,
                    add_trigger(TaskArgs#task_args.id, TD#task.id, utime:unixtime(), 0, TD#task.state,
                                TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
                    get_my_task_list(TaskType, TaskArgs),
                    refresh_npc_ico(TaskArgs),
                    {ok, ?SUCCESS}
            end;
        _R ->
            ?ERR("error have task type:~p~n _R:~p~n", [TaskType, _R]),
            {false, ?ERRCODE(err300_task_trigger)}
    end.

%% 过滤类型
filter_task_type_ids(TaskType, TaskArgs)->
    ClsState = case czone_api:zone_enter_check_city() of
        true when TaskType =:= ?TASK_TYPE_DAILY->
            2;
        _->
            1
    end,
    case data_task_lv_dynamic:get_type_task_id(TaskType,ClsState,TaskArgs#task_args.figure#figure.lv) of
        #task_lv_dynamic_id{task_ids = TaskIds} when TaskIds /= []->
            TaskId = get_next_type_task_id(TaskType, TaskIds, TaskArgs#task_args.figure#figure.lv),
            case data_task_lv_dynamic:get_type_task_dynamic(TaskId, TaskArgs#task_args.figure#figure.lv) of
                #task_lv_dynamic_content{start_npc = StartNpc, end_npc = EndNpc, scene = SceneId,
                                         x = X, y = Y, content_type = ContentType, id = Id, num = NeedNum} ->
                    case data_task:get(TaskId) of
                        #task{kind = LastKind} = TD->
                            put({'last_task_kind_type', TaskType}, LastKind),
                            format_task_dynamic_content(TD, StartNpc, EndNpc, SceneId, X, Y, ContentType, Id, NeedNum);
                        _ ->
                            ?ERR("error dynamic task_id :~p~n", [TaskId]),
                            []
                    end;
                _ ->
                    ?ERR("error dynamic content :~p~n", [[TaskIds, TaskArgs#task_args.figure#figure.lv]]),
                    []
            end;
        _ ->
            ?ERR("error dynamic task content :~p~n", [[TaskType, TaskArgs#task_args.figure#figure.lv]]),
            []
    end.

get_next_type_task_id(?TASK_TYPE_DAILY = TaskType, TaskIds, RoleLv) ->
    case lists:member(RoleLv, ?DAILY_SPECIAL_LV) of
        true -> get_special_task_id(TaskType, TaskIds);
        false -> do_get_next_type_task_id(TaskType, TaskIds)
    end;
get_next_type_task_id(TaskType, TaskIds, _RoleLv) ->
    do_get_next_type_task_id(TaskType, TaskIds).

get_special_task_id(?TASK_TYPE_DAILY = TaskType, TaskIds) ->
    Fun = fun({_, TaskId}, TmpList) ->
        case is_finish_task_id(TaskId) of
            true -> TmpList;
            false -> [TaskId | TmpList]
        end
    end,
    FilterList = lists:foldr(Fun, [], TaskIds),
    case FilterList == [] of
        true -> do_get_next_type_task_id(TaskType, TaskIds);
        false -> hd(FilterList)
    end;
get_special_task_id(TaskType, TaskIds) ->
    do_get_next_type_task_id(TaskType, TaskIds).


%%日常非类型过滤
do_get_next_type_task_id(?TASK_TYPE_DAILY, TaskIds)->
    {_, TaskId} = util:find_ratio(TaskIds, 1),
    TaskId;
    % case get({'last_task_kind_type', TaskType}) of
    %     undefined ->
    %         {_, TaskId} = util:find_ratio(TaskIds, 1),
    %         TaskId;
    %     LastKindType ->
    %         LessTaskIds = [{Weight, TId} || {Weight, TId} <- TaskIds, TaskInfo <- [data_task:get(TId)], TaskInfo#task.kind =/= LastKindType],
    %         {_, TaskId} = util:find_ratio(LessTaskIds, 1),
    %         TaskId
    % end.
do_get_next_type_task_id(TaskType, TaskIds)->
    case get({'last_task_kind_type', TaskType}) of
        undefined ->
            {_, TaskId} = util:find_ratio(TaskIds, 1),
            TaskId;
        LastKindType ->
            LessTaskIds = [{Weight, TId} || {Weight, TId} <- TaskIds, TaskInfo <- [data_task:get(TId)], TaskInfo#task.kind =/= LastKindType],
            {_, TaskId} = util:find_ratio(LessTaskIds, 1),
            TaskId
    end.

%% 组装动态任务内容
format_task_dynamic_content(TD, StartNpcId, EndNpcId, SceneId, X, Y, ContentType, Id, NeedNum)->
    Content = if
                  StartNpcId == 0 -> [];
                  true ->
                        [[0, ?TASK_CONTENT_TALK, StartNpcId, TD#task.start_talk, 0, 0, 0, 1]]
              end,
    NewContent  = if
                      ContentType == 0 orelse Id == 0 ->
                            [];
                      ContentType == 5 ->
                            Content;
                      Content == [] ->
                            [[0, ContentType, Id, NeedNum, SceneId, X, Y, 1]];
                      true ->
                            Content  ++ [[1, ContentType, Id, NeedNum, SceneId, X, Y, 1]]
                  end,
    State = length(NewContent),
    if
        EndNpcId == 0 -> EndTalk = 0;
        true ->  EndTalk = TD#task.end_talk
    end,
    TD#task{start_npc = StartNpcId, content = NewContent, end_npc = EndNpcId, state = State, end_talk = EndTalk}.

%% 获取赏金(日常)和公会周任务
get_special_task_reward(TaskId, Type, TaskArgs) ->
    RoleId = TaskArgs#task_args.id,
    case get_one_trigger(TaskId) of
        false -> Goods = [], ExtraReward = [];
        RT ->
            Goods0 = calc_task_type_reward(Type, RT#role_task.lv),
            Goods = get_award_item(data_task:get(TaskId), TaskArgs)++Goods0,
            case data_task_lv_dynamic:get_task_type(Type) of
                #task_type{module_id = ModuleId, counter_id = CounterId} ->
                    FinishCount = lib_daily:get_count(RoleId, ModuleId, CounterId)+1,
                    ExtraReward = calc_extra_task_type_reward(TaskId, Type, FinishCount, RT#role_task.lv);
                _ ->
                    ExtraReward = []
            end
    end,
    lib_server_send:send_to_uid(RoleId, pt_300, 30011, [TaskId, Goods, ExtraReward]).

%% ================================= 任务秘籍 =================================
%% 强制接取某个任务（秘籍使用）
force_trigger(TaskId, TaskArgs) ->
    %% 删除缓存
    delete_task_bag_list(TaskId),
    delete_task_log_list(TaskId),
    %% 删除db
    TD = get_data(TaskId),
    F = fun() ->
                del_trigger_from_sql(TaskArgs#task_args.id, TaskId),
                del_log(TaskArgs#task_args.id, TaskId, TD#task.type)
        end,
    db:transaction(F),
    %% 刷新
    refresh_active(TaskArgs),
    TaskArgs1 = do_dynamic_npc(TaskArgs, TD#task.npc_show),
    TaskMark = [content_to_mark(E, TaskArgs1)||E<-TD#task.content]
        ++ case TD#task.end_talk of
               0 -> []; %% end_talk=0则直接提交任务
               _ -> [content_to_mark([TD#task.state, ?TASK_CONTENT_END_TALK, TD#task.end_npc, TD#task.end_talk, 0, 0, 0, TD#task.finish_pathfind], TaskArgs1)]
           end,
    add_trigger(TaskArgs#task_args.id, TaskId, utime:unixtime(), 0, TD#task.state,
                TaskMark, TD#task.type, TD#task.kind, TaskArgs#task_args.figure#figure.lv),
    %% 转生任务接取了要通知其他模块
    if
        TD#task.type == ?TASK_TYPE_TURN ->
            lib_player:apply_cast(TaskArgs#task_args.id, ?APPLY_CAST_SAVE, transform, trigger_task, [TD#task.id]);
        true -> skip
    end,
    get_my_task_list(0, TaskArgs1),
    refresh_npc_ico(TaskArgs1),
    ok.

%% 清理自身触发的任务
gm_refresh_task(GmType, TaskArgs) ->
    put("lib_task_task_bag_id_list", []),
    db:execute(io_lib:format("delete from task_log_clear where role_id=~w", [TaskArgs#task_args.id])),
    if
        GmType == 0 -> %% 当前已接
            db:execute(io_lib:format("delete from task_bag where role_id=~w", [TaskArgs#task_args.id]));
        true -> %% 删除所有的任务,从0开始
            [delete_task_log_list(Tid) || Tid <- data_task_lv:get_ids(TaskArgs#task_args.figure#figure.lv)],
            db:execute(io_lib:format("delete from task_log where role_id=~w", [TaskArgs#task_args.id])),
            db:execute(io_lib:format("delete from task_bag where role_id=~w", [TaskArgs#task_args.id]))
    end,
    flush_role_task(TaskArgs),
    get_my_task_list(0, TaskArgs),
    refresh_npc_ico(TaskArgs).

%% 直接移除某个任务（秘籍使用）
del_task(TaskId, TaskArgs) ->
    %% 删除缓存
    delete_task_bag_list(TaskId),
    delete_task_log_list(TaskId),
    TD = get_data(TaskId),
    F = fun() ->
                db:execute(io_lib:format("delete from task_bag where role_id=~w and task_id=~p",
                                         [TaskArgs#task_args.id, TaskId])),
                del_log(TaskArgs#task_args.id, TaskId, TD#task.type)
        end,
    db:transaction(F),
    %% 刷新
    refresh_active(TaskArgs),
    get_my_task_list(0, TaskArgs),
    refresh_npc_ico(TaskArgs),
    ok.

%% 完成当前主线任务
gm_finitask(TaskArgs) ->
    % spawn(fun()-> finish_lv_task(TaskArgs) end),
    TaskList = get_task_bag_id_list(),
    Fun = fun(#role_task{task_id = TaskId, type = TaskType})->
        case TaskType == ?TASK_TYPE_MAIN of
            true -> finish(TaskId, [], TaskArgs);
            false -> ok
        end
    end,
    lists:map(Fun, TaskList),
    get_my_task_list(0, TaskArgs),
    ok.


gm_finish_lv_task(Status)->
    TaskArgs = lib_task_api:ps2task_args(Status),
    finish_lv_task(TaskArgs).


%% 完成该等级前的所有任务
finish_lv_task(#task_args{id=RoleId, figure=#figure{lv=Lv}}=TaskArgs) ->
    % Sql = io_lib:format(<<"delete from `role_npc_show` where id = ~p ">>, [RoleId]),
    % db:execute(Sql),

    AllIdList = data_task_lv:get_ids(Lv - 1),

    F2 = fun(TaskId, Acc) ->
        TD = data_task:get(TaskId),
        case TD of
            #task{type = 1} -> [TaskId|Acc];
            _ -> Acc
        end
    end,
    MainTaskIds = lists:droplast( lists:foldr(F2, [], AllIdList)), %% 过滤后把当前级即最后一个去掉

    case db:get_all(io_lib:format(<<"select task_id from task_log WHERE role_id=~p">>, [RoleId])) of
        LogIds when is_list(LogIds) -> LogIds2 = lists:usort(LogIds);
        _ -> LogIds2 = []
    end,
    NowTime = utime:unixtime(),
    F1 = fun(TaskId, Acc) ->
                TD = data_task:get(TaskId),
                case TD =/= null andalso  TD =/= [] andalso TD#task.type == 1 andalso lists:member(TaskId, LogIds2) == false of
                    true ->
                        Sql3 = io_lib:format(<<"REPLACE INTO `task_log` set `role_id`=~p, `task_id`=~p, `type`=~p, `trigger_time`=~p, `finish_time`=~p">>,
                            [RoleId, TaskId, TD#task.type, NowTime, NowTime]),
                        db:execute(Sql3),
                        [TaskId|Acc];
                    false ->
                        Acc
                end
        end,
    TIds = lists:foldl(F1, [], MainTaskIds),
    Sql2 = io_lib:format(<<"delete from `task_bag` where role_id=~p and task_id in (~s)">>, [RoleId, util:link_list(TIds)]),
    db:execute(Sql2),
    flush_role_task(TaskArgs),
    lv_up(TaskArgs),
    List = get_task_log_id_list(),
    lib_server_send:send_to_uid(RoleId, pt_300, 30017, [List]),
    ok.

%%打包多个taskid
pack_task_id(TaskList)->
    Fun = fun(TaskId) -> <<TaskId:32>> end,
    ListBin = pt:write_array(Fun, TaskList),
    ListBin.

%%解包多个taskid
unpack_task_id(TaskListBin)->
    Fun = fun(<<Bin0/binary>>) ->
        <<TaskId:32, _Args1/binary>> = Bin0,
        {TaskId, _Args1}
    end,
    {TaskList, _Bin1} = pt:read_array(Fun, TaskListBin),
    TaskList.

%%触发长剧情
event_to_story(PS, TaskId, EndTime) ->
    #player_status{id = RoleId, sid = Sid, scene = SceneId, scene_pool_id = ScenePoolId, copy_id = CopyId, x = X, y = Y} = PS,
    Utime = utime:unixtime(),
    %%默认60s
    DefaultTime = 60,
    Times = ?IF( EndTime - Utime > DefaultTime, DefaultTime, max(1, EndTime - Utime)),
    Ref = erlang:send_after(Times * 1000, self(), {mod, ?MODULE, event_to_cancel_story, [TaskId]}),
    put({?MODULE, event_story, TaskId}, Ref),
    lib_server_send:send_to_sid(Sid, pt_300, 30016, [?SUCCESS]),
    {ok, BinData} = pt_300:write(30017, [RoleId, 1]),
    lib_server_send:send_to_area_scene(SceneId, ScenePoolId, CopyId, X, Y, BinData),
    ok.

%%触发结束长剧情
event_to_cancel_story(PS, TaskId) ->
    #player_status{id = RoleId, scene = SceneId, scene_pool_id = ScenePoolId, copy_id = CopyId, x = X, y = Y} = PS,
    lib_counter:increment(RoleId, ?MOD_TASK, 1, TaskId),
    Ref = get({?MODULE, event_story, TaskId}),
    util:cancel_timer(Ref),
    erase({?MODULE, event_story, TaskId}),
    {ok, BinData} = pt_300:write(30017, [RoleId, 0]),
    lib_server_send:send_to_area_scene(SceneId, ScenePoolId, CopyId, X, Y, BinData),
    {ok, PS}.



after_finish_round_task(RoleId, TaskType, Num) ->
    if
        TaskType == ?TASK_TYPE_DAILY ->  %% 日常任务
            custom_act_mobilize:update_mobilize_task(RoleId, dailytask, Num),
            mod_hi_point:success_end(RoleId, ?MOD_TASK, 1, 1),
            custom_act_adventure:do_trigger_adventure_task(RoleId, ?MOD_TASK, 1),
            lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_TASK, 1, Num),
            lib_role_legion:trigger_task(RoleId, ?MOD_TASK, 1);
        TaskType == ?TASK_TYPE_GUILD ->  %% 公会任务
            lib_activitycalen_api:role_success_end_activity(RoleId, ?MOD_TASK, 2, Num),
            mod_hi_point:success_end(RoleId, ?MOD_TASK, 2, 1),
            custom_act_adventure:do_trigger_adventure_task(RoleId, ?MOD_TASK, 2),
            lib_guild_labor:task_active(RoleId,?GTASK_TYPE_TASK);
        true ->
            skip
    end.


%%过滤对话选项任务的完成TalkId
filter_task_talk([])->
    0;
filter_task_talk([H|T])->
    case H of
        [_, _, ?TASK_CONTENT_CHOOSE_TALK, _NeedId, _NeedNum, _Scene, _X, _Y,Talk, _PathFind]->
            Talk;
        _->
            filter_task_talk(T)
    end.

%%npc矫正
fix_task_npc([],NewTriggerList,_TaskArgs)->
    NewTriggerList;
fix_task_npc([H|T],NewTriggerList,TaskArgs)->
    #role_task{mark=Mark}=H,
    NMark = fix_task_mark(Mark,[],TaskArgs),
    fix_task_npc(T,[H#role_task{mark=NMark}|NewTriggerList],TaskArgs).

fix_task_mark([],Mark,_TaskArgs)->
    lists:reverse(Mark);
fix_task_mark([[State,CurState,?TASK_CONTENT_CHOOSE_TALK,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
    NewId=lib_role_task:exchange_npc(Id),
    {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
    fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_CHOOSE_TALK,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([[State,CurState,?TASK_CONTENT_TALK,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
    NewId=lib_role_task:exchange_npc(Id),
    {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
    fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_TALK,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([[State,CurState,?TASK_CONTENT_END_TALK,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
    NewId=lib_role_task:exchange_npc(Id),
    {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
    fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_END_TALK,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([[State,CurState,?TASK_CONTENT_MAILER_RUN,Id,Num,_SceneId,_X,_Y,NeedNum,PathFind]|Mark],NMark,TaskArgs)->
    NewId=lib_role_task:exchange_npc(Id),
    {RealSceneId, RealX, RealY} = get_npc_info(NewId, TaskArgs#task_args.npc_info),
    fix_task_mark(Mark,[[State,CurState,?TASK_CONTENT_MAILER_RUN,NewId,Num,RealSceneId, RealX, RealY,NeedNum,PathFind]|NMark],TaskArgs);
fix_task_mark([H|T],NMark,TaskArgs)->
    fix_task_mark(T,[H|NMark],TaskArgs).
