--- --- Created by zhouzhipeng. --- DateTime: 2024/11/11 上午11:13 --- Desc:开服竞技 --- OpenServerCompetition = {} local this = {} ---实时排行榜缓存 local REAL_TIME_RANK = {} -- 上次刷新时间 local LAST_REFRESH_TIME = 0 local ROLE_DATA_REPAIR = "T$competition_data_repair" --- 刷新开服竞技排行 function OpenServerCompetition.flushSortRank() local now = getbaseinfo("now") local cfgTime = tonumber(ConfigDataManager.getTableValue("cfg_global", "value", "id", 23001)) if LAST_REFRESH_TIME ~= 0 and now - LAST_REFRESH_TIME < (cfgTime * 60 * 1000) then return end LAST_REFRESH_TIME = now local severOpenDays = getbaseinfo("serveropendays") for _, type in pairs(CompetitionType) do this.updateRankInfo(type, severOpenDays) end --local globalRankData = GlobalRankCompetitionData.get() --OpenServerCompetition.print("更新开服竞技排行", globalRankData) end --- 更新排行榜 function this.updateRankInfo(type, severOpenDays) if OpenServerCompetition.checkCompetitionRank(type, severOpenDays) then return end local globalCompetitionData = GlobalCompetitionData.get() local actInfo = globalCompetitionData:getActInfoByType(type) --OpenServerCompetition.print("更新开服竞技排行 类型", type, "记录的数据", actInfo) if table.isNullOrEmpty(actInfo) then return end local sortRank = {} local rankLimitData = tonumber(ConfigDataManager.getTableValue("cfg_openSerCompetition", "ranklimitdata", "type", type)) for _, info in pairs(actInfo) do if info.num < rankLimitData then goto continue end table.insert(sortRank, info) :: continue :: end table.sort(sortRank, function(a, b) if a.num == b.num then return a.updateTime < b.updateTime end return a.num > b.num end) local rankNumber = tonumber(ConfigDataManager.getTableValue("cfg_openSerCompetition", "ranknumber", "type", type)) local rankInfo = {} local rankCount = table.count(sortRank) local rankSize = math.min(rankCount, rankNumber) local newRank = table.getTopN(rankSize, sortRank) local rank = 1 for _, info in ipairs(newRank) do info.rank = rank rank = rank + 1 table.insert(rankInfo, info) end local globalRankData = GlobalRankCompetitionData.get() globalRankData[type] = rankInfo globalRankData:save() --REAL_TIME_RANK[type] = rankInfo --OpenServerCompetition.print("更新开服竞技排行 类型", type, "满足上榜数量", rankCount, "配置排行榜数量", rankNumber, "上榜数量与配置排行数量 取最小", rankSize --, "存的排行缓存数据", rankInfo, "排行数据", sortRank) end function OpenServerCompetition.checkCompetitionRank(type, severOpenDays) local settleTime = ConfigDataManager.getTableValue("cfg_openSerCompetition", "ranksettlementtime", "type", type) if settleTime == nil or settleTime == "" then settleTime = 0 end local rankSettlementTime = tonumber(settleTime) if severOpenDays >= rankSettlementTime then return true end return false end --- 发送开服竞技排行信息 function OpenServerCompetition.sendCompetitionRankInfo(actor, msgData) local competitionType = tostring(msgData["type"]) local rankInfo = this.getRankInfoByType(competitionType) local myInfo = this.buildMyInfo(actor, rankInfo, competitionType) sendluamsg(actor, LuaMessageIdToClient.RES_COMPETITION_RANK_INFO, { type = competitionType, myInfo = myInfo, rankInfo = rankInfo }) OpenServerCompetition.print("发送开服竞技排行信息", type(competitionType), competitionType, "我的信息", myInfo, "排行信息", rankInfo) end function this.buildMyInfo(actor, rankInfo, type) local rank = 0 for _, info in pairs(rankInfo) do if info.rid == actor:toString() then rank = info.rank end end local num = this.getMyNum(actor, type) return { myNum = num, rank = rank } end function this.getMyNum(actor, type) local competitionData = GlobalCompetitionData.get() local actInfo = competitionData:getActInfoByType(type) local info = actInfo[actor:toString()] or {} if type == CompetitionType.LEVEL then return info.num or 1 end return info.num or 0 end function this.getRankInfoByType(type) local globalRankData = GlobalRankCompetitionData.get() return globalRankData[type] or {} --[[ if table.isNullOrEmpty(REAL_TIME_RANK[type]) then OpenServerCompetition.print("测试测试11 获取的时候刷新了 刷新前:", REAL_TIME_RANK[type],"内容结束", type) this.updateRankInfo(type) OpenServerCompetition.print("测试测试11 获取的时候刷新了 刷新后", REAL_TIME_RANK[type],"内容结束", type) end return REAL_TIME_RANK[type] or {}]] end --- 登录触发 function OpenServerCompetition.login(actor) RepairRoleData.action(actor, ROLE_DATA_REPAIR, 202412111423, OpenServerCompetition.repairCompetition, actor) OpenServerCompetition.sendAllCompetitionRankInfo(actor) end --- 修复竞技数据 function OpenServerCompetition.repairCompetition(actor) local competitionType = CompetitionType.BRAVE_CHALLENGE local num = this.getMyNum(actor, competitionType) local lv = BraveTest.getBraveTestLv(actor) if num > 0 and lv ~= num then OpenServerCompetition.updateRankData(actor, competitionType, lv) info(actor, "玩家", actor, "开服竞技 修复数据 竞技排行 更新排行数据", competitionType, num, lv) end info(actor, "玩家", actor, "开服竞技 数据已修复", competitionType, num, lv) end --- 发送所有开服竞技排行信息 function OpenServerCompetition.sendAllCompetitionRankInfo(actor) for _, type in pairs(CompetitionType) do if not OpenServerCompetition.isTerminate(type) then OpenServerCompetition.sendCompetitionRankInfo(actor, { type = type }) OpenServerCompetition.sendAllSingleChallengeInfo(actor, type) end end end function OpenServerCompetition.sendAllSingleChallengeInfo(actor, type) -- 已领取的个人挑战记录 local playerCompetitionData = PlayerCompetitionData.get(actor) local getAwardInfo = playerCompetitionData:getAwardInfo(type) local num = this.getMyNum(actor, type) this.sendOpenServerCompetitionInfo(actor, type, getAwardInfo, num) end --- 请求开服竞技个人挑战领取信息 function OpenServerCompetition.reqSingleChallengeInfo(actor, msgData) local competitionType = tostring(msgData["type"]) local playerCompetitionData = PlayerCompetitionData.get(actor) local getAwardInfo = playerCompetitionData:getAwardInfo(competitionType) local num = this.getMyNum(actor, competitionType) this.sendOpenServerCompetitionInfo(actor, competitionType, getAwardInfo, num) end --- 请求领取开服竞技个人挑战奖励 function OpenServerCompetition.reqSingleChallengeAward(actor, msgData) local id = msgData["id"] local challengeCfg = ConfigDataManager.getById("cfg_openSerCompetition_challenge", id) if not challengeCfg then tipinfo(actor, "个人挑战配置不存在:" .. id) return end local competitionType = challengeCfg.challengegroup if OpenServerCompetition.isTerminate(competitionType) then tipinfo(actor, "活动未开启") return end local playerCompetitionData = PlayerCompetitionData.get(actor) local getAwardInfo = playerCompetitionData:getAwardInfo(competitionType) if table.hasKey(getAwardInfo, id) then tipinfo(actor, "个人挑战该奖励已领取") return end local num = this.getMyNum(actor, competitionType) if num < tonumber(challengeCfg.typedemandvalue) then tipinfo(actor, "个人挑战目标不满足") return end local reward_item = string.toIntIntMap(challengeCfg.challengereward, "#", "|") local severOpenDays = getbaseinfo("serveropendays") local challengeLimitTime = tonumber(ConfigDataManager.getTableValue("cfg_openSerCompetition", "challengelimittime", "type", competitionType)) local isGet = false if severOpenDays < challengeLimitTime then local career = getbaseinfo(actor, "getbasecareer") string.putIntIntMap4Career(reward_item, career, challengeCfg.limittimereward, "#", "|") isGet = true OpenServerCompetition.print("开服竞技 获得限时奖励", reward_item) end getAwardInfo[id] = isGet playerCompetitionData:save(actor) --奖励进入背包 additemmaptobag(actor, reward_item, 0, 9999, '开服竞技') GameTips.sendGetRewardMsg(actor, reward_item) info(actor, "玩家", actor, "开服竞技 领取个人挑战奖励 领取id:", id) this.sendOpenServerCompetitionInfo(actor, competitionType, getAwardInfo, num) end --- 请求购买开服竞技特惠礼包 function OpenServerCompetition.reqBuyDiscountsGift(actor, msgData) local id = msgData["id"] local giftCfg = ConfigDataManager.getById("cfg_openSerCompetition_gift", id) if not giftCfg then tipinfo(actor, "特惠礼包配置不存在:" .. id) return end if not OpenServerCompetition.checkCount(actor, giftCfg.count) then tipinfo(actor, "礼包次数已上限") return end local costMap = string.toIntIntMap(giftCfg.buyconsume, "#", "|") if not Bag.checkCostMapBind(actor, costMap) then --背包道具不足 noticeTip.noticeinfo(actor, StringIdConst.TEXT346) return end CountManager.count(actor, giftCfg.count, 1) Bag.costMapBind(actor, costMap) local reward_item = string.toIntIntMap(giftCfg.reward, "#", "|") --奖励进入背包 additemmaptobag(actor, reward_item, 0, 9999, '开服竞技') info(actor, "玩家", actor, "开服竞技 购买开服竞技特惠礼包 购买id:", id) GameTips.sendGetRewardMsg(actor, reward_item) end function OpenServerCompetition.checkCount(actor, key) local c = CountManager.getCount(actor, key) if c and c:canAdd(1) then return true end info(actor, "玩家", actor, "购买次数已上限", "rechargeId", "countKey", key) return false end --- 响应开服竞技信息 function this.sendOpenServerCompetitionInfo(actor, type, data, num) sendluamsg(actor, LuaMessageIdToClient.RES_SINGLE_CHALLENGE_INFO, { type = type, num = num, challengeAwardInfo = data }) end --- 活动是否开启 false:未开启 true:开启 function OpenServerCompetition.isOpen(actor, competitionType) local activityCondition = ConfigDataManager.getTableValue("cfg_openSerCompetition", "activitycondition", "type", competitionType) -- 校验活动是否开启 return ConditionManager.Check(actor, activityCondition) end --- 是否结束 false:未结束 true:已结束 function OpenServerCompetition.isTerminate(competitionType) local severOpenDays = getbaseinfo("serveropendays") local supplementReward = ConfigDataManager.getTableValue("cfg_openSerCompetition", "supplementreward", "type", competitionType) if string.isNullOrEmpty(supplementReward) then -- 配置错误 活动未开启 已结束 info("开服竞技 cfg_openSerCompetition表supplementreward配置为空 类型:", competitionType, "当前开服天数:", severOpenDays) return true end -- 校验活动是否结束 if severOpenDays < tonumber(supplementReward) then return false end return true end --- 竞技结算 function OpenServerCompetition.competitionSettlement() this.competitionRankSettlement() this.personalChallengeSettle() end -- 竞技排行榜结算 function this.competitionRankSettlement() local severOpenDays = getbaseinfo("serveropendays") local globalCompetitionData = GlobalCompetitionData.get() local update = false OpenServerCompetition.print("测试测试结算 触发0点开服竞技排行结算") for _, type in pairs(CompetitionType) do if globalCompetitionData:isSettlement(type) then OpenServerCompetition.print("测试测试结算 已结算排行结算") goto continue end local rankSettlementTime = tonumber(ConfigDataManager.getTableValue("cfg_openSerCompetition", "ranksettlementtime", "type", type)) if rankSettlementTime ~= severOpenDays then OpenServerCompetition.print("测试测试结算 不等于结算当天 类型", type, "当前开服天数", severOpenDays, "配置结束天数", rankSettlementTime) goto continue end info("开服竞技排行结算 结算类型:", type, "当前开服天数:", severOpenDays, "配置结算天数:",rankSettlementTime) local name = ConfigDataManager.getTableValue("cfg_openSerCompetition", "name", "type", type) -- 根据缓存的排行发奖励 local rankInfos = this.getRankInfoByType(type) for _, rankInfo in ipairs(rankInfos) do local success, result = xpcall(this.sendMailReward, debug.traceback, type, name, rankInfo) gameDebug.assertPrint(success, "开服竞技排行 发送邮件奖励异常!", result, "参数", type, name, rankInfo) end globalCompetitionData:setSettlement(type, true) update = true :: continue :: end --OpenServerCompetition.print("测试测试结算 结算成功") if update then globalCompetitionData:save() end end function this.sendMailReward(competitionType, name, rankInfo) local actor = getactor(rankInfo.rid) local rank = rankInfo.rank local rankReward = ConfigDataManager.getTableValue("cfg_openSerCompetition_rank", "rankreward", "rankgroup", competitionType, "rank", rank) local career = getbaseinfo(actor, "getbasecareer") local reward_item = string.toIntIntMap4Career(career, rankReward, "#", "|") sendconfigmailbyrid(actor, rankInfo.rid, MailConfig.COMPETITION_RANK_REWARD, reward_item, name .. "#" .. rank) info(actor,"玩家", actor, "开服竞技 竞技排行结算 发送奖励 类型:", competitionType, "排名", rank, "名字:", rankInfo.name) end -- 竞技个人挑战结算 function this.personalChallengeSettle() local severOpenDays = getbaseinfo("serveropendays") local globalCompetitionData = GlobalCompetitionData.get() for _, type in pairs(CompetitionType) do OpenServerCompetition.print("type:", type) local supplementReward = tonumber(ConfigDataManager.getTableValue("cfg_openSerCompetition", "supplementreward", "type", type)) OpenServerCompetition.print("supplementReward:", supplementReward) local name = ConfigDataManager.getTableValue("cfg_openSerCompetition", "name", "type", type) if supplementReward ~= severOpenDays then goto continue end local challengeCfgs = ConfigDataManager.getTable("cfg_openSerCompetition_challenge", "challengegroup", type) if table.isNullOrEmpty(challengeCfgs) then goto continue end local challengeLimitTime = tonumber(ConfigDataManager.getTableValue("cfg_openSerCompetition", "challengelimittime", "type", type)) OpenServerCompetition.print("challengeLimitTime:", challengeLimitTime) local rankInfo = globalCompetitionData:getActInfoByType(type) OpenServerCompetition.print("rankInfo:", rankInfo) for rid, info in pairs(rankInfo) do local actor = getactor(info.rid) local career = getbaseinfo(actor, "getbasecareer") OpenServerCompetition.print("info:", info) local playerCompetitionData = PlayerCompetitionData.get(actor) OpenServerCompetition.print("playerCompetitionData:", playerCompetitionData) local getAwardInfo = playerCompetitionData:getAwardInfo(type) local num = this.getMyNum(actor, type) OpenServerCompetition.print("num:", num) local reward_item = {} for _, challengeCfg in ipairs(challengeCfgs) do local cfgId = tonumber(challengeCfg.id) local typeDemandValue = tonumber(challengeCfg.typedemandvalue) OpenServerCompetition.print("typeDemandValue:", typeDemandValue) local isGet = false -- 标记限时商品的领取情况 if num >= typeDemandValue and not table.hasKey(getAwardInfo, cfgId) then -- 未领取过的个人奖励 local comm_reward = string.toIntIntMap(challengeCfg.challengereward, "#", "|") if severOpenDays < challengeLimitTime then isGet = true string.putIntIntMap4Career(comm_reward, career, challengeCfg.limittimereward, "#", "|") end table.mergeTable(reward_item, comm_reward) getAwardInfo[cfgId] = isGet end end if not table.isNullOrEmpty(reward_item) then OpenServerCompetition.print("reward_item:", reward_item) playerCompetitionData:save(actor) sendconfigmailbyrid(actor, info.rid, MailConfig.COMPETITION_PERSONAL_REWARD, reward_item, name) end end :: continue :: end end function OpenServerCompetition.expCal(actor, exp) if OpenServerCompetition.isTerminate(CompetitionType.DEVIL_SQUARE) then return end callonserial(actor, "exp_cal", exp) end function exp_cal(actor, exp) local data = getsysvar("R$全服恶魔经验") or {} local lastExp = data[actor:toString()] or 0 data[actor:toString()] = lastExp + exp setsysvar("R$全服恶魔经验", data) -- OpenServerCompetition.print("全服恶魔经验更新",data) end function OpenServerCompetition.expEffeciencyCal() local competitionType = CompetitionType.DEVIL_SQUARE if OpenServerCompetition.isTerminate(competitionType) then return end -- 服务器分钟心跳,没有线程问题 local globalCompetitionData = GlobalCompetitionData.get() local effectData = globalCompetitionData:getActInfoByType(competitionType) local data = getsysvar("R$全服恶魔经验") or {} local updateTime = getbaseinfo("now") local update = false for rid, exp in pairs(data) do local info = effectData[rid] or {} local old = info.num or 0 if exp > old then if not effectData[rid] then local actor = getactor(rid) info.rid = rid info.job = getbaseinfo(actor, "getbasecareer") info.name = getbaseinfo(actor, "rolename") end info.num = exp info.updateTime = updateTime effectData[rid] = info OpenServerCompetition.print("开服竞技 竞技排行 恶魔经验效率更新 类型", competitionType, "名字", info.name, "当前经验", exp) update = true end :: continue :: end if next(data) ~= nil then setsysvar("R$全服恶魔经验", {}) end if update then globalCompetitionData:save() -- OpenServerCompetition.print("全服恶魔经验效率更新",effectData) end end --- 升级触发 function OpenServerCompetition.levelUp(actor, level) OpenServerCompetition.updateRankData(actor, CompetitionType.LEVEL, level) end --- 增加活跃值 function OpenServerCompetition.addActivityValue(actor, act_value) local value = tonumber(act_value) if value < 0 then OpenServerCompetition.print("开服竞技 活跃值活跃值小于0") return end local competitionType = CompetitionType.ACTIVE local oldNum = this.getMyNum(actor, competitionType) local number = oldNum + value OpenServerCompetition.updateRankData(actor, competitionType, number) end --- 更新套装阶数 function OpenServerCompetition.updateSuitStageNum(actor) local equips = getputonequipinfo(actor) if next(equips) == nil then return end OpenServerCompetition.print("更新套装阶数 开始", equips) local suitStage = 0 for _, equip in pairs(equips) do local id = equip.id local score = equip.score if score ~= 350 then goto continue end local wearBar = tonumber(gameequip.wearBar(equip.equipindex)) OpenServerCompetition.print("更新套装阶数 穿戴拦", wearBar) if wearBar ~= 1 and wearBar ~= 2 then OpenServerCompetition.print("更新套装阶数 穿戴拦 从这里跑了") goto continue end local rank = tonumber(ConfigDataManager.getTableValue("cfg_item", "rank", "id", equip.cfgid)) suitStage = suitStage + rank OpenServerCompetition.print("更新套装阶数 是套装装备", equip, equip.cfgid, rank, suitStage) :: continue :: end local competitionType = CompetitionType.SUIT local number = this.getMyNum(actor, competitionType) OpenServerCompetition.print("更新套装阶数 中", number, suitStage) if suitStage <= number then return end OpenServerCompetition.updateRankData(actor, competitionType, suitStage) end --- 更新排行数据 function OpenServerCompetition.updateRankData(actor, competitionType, number) if OpenServerCompetition.isTerminate(competitionType) then return end --if not OpenServerCompetition.isOpen(actor, competitionType) then -- OpenServerCompetition.print("开服竞技 竞技排行 更新排行数据 关闭", competitionType) -- return --end if competitionType == CompetitionType.ANGEL or competitionType == CompetitionType.CARDSCORE then local result = this.checkUpdata(actor, competitionType, number) if not result then -- 低于历史最,不更新 return end this.saveAngelOrCard(actor, competitionType, number) end callonserial(actor, "update_rank_data", competitionType, number) local playerCompetitionData = PlayerCompetitionData.get(actor) local getAwardInfo = playerCompetitionData:getAwardInfo(competitionType) this.sendOpenServerCompetitionInfo(actor, competitionType, getAwardInfo, tonumber(number)) end function update_rank_data(actor, competitionType, number) local now = getbaseinfo(actor, "now") local globalCompetitionData = GlobalCompetitionData.get() local actInfo = globalCompetitionData:getActInfoByType(competitionType) local rid = actor:toString() local activityInfo = actInfo[rid] or {} if not actInfo[rid] then activityInfo.rid = rid activityInfo.job = getbaseinfo(actor, "getbasecareer") activityInfo.name = getbaseinfo(actor, "rolename") end activityInfo.num = number activityInfo.updateTime = now actInfo[rid] = activityInfo info(actor, "玩家", actor, "开服竞技 竞技排行 更新排行数据", competitionType, activityInfo.name, number) globalCompetitionData:save() end function OpenServerCompetition.combineglobalvar(varName, varData) GlobalCompetitionData.save({}) GlobalRankCompetitionData.save({}) setsysvar("R$全服恶魔经验", {}) end PlayerCompetitionData = {} PlayerCompetitionData.__index = PlayerCompetitionData local function _playerCompetitionDbKey() return "T$OPEN_SERVER_COMPETITION" end function PlayerCompetitionData.get(actor) local obj = getplaydef(actor, _playerCompetitionDbKey()) return setmetatable(obj or {}, PlayerCompetitionData) end function PlayerCompetitionData:save(actor) setplaydef(actor, _playerCompetitionDbKey(), self); end function PlayerCompetitionData:getDataByType(competitionType) if not self[competitionType] then self[competitionType] = {} end return self[competitionType] end function PlayerCompetitionData:getAwardInfo(competitionType) local data = self:getDataByType(competitionType) if not data.getAwardInfo then data.getAwardInfo = {} end return data.getAwardInfo end GlobalCompetitionData = {} GlobalCompetitionData.__index = GlobalCompetitionData local function _globalCompetitionDbKey() return "R$OPEN_SERVER_COMPETITION" end function GlobalCompetitionData.getKey() return _globalCompetitionDbKey() end function GlobalCompetitionData.get() local obj = getsysvar(_globalCompetitionDbKey()) return setmetatable(obj or {}, GlobalCompetitionData) end function GlobalCompetitionData:save() setsysvar(_globalCompetitionDbKey(), self) end function GlobalCompetitionData:getDataByType(competitionType) if not self[competitionType] then self[competitionType] = {} end return self[competitionType] end function GlobalCompetitionData:getActInfoByType(competitionType) local data = self:getDataByType(competitionType) if not data.actInfo then data.actInfo = {} end return data.actInfo end function GlobalCompetitionData:isSettlement(competitionType) local data = self:getDataByType(competitionType) return data.isSettlement or false end function GlobalCompetitionData:setSettlement(competitionType, isSettlement) local data = self:getDataByType(competitionType) data.isSettlement = isSettlement end GlobalRankCompetitionData = {} GlobalRankCompetitionData.__index = GlobalRankCompetitionData local function _globalRankCompetitionDbKey() return "R$OPEN_SERVER_COMPETITION_RANK" end function GlobalRankCompetitionData.get() local obj = getsysvar(_globalRankCompetitionDbKey()) return setmetatable(obj or {}, GlobalRankCompetitionData) end function GlobalRankCompetitionData:save() setsysvar(_globalRankCompetitionDbKey(), self) end function this.checkUpdata(actor, competitionType, num) local value = this.getAngelOrCard(actor, competitionType) if num > value then return true end return false end function this.saveAngelOrCard(actor, competitionType, num) local data = getplaydef(actor, "T$angelOrCard") or {} data[competitionType] = num setplaydef(actor, "T$angelOrCard", data) end function this.getAngelOrCard(actor, competitionType) local data = getplaydef(actor, "T$angelOrCard") or {} return data[competitionType] or 0 end --- 打印日志 local isPrintLog = true function OpenServerCompetition.print(...) if isPrintLog then return end gameDebug.print(...) end function openservercompetitiontest(actor, id, competitionType) OpenServerCompetition.print(actor, "开服竞技测试", id, type(competitionType)) local severOpenDays = getbaseinfo("serveropendays") local updateTime = getbaseinfo("now") OpenServerCompetition.print("开服天数", severOpenDays, "当前时间", updateTime) --this.updateRankInfo(competitionType) --OpenServerCompetition.sendCompetitionRankInfo(actor, {type= competitionType }) local globalCompetitionData = GlobalCompetitionData.get() OpenServerCompetition.print(actor, "开服竞技测试结束", globalCompetitionData) end function testpersonalreward(actor) this.personalChallengeSettle() end -- 注册登录事件 LoginEventListerTable:eventLister("0", "开服竞技排行", OpenServerCompetition.login) -- 注册等级提升事件 LevelUpEventListerTable:eventLister("0", "开服竞技排行", OpenServerCompetition.levelUp)