Activity.lua 11.6 KB
local Activity = class("Activity", require("shared.ModelBase"))
local string_format = string.format

Activity.ActivityType = {
	Sign = 1,  -- 签到
	DoubleDrop = 2, -- 双倍掉落
	FoodSell = 3,	--贩卖周 料理
	DrawHero = 4,	--抽卡周 招募
	AdvDraw = 5,	--拾荒抽周 资助
	OpenBox = 6,	--拆解周 时钟箱

	SsrUpPoolChange = 10,	-- 特定英雄活动,切卡池
}


local function checkActivityType(activityType)
	if type(activityType) == "string" then
		activityType = Activity.ActivityType[activityType]
	end
	return activityType or 0
end


function Activity:ctor(properties)
	Activity.super.ctor(self, properties)

	self._isOpen = {}
end


Activity.schema = {
	actime 		= {"table", {}},  -- 最近检查某项活动的开始时间  {id = time}
	round		= {"table", {}},  -- 记录活动到了第几轮  {id = roundnum}
	act1		= {"table", {}},  -- {0 = day, 1= -1, 2 = -1} == 签到活动
	act3		= {"table", {}},  -- {0 = 抽卡次数, 1=1, 2=1}  抽卡周活动  1表示领取过该档位的奖励
	act4		= {"table", {}},  -- {0 = 贩卖数量, 1=1, 2=1}  贩卖周活动  1表示领取过该档位的奖励
	act5		= {"table", {}},  -- {0 = 拆解数量, 1=1, 2=1}  拆解周活动  1表示领取过该档位的奖励
	act6		= {"table", {}},  -- {0 = 拾荒消耗远古金币数量, 1=1, 2=1}  拾荒周活动  1表示领取过该档位的奖励
}

function Activity:data()
	return {
		actime = self:getProperty("actime"),
		round = self:getProperty("round"),
		act1 = self:getProperty("act1"),
		act3 = self:getProperty("act3"),
		act4 = self:getProperty("act4"),
		act5 = self:getProperty("act5"),
		act6 = self:getProperty("act6"),
	}
end


function Activity:updateProperty(params)
	local type, default = table.unpack(self.schema[params.field])

	if params.delta then
		self:incrProperty(params.field, params.delta)
		if not params.notNotify then
			self.owner:notifyUpdateProperty(params.field, self:getProperty(params.field))
		end
		return true
	end
	if params.value then
		self:setProperty(params.field, params.value)
		if not params.notNotify then
			self.owner:notifyUpdateProperty(params.field, self:getProperty(params.field))
		end
		return true
	end
	return false
end


function Activity:isOpenRaw(activityType, now)
	activityType = checkActivityType(activityType)
	local actData = csvdb["activity_ctrlCsv"][activityType]
	if not actData then return end

	if actData.time == "" then -- 关闭
		return false
	end

	local st = 0
	local et = 0
	local now = skynet.timex()

	if actData.ttype == 0 then -- 时间开放
		local openTimes = actData.time:toArray(false, "=")
		if openTimes[1] ~= "0" then
			st = toUnixtime(openTimes[1]..string_format("%02x", RESET_TIME))
		end
		if openTimes[2] ~= "0" then
			et = toUnixtime(openTimes[2]..string_format("%02x", RESET_TIME))
		end
 	elseif actData.ttype == 1 then -- 周期开放
 		local openTimes = actData.time:toArray(true, "=")
 		local resetTime = toUnixtime(tostring(openTimes[1]) .. string_format("%02x", RESET_TIME))
 		local r = math.floor((now - resetTime) / (openTimes[3] * 86400))
 		st = resetTime + r * (openTimes[3] * 86400)
 		et = st + openTimes[2] * 86400
	else
		return
	end

	if now >= st and (et == 0 or now < et) then
		return true, st
	end
	return false
end

-- 缓存开放
function Activity:isOpen(activityType)
	activityType = checkActivityType(activityType)
	return self._isOpen[activityType]
end

function Activity:getActData(actType)
	actType = checkActivityType(actType)
	return self:getProperty("act" .. actType)
end

function Activity:updateActData(actType, data, notNotify)
	actType = checkActivityType(actType)
	self:updateProperty({field = "act" .. actType,  value = data, notNotify = notNotify})
end


-- 跨天刷新 --登录刷新
function Activity:checkActivityStatus(now, isCrossDay, notify)
	self._isOpen = {}
	local actime = self:getProperty("actime")
	local change = false
	for actType, actData in pairs(csvdb["activity_ctrlCsv"]) do
		local isOpen, startTime = self:isOpenRaw(actType, now)
		self._isOpen[actType] = isOpen

		if isOpen then
			if actime[actType] and actime[actType] == startTime then -- 还是之前的状态 开放中
			else  -- 重置
				actime[actType] = startTime
				self:closeActivity(actType, notify, true)
				self:initActivity(actType, isCrossDay, notify)
				change = true
			end
		else
			if actime[actType] then
				self:closeActivity(actType, notify)
				actime[actType] = nil
				change = true
			end
		end
	end
	if change then
		self:updateProperty({field = "actime", value = actime, notNotify = not notify})
	end
end

local activityFunc = {}

activityFunc[Activity.ActivityType.Sign] = {
	-- ["check"] = function(self, actType, notify) -- 检查
	-- end,
	["init"] = function(self, actType, isCrossDay, notify)
		if not isCrossDay then
			activityFunc[Activity.ActivityType.Sign]["crossDay"](self, actType, notify)
		end
	end,
	-- ["close"] = function(self, actType, notify)
	-- end,
	["crossDay"] = function(self, actType, notify)
		local curData = self:getActData(actType)
		curData[0] = (curData[0] or 0) + 1
		local actData = csvdb["new_signInCsv"]
		if curData[0] > #actData then return end -- 满了就忽略了

		-- 没满更新一下
		self:updateActData(actType, curData, not notify)
	end,
}

--loop1:累计料理贩卖N次
--loop2:累计招募N次
--loop3:累计资助N次
--loop4:时钟箱拆解N个
function Activity:checkWeeklyAct(actType, notify, count, pool)
		local actInfoMap = {
			[Activity.ActivityType.DrawHero] = {mailId = MailId.ActDrawCardReward, table = "activity_loop2Csv"},
			[Activity.ActivityType.AdvDraw] = {mailId = MailId.ActAdvDrawReward, table = "activity_loop3Csv"},
			[Activity.ActivityType.OpenBox] = {mailId = MailId.ActOpenBoxReward, table = "activity_loop4Csv"},
			[Activity.ActivityType.FoodSell] = {mailId = MailId.ActSellFoodReward, table = "activity_loop1Csv"}
		}
		if actType == Activity.ActivityType.DrawHero and pool == DrawCardType.FriendDraw then
			return
		end
		local info = actInfoMap[actType]
		if not info then return end

		local curData = self:getActData(actType)
		local roundData = self:getProperty("round")
		local curRound = roundData[actType] or 0
		local ctrlData = csvdb["activity_ctrlCsv"][actType]
		if not ctrlData then return end
		if curRound >= ctrlData.condition then
			return
		end
		curData[0] = (curData[0] or 0) + count
		local totalCnt = 0
		local finishCnt = 0
		local maxCondition = 0
		for k, cfg in pairs(csvdb[info.table] or {}) do
			totalCnt = totalCnt + 1
			if maxCondition < cfg.condition1 then
				maxCondition = cfg.condition1
			end
			if not curData[cfg.id] and curData[0] >= cfg.condition1 then
				if info.mailId then 

					self.owner:log("activity", {
						activity_id = cfg.id, -- 活动ID(或活动指定任务的ID)
						activity_type = actType, -- 活动类型,见活动类型枚举表
						activity_reward = cfg.reward:toNumMap(), -- 活动奖励,json格式记录,{'itemid1':123,'itemid2':456,………...}
					})

					self.owner:sendMail(info.mailId, nil, cfg.reward, {cfg.condition1})
					curData[cfg.id] = 1
				end
			end
			if curData[cfg.id] then
				finishCnt = finishCnt + 1
			end
		end
		if totalCnt == finishCnt then
			roundData[actType] = curRound + 1
			for k,v in pairs(curData) do
				if k == 0 then
					curData[k] = curData[0] >= maxCondition and curData[0] - maxCondition or 0
				else
					curData[k] = nil
				end
			end
			self:updateProperty({field = "round", value = roundData, notNotify = not notify})
		end
		self:updateActData(actType, curData, not notify)
end

-- 抽卡周
activityFunc[Activity.ActivityType.DrawHero] = {
	["check"] = function(self, actType, notify, count, pool) -- 检查
		self:checkWeeklyAct(actType, notify, count, pool)
	end,
	["init"] = function(self, actType, isCrossDay, notify)
		local roundData = self:getProperty("round")
		roundData[actType] = 0
		self:updateProperty({field = "round",  value = roundData, notNotify = not notify})
	end,
	-- ["close"] = function(self, actType, notify)
	-- end,
	["crossDay"] = function(self, actType, notify)
		print("cross day draw card")
		self.owner:sendMail(MailId.ActDrawCard)
	end,
}

-- 售卖周
activityFunc[Activity.ActivityType.FoodSell] = {
	["check"] = function(self, actType, notify, count) -- 检查
		self:checkWeeklyAct(actType, notify, count)
	end,
	["init"] = function(self, actType, isCrossDay, notify)
		local roundData = self:getProperty("round")
		roundData[actType] = 0
		self:updateProperty({field = "round",  value = roundData, notNotify = not notify})
	end,
	-- ["close"] = function(self, actType, notify)
	-- end,
	["crossDay"] = function(self, actType, notify)
		print("cross day sell food")
		self.owner:sendMail(MailId.ActSellFood)
	end,
}

-- 拾荒周
activityFunc[Activity.ActivityType.AdvDraw] = {
	["check"] = function(self, actType, notify, count) -- 检查
		self:checkWeeklyAct(actType, notify, count)
	end,
	["init"] = function(self, actType, isCrossDay, notify)
		local roundData = self:getProperty("round")
		roundData[actType] = 0
		self:updateProperty({field = "round",  value = roundData, notNotify = not notify})
	end,
	-- ["close"] = function(self, actType, notify)
	-- end,
	["crossDay"] = function(self, actType, notify)
		self.owner:sendMail(MailId.ActAdvDraw)
	end,
}

-- 拆解周
activityFunc[Activity.ActivityType.OpenBox] = {
	["check"] = function(self, actType, notify, count) -- 检查
		self:checkWeeklyAct(actType, notify, count)
	end,
	["init"] = function(self, actType, isCrossDay, notify)
		local roundData = self:getProperty("round")
		roundData[actType] = 0
		self:updateProperty({field = "round",  value = roundData, notNotify = not notify})
	end,
	-- ["close"] = function(self, actType, notify)
	-- end,
	["crossDay"] = function(self, actType, notify)
		print("cross day open box")
		self.owner:sendMail(MailId.ActOpenBox)
	end,
}

function Activity:initActivity(actType, isCrossDay, notify)
	if activityFunc[actType] and activityFunc[actType]['close'] then
		activityFunc[actType]["init"](self, actType, isCrossDay, notify)
	end
end

function Activity:closeActivity(actType, notify, notUpdateAct)
	if activityFunc[actType] and activityFunc[actType]['close'] then
		activityFunc[actType]["close"](self, actType, notify)
	end
	if Activity.schema["act".. actType] then
		self:updateActData(actType, Activity.schema["act" .. actType][2], not notify or notUpdateAct)
	end
end

function Activity:refreshDailyData(notify)
	for actType, status in pairs(self._isOpen) do
		if status then
			if activityFunc[actType] and activityFunc[actType]['crossDay'] then
				activityFunc[actType]["crossDay"](self, actType, notify)
			end
		end
	end
end

function Activity:checkActivity(notNotify, activityType, ...)
	if not activityType then return end
	if not self:isOpen(activityType) then return end
	if activityFunc[activityType] and activityFunc[activityType]['check'] then
		activityFunc[activityType]["check"](self, activityType, not notNotify, ...)
	end
end

-- 获取此次挂机掉落翻倍时长
function Activity:getActHangDoubleTime(lastTs, nowTs)
	local type = "DoubleDrop"
	local actId = checkActivityType(type)
	local isOpen = self:isOpen(type)
	local openTs = self:getProperty("actime")[actId] or 0
	local timeNow = skynet.timex()
	lastTs =  math.max(lastTs, openTs)
	if isOpen then
		if nowTs > openTs and nowTs > lastTs then
			return nowTs - lastTs
		else
			return 0
		end
	end
	return 0
end

-- 获取活动卡池id
function Activity:getActivityPool(mainType, subType)
	if not self:isOpen(Activity.ActivityType.SsrUpPoolChange) then	
		return 0
	end
	local actData = csvdb["activity_ctrlCsv"][Activity.ActivityType.SsrUpPoolChange]
	if not actData then return 0 end

	local poolMap = actData.condition2:toMap(true, "=")
	local key = mainType .. "_" .. subType
	for k, v in pairs(poolMap) do
		if k == key then
			return v
		end
	end
	return 0
end


return Activity