local skynet = require "skynet" require "skynet.manager" local logger = require "logger" local common_fun = require "model.common_fun" local stringify = require "stringify" local pipeline = require "pipeline" local redisdriver = require "skynet.db.redis" local KEY_STR = "itemavg" local util = require "util" local redis local cjson = require "cjson" cjson.encode_sparse_array(true, 1) local cjson_decode = cjson.decode -- 解码 local cjson_encode = cjson.encode -- 编码 local change = false local CMD = {} local function toFixed(a, b) local num = 10 ^ b local ret = math.floor(a * num + 0.5)/num return ret end local clear_time = 0 local avglist = { --[[ [id] = { list = { [lv] = { num = 人数, avg = 平均, } } all = {num, avg} } ]] } local function init() local conf = assert(option.redis) redis = redisdriver.connect(conf) redis:select(12) local retnuma = redis:hgetall(KEY_STR) local time = redis:get(KEY_STR..":clear_time") if time then clear_time = tonumber(time) or 0 end for k = 1, #retnuma, 2 do local key = tostring(retnuma[k]) if key then avglist[key] = cjson_decode(retnuma[k+1]) end end end local function save() if change then local batch = pipeline(124) for id, data in pairs(avglist) do batch.add("hset", KEY_STR, id, cjson_encode(data)) end batch.execute(redis) change = false end end function CMD.updata(data) if not data then return end local lv = tostring(data.level) for _, v in ipairs(data.list or {})do local key = tostring(v.id) local num = v.num avglist[key] = avglist[key] or { list = {}, all = {num = 0, avg = 0} } avglist[key].list[lv] = avglist[key].list[lv] or { num = 0, avg = 0, } local all = avglist[key].all local cur = avglist[key].list[lv] all.num = all.num + 1 all.avg = all.avg + toFixed((num - all.avg)/all.num, 2) cur.num = cur.num + 1 cur.avg = cur.avg + toFixed((num - cur.avg)/cur.num, 2) end change = true end function CMD.show(id) if not id then return stringify(avglist) end return stringify(avglist[id] or {}) end local function check_clear(time) if time > clear_time then clear_time = util.today()+DAY_SEC redis:set(KEY_STR..":clear_time", clear_time) avglist = {} redis:del(KEY_STR) change = false end end local function watchtime() skynet.fork(function() local interval = 1-- 更新间隔为2分钟 local up_time = os.time() while(true) do local now = os.time() if now > up_time then up_time = up_time + interval check_clear(now) save() end skynet.sleep(100) end end) end function CMD.start() init() watchtime() end skynet.init(function() skynet.register(".itemavg") end) skynet.start(function() skynet.dispatch("lua", function(session, _, cmd, ...) local f = assert(CMD[cmd]) if 0==session then f(...) else skynet.retpack(f(...)) end end) end)