%%%-------------------------------------------------------------------
%%% @author  tyl
%%% @doc
%%%      樱花之礼(阶段抽奖)-逻辑文件
%%%      p.s. 协议采用的是334，错误码Id还是使用331开头
%%% @end
%%% Created : 2021-03-10
%%%-------------------------------------------------------------------
-module(sakura_gift).

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

%% API
-export([
	act_info/2              %% 活动数据
	,act_end/1              %% 活动结束清理数据
	,sakura_draw/4          %% 抽奖
	,send_draw_log/3        %% 记录数据(1-个人记录 2-全服记录)
	,send_server_log/4      %% 发送全服记录
	,init_server_log/1      %% 初始化全服记录
	% ,person_log/3
	,pack_log_list/3
	,send_reward_and_clean_data/2

	,handle_event/2         %% 登录后处理补偿奖励
	,trans_sakura_data/1

	,save_server_log_to_db/2
	,del_server_log_from_db/2
	,person_log/3
]).

%%-------------------------------------------------------------------------------------
%% @doc
%%      活动结束
%%      活动结束清理db - 个人/全服，清理玩家缓存数据, 发放积分补偿奖励
%% @end
%%-------------------------------------------------------------------------------------
act_end(SubType) ->
	%% 给在线玩家发奖并清理数据，不在线玩家上线时处理
	lib_player:cast_online_role_apply(?APPLY_CAST_STATUS, ?MODULE, send_reward_and_clean_data, [SubType]),
	%% 清理全服缓存日志
	mod_custom_act_log:cast({clean_sakura_gift_log, ?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType}),
	%% 清理数据库
	db:execute(io_lib:format(?SQL_DELETE_ALL_SAKURA_SERVER_LOG, [SubType])),   %% 全服日志
	db:execute(io_lib:format(?SQL_DELETE_ALL_SQKURA_PERSON_LOG, [SubType])),   %% 个人日志
	db:execute(io_lib:format(?SQL_DELETE_SQKURA_STORE, [SubType])),            %% 商场数据
	ok.

send_reward_and_clean_data(#player_status{id = RoleId} = Player, SubType) ->
	#custom_act_data{act_data = ActData} =
		lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType),
	ActData1 = trans_sakura_data(ActData),
	#sakura_data{points = Points} = ActData1,
	Suit = get_suit(SubType),
	ComReward = case data_sakura_gift:get_point_rest_reward(Suit, Points) of
					[_|_] = Reward -> Reward;
					_ -> []
	            end,
	ComReward =/= [] andalso
	begin
		Title = utext:get(3312001), Content = utext:get(3312002),
		lib_mail_api:send_sys_mail(
			[RoleId], ?MOD_SAKURA_GIFT, Title, Content, ComReward
		)
	end,
	%% 清理个人日志缓存 & 商城兑换缓存(如果是清理过，就不需要再重新清理)
	case ActData of
		[] -> ignore;
		_  ->
			put_dict_log(RoleId, SubType, []),
			sakura_store:put_dict_store(RoleId, SubType, []),
			%% 清理活动数据
			lib_custom_act_data:role_clean_up_custom_data(
				Player, ?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType
			)
	end,
	Player.

%%-------------------------------------------------------------------------------------
%% @doc
%%      玩家登录, 处理已经结束的但还未领取补偿奖励的子活动
%% @end
%%-------------------------------------------------------------------------------------
handle_event(Player, #event_callback{type_id = ?EVENT_CLIENT_LOGIN_SUCCESS}) ->
	CfgSubTypeList   = lib_custom_act_util:get_subtype_list(?CUSTOM_ACT_TYPE_SAKURA_GIFT),
	OpenSubTypeList  = lib_custom_act_util:get_open_subtype_list(?CUSTOM_ACT_TYPE_SAKURA_GIFT),
	OpenSubTypeList1 = [SubType||#act_info{key = {_, SubType}}<-OpenSubTypeList],
	CloseSubTypeList = CfgSubTypeList -- OpenSubTypeList1,
	F = fun(TSubType) ->
			send_reward_and_clean_data(Player, TSubType)
		end,
	lists:map(F, CloseSubTypeList),
	%% 如果上次更新时间小于本次活动的开启时间，那么就是上次活动的数据，需要清理
	F1 = fun(TSubType1) ->
		#custom_act_data{time = OldTime} =
			lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_SAKURA_GIFT, TSubType1),
		case lists:keyfind({?CUSTOM_ACT_TYPE_SAKURA_GIFT, TSubType1}, #act_info.key, OpenSubTypeList) of
			#act_info{stime = StartTime} when OldTime < StartTime, OldTime > 0 ->
				send_reward_and_clean_data(Player, TSubType1);
			_ ->
				igonre
		end end,
	lists:map(F1, OpenSubTypeList1),
	{ok, Player}.

%%-------------------------------------------------------------------------------------
%% @doc 活动数据 @end
%%-------------------------------------------------------------------------------------
act_info(#player_status{sid = Sid}, SubType) ->
	case lib_custom_act_api:is_open_act(?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType) of
		true ->
			#custom_act_data{act_data = ActData} =
				lib_custom_act_data:custom_act_data(?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType),
			case trans_sakura_data(ActData) of
				#sakura_data{lucky_value = LuckyValue, free_times = FreeTimes} -> ok;
				_  ->
					LuckyValue = 0, FreeTimes = 0
			end,
			lib_server_send:send_to_sid(
				Sid, pt_334, 33400, [SubType, LuckyValue, FreeTimes]
			);
		false ->
			lib_server_send:send_to_sid(
				Sid, pt_331, 33100, [?ERRCODE(err331_act_closed)]
			)
	end,
	ok.

%%-------------------------------------------------------------------------------------
%% @doc 抽奖 @end
%%-------------------------------------------------------------------------------------
sakura_draw(Player, SubType, DrawType, IsAuto) ->
	#player_status{id = RoleId, sid = Sid} = Player,
	Type = ?CUSTOM_ACT_TYPE_SAKURA_GIFT,
	case lib_custom_act_api:is_open_act(Type, SubType) of
		true ->
			CustomActData = lib_custom_act_data:custom_act_data(Type, SubType),
			CheckList = [{draw_type, DrawType}, {suit, SubType}],
			case check_list(CheckList) of
				true ->
					case sakura_draw_core(Player, SubType, CustomActData, DrawType, IsAuto) of
						{true, NewPlayer, NewCustomActData, RewardList} ->
							lib_custom_act_data:save_custom_data(RoleId, NewCustomActData),
							#custom_act_data{act_data = NewActData} = NewCustomActData,
							#sakura_data{
								lucky_value = NewLuckyValue,
								free_times  = NewFreeTimes
								,points     = Points
							} = NewActData,
							SendReward = pack_send_reward(RewardList),
							lib_server_send:send_to_sid(
								Sid, pt_334, 33401,
								[?SUCCESS, SubType, NewLuckyValue, NewFreeTimes, SendReward, Points]),
							NewPlayer;
						{false, ErrCode} ->
							lib_server_send:send_to_sid(
								Sid, pt_331, 33100, [ErrCode]
							),
							Player
					end;
				{false, Err} ->
					lib_server_send:send_to_sid(
						Sid, pt_331, 33100, [Err]
					),
					Player
			end;
		false ->
			lib_server_send:send_to_sid(
				Sid, pt_331, 33100, [?ERRCODE(err331_act_closed)]
			),
			Player
	end.

pack_send_reward(RewardList) ->
	F = fun(Reward, TList) ->
		case Reward of
			{_, RewardId, Num} -> [{RewardId, Num}|TList];
			{RewardId, Num} ->  [{RewardId, Num}|TList];
			_ -> TList
		end end,
	lists:foldl(F, [], RewardList).

%%-------------------------------------------------------------------------------------
%% @doc 抽奖主体逻辑
-spec sakura_draw_core(Player, SubType, CustomActData, DrawType, IsAuto) -> Return when
	Player       :: #player_status{},
	SubType      :: integer(),              %% 活动子类型
	CustomActData:: #custom_act_data{},
	DrawType     :: integer(),              %% 抽奖类型 1-单抽 2-十连抽
	IsAuto       :: integer(),              %% 是否自动购买
	Return       :: {false, integer()}| {true, #player_status{}, list(), integer()}.
%% @end
%%-------------------------------------------------------------------------------------
sakura_draw_core(Player, SubType, CustomActData, DrawType, IsAuto) ->
	#player_status{id = RoleId, figure = #figure{name = RoleName}} = Player,
	#custom_act_data{act_data = ActData} = CustomActData,
	ActData1 = trans_sakura_data(ActData),
	CostList = get_draw_cost(SubType, DrawType),
	IsFree   = check_free(SubType, DrawType, ActData1),
	#sakura_data{free_times = FreeTimes, lucky_value = LuckyValue, points = Points} = ActData1,
	DrawTimes = calc_draw_times(DrawType),
	%% 判断是否免费
	Return =
	case DrawType of
		1 when IsFree == true ->
			{LuckyValue1, RandIdList} = calc_reward_list(SubType, LuckyValue, DrawTimes, []),
			FreeTimes1 = FreeTimes + 1,
			{true, Player, RandIdList, LuckyValue1, FreeTimes1};
		_ ->
			case IsAuto of
				1 ->
					case lib_goods_api:cost_objects_with_auto_buy(
						Player, CostList, sakurra_draw, ""
					) of
						{true, Player1, _} ->
							{LuckyValue1, RandIdList} = calc_reward_list(SubType, LuckyValue, DrawTimes, []),
							{true, Player1, RandIdList, LuckyValue1, FreeTimes};
						{false, Err, _NewPS} ->
							{false, Err}
					end;
				_ ->
					case lib_goods_api:cost_object_list_with_check(
						Player, CostList, sakurra_draw, ""
					) of
						{true, Player1, _} ->
							{LuckyValue1, RandIdList} = calc_reward_list(SubType, LuckyValue, DrawTimes, []),
							{true, Player1, RandIdList, LuckyValue1, FreeTimes};
						{false, Err, _NewPS} ->
							{false, Err}
					end
			end
	end,
	case Return of
		{true, NewPlayer, RewardIdList, NewLuckyValue, NewFreeTimes} ->
			%% 增加积分
			AddPoints = calc_add_value(SubType, DrawType),
			NewPoints = Points + AddPoints,
			ActData2 = ActData1#sakura_data{lucky_value = NewLuckyValue,
				points = NewPoints, free_times = NewFreeTimes},
			NewCustomActData = CustomActData#custom_act_data{
				act_data = ActData2, time = utime:unixtime()
			},
			RewardList = calc_send_reward(RewardIdList),
			tv_and_log(RoleId, RoleName, SubType, RewardIdList),
			Produce = #produce{type = sakura_draw, reward = RewardList},
			{ok, NewPlayer1} = lib_goods_api:send_reward_with_mail(
				NewPlayer, Produce, ?MOD_SAKURA_GIFT
			),
			{true, NewPlayer1, NewCustomActData, RewardList};
		{false, ErrCode} ->
			{false, ErrCode}
	end.

get_all_reward_ids(SubType, LuckValue) ->
	Suit = get_suit(SubType),
	MaxValue = data_sakura_gift:get_kv(Suit, luck_total),
	case LuckValue >= MaxValue of
		true ->
			RewardList1 = data_sakura_gift:get_reward_ids_by_tag(SubType, ?SAKURA_RARE_REWARD),
			RewardList2 = data_sakura_gift:get_reward_ids_by_tag(SubType, ?SAKURA_EXTREME_REWARD),
			AllCfgReward = RewardList1 ++ RewardList2;
		_ ->
			AllCfgReward = data_sakura_gift:get_all_reward(SubType)
	end,
	AllCfgReward.

calc_draw_times(DrawType) ->
	Times = case DrawType of
		        ?DRAW_TYPE_TEN -> 10;
		        _ -> 1
	        end,
	Times.

%%-------------------------------------------------------------------------------------
%% @doc 记录数据 @end
%%-------------------------------------------------------------------------------------
send_draw_log(#player_status{sid = Sid, id = RoleId, figure = Figure}, SubType, LogType) ->
	case LogType of
		?LOG_TYPE_SERVER ->
			mod_custom_act_log:cast(
				{send_sakura_gift_log, ?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType, RoleId, Figure#figure.name}
			),
			ok;
		?LOG_TYPE_PERSON ->
			case lib_custom_act_api:is_open_act(?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType) of
				true ->
					LogList  = get_dict_log(RoleId, SubType),
					PackList = pack_log_list(person, Figure#figure.name, LogList),
					lib_server_send:send_to_sid(
						Sid, pt_334, 33402, [SubType, LogType, PackList]
					),
					ok;
				false ->
					lib_server_send:send_to_sid(
						Sid, pt_331, 33100, [?ERRCODE(err331_act_closed)]
					),
					ok
			end;
		_ ->
			ignore
	end.

%% 全服记录
send_server_log(SubType, LogList, RoleId, RoleName) ->
	PackList = pack_log_list(server, RoleName, LogList),
	lib_server_send:send_to_uid(
		RoleId, pt_334, 33402, [SubType, ?LOG_TYPE_SERVER, PackList]
	),
	ok.

%% 初始化全服记录
init_server_log(SubType) ->
	case db:get_all(?SQL_SELECT_SAKURA_SERVER_LOG, [SubType]) of
		[_|_] = DbList ->
			F = fun([Id, RoleId, Tag, Reward, Time], TList) ->
				Log = #sakura_server_log{
					key = Id
					,role_id = RoleId
					,tag     = Tag
					,reward  = util:bitstring_to_term(Reward)
					,time = Time
				},
				[Log|TList]
			    end,
			LogList = lists:foldl(F, [], DbList);
		_ ->
			LogList = []
	end,
	SortFun = fun(A, B) -> A#sakura_server_log.key > B#sakura_server_log.key end,
	LogList1 = lists:sort(SortFun, LogList),
	Key = {sakura_gift_log, ?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType},
	put(Key, LogList1).

get_dict_log(RoleId, SubType) ->
	LogKey = ?LOG_KEY_PERSON(RoleId, SubType),
	case get(LogKey) of
		LogList when is_list(LogList) -> ok;
		_ ->
			LogList = get_per_log_from_db(RoleId, SubType),
			put(LogKey, LogList)
	end,
	LogList.

put_dict_log(RoleId, SubType, LogList) when is_list(LogList) ->
	LogKey = ?LOG_KEY_PERSON(RoleId, SubType),
	put(LogKey, LogList),
	ok;
put_dict_log(_, _, _) ->
	ok.

get_per_log_from_db(RoleId, SubType) ->
	case db:get_all(io_lib:format(?SQL_SELECT_SAKURA_PERSON_LOG, [RoleId, SubType])) of
		[_|_] = DbList ->
			F = fun([Id, Reward, Time], TList) ->
				Log = #sakura_per_log{
					key = Id
					,reward = util:bitstring_to_term(Reward)
					,time   = Time
				},
				[Log|TList]
			end,
			LogList = lists:foldl(F, [], DbList),
			LogList;
		_ ->
			[]
	end.

save_per_log_to_db(RoleId, SubType, Log) ->
	#sakura_per_log{key = Id, reward = Reward, time = Time} = Log,
	db:execute(io_lib:format(?SQL_SAVE_SAKURA_PERSON_LOG,
		[RoleId, SubType, Id, util:term_to_string(Reward), Time])
	),
	ok.

del_per_log_from_db(RoleId, SubType, LogId) ->
	db:execute(io_lib:format(?SQL_DELETE_SQKURA_PERSON_LOG, [RoleId, SubType, LogId])),
	ok.

save_server_log_to_db(SubType, Log) ->
	#sakura_server_log{key = Id, role_id = RoleId, tag = Tag, reward = Reward, time = Time} = Log,
	db:execute(io_lib:format(?SQL_SAVE_SAKURA_SERVER_LOG,
		[SubType, Id, RoleId, Tag, util:term_to_string(Reward), Time])
	),
	ok.

del_server_log_from_db(SubType, LogId) ->
	db:execute(io_lib:format(?SQL_DELETE_SAKURA_SERVER_LOG, [SubType, LogId])),
	ok.

pack_log_list(server, _RoleName, LogList) ->
	% LogList1 = queue:to_list(LogList),
	F = fun(#sakura_server_log{
			role_id = RoleId, reward = Reward, time = Time}, TList
		) ->
		case lib_role:get_role_show(RoleId) of
			#ets_role_show{figure = Figure} -> ok;
			_ -> Figure = #figure{}
		end,
		case Reward of
			[{_, RewardId, Num}|_] -> ok;
			_ -> RewardId = 0, Num = 0
		end,
		[{Figure#figure.name, RewardId, Num, Time}|TList]
	end,
	lists:foldl(F, [], LogList);
pack_log_list(person, RoleName, LogList) ->
	F = fun(#sakura_per_log{reward = Reward, time = Time}, TList) ->
		case Reward of
			[{_, RewardId, Num}|_] -> ok;
			_ -> RewardId = 0, Num = 0
		end,
		[{RoleName, RewardId, Num, Time}|TList]
	    end,
	lists:foldl(F, [], LogList).


trans_sakura_data(#sakura_data{} = SakuraData) -> SakuraData;
trans_sakura_data(_) -> #sakura_data{}.

%% -------------------------------- builtin_function ----------------------------------
%% 判断本次是否免费
check_free(SubType, DrawType, ActData) ->
	case DrawType of
		1 ->
			Suit = get_suit(SubType),
			FreeTimeConfig = data_sakura_gift:get_kv(Suit, free_time),
			#sakura_data{free_times = FreeTimes} = ActData,
			case FreeTimes < FreeTimeConfig of
				true -> true;
				_ -> false
			end;
		_ ->
			false
	end.

%% 键值对对应的套数
get_suit(SubType) ->
	Type = ?CUSTOM_ACT_TYPE_SAKURA_GIFT,
	case lib_custom_act_util:get_act_cfg_info(Type, SubType) of
		#custom_act_cfg{condition = Condition} ->
			case lists:keyfind(suit, 1, Condition) of
				{_, Suit} -> ok;
				_ -> Suit = 0
			end;
		_ -> Suit = 0
	end,
	Suit.

%% 消耗材料
get_draw_cost(SubType, DrawType) ->
	Key = case DrawType of
			  ?DRAW_TYPE_ONE -> pray_one;
			  ?DRAW_TYPE_TEN -> pray_ten;
			  _ -> pray_one
	      end,
	Suit = get_suit(SubType),
	Cost = data_sakura_gift:get_kv(Suit, Key),
	Cost.

%% ----------------------------------------------------------------
%% @doc  奖励相关计算 @end
%% ----------------------------------------------------------------
%% 根据次数计算出随机奖励列表 - return: [reward_id...]
calc_reward_list(_SubType, LuckyValue, 0, RewardList) -> {LuckyValue, RewardList};
calc_reward_list(SubType,LuckyValue, DrawTimes, RewardList) ->
	{NewLuckyValue, RewardId} = calc_rand_reward(SubType, LuckyValue),
	calc_reward_list(SubType, NewLuckyValue, DrawTimes - 1, [RewardId|RewardList]).

%% 计算随机奖励
calc_rand_reward(SubType, LuckyValue) ->
	CfgRewardList = get_all_reward_ids(SubType, LuckyValue),
	WeightList   = config_reward_list(CfgRewardList, LuckyValue),
	% ?INFO_TTY("CfgRewardList is ~w~n",[CfgRewardList]),
	RandRewardId = urand:rand_with_weight(WeightList),
	% ?INFO_TTY("RandRewardId is ~w~n",[RandRewardId]),
	Suit = get_suit(SubType),
	AddValue = case data_sakura_gift:get_kv(Suit, pray_luck) of
		           TValue when is_integer(TValue) -> TValue;
		           _ -> 0
	           end,
	%% 判断是否是极品奖励,抽到极品奖励,幸运值清0; 达到最大幸运值也清0
	MaxValue = data_sakura_gift:get_kv(Suit, luck_total),
	case LuckyValue >= MaxValue of
		true ->
			NewLuckyValue = 0;
		_ ->
			case data_sakura_gift:get_reward_config(RandRewardId) of
				#base_sakura_gift_reward{tag = ?SAKURA_EXTREME_REWARD} ->
					NewLuckyValue = 0;
				_ ->
					NewLuckyValue = LuckyValue + AddValue
			end
	end,
	% ?INFO_TTY("LuckyValue is ~w~n",[LuckyValue]),
	% ?INFO_TTY("NewLuckyValue is ~w~n",[NewLuckyValue]),
	{NewLuckyValue, RandRewardId}.

%% 整理出符合要求的配置 - return: [{weight, reward_id}...]
config_reward_list(AllCfgReward, LuckyValue) ->
	F = fun(RewardId, TList) ->
		case data_sakura_gift:get_reward_config(RewardId) of
			#base_sakura_gift_reward{weight = BaseWeight, luck_weight = LuckWeight,
				luck_start = LuckStar, luck_end = LuckEnd}
				when LuckyValue >= LuckStar andalso LuckyValue =< LuckEnd ->
				NewWeight = BaseWeight + LuckyValue * LuckWeight,
				[{NewWeight, RewardId}|TList];
			#base_sakura_gift_reward{weight = BaseWeight} ->
				[{BaseWeight, RewardId}|TList];
			_ ->
				TList
		end end,
	WeightList = lists:foldl(F, [], AllCfgReward),
	WeightList.

%% 计算发放的奖励
calc_send_reward(RewardIdList) ->
	F = fun(RewardId, TList) ->
		case data_sakura_gift:get_reward_config(RewardId) of
			#base_sakura_gift_reward{awards = Awards} ->
				Awards ++ TList;
			_ ->
				TList
		end end,
	RewardList = lists:foldl(F, [], RewardIdList),
	RewardList.

%% ----------------------------------------------------------------
%% 增加幸运值和积分
calc_add_value(SubType, DrawType) ->
	Times = case DrawType of
		        ?DRAW_TYPE_TEN -> 10;
		        _ -> 1
	        end,
	Suit = get_suit(SubType),
	case data_sakura_gift:get_kv(Suit, pray_score) of
		Score when is_integer(Score) -> ok;
		_ -> Score = 0
	end,
	Score * Times.

%% 传闻 & 记录
tv_and_log(RoleId, RoleName, SubType, RewardList) ->
	F = fun(RewardId) ->
		case data_sakura_gift:get_reward_config(RewardId) of
			#base_sakura_gift_reward{is_tv = IsTv, tag = Tag, awards = Reward} ->
				case Reward of
					[{_, GoodsId, Num}|_] -> ok;
					_ -> GoodsId = 0, Num = 0
				end,
				NowTime = utime:unixtime(),
				ServerLog = #sakura_server_log{role_id = RoleId, reward = Reward, tag = Tag, time = NowTime},
				% PersonLog = #sakura_per_log{reward = Reward, time = NowTime},
				case Tag of
					?SAKURA_RARE_REWARD ->
						IsTv == ?SAKURA_TV andalso
							lib_chat:send_TV({all}, 331, 46, [RoleName, GoodsId, Num]),
						mod_custom_act_log:cast(
							{sakura_gift_log, ?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType, ServerLog}
						),
						% person_log(RoleId, SubType, PersonLog),
						ok;
					?SAKURA_EXTREME_REWARD ->
						IsTv == ?SAKURA_TV andalso
							lib_chat:send_TV({all}, 331, 45, [RoleName, GoodsId, Num]),
						mod_custom_act_log:cast(
							{sakura_gift_log, ?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType, ServerLog}
						),
						% person_log(RoleId, SubType, PersonLog),
						ok;
					_ ->
						%% 普通奖励也记录到个人日志当中
						% person_log(RoleId, SubType, PersonLog),
						ok
				end;
			_ ->
				ignore
		end end,
	lists:map(F, RewardList),
	ok.

%% 记录
person_log(RoleId, SubType, PersonLog) ->
	LogList = get_dict_log(RoleId, SubType),
	case LogList of
		[LastLog|_] ->
			#sakura_per_log{key = Key} = LastLog,
			PersonLog1 = PersonLog#sakura_per_log{key = Key + 1},
			MaxLen = ?LOG_LEN_PERSON,
			{NewLogList, DropLogList} = ulists:split(MaxLen, [PersonLog1|LogList]),
			save_per_log_to_db(RoleId, SubType, PersonLog1),
			F = fun(#sakura_per_log{key = Id}) ->
				del_per_log_from_db(RoleId, SubType, Id)
			end,
			lists:map(F, DropLogList),
			put_dict_log(RoleId, SubType, NewLogList);
		_ ->
			PersonLog1 = PersonLog#sakura_per_log{key = 1},
			save_per_log_to_db(RoleId, SubType, PersonLog1),
			NewLogList = [PersonLog1],
			put_dict_log(RoleId, SubType, NewLogList)
	end,
	ok.

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

do_check({draw_type, DrawType}) ->
	case lists:member(DrawType, [?DRAW_TYPE_ONE, ?DRAW_TYPE_TEN]) of
		true -> true;
		_ -> {false, ?ERRCODE(err331_draw_type_err)}
	end;
do_check({suit, SubType}) ->
	case lib_custom_act_util:get_act_cfg_info(?CUSTOM_ACT_TYPE_SAKURA_GIFT, SubType) of
		#custom_act_cfg{condition = Condition} ->
			case lists:keyfind(suit, 1, Condition) of
				{_, Suit} when is_integer(Suit) andalso Suit > 0 ->
					true;
				_ ->
					{false, ?ERRCODE(err331_suit_err)}
			end;
		_ -> {false, ?ERRCODE(err331_suit_err)}
	end;
do_check(_) ->
	?ERR("Check sakura_gift err"),
	false.