-------------------------------------------------------
-- 公会副本

-- db.ectypeCnt             挑战次数
-- db.killEctype            击杀奖励领取标记
-- db.unionThing = { likeTime ,  likeCnt : 点赞时间  点赞 次数 }

-- 每天可挑战4次，挑战失败进入CD（16小时），可花钻石跳过
-------------------------------------------------------

local MonsterExcel = require("excel.monster")
local CommonDB = require("common.CommonDB")
local Config = require("Config")
local Lang = require("common.Lang")
local FilterUtil = require("common.FilterUtil")
local UnionDBLogic = require("union.UnionDBLogic")
local UnionExcel = require("excel.union")
local MailManager = require("mail.MailManager")
local MailExcel = require("excel.mail")
local RoleDBLogic = require("role.RoleDBLogic")
local Msg = require("core.Msg")
local Broadcast = require("broadcast.Broadcast")
local ObjHuman = require("core.ObjHuman")
local Util = require("common.Util")
local Grid = require("bag.Grid")
local CombatLogic = require("combat.CombatLogic")
local CombatImpl = require("combat.CombatImpl")
local BossLogic = require("boss.BossLogic")
local BossDBLogic = require("boss.BossDBLogic")
local CombatDefine = require("combat.CombatDefine")
local CombatObj = require("combat.CombatObj")
local BagLogic = require("bag.BagLogic")
local RoleDefine = require("role.RoleDefine")
local RoleLogic = require("role.RoleLogic")
local CombatPosLogic = require("combat.CombatPosLogic")
local UnionDefine = require("union.UnionDefine")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local ChatUnion = require("chat.ChatUnion")
local MoshouLogic = require("moshou.MoshouLogic")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local DailyTaskLogic = require("dailyTask.DailyTaskLogic")
local LiLianLogic = require("dailyTask.LiLianLogic")
local UnionLogic = require("union.UnionLogic")
local CombatPosExcel = require("excel.combatPos")
local UnionLivenessLogic = require("union.UnionLivenessLogic")
local UnionDefine = require("union.UnionDefine")
local MailDefine = require("mail.MailIdDefine")
local MengxinLogic = require("present.MengxinLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local WeekTaskLogic = require("dailyTask.WeekTaskLogic")
local TriggerLogic = require("trigger.TriggerLogic")
local TriggerDefine = require("trigger.TriggerDefine")

UNION_ECTYPE_LIKE_MAX = 3    -- 公会副本 点赞每日最大次数
UNION_ECTYPE_FREE_CNT = 3    -- 公会副本 每日免费挑战次数
UNION_ECTYPE_JIJIE_TIME = 60 * 60
FIGHT_MAX_CNT = 4

local PAGE_PER_CNT = 9
local FIGHT_FAIL_CD = 16 * 3600
local FIGHT_COST_ZUANSHI = {0, 0, 0, 20, 30, 40, 60, 80, 100}

local STATU_BOSS_DIE = 0
local STATU_BOSS_ING = 1
local STATU_BOSS_READY = 2

local CLAN_ORDER_TYPE = 3

-- 初始化副本
-- unionUuid  公会Uuid
-- level      关卡等级
function initEctype(unionUuid, level)
    local conf = UnionExcel.ectype[level]
    if not conf then return end

    local monsterOutID = conf.monsterOutID
    local mapID = conf.mapID
    local cbParam = {}
    cbParam.level = level
    return BossDBLogic.createBossData(BossDBLogic.BOSS_TYPE_UNION, unionUuid, monsterOutID, mapID, cbParam)
end

-- 获取副本头像
local function getBossHead(conf)    
    local monsterOutConfig = MonsterExcel.monsterOut[conf.monsterOutID]
    local bossId = monsterOutConfig.member[1][1]
    local monsterConfig = MonsterExcel.monster[bossId]    
    if not monsterConfig then return 0 end
    return monsterConfig.head
end

-- 
local function getParamLv(bossData)
    if not bossData then return 0 end
    if not bossData.cbParam then return 0 end
    return bossData.cbParam.level or 0
end

-- 获取Boss
local function getBossData(unionUuid, level)
    local bossDataList = BossDBLogic.getBossDatas(BossDBLogic.BOSS_TYPE_UNION, unionUuid)
    if not bossDataList then return end

    for _, bossData in ipairs(bossDataList) do
        if getParamLv(bossData) == level then
            return bossData
        end
    end
end

-- 根据排名获取奖励
local function getRewardIndexByRank(rank)
    if rank <= 3 then return rank end
    if rank <= 10 then return 4 end
    if rank <= 15 then return 5 end
    if rank <= 20 then return 6 end
    return 7
end

local function getMinMaxRankByRank(rank)
    if rank <= 3 then return rank,rank end
    if rank == 4 then return 4, 10 end
    if rank == 5 then return 11,15 end
    if rank == 6 then return 16,20 end
    return 21,50
end

-- 获取页数
local function getDefaultPage(union)
    local bossLv = math.min(#UnionExcel.ectype, union.bossLv)
    return math.ceil(bossLv / PAGE_PER_CNT)
end

local function getCurTzCnt(human)
    if not human.db.ectypeCnt then
        return UNION_ECTYPE_FREE_CNT
    else
        local cnt = human.db.ectypeCnt or 0
        local cur = UNION_ECTYPE_FREE_CNT - cnt
        return cur > 0 and cur or 0
    end 
end

-- 副本查询，分页查询
-- page   页码
function ectypeQuery(human)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
   
   
    local msgRet = Msg.gc.GC_UNION_ECTYPE_QUERY  
    msgRet.ectypeState[0] = 0
    msgRet.isStart = 0
    msgRet.isEnd   = 0
    for i = 1, #UnionExcel.ectype do        
        local conf = UnionExcel.ectype[i]
        if not conf then break end
        local monsterOutConfig = MonsterExcel.monsterOut[conf.monsterOutID]
        local bossId = monsterOutConfig.member[1][1]
        local monsterConfig = MonsterExcel.monster[bossId]
        if not monsterConfig then
            print("  not monsterConfig :  ",  bossId,    "   monsterOutID  is : ",   conf.monsterOutID ,  " , ectype  id  :",  i )
        end
        if i == 1 then  msgRet.isStart = 1 end
        msgRet.ectypeState[0] = msgRet.ectypeState[0] + 1
        local ectNet = msgRet.ectypeState[msgRet.ectypeState[0]]
        ectNet.statu = (i == union.bossLv) and STATU_BOSS_ING or STATU_BOSS_DIE
        if i > union.bossLv then ectNet.statu = STATU_BOSS_READY end
        ectNet.bossID = getBossHead(conf)
        ectNet.level = i
        ectNet.name = monsterConfig.name or ""
        if msgRet.ectypeState[0] >= 50 then
            if i == #UnionExcel.ectype then  msgRet.isEnd = 1 end
			Msg.send(msgRet, human.fd)
            msgRet.ectypeState[0] = 0
            msgRet.isStart = 0
            msgRet.isEnd   = 0
		end
    end

    if msgRet.ectypeState[0] > 0 then
        msgRet.isEnd = 1
        Msg.send(msgRet, human.fd)    
    end    
end

-- 获取副本buff
function getEctypeBuff(union)
    local lv = 0
    local endTime = 0
    local buff = {}

    if union and union.copyBuff then
        local now = os.time()
        if now < union.copyBuff.endTime then
            lv = union.copyBuff.lv
            endTime = union.copyBuff.endTime - now
        end
    end
    return lv, endTime
end

-- 激活 或升级 公会BUF
function upEctypeBuff(human, level)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end

    local lv,endTime = getEctypeBuff(union)
    local newLv = lv + 1
    if newLv > #UnionExcel.ectypeBuff then
        return
    end

    local nextConifg = UnionExcel.ectypeBuff[newLv]
    if not nextConifg then return end

    if not ObjHuman.checkRMB(human, nextConifg.needZuanshi) then
        return
    end  

    if endTime <= 0 then
        endTime = 0
    end

    ObjHuman.decZuanshi(human, -nextConifg.needZuanshi, "unionBoss")

    union.copyBuff = union.copyBuff or {}
   
    union.copyBuff.lv = newLv
    union.copyBuff.endTime = os.time() + endTime + nextConifg.addTime 

    UnionDBLogic.updateEctypeBuf(union)

    oneEctypeQuery(human, level)

    if newLv == 1 then
        Broadcast.sendErr(human, Lang.UNION_ECTYPE_ACTIVATE_SUCCESS)
        UnionLivenessLogic.touchLiveness(human,UnionDefine.UNION_LIVENESS_BOSS_BUFF,1)
    else
        Broadcast.sendErr(human, Lang.UNION_TECH_LV_UP_SUCCESS)
    end
end

function toUnionBossLvGm(human, lv)
   -- 公会是否存在
   local union = UnionDBLogic.getUnion(human.db.unionUuid)
   if not union then
       return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
   end
   UnionDBLogic.updateBossLv(union, lv)

end

-- 指定某个公会副本查询
-- level  指定关卡
function oneEctypeQuery(human, level)
    -- 公会是否存在
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end

    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1002, true) then
        return 
    end    

    -- 传入关卡是否合法
    if level > union.bossLv then
        return Broadcast.sendErr(human, Lang.UNION_ECTYPE_LEVEL_ERR)
    end

    local conf = UnionExcel.ectype[level]
    if not conf then  return end

    local monsterOutConfig = MonsterExcel.monsterOut[conf.monsterOutID]
    local bossId = monsterOutConfig.member[1][1]
    local monsterConfig = MonsterExcel.monster[bossId]
    if not monsterConfig then  return end
    -- 副本是否存在
    local bossData = getBossData(human.db.unionUuid, level)
    if not bossData then    
        bossData = initEctype(human.db.unionUuid, level)
    end

    if not bossData then return end

    local boardList = BossDBLogic.getHurtBoard(bossData)
    local boardLen = boardList and #boardList or 0
    local msgRet = Msg.gc.GC_UNION_ONE_ECTYPE_QUERY
    msgRet.praiseCnt = UNION_ECTYPE_LIKE_MAX
    local dataNet = msgRet.ectypeMsg
    dataNet.level = level
    dataNet.monsterName = monsterConfig.name
    dataNet.body = monsterConfig.body
    msgRet.lastHurt = 0
    if human.db.ectypHurt and human.db.ectypHurt[level] then
        msgRet.lastHurt = human.db.ectypHurt[level].hurtSum
    end
    dataNet.bloodVolume = BossDBLogic.getBossHpSum(bossData)
    if level < union.bossLv then
        dataNet.bloodVolume = 0
    end
    dataNet.allBlood = BossDBLogic.getBossHpMaxSum(bossData) 
    dataNet.comEff = conf.comEff
    dataNet.rankList[0] = 0
    for i = 1, boardLen do
        if dataNet.rankList[0] >= #dataNet.rankList then
            break
        end
        local bdata = boardList[i]
        local rank = dataNet.rankList[0] + 1
        local rankNet = dataNet.rankList[rank]
        local rewardIndex = getRewardIndexByRank(rank)
      
        local rconf = conf.rankReward[rewardIndex]
        if RoleLogic.getRoleBaseByUuid(bdata.uuid, rankNet.roleBase) then
            rankNet.damage = bdata.hurt            
            rankNet.like = bdata.like or 0
            rankNet.isLike = getGiveLikeSate(human, bdata.uuid) and 1 or 0
            rankNet.reward[0] = rconf and #rconf or 0
            for j = 1, rankNet.reward[0] do
                local itemID = rconf[j][1]
                local itemCnt = rconf[j][2]
                Grid.makeItem(rankNet.reward[j], itemID, itemCnt)
            end
            dataNet.rankList[0] = dataNet.rankList[0] + 1
            local member = UnionDBLogic.getUnionMember(union, bdata.uuid)
            rankNet.post = member and member.post or UnionDefine.POST_MEMBER
        end
    end

    dataNet.rankReward[0] = #conf.rankReward
    for i = 1, dataNet.rankReward[0] do        
        local minRank,maxRank = getMinMaxRankByRank(i)
        local rewardNet = dataNet.rankReward[i]
        local rconf = conf.rankReward[i]
        rewardNet.minRank = minRank
        rewardNet.maxRank = maxRank
        rewardNet.reward[0] = #rconf
        for j = 1, rewardNet.reward[0] do
            local itemID = rconf[j][1]
            local itemCnt = rconf[j][2]
            Grid.makeItem(rewardNet.reward[j], itemID, itemCnt)
        end
    end

    dataNet.reward[0] = #conf.onceReward
    for i = 1, dataNet.reward[0] do
        local itemID = conf.onceReward[i][1]
        local itemCnt = conf.onceReward[i][2]
        Grid.makeItem(dataNet.reward[i], itemID, itemCnt)
    end

    dataNet.killReward[0] = #conf.killReward
    for i = 1, dataNet.killReward[0] do
        local itemID = conf.killReward[i][1]
        local itemCnt = conf.killReward[i][2]
        Grid.makeItem(dataNet.killReward[i], itemID, itemCnt)
    end

    local fightCnt = (human.db.ectypeCnt or 0) + 1
    msgRet.curCnt = getCurTzCnt(human)
    msgRet.curBuy = #FIGHT_COST_ZUANSHI - UNION_ECTYPE_FREE_CNT
    if msgRet.curCnt <= 0 then
        msgRet.curBuy = msgRet.curBuy - human.db.ectypeCnt + UNION_ECTYPE_FREE_CNT
    end
    msgRet.needZuanShi = FIGHT_COST_ZUANSHI[fightCnt] or FIGHT_COST_ZUANSHI[#FIGHT_COST_ZUANSHI]
    local lv , endTime = getEctypeBuff(union)
    if lv > 0 then
        local bufConfig = UnionExcel.ectypeBuff[lv]

        msgRet.buffMsg.lv = lv
        msgRet.buffMsg.maxLv = #UnionExcel.ectypeBuff
        msgRet.buffMsg.endTime = endTime
        msgRet.buffMsg.upNeed = 0
        msgRet.buffMsg.attr[0] = 0
        msgRet.buffMsg.nextAttr[0] = 0
        for k, v in ipairs(bufConfig.buff) do
            local net = msgRet.buffMsg.attr[k]
            net.key = v[1]
            net.value = v[2]
        end
        msgRet.buffMsg.attr[0] = #bufConfig.buff

        local nextBufConfig = UnionExcel.ectypeBuff[lv + 1]
        if nextBufConfig then
            msgRet.buffMsg.upNeed = nextBufConfig.needZuanshi
            for k, v in ipairs(nextBufConfig.buff) do
                local net = msgRet.buffMsg.nextAttr[k]
                net.key = v[1]
                net.value = v[2]
            end
            msgRet.buffMsg.nextAttr[0] = #nextBufConfig.buff
        end
    else        
        local bufConfig = UnionExcel.ectypeBuff[1]
        msgRet.buffMsg.lv = 0
        msgRet.buffMsg.maxLv = #UnionExcel.ectypeBuff
        msgRet.buffMsg.endTime = 0
        msgRet.buffMsg.upNeed = bufConfig.needZuanshi
        msgRet.buffMsg.nextAttr[0] = 0
        for k, v in ipairs(bufConfig.buff) do
            local net = msgRet.buffMsg.nextAttr[k]
            net.key = v[1]
            net.value = v[2]
        end
        msgRet.buffMsg.nextAttr[0] = #bufConfig.buff
        msgRet.buffMsg.attr[0] = 0
    end

    msgRet.jijieTime = 0
    if union.jihuoTime then
        local endTime  = UNION_ECTYPE_JIJIE_TIME - (os.time() - union.jihuoTime)
        msgRet.jijieTime = endTime >= 0 and  endTime or 0 
    end

    if  human.db.ectypeCnt and  human.db.ectypeCnt > UNION_ECTYPE_FREE_CNT then
        msgRet.curBuy = #FIGHT_COST_ZUANSHI - human.db.ectypeCnt 
    end
    if human.db.ectypeLike and human.db.ectypeLike > 0 then
        msgRet.praiseCnt = UNION_ECTYPE_LIKE_MAX - human.db.ectypeLike
        msgRet.praiseCnt = msgRet.praiseCnt > 0 and msgRet.praiseCnt or 0
    end
   -- Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

-- 获取点赞状态
function getGiveLikeSate(human, uuid)
    if not uuid or uuid ==  "" then return end

    if human.db.ectypLikeUuid and human.db.ectypLikeUuid[uuid] then
        return true
    end    
end

-- 点赞
function giveLike(human, level, uuid)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1002, true) then
        return 
    end   
    -- 不能点赞自己
    if human.db._id == uuid then
        return 
    end    
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end
  
    if level > union.bossLv then
        return Broadcast.sendErr(human, Lang.UNION_ECTYPE_LEVEL_ERR)
    end

    if human.db.ectypLikeUuid and human.db.ectypLikeUuid[uuid] then
        return 
    end

    local conf = UnionExcel.ectype[level]
    if not conf then return end

    if human.db.ectypeLike and human.db.ectypeLike >= UNION_ECTYPE_LIKE_MAX then
        return  Broadcast.sendErr(human, Lang.UNION_ECTYPE_LIKE_MAX_ERR) 
    end

    local bossData = getBossData(human.db.unionUuid, level)

    if not bossData then return end


    local state = BossLogic.giveLikeBossRecord(bossData, uuid)

    if not state then return end
    human.db.ectypLikeUuid = human.db.ectypLikeUuid or {}
    human.db.ectypLikeUuid[uuid] = 1
    human.db.ectypeLike =  human.db.ectypeLike or 0
    human.db.ectypeLike =  human.db.ectypeLike + 1
    -- 点赞成功  
    BagLogic.cleanMomentItemList()
	BagLogic.updateMomentItem(1, 101, 1000)
    BagLogic.addMomentItemList(human, "unionBoss")
    oneEctypeQuery(human, level)
end

-- 集结
function jiJie(human, level,str)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end    

    local config = UnionExcel.ectype[level]
    if not config then 
        return 
    end 

    -- 检测官职 能否满足要求
    local member = UnionDBLogic.getUnionMember(union, human.db._id)
    if not member 
       or (member.post ~= UnionDefine.POST_PRESIDENT and member.post ~= UnionDefine.POST_OFFICIAL) then
        return Broadcast.sendErr(human, Lang.UNION_HAVE_NO_POWER)
    end

    local lastTime = union.jihuoTime or 0
    local now = os.time()

    if now - lastTime < UNION_ECTYPE_JIJIE_TIME then
        return
    end

    union.jihuo = level
    union.jihuoTime = now 
    UnionDBLogic.updateJihuo(union)
    
    -- 发送 聊天 到公会
    if ChatUnion.chatUnionEctype(human, str) == 1 then
        return
    end

    Broadcast.sendErr(human, Lang.UNION_ECTYPE_JIJIE_SUCCESS) 
    oneEctypeQuery(human, level)
end

-- 可否打开上阵
function checkCombatPos(human, args)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end    
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1002, true) then
        return 
    end
    local level = tonumber(args[1])
    local touch = tonumber(args[2] or 0)
    if union.bossLv ~= level then
        return Broadcast.sendErr(human,Lang.UNION_ECTYPE_LEVEL_ERR)
    end
    local bossData = getBossData(human.db.unionUuid, level)
    if not bossData then return end
    getCurTzCnt(human)
    
    local ectypeCnt = (human.db.ectypeCnt or 0)
    local cost = nil
    local killCnt = 0
    if touch == 0 then
        local fightCnt = ectypeCnt + 1
        cost = FIGHT_COST_ZUANSHI[fightCnt]
        killCnt = 1
    else
        for i = ectypeCnt + 1, #FIGHT_COST_ZUANSHI do
            cost = cost or 0
            cost = cost + FIGHT_COST_ZUANSHI[i]
            killCnt = killCnt + 1
        end
    end

    if not cost then
        return Broadcast.sendErr(human,Lang.BATTLE_CNT_OVER)
    end
   
    if cost > 0 then
        if not ObjHuman.checkRMB(human, cost) then
            return
        end            
    end
    return true, bossData, cost, killCnt
end

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

    local level = tonumber(args[1])
    local conf = UnionExcel.ectype[level]
    if not conf then return end
    local bossData = getBossData(human.db.unionUuid, level)
    if not bossData then return end
    local monsterOutConfig = MonsterExcel.monsterOut[conf.monsterOutID]
    if not monsterOutConfig then return  end

    local mationConfig = CombatPosExcel.formation[monsterOutConfig.formation] 
    local posList = mationConfig.pos
    if not posList then return end

    local objList = nil
    local zhandouli = 0
	for i, member in ipairs(monsterOutConfig.member) do
		local monsterID = member[1]		
		local monsterConfig = MonsterExcel.monster[monsterID]			
		if posList[i] then
			local monsterLv = member[2]
			local attrID = monsterOutConfig.attrID[i]	
			local obj = CombatLogic.createMonsterObj(monsterID, monsterLv, attrID, i, CombatDefine.COMBAT_OBJ_TYPE2, monsterOutConfig.beSkill[i])
			if obj then
				zhandouli = zhandouli + obj.attrs[RoleDefine.ZHANDOULI]
				objList = objList or {}

                local pos = posList[i]
				objList[pos] = obj
			end
		end
	end
	if not objList then
		assert(nil, "getMonsterObjList is nil, monsterOutID = " .. monsterOutConfig.monsterOutID)
	end
    local rolebase = CombatLogic.createRoleBaseByMOutID(monsterOutConfig.monsterOutID, zhandouli, args)
    

    local helpList = {}
    return BossLogic.getCombatObjList(bossData, conf.comEff), nil, rolebase, monsterOutConfig.formation
end

-- 刷副本
function fight(human, args, combatType)
    local isok, bossData, cost = checkCombatPos(human, args)
    if not isok then return end

    if cost > 0 then
        ObjHuman.decZuanshi(human, -cost, "unionBoss")
    end
    
  --  human.db.ectypeCnt = (human.db.ectypeCnt or 0) + 1    
    
    local level = tonumber(args[1])
    local conf = UnionExcel.ectype[level]
    local mapID = conf.mapID
    
    CombatLogic.combatBegin(human, mapID, args, combatType, bossData)
    
    ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_10,1)
end

-- 获取当前地图ID
function getMapID(human, args)
    local isok, cf, throne, lv, exp = checkCombatPos(human, args)
    if not isok then return end
    return cf.mapID
end


function onFightBegin(human, bossData)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then
        return Broadcast.sendErr(human, Lang.UNION_PLAYER_IN_NO)
    end

    local lv , endTime = getEctypeBuff(union)

    if lv  > 0 then
        for index = 1, CombatDefine.COMBAT_HERO_CNT do
            local atkPos = CombatLogic.getPos(CombatDefine.ATTACK_SIDE, index)
            local atkObj = CombatImpl.objList[atkPos]
            if atkObj then
                local bufConfig = UnionExcel.ectypeBuff[lv]
                for k, v in ipairs(bufConfig.buff) do
                    local key = v[1]
                    local value = v[2]
                    atkObj.sysAttr[key] = atkObj.sysAttr[key] + value
                    atkObj.isSysAttrChange = true
                end
            end
        end
    end
 
    BossLogic.onFightBegin(human, bossData)
end

-- 挑战结束
local FieldsKill = {killEctype = 1}
function onFightEnd(human, result, combatType, bossData, combatInfo)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then return end    

    local level = getParamLv(bossData)
    local conf = UnionExcel.ectype[level]
    if not conf then return end

    combatInfo.defender.name = Util.format(Lang.COMBAT_UNIONECTYPE_NAME, level)
    combatInfo.defender.head = getBossHead(conf)
    local hurtSum , hurtList = BossLogic.onFightHurt(human, bossData, combatInfo)  

    
    -- 从DB 中获取最新的BOSS DB 来计算  防止玩家在战斗画面中 未fightEnd 播完  别的玩家 扫荡打出伤害
    local realBoss = getBossData(human.db.unionUuid, level)
    local oldIsSkill = BossDBLogic.isBossDie(realBoss)
    if oldIsSkill then 
        combatInfo.double = 0
        return
    end

    local realHurt = BossLogic.updateFightHurt(human, realBoss, hurtList, combatInfo)
    local bKill = BossDBLogic.isBossDie(realBoss)

    DailyTaskLogic.recordDailyTaskFinishCnt(human, DailyTaskLogic.DAILY_TASK_ID_6, 1)
    LiLianLogic.onCallbackByCombat(human,combatInfo)
    MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_11,1)
    
    UnionLogic.addUnionLog(union._id, 9, human.db.name,UnionDefine.UNION_LOG_CLASSIFY_BOSS, realHurt)

    human.db.ectypeCnt = (human.db.ectypeCnt or 0) + 1    
    human.db.ectypHurt = {}
    human.db.ectypHurt[level] = {}
    human.db.ectypHurt[level].hurtSum = realHurt
    human.db.ectypHurt[level].hurtList = Util.copyTable(hurtList)

    local double = RoleSystemLogic.isDouble(human, RoleSystemDefine.ROLE_SYS_ID_1002)
    local rewardCnt = double and 2 or 1

    for i = 1, #conf.onceReward do
        local itemID = conf.onceReward[i][1]
        local itemCnt = conf.onceReward[i][2] * rewardCnt
        BagLogic.addItem(human, itemID, itemCnt, "unionBoss")
        combatInfo.rewardItem[#combatInfo.rewardItem + 1] = {itemID, itemCnt}
    end
    combatInfo.double = double and 2 or 0
    -- boss死亡
    if bKill then
        UnionDBLogic.updateBossLv(union, level + 1)
        -- 给击杀者发送奖励
        local mailID = MailDefine.MAIL_ID_UNION_BOSS_REWARD2
        local title = MailExcel.mail[mailID].title
        local content = Util.format(MailExcel.mail[mailID].content, level)  
        local senderName = MailExcel.mail[mailID].senderName
        MailManager.add(MailManager.SYSTEM, human.db._id, title, content, conf.killReward, senderName)

        -- 排名奖励
        local boardList = BossDBLogic.getHurtBoard(realBoss)
        local boardLen = boardList and #boardList or 0
        local rank = 0
        for i = 1, boardLen do
            local bdata = boardList[i]
            local db, online = RoleDBLogic.getDb(bdata.uuid, FieldsKill)
            if db then
                rank = rank + 1
                if db.killEctype and db.killEctype[level] then
                    local mailID = MailDefine.MAIL_ID_UNION_BOSS_REWARD3
                    local title = MailExcel.mail[mailID].title
                    local content = MailExcel.mail[mailID].content
                    local senderName = MailExcel.mail[mailID].senderName
                    MailManager.add(MailManager.SYSTEM, db._id, title, content, nil, senderName)
                else
                    db.killEctype = db.killEctype or {}
                    db.killEctype[level] = 1
                    if not online then RoleDBLogic.saveRoleSset(db) end

                    local mailID = MailDefine.MAIL_ID_UNION_BOSS_REWARD1
                    local title = MailExcel.mail[mailID].title
                    local content = Util.format(MailExcel.mail[mailID].content, level , rank)
                    local senderName = MailExcel.mail[mailID].senderName
                    local rewardIndex = getRewardIndexByRank(rank)
                    local rconf = conf.rankReward[rewardIndex]
                    MailManager.add(MailManager.SYSTEM, db._id, title, content, rconf, senderName)
                end
            end
        end
    end
    
    if bKill then
        oneEctypeQuery(human, level + 1)
    else
        oneEctypeQuery(human, level)
    end
    local WarOrder = require("shop.WarOrder")
    WarOrder.trigger(human,CLAN_ORDER_TYPE)
    UnionLivenessLogic.touchLiveness(human,UnionDefine.UNION_LIVENESS_ECTYPE,1)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1002)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1001)
    YunYingLogic.onCallBack(human, "onUnionEctypeFight",1)

    ---周任务公会boss挑战次数
    WeekTaskLogic.recordWeekTaskFinishCnt(human, WeekTaskLogic.WEEK_TASK_ID_4, 1)

    TriggerLogic.PublishEvent(TriggerDefine.UNIONS_CHALLENGE_BOSS, human.db._id, 1)
end


function saodang(human, level, touch)
    local union = UnionDBLogic.getUnion(human.db.unionUuid)
    if not union then return end    

    if not human.db.ectypHurt or not human.db.ectypHurt[level] then
        return
    end

    if not human.db.ectypHurt[level].hurtList then
        return
    end
    local lastHurt = human.db.ectypHurt[level].hurtSum
    if lastHurt < 0 then
        return 
    end

    local args = {}
    args[1] = level
    args[2] = touch or 1
    local isok, bossData, cost, killCnt = checkCombatPos(human, args)
    if not isok then return end
    
    local conf = UnionExcel.ectype[level]
    local totalRealHurt = 0
    local bKill = nil

    local ectypeCnt = (human.db.ectypeCnt or 0)
    local phyCnt = 0
    local nextIndex = ectypeCnt + 1
    local hadCost = 0
    for i=1, killCnt do
        local realHurt = BossLogic.saodangEnd(human, bossData,  human.db.ectypHurt[level].hurtList)
        bKill = BossDBLogic.isBossDie(bossData)
        totalRealHurt = totalRealHurt + realHurt
        phyCnt = phyCnt + 1

        if not FIGHT_COST_ZUANSHI[nextIndex] then
           return 
        end
        hadCost = hadCost + FIGHT_COST_ZUANSHI[nextIndex]
        nextIndex = nextIndex + 1
        if bKill then
           break
        end
    end

    if cost ~= hadCost then
       cost = hadCost
       killCnt = phyCnt
    end

    if cost > 0 then
        ObjHuman.decZuanshi(human, -cost, "unionBoss")
    end
    human.db.ectypeCnt = (human.db.ectypeCnt or 0) + killCnt
    


    UnionLogic.addUnionLog(union._id, 10, human.db.name,UnionDefine.UNION_LOG_CLASSIFY_BOSS, totalRealHurt)
    local double = RoleSystemLogic.isDouble(human, RoleSystemDefine.ROLE_SYS_ID_1002)
    local rewardCnt = double and 2 or 1

    local msgRet = Msg.gc.GC_UNION_ECTYPE_REWARD
    msgRet.result = bKill and 1 or 0    
    msgRet.hurt = totalRealHurt
    msgRet.double = double and 1 or 0
    msgRet.reward[0] = #conf.onceReward
    for i = 1, msgRet.reward[0] do
        local itemID = conf.onceReward[i][1]
        local itemCnt = conf.onceReward[i][2] * rewardCnt * killCnt
        BagLogic.addItem(human, itemID, itemCnt, "unionBoss")
        Grid.makeItem(msgRet.reward[i], itemID, itemCnt)
    end
    Msg.send(msgRet, human.fd)

    -- boss死亡
    if bKill then
        UnionDBLogic.updateBossLv(union, level + 1)
        -- 给击杀者发送奖励
        local mailID = MailDefine.MAIL_ID_UNION_BOSS_REWARD2
        local title = MailExcel.mail[mailID].title
        local content = Util.format(MailExcel.mail[mailID].content, level)   
        local senderName = MailExcel.mail[mailID].senderName
        MailManager.add(MailManager.SYSTEM, human.db._id, title, content, conf.killReward, senderName)

        -- 排名奖励
        local boardList = BossDBLogic.getHurtBoard(bossData)
        local boardLen = boardList and #boardList or 0
        local rank = 0
        for i = 1, boardLen do
            local bdata = boardList[i]
            local db, online = RoleDBLogic.getDb(bdata.uuid, FieldsKill)
            if db then
                rank = rank + 1
                if db.killEctype and db.killEctype[level] then
                    mailID = MailDefine.MAIL_ID_UNION_BOSS_REWARD3
                    local title = MailExcel.mail[mailID].title
                    local content = MailExcel.mail[mailID].content
                    local senderName = MailExcel.mail[mailID].senderName
                    MailManager.add(MailManager.SYSTEM, db._id, title, content, nil, senderName)
                else
                    db.killEctype = db.killEctype or {}
                    db.killEctype[level] = 1
                    if not online then RoleDBLogic.saveRoleSset(db) end
                    
                    mailID = MailDefine.MAIL_ID_UNION_BOSS_REWARD1
                    local title = MailExcel.mail[mailID].title
                    local content = Util.format(MailExcel.mail[mailID].content, level, rank) 
    
                    local senderName = MailExcel.mail[mailID].senderName
                    local rewardIndex = getRewardIndexByRank(rank)
                    local rconf = conf.rankReward[rewardIndex]
                    MailManager.add(MailManager.SYSTEM, db._id, title, content, rconf, senderName)
                end
            end
        end

    end  

    if bKill then
        oneEctypeQuery(human, level + 1)
    else
        oneEctypeQuery(human, level)
    end
    
    UnionLivenessLogic.touchLiveness(human,UnionDefine.UNION_LIVENESS_ECTYPE,1)
    DailyTaskLogic.recordDailyTaskFinishCnt(human, DailyTaskLogic.DAILY_TASK_ID_6, killCnt)
    MengxinLogic.onCallBack(human,MengxinLogic.MX_TASK_TYPE_11,1)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1002)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1001)
    local WarOrder = require("shop.WarOrder")
    WarOrder.trigger(human,CLAN_ORDER_TYPE,killCnt or 1)
    WeekTaskLogic.recordWeekTaskFinishCnt(human, WeekTaskLogic.WEEK_TASK_ID_4, killCnt or 1)
    YunYingLogic.onCallBack(human, "onUnionEctypeFight", killCnt or 0)

    TriggerLogic.PublishEvent(TriggerDefine.UNIONS_CHALLENGE_BOSS, human.db._id, killCnt or 1)
end

function isDot(human)
    if human.db.unionUuid == nil then 
        return 
    end
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1002) then
        return
    end
    if getCurTzCnt(human) > 0 then
        print("[isDot] 免费挑战副本次数 大于 0 name = "..human.db.name)
        return true
    end 
end