itemavg.lua 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. local skynet = require "skynet"
  2. require "skynet.manager"
  3. local logger = require "logger"
  4. local common_fun = require "model.common_fun"
  5. local stringify = require "stringify"
  6. local pipeline = require "pipeline"
  7. local redisdriver = require "skynet.db.redis"
  8. local KEY_STR = "itemavg"
  9. local util = require "util"
  10. local redis
  11. local cjson = require "cjson"
  12. cjson.encode_sparse_array(true, 1)
  13. local cjson_decode = cjson.decode -- 解码
  14. local cjson_encode = cjson.encode -- 编码
  15. local change = false
  16. local CMD = {}
  17. local function toFixed(a, b)
  18. local num = 10 ^ b
  19. local ret = math.floor(a * num + 0.5)/num
  20. return ret
  21. end
  22. local clear_time = 0
  23. local avglist = {
  24. --[[
  25. [id] = {
  26. list = {
  27. [lv] = {
  28. num = 人数,
  29. avg = 平均,
  30. }
  31. }
  32. all = {num, avg}
  33. }
  34. ]]
  35. }
  36. local function init()
  37. local conf = assert(option.redis)
  38. redis = redisdriver.connect(conf)
  39. redis:select(12)
  40. local retnuma = redis:hgetall(KEY_STR)
  41. local time = redis:get(KEY_STR..":clear_time")
  42. if time then
  43. clear_time = tonumber(time) or 0
  44. end
  45. for k = 1, #retnuma, 2 do
  46. local key = tostring(retnuma[k])
  47. if key then
  48. avglist[key] = cjson_decode(retnuma[k+1])
  49. end
  50. end
  51. end
  52. local function save()
  53. if change then
  54. local batch = pipeline(124)
  55. for id, data in pairs(avglist) do
  56. batch.add("hset", KEY_STR, id, cjson_encode(data))
  57. end
  58. batch.execute(redis)
  59. change = false
  60. end
  61. end
  62. function CMD.updata(data)
  63. if not data then
  64. return
  65. end
  66. local lv = tostring(data.level)
  67. for _, v in ipairs(data.list or {})do
  68. local key = tostring(v.id)
  69. local num = v.num
  70. avglist[key] = avglist[key] or {
  71. list = {},
  72. all = {num = 0, avg = 0}
  73. }
  74. avglist[key].list[lv] = avglist[key].list[lv] or {
  75. num = 0,
  76. avg = 0,
  77. }
  78. local all = avglist[key].all
  79. local cur = avglist[key].list[lv]
  80. all.num = all.num + 1
  81. all.avg = all.avg + toFixed((num - all.avg)/all.num, 2)
  82. cur.num = cur.num + 1
  83. cur.avg = cur.avg + toFixed((num - cur.avg)/cur.num, 2)
  84. end
  85. change = true
  86. end
  87. function CMD.show(id)
  88. if not id then
  89. return stringify(avglist)
  90. end
  91. return stringify(avglist[id] or {})
  92. end
  93. local function check_clear(time)
  94. if time > clear_time then
  95. clear_time = util.today()+DAY_SEC
  96. redis:set(KEY_STR..":clear_time", clear_time)
  97. avglist = {}
  98. redis:del(KEY_STR)
  99. change = false
  100. end
  101. end
  102. local function watchtime()
  103. skynet.fork(function()
  104. local interval = 1-- 更新间隔为2分钟
  105. local up_time = os.time()
  106. while(true) do
  107. local now = os.time()
  108. if now > up_time then
  109. up_time = up_time + interval
  110. check_clear(now)
  111. save()
  112. end
  113. skynet.sleep(100)
  114. end
  115. end)
  116. end
  117. function CMD.start()
  118. init()
  119. watchtime()
  120. end
  121. skynet.init(function()
  122. skynet.register(".itemavg")
  123. end)
  124. skynet.start(function()
  125. skynet.dispatch("lua", function(session, _, cmd, ...)
  126. local f = assert(CMD[cmd])
  127. if 0==session then
  128. f(...)
  129. else
  130. skynet.retpack(f(...))
  131. end
  132. end)
  133. end)