-- 竞技场逻辑

-- 开始结束赛季 给赛季奖励 ok
-- 设置防守阵容 ok
-- 查询基础 ok
-- 战斗		ok
-- 积分		ok
-- 排行 根据排行给奖励 ok
-- 保存战斗记录和查询战斗记录
-- 门票购买 ok


--[=[
	------JjcDB---------
	jjcDB.initAfterStart()开始
	如果是第一次开启
		1.设定本轮活动结束时间, 即开服时间 + 7*86400 - 10800
		2.jjcDB.initJJCDB()——>jjcDB.resetJJCDB()——>jjcDB.addNpc() 生成机器人,缓存到RANK_2_JJCDATA 和 ROBOT_LIST，并把机器人数据插入到数据库 db_jjc 中
	非第一次开启
		把竞技场玩家和npc数据读取到内存


	--------JjcLogin.lua-----------
	onHour() 定时整点函数
		4点, 删除符合条件的战斗视频数据
		21点, 发放当日排行奖励

		如果本轮活动结束, 发放排行奖励, 重置数据(包括删除竞技场战斗视频数据), 设置新一轮活动结束时间。

	
	每次查询或者战斗时, 检测如果玩家如果没有加入竞技场, 且设置了竞技场的防守阵容, 则会把玩家加入竞技场, 排名为现有竞技场人数(包含npc) + 1。
	挑战胜利, 则更新对战双方的积分和排名。


]=]--



local Util = require("common.Util")
local HtmlUtil = require("common.HtmlUtil")
local Lang = require("common.Lang")
local CommonDB = require("common.CommonDB")
local JjcExcel = require("excel.jjc")
local MonsterExcel = require("excel.monster")
local MailExcel = require("excel.mail")
local Msg = require("core.Msg")
local ObjHuman = require("core.ObjHuman")
local Broadcast = require("broadcast.Broadcast")
local Grid = require("bag.Grid")
local BagLogic = require("bag.BagLogic")
local ItemDefine = require("bag.ItemDefine")
local JjcDB = require("jjc.JjcDB")
local JjcActLogic = require("jjc.JjcActLogic")
local RoleDBLogic = require("role.RoleDBLogic")
local HeroDefine = require("hero.HeroDefine")
local HeroGrid = require("hero.HeroGrid")
local CombatDefine = require("combat.CombatDefine")
local CombatLogic = require("combat.CombatLogic")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local MailManager = require("mail.MailManager")
local DailyTaskLogic = require("dailyTask.DailyTaskLogic")
local MonthHzz = require("monthAct.MonthHzz")
local UnionDBLogic = require("union.UnionDBLogic")
local HeroExcel = require("excel.hero").hero
local HeroLogic = require("hero.HeroLogic")
local CombatPosLogic = require("combat.CombatPosLogic")
local ChatPaoMaLogic = require("chat.ChatPaoMaLogic")
local RoleDefine = require("role.RoleDefine")
local RoleLogic = require("role.RoleLogic")
local CombatVideo = require("combat.CombatVideo")
local WarReportLogic = require("warReport.WarReportLogic")
local LiLianLogic = require("dailyTask.LiLianLogic")
local MailDefine = require("mail.MailIdDefine")
local HeroLogLogic = require("absAct.HeroLogLogic")
local HeroGrowUp = require("absAct.HeroGrowUp")
local MengxinLogic = require("present.MengxinLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local Timer = require("core.Timer")
local WarOrder = require("shop.WarOrder")
local TriggerDefine = require("trigger.TriggerDefine")
local TriggerLogic = require("trigger.TriggerLogic")

local ARENA_ORDER_TYPE = 4

JJC_TARGET_CNT = 15		            -- 每次找15个对手
JJC_FREE_DAILY_CNT = 3	            -- 每天3次免费战斗次数
JJC_WORSHIP_CNT = 10	            -- 每天10次膜拜次数
JJC_WORSHIP_DOT_CNT = 3	            -- 每天膜拜3次后红点消失
JJC_WORSHIP_JINBI_CNT = 3000	    -- 膜拜成功给金币数量
JJC_COST_ITEM_CNT = 10	            -- 竞技场挑战花费数量
JJC_OPEN_QUICK = 20
JJC_DOUBLE_CNT = 20                 -- 双倍奖励次数

JJC_COOL_TIME = 60

JJC_RESULT_DEF_FAIL = 0
JJC_RESULT_ATK_WIN = 1
JJC_RESULT_ATK_FAIL = 2
JJC_RESULT_DEF_WIN = 3

local QUICK_COND_TIMES = 10  -- 跳过战斗需要战斗次数

local WORSHIP_NUM = 10		-- 一键膜拜数量


-- 检查是否加入竞技场
function checkNeedJoin(human)
	if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1301) then
		return
	end
	-- 如果还没参加竞技场 并且已经设置过防守阵容 那么加入竞技场
	local data = JjcDB.getJjcData(human.db._id)
	if data then return end
	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE3, nil, true) 
	if not combatHero or not next(combatHero) then return end
	JjcDB.addPlayer(human)
end

-- 构造成员结构体
function fontMemberNet(net, rank, data,worshipCnt,worshipState)
	net.rank = rank
	net.jifen = data and data.point or 0
	net.worshipCnt = worshipCnt
	net.worshipState = worshipState
	if data.monsterOutID then
		RoleLogic.makeRoleBase(data, net.roleBase)
	else
		RoleLogic.getRoleBaseByUuid(data._id, net.roleBase, CombatDefine.COMBAT_TYPE3)
	end
end

-- 竞技场查询
function query(human)
	local flag, config = RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1301)
	if flag ~= true then
		--return Broadcast.sendErr(human, Lang.JJC_OPEN_NEED_LV)
		return Broadcast.sendErr(human, Util.format(Lang.COMMON_NEED_LEVEL, config.lv))
	end

	local leftSec = getLeftSec()
	if leftSec == nil then
		return Broadcast.sendErr(human, Lang.JJC_NOT_SET_OPEN_TIME) 
	end
    
    -- 检查是否加入到竞技场
	checkNeedJoin(human)	

    local seasonBox = JjcDB.getJjcSeasonBox(human.db._id)
    local totalFight = JjcDB.getJjcTotalFight(human.db._id)
    local totalFightCnt = JjcDB.getTotalFightCnt(human.db._id)
	local msgRet = Msg.gc.GC_JJC_QUERY
	msgRet.leftSec = leftSec
	msgRet.ownRank = JjcDB.getRank(human.db._id)
	msgRet.ownJifen = JjcDB.getJjcPoint(human.db._id)
	msgRet.defZDL = CombatPosLogic.getCombatHeroZDL(human, CombatDefine.COMBAT_TYPE3)	
	msgRet.atkZDL = CombatPosLogic.getCombatHeroZDL(human, CombatDefine.COMBAT_TYPE1)	
    msgRet.dotList[0] = 3
    msgRet.dotList[1] = championChallengeDot(human)
    msgRet.dotList[2] = championBillboardDot(human)
    msgRet.dotList[3] = championRecordDot(human)
    msgRet.challengeCnt = totalFight
    Grid.makeItem(msgRet.challengeCostItem,ItemDefine.ITEM_JJC_TICKET_ID,JJC_COST_ITEM_CNT)
    msgRet.isQuick = human.db.combatQuick[CombatDefine.COMBAT_TYPE2] or 0
    if human.db.combatQuick[CombatDefine.COMBAT_TYPE2] == nil then
        if totalFightCnt >= QUICK_COND_TIMES then
            human.db.combatQuick[CombatDefine.COMBAT_TYPE2] = 0
        else
            msgRet.isQuick = -1
        end 
    end

    local boxExcel = JjcExcel.seasonBox
    local boxLen = #boxExcel
    for i = 1,boxLen do
        local v = boxExcel[i]
        local net = msgRet.jjcBox[i]
        net.reachCnt = v.reachCnt

        if seasonBox == nil or seasonBox[i] == nil then
            -- 未领取
            if totalFight >= v.reachCnt then
                -- 已达标
                net.state = 1
            else
                net.state = 0
            end
        else
            -- 已领取
            net.state = 2
        end
        local itemLen = #v.item
        for j = 1,itemLen do
            Grid.makeItem(net.item[j],v.item[j][1],v.item[j][2])
        end
        net.item[0] = itemLen
    end
    msgRet.jjcBox[0] = boxLen

	Msg.send(msgRet, human.fd)
	
	local nowRank = JjcDB.getRank(human.db._id)
	if nowRank > 0 and ((human.db.jjcBestRank or 0) <= 0 or nowRank < (human.db.jjcBestRank or 0)) then
		human.db.jjcBestRank = nowRank
	end
end

function getQuick(human, combatType)
   local totalFight = JjcDB.getJjcTotalFight(human.db._id)
   if totalFight > JJC_OPEN_QUICK then
      return 1
   end
   return 0
end

-- 挑战记录查询
function recordQuery(human)
	local msgRet = Msg.gc.GC_JJC_RECORD_QUERY    
    local recordList = JjcDB.getJjcRecordList(human.db._id)
    
    local nowFightCnt = human.db.jjcDailyFight or 0
	msgRet.leftFreeCnt = math.max(JJC_FREE_DAILY_CNT - nowFightCnt, 0)
	msgRet.recordList[0] = 0
    if not recordList then
	    Msg.send(msgRet, human.fd)
        return
    end	
	for i = 1, #recordList do
		local videoUuid = recordList[i]
		local combatVideo = CombatVideo.getCombatVideo(videoUuid)
		if combatVideo then
			msgRet.recordList[0] = msgRet.recordList[0] + 1
			local net = msgRet.recordList[msgRet.recordList[0]]
			local combatInfo = combatVideo.combatInfo
			local parms = combatInfo.endParam and Util.split(combatInfo.endParam, "|")	
			net.time = combatInfo.time		    
			net.identity = combatVideo._id 			
            if combatInfo.attacker.uuid == human.db._id then
                RoleLogic.makeRoleBase(combatInfo.defender, net.roleBase)
				net.result = combatInfo.isWin and JJC_RESULT_ATK_WIN or JJC_RESULT_ATK_FAIL
				net.jifenChange = tonumber(parms and parms[3]) or 0
			else
                RoleLogic.makeRoleBase(combatInfo.attacker, net.roleBase)
                net.result = (not combatInfo.isWin) and JJC_RESULT_DEF_WIN or JJC_RESULT_DEF_FAIL
				net.jifenChange = tonumber(parms and parms[4]) or 0
			end
		end			
	end
	Msg.send(msgRet, human.fd)

    -- 记录点开战斗记录时间
    human.db.jjcNewestRecord = os.time()
    RoleSystemLogic.onDot(human,RoleSystemDefine.ROLE_SYS_ID_1300)
end

--[[-- 计算分数
function calcPoint(comBatResult, atkPoint, defPoint)
    -- 赢 加积分 扣对方积分
	local addPoint = 0
    local delPoint = 0

    if comBatResult == CombatDefine.RESULT_WIN then
       if defPoint > 0 then
		    if atkPoint >= defPoint then
                local tp1 = (defPoint/atkPoint)^2 * (1250/atkPoint) * 25
                local tp2 = 1 + math.floor((defPoint-atkPoint)/50 + 0.5) / 10
                addPoint =  math.ceil (tp1 * tp2)
                delPoint = math.ceil(addPoint * (atkPoint/defPoint))
		    else
                --我方积分较低的胜场
                addPoint = math.ceil((defPoint/atkPoint)^2 * (1250/atkPoint)*25)
                delPoint = math.ceil(addPoint * (atkPoint/defPoint)) 
            end
        end
        
	    if addPoint <= 0 or delPoint <= 0 then
			addPoint = 0
			delPoint = 0
		else
            addPoint = addPoint > 100 and 100 or addPoint
            delPoint = delPoint > 100 and 100 or delPoint
        end

        atkPoint = atkPoint + addPoint --我方积分
		defPoint = defPoint - delPoint --防守方积分
       
    else
        -- 输 减积分 加对方积分
        local scal = 15
		if atkPoint >= defPoint then
            scal = 25
        end

        if defPoint > 0 then
           addPoint = math.ceil((atkPoint / defPoint) * scal)
           delPoint = math.ceil(addPoint * (atkPoint/defPoint))
        end

	    if addPoint <= 0 or delPoint <= 0 then
			addPoint = 0
			delPoint = 0
		else
            addPoint = addPoint > 100 and 100 or addPoint
            delPoint = delPoint > 100 and 100 or delPoint
        end

        atkPoint = atkPoint - addPoint
		defPoint = defPoint + delPoint
    end

    if atkPoint < 0 then
       atkPoint = 1
    end
    if defPoint < 0 then
       defPoint = 1
    end

    return atkPoint, defPoint
end]]

-- 计算分数
function calcPoint(comBatResult, atkPoint, defPoint)
    -- 赢 加积分 扣对方积分
	local addPoint = 0
    local delPoint = 0

	addPoint = math.ceil(22/(atkPoint/defPoint)^2)
    delPoint = math.ceil(22/(atkPoint/defPoint)^2 - 5) 

	if addPoint <= 1 then
		addPoint = 1
    end

    if defPoint <= 1 then
		defPoint = 1
    end

    if comBatResult == CombatDefine.RESULT_WIN then
        atkPoint = atkPoint + addPoint --我方积分
		defPoint = defPoint - delPoint --防守方积分
    end

    if atkPoint < 0 then
       atkPoint = 1
    end

    if defPoint < 0 then
       defPoint = 1
    end

    return atkPoint, defPoint
end

function rewardQuery(human, type)
	if type ~= 1 and type ~= 2 then
		return
	end
	
	local msgRet = Msg.gc.GC_JJC_DAY_REWARD_QUERY
	msgRet.type = type
	msgRet.rank = JjcDB.getRank(human.db._id)
	msgRet.canGet[0] = 0
	if type == 1 then
		-- 每日奖励
		for i = 1, #JjcExcel.dayReward do
			local configTemp = JjcExcel.dayReward[i]
			msgRet.list[i].maxRank = configTemp.rankMax
			msgRet.list[i].minRank = configTemp.rankMin
            local len = #configTemp.reward
			msgRet.list[i].items[0] = len
			for j = 1, len do
				local itemID = configTemp.reward[j][1]
				local itemCnt = configTemp.reward[j][2]
				Grid.makeItem(msgRet.list[i].items[j], itemID, itemCnt)
			end		
            if msgRet.rank >= configTemp.rankMin and msgRet.rank <= configTemp.rankMax then
                for j = 1, len do
			    	local itemID = configTemp.reward[j][1]
			    	local itemCnt = configTemp.reward[j][2]
			    	Grid.makeItem(msgRet.canGet[j], itemID, itemCnt)
			    end
                msgRet.canGet[0] = len
            end
		end
		msgRet.list[0] = #JjcExcel.dayReward
		
		local now = os.time()
		local ts1 = Util.getDayHourTime(now, 21)
		if now >= ts1 then
			msgRet.leftSec = ts1 + 24 * 3600 - now
		else
			msgRet.leftSec = ts1 - now
		end
	else
		-- 赛季奖励
		for i = 1, #JjcExcel.seasonReward do
			local configTemp = JjcExcel.seasonReward[i]
			msgRet.list[i].maxRank = configTemp.rankMax
			msgRet.list[i].minRank = configTemp.rankMin
            local len = #configTemp.reward
			msgRet.list[i].items[0] = len
			for j = 1, len do
				local itemID = configTemp.reward[j][1]
				local itemCnt = configTemp.reward[j][2]
				Grid.makeItem(msgRet.list[i].items[j], itemID, itemCnt)
			end		
            if msgRet.rank >= configTemp.rankMin and msgRet.rank <= configTemp.rankMax then
                for j = 1, len do
			    	local itemID = configTemp.reward[j][1]
			    	local itemCnt = configTemp.reward[j][2]
			    	Grid.makeItem(msgRet.canGet[j], itemID, itemCnt)
			    end
                msgRet.canGet[0] = len
            end
		end
		msgRet.list[0] = #JjcExcel.seasonReward
		
		msgRet.leftSec = 0
	end

	Msg.send(msgRet, human.fd)
end

--[[
-- 查找对手
function targetFind(human)

    ObjHuman.updateDaily(human)
	
	local rank = 0
	local len = 0
	local tempRank = {}
	local targetIndexs = {}
	local nowFightCnt = human.db.jjcDailyFight or 0
	local leftFreeCnt = 0
	if JJC_FREE_DAILY_CNT > nowFightCnt then
		leftFreeCnt = JJC_FREE_DAILY_CNT - nowFightCnt
	end
	
	local msgRet = Msg.gc.GC_JJC_TARGET_FIND
	msgRet.leftFreeCnt = leftFreeCnt
	
	--没有加入队列
	local humanRank = JjcDB.getRank(human.db._id)
	if humanRank < 1 then
		--随机取机器人
		local randomCount = #JjcDB.ROBOT_LIST - 30
		local randomIndex = math.random(1, randomCount)
		local randomEnd = randomIndex + 30
		for i = randomIndex, randomEnd do
			local dataTemp = JjcDB.ROBOT_LIST[i]
			if dataTemp ~= nil then
				if len >= 30 then
					break
				end
				len = len + 1
				fontMemberNet(msgRet.targetList[len], rank, dataTemp,0,0)
			end	
		end
		msgRet.targetList[0] = len
		Msg.send(msgRet, human.fd)
		return
	end
	
	local leftCnt = 8 -- 往前取8个
	local rightCnt = JJC_TARGET_CNT - leftCnt -- 往后取7个
	if humanRank <= leftCnt then
		leftCnt = humanRank - 1
		rightCnt = JJC_TARGET_CNT - leftCnt
	end
	if humanRank >= #JjcDB.RANK_2_JJCDATA - rightCnt then
		rightCnt = #JjcDB.RANK_2_JJCDATA - humanRank 
		leftCnt = JJC_TARGET_CNT - rightCnt
	end

	if leftCnt > 0 then
		for i = humanRank - leftCnt, humanRank - 1 do
			table.insert(targetIndexs, i)
		end
	end
	if rightCnt > 0 then
		for i = humanRank + 1, humanRank + rightCnt do
			table.insert(targetIndexs, i)
		end	
	end

	for i = 1, JJC_TARGET_CNT do
		rank = targetIndexs[i]
		if rank > 0 then
			tempRank[rank] = rank
		end
        
	end
    
	-- 自己的前20位 再随机 取5个
    local rankMin= humanRank - 20
	local rankMax = humanRank - 1
	if rankMin > 0 and rankMax > 0 then
		local randIndex = math.random(rankMin, rankMax)
		local endRank = randIndex + 5
		for i = randIndex, endRank do
			if tempRank[i] == nil and i ~= humanRank and JjcDB.RANK_2_JJCDATA[i] ~= nil then
				tempRank[i] = i
			end			
		end		
	end
	
	-- 自己的后100位 再随机 取10个
    rankMin = humanRank + 1
	rankMax = humanRank + 300
    
	if rankMin > 0 and rankMax > 0 then
		local randIndex = math.random(rankMin, rankMax)
		local endRank = randIndex + 10
		for i = randIndex, endRank do
			if tempRank[i] == nil and i ~= humanRank and JjcDB.RANK_2_JJCDATA[i] ~= nil then
				tempRank[i] =  i
			end			
		end		
	end
	
	local unionUuid = ""
	for k, rank in pairs(tempRank) do
		local dataTemp = JjcDB.RANK_2_JJCDATA[rank]
		if dataTemp ~= nil and rank ~= humanRank then
			if len >= 30 then
				break
			end
			len = len + 1
            local db = RoleDBLogic.getDb(dataTemp._id)
            if db == nil then
			    fontMemberNet(msgRet.targetList[len], rank, dataTemp,0,0)
            else
                local worshipCnt = db.jjcBeWorship and db.jjcBeWorship or 0
                local worshipState = 0
                if db._id ~= human.db._id and (human.db.jjcWorship == nil or human.db.jjcWorship[dataTemp._id] == nil) then
                    worshipState = 1
                end
			    fontMemberNet(msgRet.targetList[len], rank, dataTemp,worshipCnt,worshipState)
            end
		end	
	end
	msgRet.targetList[0] = len
	Msg.send(msgRet, human.fd)
end
]]

-- 查找对手
function targetFind(human,type)

    ObjHuman.updateDaily(human)
	
	local rank = 0
	local len = 0
	local targetIndexs = {}
	local nowFightCnt = human.db.jjcDailyFight or 0
	local leftFreeCnt = 0
	if JJC_FREE_DAILY_CNT > nowFightCnt then
		leftFreeCnt = JJC_FREE_DAILY_CNT - nowFightCnt
	end
	
	local msgRet = Msg.gc.GC_JJC_TARGET_FIND
	msgRet.leftFreeCnt = leftFreeCnt
	
	--没有加入队列
	local humanPoint = JjcDB.getJjcPoint(human.db._id)
    local areaList = {}
    local choseUuid = {}
    local count = 0
    local jjcRival = JjcDB.getJjcRival(human.db._id)
    if jjcRival ~= nil and #jjcRival ~= 0 and type == 0 then
        for k,v in pairs(jjcRival) do
            local rank = JjcDB.getRank(v) 
            local jjcData = JjcDB.RANK_2_JJCDATA[rank]
            len = len + 1
            local db = RoleDBLogic.getDb(v)
            if db == nil then
	            fontMemberNet(msgRet.targetList[len], rank, jjcData,0,0)
            else
                local worshipCnt = db.jjcBeWorship and db.jjcBeWorship or 0
                local worshipState = 0
                if db._id ~= human.db._id and (human.db.jjcWorship == nil or human.db.jjcWorship[v] == nil) then
                    worshipState = 1
                end
	            fontMemberNet(msgRet.targetList[len], rank, jjcData,worshipCnt,worshipState)
            end
            if len >= 3 then
                break
            end
        end
    else
        local minRate = 95
        local maxRate = 110
        while true do
            local minPoint = math.floor(humanPoint*minRate/100)
            local maxPoint = math.floor(humanPoint*maxRate/100)
	        for k,v in pairs(JjcDB.RANK_2_JJCDATA) do
                if v.point > minPoint and v.point < maxPoint and v._id ~= human.db._id and choseUuid[v._id] == nil then
                    count = count + 1
                    areaList[count] = v._id
                    choseUuid[v._id] = 1
                end
            end
            if count < 10 then
                minRate = minRate - 10
                maxRate = maxRate + 10
            else
                break
            end
        end
        for i = 1,3 do
            local index = 0
            while true do
                index = math.random(1,count)
                if areaList[index] ~= nil then
                    break
                end
            end
            local uuid = areaList[index]
            areaList[index] = nil
            local rank = JjcDB.getRank(uuid) 
            local v = JjcDB.RANK_2_JJCDATA[rank]
            local db = RoleDBLogic.getDb(uuid)
            if db == nil then
	            fontMemberNet(msgRet.targetList[i], rank, v,0,0)
            else
                local worshipCnt = db.jjcBeWorship and db.jjcBeWorship or 0
                local worshipState = 0
                if db._id ~= human.db._id and (human.db.jjcWorship == nil or human.db.jjcWorship[v._id] == nil) then
                    worshipState = 1
                end
	            fontMemberNet(msgRet.targetList[i], rank, v,worshipCnt,worshipState)
            end
            JjcDB.updateRival(human.db._id,i,v._id)
        end
    end
    
	msgRet.targetList[0] = 3
	Msg.send(msgRet, human.fd)
end

-- 获取竞技场箱子奖励
function getChampionBoxReward(human,index)
    local leftSec = getLeftSec()
	-- 竞技场未开，返回
    if leftSec == nil then
		return  
	end
    
    local seasonBox = JjcDB.getJjcSeasonBox(human.db._id)
    local totalFight = JjcDB.getJjcTotalFight(human.db._id)

	if not seasonBox then
		return
	end

	local tItem = {}
	for nIndex, v in ipairs(JjcExcel.seasonBox) do
		-- 奖励已被领取
		if seasonBox[nIndex] == nil and totalFight >= v.reachCnt then
			JjcDB.updateSeasonBox(human.db._id, nIndex)
			for _, tData in ipairs(v.item) do
				if not tItem[tData[1]] then
					tItem[tData[1]] = 0
				end

				tItem[tData[1]] = tItem[tData[1]] + tData[2]
			end
		end
	end

	if nil ~= _G.next(tItem) then
		local tGoods = {}
		for nGoodID, nGoodNum in pairs(tItem) do
			table.insert(tGoods, {nGoodID, nGoodNum})
		end

		BagLogic.addItemList(human, tGoods, "jjc_season_box")  
    	RoleSystemLogic.onDot(human,RoleSystemDefine.ROLE_SYS_ID_1300)
    	query(human)
	end

	-- -- 奖励已被领取
	-- if seasonBox and seasonBox[index] ~= nil then
	-- 	return
	-- end
    
    -- -- 参数错误
    -- local v = JjcExcel.seasonBox[index]
    -- if v == nil then
    --     return
    -- end

    -- -- 奖励未达成
    -- if totalFight < v.reachCnt then
    --     return
    -- end

    -- -- 写DB
    -- JjcDB.updateSeasonBox(human.db._id,index)

    -- -- 给物品
	-- BagLogic.addItemList(human, v.item, "jjc_season_box")  
    -- RoleSystemLogic.onDot(human,RoleSystemDefine.ROLE_SYS_ID_1300)
    -- query(human)
end

function championWorship(human,uuid)
    -- 不能膜拜自己
    if uuid == human.db._id then
        return
    end

    -- 初始化膜拜数据
    human.db.jjcWorship = human.db.jjcWorship or {}
    human.db.jjcWorship.count = human.db.jjcWorship.count or 0

    -- 每日膜拜已达上限
    if human.db.jjcWorship.count >= JJC_WORSHIP_CNT then
        return  Broadcast.sendErr(human, Lang.GODWAR_MOBAI_ERR) 
    end

    -- 已膜拜过此玩家
    if human.db.jjcWorship[uuid] ~= nil then
        return Broadcast.sendErr(human, Lang.GODWAR_MOBAI_HAD) 
    end

    -- 写数据库
    human.db.jjcWorship[uuid] = 1
    human.db.jjcWorship.count = human.db.jjcWorship.count + 1

    -- 写被膜拜玩家数据库
    local worshipCnt = 0
    local db = RoleDBLogic.getDb(uuid)
    if db == nil then
        JjcDB.updateWorshipCnt(uuid)
        worshipCnt = JjcDB.getWorshipCnt(uuid)
    else
        db.jjcBeWorship = db.jjcBeWorship or 0
        db.jjcBeWorship = db.jjcBeWorship + 1
        RoleDBLogic.saveRole(db) 
        worshipCnt = db.jjcBeWorship
    end

	-- 给奖励
	BagLogic.addItem(human, ItemDefine.ITEM_JINBI_ID, JJC_WORSHIP_JINBI_CNT, "jjc_worship")
	Broadcast.sendErr(human, Util.format(Lang.JJC_WORSHIP_GOOD, JJC_WORSHIP_JINBI_CNT))

    local msgRet = Msg.gc.GC_JJC_CHAMPION_WORSHIP
    msgRet.worshipCnt = worshipCnt
    msgRet.dot = 1
    if human.db.jjcWorship.count >= 3 or human.db.lv < 9 then
        msgRet.dot = 0
    end
    Msg.send(msgRet,human.fd)
end


local function getRankdByRand(human, excludeIdxList)
	human.db.jjcWorship = human.db.jjcWorship or {}
	local jjcWorship  = human.db.jjcWorship
	local rankCnt = 50 --#JjcDB.RANK_2_JJCDATA  --只在前50名随机点赞

	local bl = false
	local randArr = {}

	for i=1, rankCnt do
		local dataTemp = JjcDB.RANK_2_JJCDATA[i]
		if not excludeIdxList[i] and not jjcWorship[dataTemp._id] then
			table.insert(randArr, i)
			bl = true
		end
	end

	if not bl then
		return
	end

	local randIdx = randArr[math.random(1, #randArr)]
	return randIdx
end


-- 一键膜拜
function WorshipByOneTouch(human)
	-- 初始化膜拜数据
    human.db.jjcWorship = human.db.jjcWorship or {}
    human.db.jjcWorship.count = human.db.jjcWorship.count or 0

    -- 每日膜拜已达上限
    if human.db.jjcWorship.count >= JJC_WORSHIP_CNT then
        return  Broadcast.sendErr(human, Lang.GODWAR_MOBAI_ERR)
    end

	local subCnt = JJC_WORSHIP_CNT - human.db.jjcWorship.count
	local rankCnt = #JjcDB.RANK_2_JJCDATA
	subCnt = math.min(subCnt, rankCnt)

	if subCnt <= 0 then
		return  Broadcast.sendErr(human, Lang.GODWAR_MOBAI_ERR)
	end

	local excludeIdxList = {}
	local rank = JjcDB.UUID_2_RANK[human.db._id]
	if rank then
		excludeIdxList[rank] = true
	end

	local cnt = 0
	for i=1, subCnt do
		local rankIdx = getRankdByRand(human, excludeIdxList)
		if not rankIdx then
			break
		end

		-- 写被膜拜玩家数据库
		local dataTemp = JjcDB.RANK_2_JJCDATA[rankIdx]
		local db = RoleDBLogic.getDb(dataTemp._id)
		if db == nil then
			JjcDB.updateWorshipCnt(dataTemp._id)
		else
			db.jjcBeWorship = db.jjcBeWorship or 0
			db.jjcBeWorship = db.jjcBeWorship + 1
			RoleDBLogic.saveRole(db)
		end

		cnt = cnt + 1
		excludeIdxList[rankIdx] = true

		-- 写数据库
		human.db.jjcWorship[dataTemp._id] = 1
		human.db.jjcWorship.count = human.db.jjcWorship.count + 1
	end

	if cnt > 0 then
		-- 给奖励
		local itemCnt = JJC_WORSHIP_JINBI_CNT * cnt
		BagLogic.addItem(human, ItemDefine.ITEM_JINBI_ID, itemCnt, "jjc_worship")
		Broadcast.sendErr(human, Util.format(Lang.JJC_WORSHIP_GOOD, itemCnt))

		-- 推送数据
		championBillboardQuery(human)
	end
end



function championBillboardQuery(human)
    local flag = RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1301)
	if flag ~= true then
		return Broadcast.sendErr(human, Lang.JJC_OPEN_NEED_LV)
	end

	local leftSec = getLeftSec()
	if leftSec == nil then
		return Broadcast.sendErr(human, Lang.JJC_NOT_SET_OPEN_TIME) 
	end
    
    local seasonBox = JjcDB.getJjcSeasonBox(human.db._id)
    local totalFight = JjcDB.getJjcTotalFight(human.db._id)

	local msgRet = Msg.gc.GC_JJC_CHAMPION_BILLBOARD_QUERY
	msgRet.leftSec = leftSec
    msgRet.topList[0] = 0
	for i = 1, #JjcDB.RANK_2_JJCDATA do
		if i > 50 then
			break
		end
		
        msgRet.topList[0] = msgRet.topList[0] + 1
        
		local dataTemp = JjcDB.RANK_2_JJCDATA[i]
        local db = RoleDBLogic.getDb(dataTemp._id)
        if db == nil then
            local worshipCnt = dataTemp.worshipCnt or 0
            local worshipState = 0
            if dataTemp._id ~= human.db._id and (human.db.jjcWorship == nil or human.db.jjcWorship[dataTemp._id] == nil) then
                worshipState = 1
            end
            fontMemberNet(msgRet.topList[msgRet.topList[0]], i, dataTemp,worshipCnt,worshipState)
        else
            local worshipCnt = db.jjcBeWorship or 0
            local worshipState = 0
            if db._id ~= human.db._id and (human.db.jjcWorship == nil or human.db.jjcWorship[dataTemp._id] == nil) then
                worshipState = 1
            end
            fontMemberNet(msgRet.topList[msgRet.topList[0]], i, dataTemp,worshipCnt,worshipState)
        end
	end

    local rank = JjcDB.UUID_2_RANK[human.db._id]
	local jjcData = JjcDB.RANK_2_JJCDATA[rank] or {}
    local worshipCnt = human.db.jjcBeWorship and human.db.jjcBeWorship or 0
    fontMemberNet(msgRet.ownRank, rank, jjcData,worshipCnt,0)

    msgRet.dotList[0] = 3
    msgRet.dotList[1] = championChallengeDot(human)
    msgRet.dotList[2] = championBillboardDot(human)
    msgRet.dotList[3] = championRecordDot(human)

	Msg.send(msgRet, human.fd)
	
	if rank > 0 and ((human.db.jjcBestRank or 0) <= 0 or rank < (human.db.jjcBestRank or 0)) then
		human.db.jjcBestRank = rank
	end
end

function onHour(hour)
	-- 判断是赛季结束还是每日结束
	if _G.is_middle == true then
		return
	end

	if hour == 4 then -- 错开整点一些处理
		Timer.addLater(11, JjcDB.cleanOldVideos)
        return
	end

	
	local openDay = CommonDB.getServerOpenDay()
	if openDay == nil then return end

	if hour == 21 then
		-- 发每日奖励
		local mailConfig = MailExcel.mail[MailDefine.MAIL_ID_JJC_DAY]
		local title = mailConfig.title
		local senderName = mailConfig.senderName
		local nowDateStr = HtmlUtil.getDataStr(os.time())
		-- 发每日奖励
		for i = 1, #JjcExcel.dayReward do
			local config = JjcExcel.dayReward[i]
			for j = config.rankMin, config.rankMax do
				local data = JjcDB.RANK_2_JJCDATA[j]
				if data == nil then
					break
				end
				if data.monsterOutID == nil then
					local content = Util.format(mailConfig.content, nowDateStr, j)
					MailManager.add(MailManager.SYSTEM, data._id, title, content, config.reward, senderName)	
				end
			end
		end
		
        if openDay % JjcDB.SEASON_KEEP_DAY == 0 then
			-- 赛季结束结算
			Msg.sendWorld(Msg.gc.GC_JJC_SEASON_END)
			
			local mailConfig = MailExcel.mail[MailDefine.MAIL_ID_JJC_SEASON]
			local title = mailConfig.title
			local senderName = mailConfig.senderName
			
			-- 发每日奖励
			for i = 1, #JjcExcel.seasonReward do
				local config = JjcExcel.seasonReward[i]
				for j = config.rankMin, config.rankMax do
					local data = JjcDB.RANK_2_JJCDATA[j]
					if data == nil then
						break
					end
					if data.monsterOutID == nil then
						local content = Util.format(mailConfig.content, j)
						MailManager.add(MailManager.SYSTEM, data._id, title, content, config.reward, senderName)	
					end
				end
			end
			
			-- reset数据
			JjcDB.resetJJCDB()
            -- 开启新赛季
            JjcDB.setSeasonEndTime()	
		end	
		return
	end
end

-- 获取剩余时间
function getLeftSec()
	local endTime = JjcDB.getSeasonEndTime()
	if not endTime then return end
	return endTime - os.time()
end

function getHeroShareMonster(uuid, heroIndex)
    local jjcData = JjcDB.getJjcData(uuid)
    if not jjcData then return end	
    if not jjcData.monsterOutID then return end

    local monsterOutConfig = MonsterExcel.monsterOut[jjcData.monsterOutID]
    if not monsterOutConfig then return end
    local mcf = monsterOutConfig.member[heroIndex]
    if not mcf then return end
    local monsterID = mcf[1]
    if not monsterID or monsterID < 1 then return end    
    return monsterID, jjcData.lv
end

--------------- 以下内容是竞技场列表显示要用到的 start ---------------------------
-- 额外参数设置
function fontActArgs(args, human)
	args[0] = 2
    local rank,score = getActRank(human)
    args[1] = rank
    args[2] = score
end

function getActRank(human)
	local rank = JjcDB.getRank(human.db._id)
	local score = JjcDB.getJjcPoint(human.db._id)

	return math.max(rank, 0), math.max(score, 0) -- 0表示未上榜
end

function getActZhandouli(human)
	return CombatPosLogic.getCombatHeroZDL(human, CombatDefine.COMBAT_TYPE3, true)
end

-- 赛季开始时间段
function getActDesc(desc)
	local endTime, startTime = JjcDB.getSeasonEndTime()
	if not endTime or not startTime then 
		return Lang.COMMON_SYSTEM_NEED_OPENTIME
	end

	local d1 = os.date("*t", startTime)
	local d2 = os.date("*t", endTime)
	return Util.format(desc, d1.month .. "月" .. d1.day.."日", d2.month .. "月" .. d2.day.."日")
end

-- 活动状态
function getActState()
	local endTime = JjcDB.getSeasonEndTime()
	if not endTime then 
		return JjcActLogic.STATE_NOOPEN, 0
	end
	return JjcActLogic.STATE_START, endTime - os.time()
end

-- 红点
function isActRed(human)
    if human.db.lv < 9 then
       return false
    end

	if championChallengeDot(human) == 1 then
		return true
	end
	if championBillboardDot(human) == 1 then
		return true
	end
	if championRecordDot(human) == 1 then
		return true
	end
end

function getCombatObjList(human, side, args)	
    if side ~= CombatDefine.DEFEND_SIDE then return end

	local uuid = args[1]
	local jjcData = JjcDB.getJjcData(uuid)
	if not jjcData then return end
	if jjcData.monsterOutID then return end

	local target = CombatLogic.createCombatFakeHuman(uuid)
	if not target then return end
	return CombatLogic.getHumanObjList(target, CombatDefine.COMBAT_TYPE3)
end

function getCombatMonsterOutID(human, side, args)
    if side ~= CombatDefine.DEFEND_SIDE then return end
	local uuid = args[1]
	local jjcData = JjcDB.getJjcData(uuid)
	if not jjcData then return end
	if not jjcData.monsterOutID then return end
	return jjcData.monsterOutID, jjcData.zhandouli
end

function checkCombatPos(human, args, combatType)
	if combatType == CombatDefine.COMBAT_TYPE3 then
		return true
	end
	local uuid = args[1]
    local leftSec = getLeftSec()
	if leftSec == nil then
		return Broadcast.sendErr(human, Lang.JJC_NOT_SET_OPEN_TIME) 
	end
	local jjcData = JjcDB.getJjcData(uuid)
	if not jjcData then return end

	-- 判断是否免费
	ObjHuman.updateDaily(human)
	local nowFightCnt = human.db.jjcDailyFight or 0
	if JJC_FREE_DAILY_CNT <= nowFightCnt then
		-- 判断是否有门票
		if BagLogic.getItemCnt(human, ItemDefine.ITEM_JJC_TICKET_ID) < 1 then
			return Broadcast.sendErr(human, Lang.JJC_ERR_FIGHT_NO_ITEM) 
		end
	end	
	return true, uuid	
end

function fight(human, args, combatType)	
	if combatType ~= CombatDefine.COMBAT_TYPE2 then return end	
	local isok, uuid = checkCombatPos(human, args, combatType) 
	if not isok then return end
	
	local nowFightCnt = human.db.jjcDailyFight or 0
	if JJC_FREE_DAILY_CNT <= nowFightCnt then
		-- 扣门票
		BagLogic.delItem(human, ItemDefine.ITEM_JJC_TICKET_ID, 1, "jjc_fight")		
	end	
	human.db.jjcDailyFight = (human.db.jjcDailyFight or 0) + 1	
    
	JjcDB.updateTotalFight(human.db._id)
	JjcDB.updateTotalFightCnt(human.db._id)

	local combatHero = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE2, nil, true) 
	if not combatHero or not next(combatHero) then 
		CombatPosLogic.copyCombatHeros(human, CombatDefine.COMBAT_TYPE1, CombatDefine.COMBAT_TYPE2)
	end

	checkNeedJoin(human)		
	CombatLogic.combatBegin(human, nil, args, CombatDefine.COMBAT_TYPE2, uuid)
	DailyTaskLogic.recordDailyTaskFinishCnt(human, DailyTaskLogic.DAILY_TASK_ID_4, 1)
    ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_5,1)
    MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_3,1)
    HeroLogLogic.finishTaskCB(human,HeroLogLogic.HERO_LOG_TYPE_2,1)
    YunYingLogic.onCallBack(human, "onJjcFight",1)
	TriggerLogic.PublishEvent(TriggerDefine.EVENT_TYPE_CHAMPIONSNUM, human.db._id, 1)
end

-- 挑战结束
function onFightEnd(human, result, combatType, defUuid, combatInfo)	
	local defData = JjcDB.getJjcData(defUuid)	
	local atkPoint = JjcDB.getJjcPoint(human.db._id)
	local defPoint = JjcDB.getJjcPoint(defUuid)
	local oldAtkPoint = atkPoint
	local oldDefPoint = defPoint
	
	local defHuman  = ObjHuman.onlineUuid[defUuid]			
    if result == CombatDefine.RESULT_WIN then        
		if defHuman ~= nil then
			defHuman.jjcWinCount = nil
		end
		human.jjcWinCount = (human.jjcWinCount or 0) + 1
        JjcDB.cleanRival(human.db._id)
		ChatPaoMaLogic.broadcast(human, ChatPaoMaLogic.PAOMA_TYPE_BROAD_TYPE8, human.jjcWinCount)
        LiLianLogic.onCallbackByCombat(human,combatInfo)
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_15,1)
        
	    HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE7, 1)
	    HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE11, combatInfo)
		WarOrder.trigger(human,ARENA_ORDER_TYPE)
	else
		human.jjcWinCount = nil
	end
	MonthHzz.addJjcFight(human, result)

	atkPoint, defPoint = calcPoint(result, atkPoint, defPoint)
	-- 重置名字和头像
	if defData.monsterOutID then
		combatInfo.defender.head = defData.head
		combatInfo.defender.name = defData.name
		combatInfo.defender.lv = defData.lv 
		combatInfo.defender.zhandouli = defData.zhandouli
		combatInfo.defender.uuid = defData._id	
	end
	combatInfo.endParam = atkPoint .. "|" .. defPoint .. "|" .. (atkPoint - oldAtkPoint) .. "|" .. (defPoint - oldDefPoint)
	
	JjcDB.updatePlayerPoint(human.db._id, atkPoint, true)
	JjcDB.updatePlayerPoint(defUuid, defPoint, nil)	

	-- 保存战斗记录
	JjcDB.addJjcRecord(human.db._id, defUuid, combatInfo)

    -- 保存战报 名次前20次
    local rank = JjcDB.getRank(human.db._id)
    if rank <= WarReportLogic.WAR_JJC_RANK then
       local defRank = JjcDB.getRank(defUuid)
       WarReportLogic.add(WarReportLogic.WAR_REPORT_1, combatInfo, rank, defRank)
    end

	-- 给奖励
	local totalWeight = 0
	for i = 1, #JjcExcel.fightReward do
		totalWeight = totalWeight + JjcExcel.fightReward[i].weight
	end

	local msgRet = Msg.gc.GC_JJC_AFTER_FIGHT
    
	msgRet.atkPoint = atkPoint
	msgRet.atkPointChange = atkPoint - oldAtkPoint
	msgRet.defPoint = defPoint
	msgRet.defPointChange = defPoint - oldDefPoint
	RoleLogic.makeRoleBase(combatInfo.defender,msgRet.defRole)
	RoleLogic.makeRoleBase(combatInfo.attacker,msgRet.atkRole)
	
	msgRet.items[0] = 1	
	local randNum = math.random(1, totalWeight)
	local indexTemp = 1
	for i = 1, #JjcExcel.fightReward do
		if randNum <= JjcExcel.fightReward[i].weight then
			indexTemp = i
			break
		end
		randNum = randNum - JjcExcel.fightReward[i].weight
	end
	local itemID = JjcExcel.fightReward[indexTemp].itemID
	local itemCntMin = JjcExcel.fightReward[indexTemp].itemCnt1
	local itemCntMax = JjcExcel.fightReward[indexTemp].itemCnt2
	local itemCnt = math.random(itemCntMin, itemCntMax)
    -- 双倍结算
    local double = RoleSystemLogic.isDouble(human, RoleSystemDefine.ROLE_SYS_ID_1301)
	local isDouble 
    if double and (not human.db.jjcDailyFight or human.db.jjcDailyFight <= JJC_DOUBLE_CNT) then
        itemCnt = itemCnt * 2
	    isDouble = true
    end

    BagLogic.addItem(human, itemID, itemCnt, "jjc_fight")
	
	Grid.makeItem(msgRet.items[1], itemID, itemCnt)	
	-- Grid.makeItem(msgRet.items[1], itemID, itemCnt, nil ,nil, nil, nil, nil, nil, sourceId)

	msgRet.double = isDouble and 1 or 0
    msgRet.result = result
	Msg.send(msgRet, human.fd)
    human.db.jjcNewestRecord = os.time()
    -- 当被挑战玩家在线时，向被挑战玩家发送协议告知玩家被挑战
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1300)
    if defHuman ~= nil then
        local msg = Msg.gc.GC_JJC_CHAMPION_BE_CHALLENGE
	    Msg.send(msg, defHuman.fd)
        RoleSystemLogic.onDot(defHuman, RoleSystemDefine.ROLE_SYS_ID_1300)
    end
end

-- 获取 竞技场 剩余双倍次数
function getJJCDoubleCnt(human)
	local double = RoleSystemLogic.isDouble(human, RoleSystemDefine.ROLE_SYS_ID_1301)
	if double then
		if human.db.jjcDailyFight then
			local cnt = JJC_DOUBLE_CNT - human.db.jjcDailyFight
			return  cnt > 0 and cnt or 0
		end
		return JJC_DOUBLE_CNT
	end
	return 0
end

--------------------- about dot -------------------------------------
-- 冠军联赛挑战记录红点
function championRecordDot(human)
    if human.db.lv < 9 then
       return 0
    end
    -- 没有战斗记录，红点不亮
    local recordList = JjcDB.getJjcRecordList(human.db._id)
    if not recordList then
        return 0
    end	

    -- 有战斗记录，玩家没点开过战斗记录，红点亮
    if human.db.jjcNewestRecord == nil then
        return 1
    end

	local videoUuid = recordList[1]
	local combatInfo = CombatVideo.getCombatVideo(videoUuid)
    -- 最新一条战斗记录时间比上次点开战斗记录时间大，红点亮
    if combatInfo and combatInfo.combatInfo.time > human.db.jjcNewestRecord then
        return 1
    end

    -- 否则不亮
    return 0
end

-- 冠军联赛挑战红点
function championChallengeDot(human)
    if human.db.lv < 9 then
       return 0
    end

    -- 今日挑战次数小于免费次数，红点亮
    if human.db.jjcDailyFight == nil or human.db.jjcDailyFight < JJC_FREE_DAILY_CNT then
        return 1
    end

    return boxRewardDot(human) 
end

-- 冠军联赛排行榜红点
function championBillboardDot(human)
    if human.db.lv < 9 then
       return 0
    end
    -- 今日膜拜次数小于3次，红点亮
    if human.db.jjcWorship == nil or human.db.jjcWorship.count < JJC_WORSHIP_DOT_CNT then
        return 1
    end

    return 0
end

function boxRewardDot(human)
    if human.db.lv < 9 then
       return 0
    end

    local seasonBox = JjcDB.getJjcSeasonBox(human.db._id)
    local totalFight = JjcDB.getJjcTotalFight(human.db._id)

    local len = #JjcExcel.seasonBox
    for i = 1,len do
        if not seasonBox or not seasonBox[i] then
            if totalFight >= JjcExcel.seasonBox[i].reachCnt then
                return 1
            end
        end
    end
    return 0
end