%%%-------------------------------------------------------------------
%%% @doc     精英考核(任务考核)
%%% Module  : lib_elite_assessment.erl
%%% Created : 2020-07-13
%%% @Author : tyl
%%%-------------------------------------------------------------------
-module(lib_elite_assessment).

-include("common.hrl").
-include("server.hrl").
-include("figure.hrl").
-include("role.hrl").
-include("errcode.hrl").
-include("goods.hrl").
-include("def_module.hrl").
-include("def_fun.hrl").
-include("rec_event.hrl").
-include("def_event.hrl").
-include("def_goods.hrl").
-include("predefine.hrl").
-include("elite_assessment.hrl").

%% API
-export([
	login/2
	,logout/2
	,trigger/4                      %% 任务触发
	,handle_event/2                 %% 升级触发开放下一章节

	,send_category_list/1           %% 查看当前章节(包括任务)信息
	,receive_category_reward/2      %% 领取章节奖励
	,receive_reward/3               %% 领取任务奖励

	,get_elite_assess_dict/2        %% 内存数据获取
	,save_elite_assess_dict/1       %% 内存数据保存
	,db_save_login_days/3
	,gm_finish_category_all_task/2  %% 完成当前章节所有任务

	,open_category_by_config/1
]).

%% 升级/0点检查开服天数 触发开放下一章节
handle_event(PS, #event_callback{type_id = TypeId}) when is_record(PS, player_status) andalso
	(TypeId == ?EVENT_LV_UP orelse TypeId == ?EVENT_ZERO_CLOCK) ->
	#player_status{figure = Figure, id = RoleId} = PS,
	case get_elite_assess_dict(RoleId, Figure#figure.lv) of
		{ok, StatusEliteAssess} ->
			#status_elite_assess{current_category = CurrentCategory, progress_list = ProgressList
			} = StatusEliteAssess,
			%% 已经领取本章节奖励并达到下一章节开放条件
			CategoryMap = get_category_map(ProgressList),
			CfgOpenCategoryL = open_category_by_config(Figure#figure.lv),
			NewCategory = get_current_category(CfgOpenCategoryL, CategoryMap),
			NewStatusEliteAssess = StatusEliteAssess#status_elite_assess{
				current_category = NewCategory
			},
			NewCategory =/= CurrentCategory andalso
				notify_client_category(RoleId, Figure#figure.lv, NewStatusEliteAssess),
			save_elite_assess_dict(NewStatusEliteAssess);
		_ ->
			skip
	end,
	{ok, PS};
handle_event(Player, #event_callback{}) ->
	{ok, Player}.

%% 登录
login(RoleId, RoleLv) ->
	case db_select_elite_assess_task(RoleId) of
		[_|_] = TaskInfos ->
			ProgressList = make_list(task, TaskInfos);
		_ ->
			ProgressList = []
	end,
	CategoryMap = get_category_map(ProgressList),
	CfgOpenCategoryL = open_category_by_config(RoleLv),
	CurrentCategory  = get_current_category(CfgOpenCategoryL, CategoryMap),
	StatusEliteAssess = #status_elite_assess{
		progress_list = ProgressList
		,category_map = CategoryMap
		,current_category = CurrentCategory
	},
	save_elite_assess_dict(StatusEliteAssess).

%% 退出更新进度(未完成部分有写库CD)
logout(RoleId, RoleLv) ->
	case get_elite_assess_dict(RoleId, RoleLv) of
		{ok, StatusEliteAssess} ->
			#status_elite_assess{
				progress_list = ProgressList
			} = StatusEliteAssess,
			F = fun(T, TmpSql) ->
				case T of
					#elite_assess{
						task_id = TaskId,
						progress = Progress,
						status   = ?CAN_NOT_RECEIVE,
						wstatus  = ?ELITE_WSTATUS_WAIT
					} ->
						Value = io_lib:format(<<"(~p, ~p, ~p, ~p)">>, [
							RoleId, TaskId, Progress, ?CAN_NOT_RECEIVE]),
						[Value|TmpSql];
					_ -> TmpSql
				end end,
			case lists:foldl(F, [], ProgressList) of
				[_|_] = SqlList ->
					NewValues = util:join_bitstring(SqlList, <<", ">>),
					FinalSql  = util:fmt_bin(
						<<"replace into elite_assess_task (`role_id`, `task_id`, `progress`, `status`) values ~ts">>,
						[NewValues]),
					db:execute(FinalSql);
				_ -> skip
			end;
		_ -> skip
	end.

%% 章节进度
send_category_list(Player) ->
	#player_status{id = RoleId, figure = Figure} = Player,
	case get_elite_assess_dict(RoleId, Figure#figure.lv) of
		{ok, StatusEliteAssess} ->
			#status_elite_assess{progress_list = ProgressList,
				category_map = _CategoryMap, current_category = CurrentCategory
			} = StatusEliteAssess,
			% CfgOpenCategoryL = open_category_by_config(Figure#figure.lv),
			% CurrentCategory  = get_current_category(CfgOpenCategoryL, CategoryMap),
			MinCategory = min_category(),
			PackTaskL = pack_task_list(MinCategory, CurrentCategory, ProgressList),
			{ok, BinData} = pt_452:write(45201, [PackTaskL]),
			lib_server_send:send_to_uid(RoleId, BinData);
		_ ->
			{ok, BinData} = pt_452:write(45201, [[]]),
			lib_server_send:send_to_uid(RoleId, BinData)
	end.

pack_task_list(MinCategory, CurrentCategory, ProgressList) ->
	case CurrentCategory >= MinCategory of
		true ->
			lists:foldl(fun(Category, TList) ->
				case data_elite_assessment:get_all_task_cfg(Category) of
					[_|_] = TaskIdL ->
						TaskList = get_task_progress(Category, TaskIdL, ProgressList),
						[{Category, TaskList}|TList];
					_ ->
						TList
				end end,
				[], lists:seq(MinCategory, CurrentCategory));
		_ ->
			[]
	end.

%% return: #{category=>1} 全部完成的章节才会有数据
get_category_map(ProgressList) ->
	AllCategory = data_elite_assessment:get_all_category(),
	CategoryMap = lists:foldl(
		fun(Category, TMap) ->
			Status = each_category(Category, ProgressList),
			case Status > 0 of
				true -> maps:put(Category, Status, TMap);
				_ -> TMap
			end
		end, #{}, AllCategory),
	CategoryMap.

each_category(Category, ProgressList) ->
	AllTask = data_elite_assessment:get_all_task_cfg(Category),
	FinishList =
	[Status||#elite_assess{task_id = TaskId, status = Status}<-ProgressList,
		lists:member(TaskId, AllTask), Status == ?HAS_RECEIVED
	],
	case erlang:length(FinishList) == erlang:length(AllTask) of
		true -> 1;
		_ -> 0
	end.

open_category_by_config(RoleLv) ->
	AllCategory = data_elite_assessment:get_all_category(),
	OpenDay = util:get_open_day(),
	Categories = lists:foldl(
		fun(Category, TList) ->
			case data_elite_assessment:get_elite_assess_category_reward_cfg(Category) of
				#elite_assess_reward_cfg{open_lv = CfgLv, open_day = CfgDay} ->
					case RoleLv >= CfgLv andalso OpenDay >= CfgDay of
						true -> [Category|TList];
						_ -> TList
					end;
				_ -> TList
			end
		end, [], AllCategory),
	Categories.

%% 获取当前应该展示的章节进度
%% 控制条件：等级，开服天数，前一章节任务全部完成
get_current_category(CfgCateList, CategoryMap) ->
	MinCategory = min_category(),
	MaxCategory = max_category(),
	case CfgCateList =/= [] of
		true ->
			Categories = maps:keys(CategoryMap),
			case Categories of
				[_|_] ->
					Theoretic = min(lists:max(Categories)+1, MaxCategory),
					CfgCateList1 = lists:sort(CfgCateList),
					get_true_category(Theoretic, CfgCateList1);
				_ ->
					MinCategory
			end;
		_ ->
			0
	end.

%% 根据配置的等级和开服天数来判断理论上的章节是否开放
get_true_category(Theoretic, CfgCateList) ->
	F = fun(Category, TrueCate) ->
		case Theoretic >= Category of
			true -> Category;
			_ -> TrueCate
		end end,
	lists:foldl(F, 0, CfgCateList).

min_category() ->
	AllCategory = data_elite_assessment:get_all_category(),
	MinCategory = case AllCategory of
		              [_|_] -> lists:min(AllCategory);
		              _ -> 0
	              end,
	MinCategory.

max_category() ->
	AllCategory = data_elite_assessment:get_all_category(),
	MaxCategory = case AllCategory of
		              [_|_] -> lists:max(AllCategory);
		              _ -> 0
	              end,
	MaxCategory.

%% 领取章节奖励(废弃)
receive_category_reward(Player, Category) ->
	#player_status{sid = Sid, id = RoleId, figure = Figure} = Player,
	case get_elite_assess_dict(RoleId, Figure#figure.lv) of
		{ok, StatusEliteAssess} ->
			#status_elite_assess{category_reward_list = CategoryRewardL, category_map = CategoryMap} = StatusEliteAssess,
			CheckList = [{is_category_true, Category}, {can_receive, Category, CategoryMap, CategoryRewardL},
				{can_give_goods, Player, Category}],
			case check_list(CheckList) of
				true ->
					#elite_assess_reward_cfg{reward = RewardL, category_name = CategoryName}
						= data_elite_assessment:get_elite_assess_category_reward_cfg(Category),
					db_save_category_reward(RoleId, Category, ?HAS_RECEIVED),
					NewCategoryRewardL = [{Category, ?HAS_RECEIVED}|CategoryRewardL],
					Produce = #produce{type = elite_assess_category_reward, subtype = Category, reward = RewardL,
						remark = "", show_tips = 1},
					%% 更新下一章节
					CurrentCategory = StatusEliteAssess#status_elite_assess.current_category,
					MaxCategory = lists:max(data_elite_assessment:get_all_category()),
					NextCategory = min(CurrentCategory + 1, MaxCategory),
					NextOpenLv = get_category_open_lv(NextCategory),
					case CurrentCategory =/= NextCategory of
						true when Figure#figure.lv >= NextOpenLv ->
							NewCategory = NextCategory;
						_ ->
							NewCategory = CurrentCategory
					end,
					NewStatusEliteAssess = StatusEliteAssess#status_elite_assess{
						current_category     = NewCategory,
						category_reward_list = NewCategoryRewardL
					},
					save_elite_assess_dict(NewStatusEliteAssess),
					%% 推送新章节数据
					NewCategory =/= CurrentCategory andalso notify_client_category(RoleId, Figure#figure.lv, NewStatusEliteAssess),
					lib_log_api:log_elite_assess_award(RoleId, Figure#figure.lv, Category, 0, 2, Category, CategoryName, RewardL),
					{ok, NewPlayer} = lib_goods_api:send_reward_with_mail(Player, Produce),
					send_msg(Sid, 45202, [?SUCCESS, Category]),
					{ok, NewPlayer};
				{false, Err} ->
					send_msg(Sid, 45202, [Err, Category]),
					{ok, Player}
			end;
		_ ->
			{ok, Player}
	end.

%% 领取任务奖励
%% 领取任务奖励的时候同时计算当前完成的所有章节
receive_reward(Player, Category, TaskId) ->
	#player_status{sid = Sid, id = RoleId, figure = Figure} = Player,
	case get_elite_assess_dict(RoleId, Figure#figure.lv) of
		{ok, StatusEliteAssess} ->
			#status_elite_assess{progress_list = ProgressList, current_category = CurrentCategory} = StatusEliteAssess,
			CheckList = [{is_current_category, Category, CurrentCategory}, {task_id_true, TaskId, CurrentCategory},
				{is_sub_category_true, TaskId, ProgressList}, {task_finish, TaskId, ProgressList}],
			case check_list(CheckList) of
				true ->
					#elite_assess_task_cfg{reward = RewardL, sub_category = SubCategory, task_desc = TaskDesc} =
						data_elite_assessment:get_elite_assess_task_cfg(TaskId),
					case lib_goods_api:can_give_goods(Player, RewardL) of
						true ->
							EliteAssess = lists:keyfind(TaskId, #elite_assess.task_id, ProgressList),
							db_update_elite_assess_status(RoleId, TaskId, ?HAS_RECEIVED),
							NewProgressList = lists:keystore(TaskId, #elite_assess.task_id, ProgressList,
								EliteAssess#elite_assess{status = ?HAS_RECEIVED}),
							StatusEliteAssess1 = StatusEliteAssess#status_elite_assess{
								progress_list = NewProgressList
							},
							%% 更新章节进度
							NewStatusEliteAssess = update_category_progress(StatusEliteAssess1, RoleId, Figure#figure.lv),
							save_elite_assess_dict(NewStatusEliteAssess),
							Produce = #produce{type = elite_assess_task_reward, subtype = 1, reward = RewardL, show_tips = 1},
							{ok, NewPlayer} = lib_goods_api:send_reward_with_mail(Player, Produce),
							notify_client_category(RoleId, Figure#figure.lv, NewStatusEliteAssess),
							%% 日志
							lib_log_api:log_elite_assess_award(RoleId, Figure#figure.lv, Category, SubCategory, 1, TaskId, TaskDesc, RewardL),
							send_msg(Sid, 45203, [?SUCCESS, Category, TaskId]),
							{ok, NewPlayer};
						_ ->
							send_msg(Sid, 45203, [?ERRCODE(err150_no_cell), Category, TaskId]),
							{ok, Player}
					end;
				{false, Err} ->
					send_msg(Sid, 45203, [Err, Category, TaskId]),
					{ok, Player}
			end;
		_ ->
			{ok, Player}
	end.

%% 任务触发
trigger(RoleId, RoleLv, Key, Args) ->
	case get_elite_assess_dict(RoleId, RoleLv) of
		{ok, StatusEliteAssess} ->
			NowTime = utime:unixtime(),
			AllIds  = get_all_tasks(),
			CfgL = filter_task_cfg_by_key(AllIds, Key, []),
			F = fun() ->
				% put(broadcast_info, []),
				{TNewStatusEliteAssess, TUCategoryL} = do_trigger(CfgL, RoleId, RoleLv, StatusEliteAssess, Args, NowTime, []),
				TUpdateList = [], % erase(broadcast_info), %% TODO
				{ok, TUpdateList, TUCategoryL, TNewStatusEliteAssess}
			    end,
			case catch db:transaction(F) of
				{ok, _UpdateList, _UCategoryL, NewStatusEliteAssess} ->
					save_elite_assess_dict(NewStatusEliteAssess);
				Error ->
					?ERR("role_id:~p trigger achievement args:~p err:~p~n", [RoleId, Args, Error])
			end;
		_ ->
			skip
	end.

do_trigger([], _RoleId, _RoleLv,  StatusEliteAssess, _Args, _NowTime, UCategoryL) ->
	{StatusEliteAssess, lists:usort(UCategoryL)};  %% TODO
do_trigger([#elite_assess_task_cfg{category = Category, sub_category = SubCategory, task_id = TaskId} = Cfg|L], RoleId, RoleLv, StatusEliteAssess, Args, NowTime, UCategoryL) ->
	#status_elite_assess{
		progress_list    = ProgressList,
		current_category = CurrentCategory
	} = StatusEliteAssess,
	case lists:keyfind(TaskId, #elite_assess.task_id, ProgressList) of
		#elite_assess{} = OldEliteAssessInfo ->
			skip;
		false ->
			OldEliteAssessInfo = #elite_assess{
				category = Category, sub_category = SubCategory,
				task_id = TaskId
			}
	end,
	#elite_assess{
		progress = OldProgress,
		status   = Status,
		wtime    = LastWtime
	} = OldEliteAssessInfo,
	#elite_assess_task_cfg{content = Content, task_desc = TaskDesc} = Cfg,
	case Status == ?CAN_NOT_RECEIVE of
		true ->
			NewEliteAssessInfo = lib_elite_assess_trigger:trigger(Args, Content, OldEliteAssessInfo),
			#elite_assess{progress = NewProgress, status = NewStatus} = NewEliteAssessInfo,
			case NewProgress =/= OldProgress orelse Status =/= NewStatus of
				true ->
					%% 杀怪的成就触发太频繁,只有第一次以及完成的时候才实时写入数据库,其他情况根据实际情况调整写入数据库的CD时间
					SaveDBCD = case Args of
						           [{kill_mon, _}]    -> 1800;      % 半小时存一次
						           [{cumulative_coin, _}] -> 300;
						           [{cumulative_gold, _}] -> 300;
						           [{power, _}] -> 300;
						           _ -> ?ELITE_TASK_SAVE_DB_CD
					           end,
					case NewStatus == ?CAN_RECEIVE orelse LastWtime == 0 orelse NowTime - LastWtime >= SaveDBCD of
						true ->
							db_save_elite_assess(RoleId, TaskId, NewProgress, NewStatus),
							LastEliteAssessInfo = NewEliteAssessInfo#elite_assess{wtime = NowTime, wstatus = ?ELITE_WSTATUS_SUCCESS};
						_ ->
							LastEliteAssessInfo = NewEliteAssessInfo#elite_assess{wstatus = ?ELITE_WSTATUS_WAIT}
					end,
					% broadcast_info_add(Category, SubCategory, NewStatus, NewProgress),
					case NewStatus == ?CAN_RECEIVE of
						true ->
							%% 日志
							lib_log_api:log_elite_assess_task(RoleId, RoleLv, Category, SubCategory, TaskId, TaskDesc),
							case Category == CurrentCategory of
								true ->
									NewUCategoryL = [Category|lists:delete(Category, UCategoryL)];
								_ ->
									NewUCategoryL = UCategoryL
							end;
						false ->
							NewUCategoryL  = UCategoryL
					end,
					NewProgressList = lists:keystore(TaskId, #elite_assess.task_id, ProgressList, LastEliteAssessInfo),
					NewStatusEliteAssess = StatusEliteAssess#status_elite_assess{progress_list = NewProgressList},
					%% 缓存更新的成就进度(包括完成/未完成),整理后推送给客户端
					Category == CurrentCategory andalso notify_client_category(RoleId, RoleLv, NewStatusEliteAssess);
				false ->
					NewUCategoryL   = UCategoryL,
					NewProgressList = ProgressList,
					NewStatusEliteAssess = StatusEliteAssess#status_elite_assess{progress_list = NewProgressList}
			end,
			do_trigger(L, RoleId, RoleLv, NewStatusEliteAssess, Args, NowTime, NewUCategoryL);
		_ ->
			do_trigger(L, RoleId, RoleLv, StatusEliteAssess, Args, NowTime, UCategoryL)
	end.

%% 获取{Category, TaskId}格式的Id列表
get_all_tasks() ->
	case data_elite_assessment:get_all_category() of
		CategoryList when is_list(CategoryList) ->
			F = fun(Category, TList) ->
				case data_elite_assessment:get_all_task_cfg(Category) of
					TaskL when is_list(TaskL) ->
						[{Category, TaskId}|| TaskId <- TaskL] ++ TList;
					_ ->
						TList
				end end,
			lists:foldl(F, [], CategoryList);
		_ ->
			[]
	end.

%% 通过Key筛选出符合的任务配置
filter_task_cfg_by_key([], _, ResultL) ->
	lists:sort(ResultL);
filter_task_cfg_by_key([{_Category, TaskId}|L], Key, ResultL) ->
	case data_elite_assessment:get_elite_assess_task_cfg(TaskId) of
		#elite_assess_task_cfg{content = Content} = Cfg ->
			% SureKeys = [1 || Key <- Keys, lists:keyfind(Key, 1, Condition) == true],    % 确保key和条件完全匹配
			case lists:keyfind(Key, 1, Content) of
				false ->
					filter_task_cfg_by_key(L, Key, ResultL);
				_ ->
					filter_task_cfg_by_key(L, Key, [Cfg|ResultL])
			end;
		_ ->
			filter_task_cfg_by_key(L, Key, ResultL)
	end.

%% 推送最新章节数据给前端
notify_client_category(RoleId, RoleLv, NewStatusEliteAssess) ->
	%% 达到模块等级才推送
	OpenLv = lib_module:get_open_lv(?MOD_ELITE_ASSESS),
	case RoleLv >= OpenLv of
		true ->
			#status_elite_assess{
				current_category      = CurrentCategory
				,progress_list        = ProgressList
			} = NewStatusEliteAssess,
			MinCategory = min_category(),
			PackTaskL = pack_task_list(MinCategory, CurrentCategory, ProgressList),
			{ok, BinData} = pt_452:write(45201, [PackTaskL]),
			lib_server_send:send_to_uid(RoleId, BinData);
		_ ->
			skip
	end.

%% -------------------------- 内存数据操作 --------------------------
get_elite_assess_dict(RoleId, Lv) ->
	Pid = misc:get_player_process(RoleId),
	case Pid =:= self() of
		true ->
			case get(?D_ELITE_ASSESS) of
				undefined ->
					StatusEliteAssess = login(RoleId, Lv),
					save_elite_assess_dict(StatusEliteAssess),
					{ok, StatusEliteAssess};
				Val -> {ok, Val}
			end;
		false -> skip
	end.

save_elite_assess_dict(StatusEliteAssess) ->
	put(?D_ELITE_ASSESS, StatusEliteAssess).

%% ---------------------------- builtin function -------------------------------
%% 组织数据结构
make_list(task, TaskInfos) ->
	F = fun([TaskId, Progress, Status], TProgressList) ->
		case data_elite_assessment:get_elite_assess_task_cfg(TaskId) of
			#elite_assess_task_cfg{category = Category, sub_category = SubCategory} ->
				EliteAssess = #elite_assess{
					task_id       = TaskId
					,category     = Category
					,sub_category = SubCategory
					,progress     = Progress
					,status       = Status
				},
				[EliteAssess|TProgressList];
			_ ->
				TProgressList
		end end,
	lists:foldl(F, [], TaskInfos);
make_list(category, CategoryInfos) ->
	F = fun([Category, Status], TCategoryList) ->
			[{Category, Status}|TCategoryList]
		end,
	lists:foldl(F, [], CategoryInfos).

%% 章节进度
%%make_category_map([], Map) -> Map;
%%make_category_map([TaskProgress|L], TMap) ->
%%	case TaskProgress of
%%		#elite_assess{category = Category, status = Status} when Status == ?HAS_RECEIVED ->
%%			case maps:get(Category, TMap, 0) of
%%				Progress when is_integer(Progress) ->
%%					NewMap = maps:put(Category, Progress+1, TMap);
%%				_ ->
%%					NewMap = maps:put(Category, 1, TMap)
%%			end,
%%			make_category_map(L, NewMap);
%%		_ ->
%%			make_category_map(L, TMap)
%%	end.

%% 获取当前的章节
%%get_current_category(CategoryRewardList, Lv) ->
%%	CategoryL = [Category || {Category, Status} <- CategoryRewardList, Status >= ?HAS_RECEIVED],
%%	CurrentCategory =
%%	case CategoryL of
%%		[_Category|_] ->
%%			NowCategory = lists:max(CategoryL),
%%			NextCategory = NowCategory + 1,
%%			case data_elite_assessment:get_elite_assess_category_reward_cfg(NextCategory) of
%%				#elite_assess_reward_cfg{open_lv = OpenLv} when Lv >= OpenLv ->
%%					NextCategory;
%%				_ ->
%%					NowCategory
%%			end;
%%		_ -> 1
%%	end,
%%	CurrentCategory.

%% 获取章节的开放等级
get_category_open_lv(Category) ->
	case data_elite_assessment:get_elite_assess_category_reward_cfg(Category) of
		#elite_assess_reward_cfg{open_lv = OpenLv} -> skip;
		_ ->
			OpenLv = lib_module:get_open_lv(?MOD_ELITE_ASSESS)
	end,
	OpenLv.

%% 打包章节数据
%%pack_category_list(CurrentCategory, CategoryMap, RewardList) ->
%%	Count = maps:get(CurrentCategory, CategoryMap, 0),
%%	case lists:keyfind(CurrentCategory, 1, RewardList) of
%%		{_, Status} ->
%%			skip;
%%		_ ->
%%			Status =
%%			case data_elite_assessment:get_elite_assess_category_reward_cfg(CurrentCategory) of
%%				#elite_assess_reward_cfg{} ->
%%					NeedCount = length(data_elite_assessment:get_all_task_cfg(CurrentCategory)),
%%					?IF(Count >= NeedCount, ?CAN_RECEIVE, ?CAN_NOT_RECEIVE);
%%				_ ->
%%					?CAN_NOT_RECEIVE
%%			end
%%	end,
%%	[CurrentCategory, Count, Status].

%% 更新章节进度
update_category_progress(StatusEliteAssess, _RoleId, RoleLv) ->
	#status_elite_assess{
		progress_list  = ProgressList
	} = StatusEliteAssess,
	CategoryMap = get_category_map(ProgressList),
	CfgOpenCategoryL = open_category_by_config(RoleLv),
	CurrentCategory  = get_current_category(CfgOpenCategoryL, CategoryMap),
	StatusEliteAssess#status_elite_assess{
		category_map = CategoryMap, current_category = CurrentCategory
	}.

%% 判断是否可以领取章节奖励
can_receive_category_reward(CategoryMap, Category) ->
	case maps:get(Category, CategoryMap, 0) of
		0 -> false;
		Num ->
			case data_elite_assessment:get_elite_assess_category_reward_cfg(Category) of
				#elite_assess_reward_cfg{} ->
					Count = length(data_elite_assessment:get_all_task_cfg(Category)),
					if
						Num >= Count ->
							true;
						true ->
							false
					end
			end
	end.

%% 获取当前任务进度信息
get_task_progress(CurrentCategory, TaskIdL, ProgressList) ->
	F = fun(TaskId, Acc) ->
		case lists:keyfind(TaskId, #elite_assess.task_id, ProgressList) of
			#elite_assess{
				category = CurrentCategory,
				progress = Progress,
				status = Status
			} ->
				[{TaskId, Progress, Status}|Acc];
			_ ->
				[{TaskId, 0, 0}|Acc]
		end
	end,
	lists:foldl(F, [], TaskIdL).

%%get_cur_task_progress([], _ProgressList, ShowList) -> ShowList;
%%get_cur_task_progress([Id|L], ProgressList, TShowList) ->
%%	case lists:keyfind(Id, #elite_assess.task_id, ProgressList) of
%%		false ->
%%			get_cur_task_progress(L, ProgressList, TShowList);
%%		TaskInfo ->
%%			get_cur_task_progress(L, ProgressList, [TaskInfo|TShowList])
%%	end.

check_list([]) -> true;
check_list([Check|L]) ->
	case do_check(Check) of
		true -> check_list(L);
		{false, Res} -> {false, Res}
	end.

do_check({is_category_true, Category}) ->
	case data_elite_assessment:get_elite_assess_category_reward_cfg(Category) of
		#elite_assess_reward_cfg{} ->
			true;
		_ ->
			{false, ?ERRCODE(err452_category_err)}
	end;
do_check({can_receive, Category, CategoryMap, CategoryRewardL}) ->
	case data_elite_assessment:get_elite_assess_category_reward_cfg(Category) of
		#elite_assess_reward_cfg{} ->
			case lists:keyfind(Category, 1, CategoryRewardL) of
				false ->
					{false, ?ERRCODE(err452_category_not_finish)};
				{_, Status} when Status == ?CAN_RECEIVE ->
					CanReceive = can_receive_category_reward(CategoryMap, Category),
					case CanReceive of
						false ->
							{false, ?ERRCODE(err452_category_not_finish)};
						_ ->
							true
					end;
				_ ->
					{false, ?ERRCODE(err452_category_has_received)}
			end;
		_ ->
			{false, ?ERRCODE(err452_category_err)}
	end;
do_check({can_give_goods, Player, Category}) ->
	#elite_assess_reward_cfg{reward = RewardL} = data_elite_assessment:get_elite_assess_category_reward_cfg(Category),
	case lib_goods_api:can_give_goods(Player, RewardL) of
		true -> true;
		_ ->
			{false, ?ERRCODE(err150_no_cell)}
	end;
do_check({is_current_category, Category, CurrentCategory}) ->
	case Category == CurrentCategory of
		true when Category > 0 -> true;
		_ ->
			{false, ?ERRCODE(err452_category_err)}
	end;
do_check({is_sub_category_true, TaskId, ProgressList}) ->
	case data_elite_assessment:get_elite_assess_task_cfg(TaskId) of
		#elite_assess_task_cfg{category = Category, sub_category = SubCategory} ->
			case SubCategory of
				%% 第一小节可以直接领取,其他小节必须是前面的小节领取完
				1 -> true;
				_ ->
					case data_elite_assessment:get_all_sub_category_task_cfg(Category, SubCategory-1) of
						[_|_] = TaskIdL ->
							F = fun(TTaskId, TSum) ->
								case lists:keyfind(TTaskId, #elite_assess.task_id, ProgressList) of
									#elite_assess{status = Status} when Status == ?HAS_RECEIVED ->
										TSum + 1;
									_ -> TSum
								end end,
							Sum = lists:foldl(F, 0, TaskIdL),
							NeedCount = length(TaskIdL),
							case Sum >= NeedCount of
								true -> true;
								_ -> {false, ?ERRCODE(err452_pre_sub_category)}
							end;
						_ ->
							true
					end
			end;
		_ ->
			{false, ?ERRCODE(err452_task_id_err)}
	end;

do_check({task_id_true, TaskId, CurrentCategory}) ->
	case data_elite_assessment:get_elite_assess_task_cfg(TaskId) of
		#elite_assess_task_cfg{category = Category} when Category == CurrentCategory -> true;
		_ ->
			{false, ?ERRCODE(err452_task_id_err)}
	end;
do_check({task_finish, TaskId, ProgressList}) ->
	case lists:keyfind(TaskId, #elite_assess.task_id, ProgressList) of
		#elite_assess{status = Status} when Status == ?CAN_RECEIVE -> true;
		#elite_assess{status = Status} when Status == ?HAS_RECEIVED ->
			{false, ?ERRCODE(err452_reward_has_received)};      %% todo
		_ ->
			{false, ?ERRCODE(err452_can_not_receive)}
	end;
do_check(_Check) ->
	?ERR("<<Error check_elite_assess>>").

send_msg(Sid, Cmd, Msg) ->
	lib_server_send:send_to_sid(Sid, pt_452, Cmd, Msg).

%% ---------------------------- 数据库操作 -------------------------------
db_save_elite_assess(RoleId, TaskId, Progress, Status) ->
	db:execute(io_lib:format(?insert_elite_assessment, [RoleId, TaskId, Progress, Status])).

db_select_elite_assess_task(RoleId) ->
	db:get_all(io_lib:format(?select_elite_assessment, [RoleId])).

db_update_elite_assess_status(RoleId, TaskId, Status) ->
	% NowTime = utime:unixtime(),
	db:execute(io_lib:format(?update_elite_assess_status, [Status, RoleId, TaskId])).


db_save_category_reward(RoleId, Category, Status) ->
	% NowTime = utime:unixtime(),
	db:execute(io_lib:format(?insert_elite_assessment_category_reward, [RoleId, Category, Status])).

%%db_select_category_reward(RoleId) ->
%%	db:get_all(io_lib:format(?select_elite_assessment_category_reward, [RoleId])).

db_save_login_days(RoleId, Days, ReFreshTime) ->
	db:execute(io_lib:format(?insert_elite_assessment_login_days, [RoleId, Days, ReFreshTime])).

%%db_select_login_days(RoleId) ->
%%	db:get_row(io_lib:format(?select_elite_assessment_login_days, [RoleId])).

%% ---------------------------- gm -------------------------------
gm_finish_category_all_task(Player, Category) ->
	#player_status{sid = Sid, id = RoleId, figure = Figure} = Player,
	case get_elite_assess_dict(RoleId, Figure#figure.lv) of
		{ok, StatusEliteAssess} ->
			#status_elite_assess{
				current_category = CurrentCategory
				,progress_list   = ProgressList
			} = StatusEliteAssess,
			case Category == CurrentCategory of
				true ->
					case data_elite_assessment:get_all_task_cfg(Category) of
						[_|_] = TaskIds ->
							MaxTaskId = lists:max(TaskIds),
							F = fun(TaskId, TList) when TaskId =/= MaxTaskId ->
								case lists:keyfind(TaskId, #elite_assess.task_id, TList) of
									#elite_assess{status = Status} when Status >= ?CAN_RECEIVE ->
										TList;
									_ ->
										case data_elite_assessment:get_elite_assess_task_cfg(TaskId) of
											#elite_assess_task_cfg{content = Content, sub_category = SubCategory} ->
												case Content of
													[{Key, Value}|_] when Key =/= pass_dun -> skip;
													_ ->
														Value = 1
												end,
												db_save_elite_assess(RoleId, TaskId, Value, ?CAN_RECEIVE),
												lists:keystore(TaskId, #elite_assess.task_id, TList,
													#elite_assess{category = Category, sub_category = SubCategory,
														task_id = TaskId, progress = Value, status = ?CAN_RECEIVE});
											_ ->
												TList
										end
								end;
								(_, TList) -> TList
							end,
							NewProgressList = lists:foldl(F, ProgressList, TaskIds),
							NewStatusEliteAssess = StatusEliteAssess#status_elite_assess{progress_list = NewProgressList},
							save_elite_assess_dict(NewStatusEliteAssess),
							notify_client_category(RoleId, Figure#figure.lv, NewStatusEliteAssess);
						_ ->
							send_msg(Sid, 45202, [?ERRCODE(err452_category_not_finish), Category])
					end;
				_ ->
					send_msg(Sid, 45202, [?ERRCODE(err452_category_not_finish), Category])
			end;
		_ ->
			skip
	end.
