rankinglist.lua 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. --排行榜服务
  2. local skynet = require "skynet"
  3. require "skynet.manager"
  4. local util = require "util"
  5. local logger = require "logger"
  6. local common_fun = require "model.common_fun"
  7. local stringify = require "stringify"
  8. local pipeline = require "pipeline"
  9. local redisdriver = require "skynet.db.redis"
  10. local redis
  11. local KEY_STR = "ranking:%d:list"
  12. local cjson = require "cjson"
  13. local cjson_decode = cjson.decode -- 解码
  14. local cjson_encode = cjson.encode -- 编码
  15. local MAX_RANK = 300
  16. local compare = function(a, b)
  17. if a.num > b.num then
  18. return true
  19. end
  20. if a.num == b.num and a.num2 and b.num2 then
  21. return a.num2 > b.num2
  22. end
  23. return false
  24. end
  25. local function inserting(t, n, f)
  26. assert(type(t) == "table")
  27. local f = f or compare
  28. local size = #t
  29. local n = n or size + 1
  30. for i = 2, size do
  31. local num = math.min(i, n)
  32. if i > n and f(t[i], t[num]) then
  33. t[i], t[num] = t[num], t[i]
  34. end
  35. local temp = t[num]
  36. local j = num -1
  37. while j >= 1 and f(temp, t[j]) do
  38. t[j+1] = t[j]
  39. j = j - 1
  40. end
  41. t[j+1] = temp
  42. end
  43. -- if n < size then
  44. -- t[n+1] = nil
  45. -- end
  46. for i = n + 1, size do
  47. t[i] = nil
  48. end
  49. return t
  50. end
  51. local CMD = {}
  52. local ranklist = {
  53. }
  54. local showlist = {
  55. }
  56. local function update()
  57. for rank_type, list in pairs(ranklist) do
  58. inserting(list, MAX_RANK)
  59. showlist[rank_type] = {}
  60. local key = string.format(KEY_STR, rank_type)
  61. redis:del(key)
  62. local batch = pipeline(100)
  63. for rank, data in ipairs(list) do
  64. batch.add("hset", key, data.role.uid, cjson_encode(data))
  65. showlist[rank_type][rank] = common_fun.scopy(data)
  66. end
  67. batch.execute(redis,{})
  68. end
  69. end
  70. local function init()
  71. local conf = assert(option.redis)
  72. redis = redisdriver.connect(conf)
  73. redis:select(12)
  74. for rank_type= RANKING_ADV, RANKING_POWER do
  75. ranklist[rank_type] = {}
  76. local key = string.format(KEY_STR, rank_type)
  77. local retnuma = redis:hgetall(key)
  78. for k = 1, #retnuma, 2 do
  79. local data = cjson_decode(retnuma[k+1])
  80. ranklist[rank_type][#ranklist[rank_type]+1] = data
  81. end
  82. end
  83. end
  84. local function watchtime()
  85. skynet.fork(function()
  86. local interval = 60*2 -- 更新间隔为2分钟
  87. local up_time = os.time()
  88. while(true) do
  89. local now = os.time()
  90. if now > up_time then
  91. up_time = now + interval
  92. update()
  93. end
  94. skynet.sleep(300)
  95. end
  96. end)
  97. end
  98. local function find_uid(list, uid)
  99. for k, info in ipairs(list or {})do
  100. if info.role.uid == uid then
  101. return k, info
  102. end
  103. end
  104. end
  105. function CMD.player_rename(uid, name)
  106. for _, list in pairs(ranklist) do
  107. local _, info = find_uid(list, uid)
  108. if info then
  109. info.role.nickname = name
  110. end
  111. end
  112. end
  113. function CMD.update(rank_type, data)
  114. local key = string.format(KEY_STR, rank_type)
  115. ranklist[rank_type] = ranklist[rank_type] or {}
  116. local list = ranklist[rank_type]
  117. local k = find_uid(list, data.role.uid)
  118. if k then
  119. list[k] = data
  120. redis:hset(key, data.role.uid, cjson_encode(data))
  121. return
  122. end
  123. local show = showlist[rank_type] or {}
  124. if show[MAX_RANK] and show[MAX_RANK].num > data.num then
  125. return
  126. end
  127. list[#list+1] = data
  128. redis:hset(key, data.role.uid, cjson_encode(data))
  129. end
  130. function CMD.get_ranking(rank_type)
  131. return showlist[rank_type] or {}
  132. end
  133. -- 从排行榜中删除玩家
  134. function CMD.del(uid)
  135. for _, list in pairs(showlist) do
  136. local k = find_uid(list, uid)
  137. if k then
  138. table.remove(list, k)
  139. end
  140. end
  141. for rank_type, list in pairs(ranklist) do
  142. local key = string.format(KEY_STR, rank_type)
  143. local k = find_uid(list, uid)
  144. if k then
  145. table.remove(list, k)
  146. redis:hdel(key, uid)
  147. end
  148. end
  149. end
  150. function CMD.start()
  151. init()
  152. watchtime()
  153. end
  154. skynet.init(function()
  155. skynet.register(".rankinglist")
  156. end)
  157. skynet.start(function()
  158. skynet.dispatch("lua", function(session, _, cmd, ...)
  159. local f = assert(CMD[cmd])
  160. if 0==session then
  161. f(...)
  162. else
  163. skynet.retpack(f(...))
  164. end
  165. end)
  166. end)