Commit 68a6dc62ec61db12b5bfa60653991c6082b9a7a6

Authored by zhouhaihai
1 parent cf584618

匹配规则调整

Showing 2 changed files with 261 additions and 141 deletions   Show diff stats
src/actions/PvpAction.lua
@@ -171,7 +171,7 @@ function _M.infoRpc(agent, data) @@ -171,7 +171,7 @@ function _M.infoRpc(agent, data)
171 171
172 local pvpMC = role:getProperty("pvpMC") 172 local pvpMC = role:getProperty("pvpMC")
173 if not next(pvpMC) then --没有分配过对手 173 if not next(pvpMC) then --没有分配过对手
174 - role:refreshPvpMatchC(score) 174 + role:refreshPvpMatchC(score, -1)
175 pvpMC = role:getProperty("pvpMC") 175 pvpMC = role:getProperty("pvpMC")
176 end 176 end
177 if not next(pvpMC) then return end 177 if not next(pvpMC) then return end
@@ -191,7 +191,7 @@ function _M.infoRpc(agent, data) @@ -191,7 +191,7 @@ function _M.infoRpc(agent, data)
191 191
192 local pvpMH = role:getProperty("pvpMH") 192 local pvpMH = role:getProperty("pvpMH")
193 if not next(pvpMH) then --没有分配过对手 193 if not next(pvpMH) then --没有分配过对手
194 - role:refreshPvpMatchH(score) 194 + role:refreshPvpMatchH(score, -1)
195 pvpMH = role:getProperty("pvpMH") 195 pvpMH = role:getProperty("pvpMH")
196 end 196 end
197 if not next(pvpMH) then return end 197 if not next(pvpMH) then return end
src/models/RolePvp.lua
@@ -6,7 +6,12 @@ RolePvp.bind = function (Role) @@ -6,7 +6,12 @@ RolePvp.bind = function (Role)
6 local PVP_RANK_TIME_SORT_STD = 1924876800 -- 2030-12-31 00:00:00 6 local PVP_RANK_TIME_SORT_STD = 1924876800 -- 2030-12-31 00:00:00
7 local PVP_RANK_TIME_SORT_PLACE = 1000000 -- 时间戳占据 6位数 7 local PVP_RANK_TIME_SORT_PLACE = 1000000 -- 时间戳占据 6位数
8 local PVP_RANK_TIME_SORT_PRECISION = 360 -- 时间精度 每6分钟忽略差异 8 local PVP_RANK_TIME_SORT_PRECISION = 360 -- 时间精度 每6分钟忽略差异
9 -local PVP_RANK_BASE_SCORE = globalCsv.pvp_base_score -- 机器人积分 9 +local PVP_RANK_BASE_SCORE = globalCsv.pvp_base_score -- 初始积分
  10 +
  11 +-- 匹配规则改为以排名来匹配
  12 +local PVP_GET_ROBOT_SCORE = 2400 -- 2400分以下低档位匹配机器人
  13 +local PRE_RANGE_COUNT = 20 -- 每个档位人数
  14 +local NEED_MATCH = 3 --匹配到多少人
10 15
11 16
12 function Role:unpackPvpScore(score) 17 function Role:unpackPvpScore(score)
@@ -78,7 +83,7 @@ function Role:changePvpScoreCommon(matchId, isWin) @@ -78,7 +83,7 @@ function Role:changePvpScoreCommon(matchId, isWin)
78 end 83 end
79 84
80 local result = self:changePvpScore(RANK_PVP_COMMON, changeScoreCallback, matchId) 85 local result = self:changePvpScore(RANK_PVP_COMMON, changeScoreCallback, matchId)
81 - self:refreshPvpMatchC(result[1]) 86 + self:refreshPvpMatchC(result[1], result[5])
82 return table.unpack(result) 87 return table.unpack(result)
83 end 88 end
84 89
@@ -162,7 +167,7 @@ function Role:changePvpScoreHigh(matchId, isWin) @@ -162,7 +167,7 @@ function Role:changePvpScoreHigh(matchId, isWin)
162 }) 167 })
163 end 168 end
164 169
165 - self:refreshPvpMatchH(result[1]) 170 + self:refreshPvpMatchH(result[1], result[5])
166 return table.unpack(result) 171 return table.unpack(result)
167 end 172 end
168 173
@@ -179,82 +184,33 @@ function Role:isInPvpRank(rankKey) @@ -179,82 +184,33 @@ function Role:isInPvpRank(rankKey)
179 return false 184 return false
180 end 185 end
181 186
182 -  
183 -function Role:refreshPvpMatch(score, rankKey)  
184 - 187 +-- 新的匹配规则
  188 +function Role:refreshPvpMatch(score, rank, rankKey)
185 local Fields = { 189 local Fields = {
186 [RANK_PVP_COMMON] = "pvpMC", 190 [RANK_PVP_COMMON] = "pvpMC",
187 [RANK_PVP_HIGHT] = "pvpMH", 191 [RANK_PVP_HIGHT] = "pvpMH",
188 } 192 }
189 local RobotCsvs = { 193 local RobotCsvs = {
190 [RANK_PVP_COMMON] = "pvp_robotCsv", 194 [RANK_PVP_COMMON] = "pvp_robotCsv",
191 - [RANK_PVP_HIGHT] = "pvp_robotCsv", 195 + [RANK_PVP_HIGHT] = "pvp_robot_groupCsv",
192 } 196 }
  197 +
193 local mField = Fields[rankKey] 198 local mField = Fields[rankKey]
194 local robotCsv = RobotCsvs[rankKey] 199 local robotCsv = RobotCsvs[rankKey]
195 - local dbKey = self:getPvpDBKey(rankKey)  
196 200
  201 + local dbKey = self:getPvpDBKey(rankKey)
197 local roleId = self:getProperty("id") 202 local roleId = self:getProperty("id")
198 - score = score or self:unpackPvpScore(redisproxy:zscore(dbKey, roleId))  
199 -  
200 - local function getPlayers(levels) 203 + if not score and not rank then
201 local redret = redisproxy:pipelining(function(red) 204 local redret = redisproxy:pipelining(function(red)
202 - for _, level in ipairs(levels) do  
203 - local low, high = table.unpack(level)  
204 - red:zadd(dbKey, low * PVP_RANK_TIME_SORT_PLACE, "std_temp1")  
205 - red:zadd(dbKey, high * PVP_RANK_TIME_SORT_PLACE + PVP_RANK_TIME_SORT_PLACE - 1, "std_temp2")  
206 - red:ZREVRANK(dbKey, "std_temp1")  
207 - red:ZREVRANK(dbKey, "std_temp2")  
208 - end  
209 - red:zrem(dbKey, "std_temp1", "std_temp2") 205 + red:zscore(dbKey, roleId)
  206 + red:zrevrank(dbKey, roleId)
210 end) 207 end)
211 -  
212 - local PreGetCount = 7  
213 - local redret = redisproxy:pipelining(function(red)  
214 - for idx, level in ipairs(levels) do  
215 - local rank1 = tonumber(redret[(idx - 1) * 4 + 3])  
216 - local rank2 = tonumber(redret[(idx - 1) * 4 + 4])  
217 - if rank1 - rank2 > PreGetCount then  
218 - rank2 = math.randomInt(rank2, rank1 - PreGetCount + 1)  
219 - rank1 = rank2 + PreGetCount - 1  
220 - end  
221 - red:ZREVRANGE(dbKey, rank2, rank1)  
222 - end  
223 - end)  
224 - return redret  
225 - end  
226 -  
227 - local findIdx = #globalCsv.pvp_division  
228 - for idx, limit in ipairs(globalCsv.pvp_division) do  
229 - if score < limit then  
230 - findIdx = idx - 1  
231 - break  
232 - end  
233 - end  
234 - local levels = {  
235 - {}, {}, {}  
236 - }  
237 - if globalCsv.pvp_division[findIdx + 1] then  
238 - levels[1] = {globalCsv.pvp_division[findIdx + 1], (globalCsv.pvp_division[findIdx + 2] or 100000000) - 1}  
239 - end  
240 - levels[2] = {globalCsv.pvp_division[findIdx], (globalCsv.pvp_division[findIdx + 1] or 100000000) - 1}  
241 - if globalCsv.pvp_division[findIdx - 1] then  
242 - levels[3] = {globalCsv.pvp_division[findIdx - 1], globalCsv.pvp_division[findIdx] - 1}  
243 - end  
244 - local redirect = {}  
245 - for i = #levels , 1, -1 do  
246 - if not next(levels[i]) then  
247 - table.remove(levels, i)  
248 - redirect[i] = -1  
249 - for _, v in pairs(redirect) do  
250 - redirect[_] = v - 1  
251 - end  
252 - else  
253 - redirect[i] = i  
254 - end 208 + score = self:unpackPvpScore(redret[1])
  209 + rank = tonumber(redret[2] or -2) + 1
255 end 210 end
256 -  
257 - local result = getPlayers(levels) 211 + score = score or self:unpackPvpScore(redisproxy:zscore(dbKey, roleId))
  212 + rank = rank or tonumber(redisproxy:zrevrank(dbKey, roleId) or -2) + 1
  213 +
258 local match = self:getProperty(mField) 214 local match = self:getProperty(mField)
259 local hadPlayer = {[roleId] = 1} 215 local hadPlayer = {[roleId] = 1}
260 local hadRobot = {} 216 local hadRobot = {}
@@ -266,97 +222,261 @@ function Role:refreshPvpMatch(score, rankKey) @@ -266,97 +222,261 @@ function Role:refreshPvpMatch(score, rankKey)
266 end 222 end
267 end 223 end
268 224
269 - for _, temp in pairs(result) do  
270 - for i = #temp, 1, -1 do  
271 - local id = tonumber(temp[i])  
272 - if hadPlayer[id] then  
273 - table.remove(temp, i)  
274 - else  
275 - temp[i] = id  
276 - hadPlayer[id] = 1  
277 - end 225 + local tempMatch = {}
  226 + local needRobot = 0
  227 + -- -1 没有上榜
  228 + if rank == -1 then
  229 + needRobot = NEED_MATCH
  230 + else
  231 + local need = PRE_RANGE_COUNT * NEED_MATCH
  232 + local low, heigh = math.floor(rank - need / 2 - 1), math.floor(rank + need / 2 - 1)
  233 + if low < 0 then
  234 + low = 0
278 end 235 end
279 - end  
280 - -- 增加第几个  
281 - local function getPlayer(idx)  
282 - for i = idx, 3 do  
283 - if redirect[i] ~= -1 then  
284 - local curR = result[redirect[i]] or {}  
285 - if next(curR) then  
286 - local curIdx = math.randomInt(1, #curR)  
287 - local objId = curR[curIdx]  
288 - table.remove(curR, curIdx)  
289 - return objId  
290 - end 236 + print(low, heigh)
  237 + local rangeIds = redisproxy:ZREVRANGE(dbKey, low, heigh)
  238 + local lastRangeIds = {}
  239 + for idx, one in ipairs(rangeIds) do
  240 + local cid = tonumber(one)
  241 + if not hadPlayer[cid] then
  242 + lastRangeIds[#lastRangeIds + 1] = cid
291 end 243 end
292 end 244 end
293 - end  
294 -  
295 - local tempMatch = {}  
296 - local curCount = 0  
297 - for i = 1, 3 do  
298 - local objId = getPlayer(i)  
299 - if objId then  
300 - tempMatch[i] = {t = 1, id = objId}  
301 - curCount = curCount + 1 245 + if score < PVP_GET_ROBOT_SCORE then
  246 + needRobot = 1
302 end 247 end
303 - end  
304 -  
305 - -- 正常的玩家不够了 低一档继续  
306 - if curCount < 3 then  
307 - local level = nil  
308 - if globalCsv.pvp_division[findIdx - 2] then  
309 - level = {globalCsv.pvp_division[findIdx - 2], globalCsv.pvp_division[findIdx - 1] - 1} 248 + local len = #lastRangeIds
  249 + if len < NEED_MATCH then
  250 + needRobot = NEED_MATCH - len
310 end 251 end
311 - if level then  
312 - local result = getPlayers({level})[1] or {}  
313 - for i = #result, 1, -1 do  
314 - local id = tonumber(result[i])  
315 - if hadPlayer[id] then  
316 - table.remove(result, i)  
317 - else  
318 - result[i] = id  
319 - hadPlayer[id] = 1  
320 - end 252 + local needPlayer = NEED_MATCH - needRobot
  253 + if needPlayer > 0 then
  254 + local pre = math.floor(len / needPlayer)
  255 + for i = 1, needPlayer do
  256 + local idx = math.randomInt((i - 1) * pre + 1, i * pre)
  257 + tempMatch[#tempMatch + 1] = {t = 1, id = lastRangeIds[idx]}
321 end 258 end
  259 + end
322 260
323 - if next(result) then  
324 - for i = curCount + 1, 3 do  
325 - local curIdx = math.randomInt(1, #result)  
326 - local objId = result[curIdx]  
327 - table.remove(result, curIdx)  
328 - tempMatch[i] = {t = 1, id = objId}  
329 - curCount = curCount + 1  
330 - if not next(result) then  
331 - break  
332 - end  
333 - end 261 + end
  262 + if needRobot > 0 then
  263 + local RobotPoolCount = 20
  264 + local max = #csvdb[robotCsv]
  265 + local min = 1
  266 + local mid
  267 + while min <= max do
  268 + mid = math.floor((min + max) / 2)
  269 + local tempPt = csvdb[robotCsv][mid].pt
  270 + if score == tempPt then
  271 + break
  272 + elseif score > tempPt then
  273 + min = mid + 1
  274 + elseif score < tempPt then
  275 + max = mid - 1
334 end 276 end
335 end 277 end
336 - end  
337 -  
338 - -- 增加机器人  
339 - if curCount < 3 then  
340 - for i = curCount + 1, 3 do  
341 - while true do  
342 - local id = math.randomInt(1, #csvdb[robotCsv])  
343 - if not hadRobot[id] then  
344 - hadRobot[id] = 1  
345 - tempMatch[i] = {t = 2, id = id}  
346 - break  
347 - end 278 + assert(mid, "pvp no robot " .. robotCsv)
  279 + local low = mid - RobotPoolCount / 2
  280 + local heigh = mid + RobotPoolCount / 2
  281 + if low < 1 then
  282 + heigh = heigh + (1 - low)
  283 + low = 1
  284 + end
  285 + if heigh > #csvdb[robotCsv] then
  286 + heigh = #csvdb[robotCsv]
  287 + end
  288 + local pools = {}
  289 + for i = low, heigh do
  290 + if not hadRobot[i] then
  291 + pools[#pools + 1] = i
348 end 292 end
349 end 293 end
  294 + local pre = math.floor(#pools / needRobot)
  295 + for i = 1, needRobot do
  296 + local idx = math.randomInt((i - 1) * pre + 1, i * pre)
  297 + tempMatch[#tempMatch + 1] = {t = 2, id = pools[idx]}
  298 + end
350 end 299 end
351 self:setProperty(mField, tempMatch) 300 self:setProperty(mField, tempMatch)
352 end 301 end
353 302
354 -function Role:refreshPvpMatchC(score)  
355 - self:refreshPvpMatch(score, RANK_PVP_COMMON) 303 +-- function Role:refreshPvpMatch(score, rank, rankKey)
  304 +
  305 +-- local Fields = {
  306 +-- [RANK_PVP_COMMON] = "pvpMC",
  307 +-- [RANK_PVP_HIGHT] = "pvpMH",
  308 +-- }
  309 +-- local RobotCsvs = {
  310 +-- [RANK_PVP_COMMON] = "pvp_robotCsv",
  311 +-- [RANK_PVP_HIGHT] = "pvp_robotCsv",
  312 +-- }
  313 +-- local mField = Fields[rankKey]
  314 +-- local robotCsv = RobotCsvs[rankKey]
  315 +-- local dbKey = self:getPvpDBKey(rankKey)
  316 +
  317 +-- local roleId = self:getProperty("id")
  318 +-- score = score or self:unpackPvpScore(redisproxy:zscore(dbKey, roleId))
  319 +
  320 +-- local function getPlayers(levels)
  321 +-- local redret = redisproxy:pipelining(function(red)
  322 +-- for _, level in ipairs(levels) do
  323 +-- local low, high = table.unpack(level)
  324 +-- red:zadd(dbKey, low * PVP_RANK_TIME_SORT_PLACE, "std_temp1")
  325 +-- red:zadd(dbKey, high * PVP_RANK_TIME_SORT_PLACE + PVP_RANK_TIME_SORT_PLACE - 1, "std_temp2")
  326 +-- red:ZREVRANK(dbKey, "std_temp1")
  327 +-- red:ZREVRANK(dbKey, "std_temp2")
  328 +-- end
  329 +-- red:zrem(dbKey, "std_temp1", "std_temp2")
  330 +-- end)
  331 +
  332 +-- local PreGetCount = 7
  333 +-- local redret = redisproxy:pipelining(function(red)
  334 +-- for idx, level in ipairs(levels) do
  335 +-- local rank1 = tonumber(redret[(idx - 1) * 4 + 3])
  336 +-- local rank2 = tonumber(redret[(idx - 1) * 4 + 4])
  337 +-- if rank1 - rank2 > PreGetCount then
  338 +-- rank2 = math.randomInt(rank2, rank1 - PreGetCount + 1)
  339 +-- rank1 = rank2 + PreGetCount - 1
  340 +-- end
  341 +-- red:ZREVRANGE(dbKey, rank2, rank1)
  342 +-- end
  343 +-- end)
  344 +-- return redret
  345 +-- end
  346 +
  347 +-- local findIdx = #globalCsv.pvp_division
  348 +-- for idx, limit in ipairs(globalCsv.pvp_division) do
  349 +-- if score < limit then
  350 +-- findIdx = idx - 1
  351 +-- break
  352 +-- end
  353 +-- end
  354 +-- local levels = {
  355 +-- {}, {}, {}
  356 +-- }
  357 +-- if globalCsv.pvp_division[findIdx + 1] then
  358 +-- levels[1] = {globalCsv.pvp_division[findIdx + 1], (globalCsv.pvp_division[findIdx + 2] or 100000000) - 1}
  359 +-- end
  360 +-- levels[2] = {globalCsv.pvp_division[findIdx], (globalCsv.pvp_division[findIdx + 1] or 100000000) - 1}
  361 +-- if globalCsv.pvp_division[findIdx - 1] then
  362 +-- levels[3] = {globalCsv.pvp_division[findIdx - 1], globalCsv.pvp_division[findIdx] - 1}
  363 +-- end
  364 +-- local redirect = {}
  365 +-- for i = #levels , 1, -1 do
  366 +-- if not next(levels[i]) then
  367 +-- table.remove(levels, i)
  368 +-- redirect[i] = -1
  369 +-- for _, v in pairs(redirect) do
  370 +-- redirect[_] = v - 1
  371 +-- end
  372 +-- else
  373 +-- redirect[i] = i
  374 +-- end
  375 +-- end
  376 +
  377 +-- local result = getPlayers(levels)
  378 +-- local match = self:getProperty(mField)
  379 +-- local hadPlayer = {[roleId] = 1}
  380 +-- local hadRobot = {}
  381 +-- for _, one in pairs(match) do
  382 +-- if one.t == 1 then
  383 +-- hadPlayer[one.id] = 1
  384 +-- elseif one.t == 2 then
  385 +-- hadRobot[one.id] = 1
  386 +-- end
  387 +-- end
  388 +
  389 +-- for _, temp in pairs(result) do
  390 +-- for i = #temp, 1, -1 do
  391 +-- local id = tonumber(temp[i])
  392 +-- if hadPlayer[id] then
  393 +-- table.remove(temp, i)
  394 +-- else
  395 +-- temp[i] = id
  396 +-- hadPlayer[id] = 1
  397 +-- end
  398 +-- end
  399 +-- end
  400 +-- -- 增加第几个
  401 +-- local function getPlayer(idx)
  402 +-- for i = idx, 3 do
  403 +-- if redirect[i] ~= -1 then
  404 +-- local curR = result[redirect[i]] or {}
  405 +-- if next(curR) then
  406 +-- local curIdx = math.randomInt(1, #curR)
  407 +-- local objId = curR[curIdx]
  408 +-- table.remove(curR, curIdx)
  409 +-- return objId
  410 +-- end
  411 +-- end
  412 +-- end
  413 +-- end
  414 +
  415 +-- local tempMatch = {}
  416 +-- local curCount = 0
  417 +-- for i = 1, 3 do
  418 +-- local objId = getPlayer(i)
  419 +-- if objId then
  420 +-- tempMatch[i] = {t = 1, id = objId}
  421 +-- curCount = curCount + 1
  422 +-- end
  423 +-- end
  424 +
  425 +-- -- 正常的玩家不够了 低一档继续
  426 +-- if curCount < 3 then
  427 +-- local level = nil
  428 +-- if globalCsv.pvp_division[findIdx - 2] then
  429 +-- level = {globalCsv.pvp_division[findIdx - 2], globalCsv.pvp_division[findIdx - 1] - 1}
  430 +-- end
  431 +-- if level then
  432 +-- local result = getPlayers({level})[1] or {}
  433 +-- for i = #result, 1, -1 do
  434 +-- local id = tonumber(result[i])
  435 +-- if hadPlayer[id] then
  436 +-- table.remove(result, i)
  437 +-- else
  438 +-- result[i] = id
  439 +-- hadPlayer[id] = 1
  440 +-- end
  441 +-- end
  442 +
  443 +-- if next(result) then
  444 +-- for i = curCount + 1, 3 do
  445 +-- local curIdx = math.randomInt(1, #result)
  446 +-- local objId = result[curIdx]
  447 +-- table.remove(result, curIdx)
  448 +-- tempMatch[i] = {t = 1, id = objId}
  449 +-- curCount = curCount + 1
  450 +-- if not next(result) then
  451 +-- break
  452 +-- end
  453 +-- end
  454 +-- end
  455 +-- end
  456 +-- end
  457 +
  458 +-- -- 增加机器人
  459 +-- if curCount < 3 then
  460 +-- for i = curCount + 1, 3 do
  461 +-- while true do
  462 +-- local id = math.randomInt(1, #csvdb[robotCsv])
  463 +-- if not hadRobot[id] then
  464 +-- hadRobot[id] = 1
  465 +-- tempMatch[i] = {t = 2, id = id}
  466 +-- break
  467 +-- end
  468 +-- end
  469 +-- end
  470 +-- end
  471 +-- self:setProperty(mField, tempMatch)
  472 +-- end
  473 +
  474 +function Role:refreshPvpMatchC(score, rank)
  475 + self:refreshPvpMatch(score, rank, RANK_PVP_COMMON)
356 end 476 end
357 477
358 -function Role:refreshPvpMatchH(score)  
359 - self:refreshPvpMatch(score, RANK_PVP_HIGHT) 478 +function Role:refreshPvpMatchH(score, rank)
  479 + self:refreshPvpMatch(score, rank, RANK_PVP_HIGHT)
360 end 480 end
361 481
362 function Role:getPvpDBKey(ptype) 482 function Role:getPvpDBKey(ptype)