123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- local skynet = require "skynet"
- require "skynet.manager"
- local redisdriver = require "skynet.db.redis"
- local util = require "util"
- local common_fun = require "model.common_fun"
- local pipeline = require "pipeline"
- local logger = require "logger"
- local stringify = require "stringify"
- local httpc = require "http.httpc"
- local cjson = require "cjson"
- local db_list
- local db_character
- local KEY_STR = "statistics"
- local math_min = math.min
- local math_max = math.max
- local CMD = {}
- local next_collect = 0
- local function time_key(tm)
- return os.date("%Y%m%d", tm)
- end
- local function check_next()
- if next_collect == 0 then
- next_collect = util.today()
- end
- local key = time_key(next_collect-DAY_SEC)
- if db_list:hexists(KEY_STR, key) == 1 then
- next_collect = next_collect + DAY_SEC
- else
- next_collect = next_collect
- end
- end
- local function init()
- local conf = assert(option.redis)
- db_character = redisdriver.connect(conf)
- db_character:select(0)
- db_list = redisdriver.connect(conf)
- db_list:select(11)
- check_next()
- end
- local function myfloor(num)
- return math.floor(num*100)/100
- end
- local function collect(tm)
- local time = tm
- local keys = common_fun.redis_keys_wait(db_character, "character:*")
- local block = pipeline(1024)
- if next(keys) then
- for _, k in pairs(keys) do
- block.add("hmget", k, "nickname", "uid", "level", "lastlogin", "lastlogout", "createtime")
- end
- end
- local list = {
- create = 0, -- 激活用户
- dau = 0, -- 日活
- wau = 0, -- 周活
- mau = 0, -- 月活
- lost = 0, -- 流失
- login = 0, -- 再次登录的玩家
- keep = 0, -- 次日留存
- keep3 = 0, -- 3日留存
- keep7 = 0, -- 7日留存
- keep30 = 0, -- 30日留存
- all = 0, -- 总人数
- rcg_player = 0, -- 充值人数(每日)
- rcg_money = 0, -- 充值金额(每日)
- arpu = 0, -- 付费玩家价值(每日)
- rcg_money30 = 0, -- 充值金额(每月)
- ltv = 0, -- 价值
- }
- local resp = block.execute(db_character, {})
- for _, v in ipairs(resp) do
- assert(v.ok)
- local rs = v.out
- if rs[2] then
- local name = rs[1]
- local uid = rs[2]
- local level = tonumber(rs[3])
- local lastlogin = tonumber(rs[4]) or 0
- local lastlogout = tonumber(rs[5]) or 0
- local createtime = tonumber(rs[6]) or 0
- -- 当日激活
- if createtime >= time and createtime < time + DAY_SEC then
- list.create = list.create + 1
- end
- if lastlogin - createtime > 10 then
- list.login = list.login + 1
- end
- if createtime < time + DAY_SEC then
- local temp = math_min(time - lastlogout, time - lastlogin)
- if temp < 0 then
- list.dau = list.dau + 1
- end
- if temp < 6 * DAY_SEC then
- list.wau = list.wau + 1
- end
-
- if temp < 29 * DAY_SEC then
- list.mau = list.mau + 1
- end
- if temp > 30 * DAY_SEC then
- list.lost = list.lost + 1
- end
- local temp2 = math_max(math_min(lastlogin, time + DAY_SEC), math_min(lastlogout, time + DAY_SEC)) - createtime
- if temp2 > DAY_SEC then
- list.keep = list.keep + 1
- end
- if temp2 > 2 * DAY_SEC then
- list.keep3 = list.keep3 + 1
- end
- if temp2 > 6 * DAY_SEC then
- list.keep7 = list.keep7 + 1
- end
- if temp2 > 29 * DAY_SEC then
- list.keep30 = list.keep30 + 1
- end
- list.all = list.all + 1
- end
- end
- end
- local ok,herrno,info = pcall(httpc.post, RECHARGE_SERVICE, '/recharge_info', {
- serverid = option.sid,
- starttime = time,
- })
- if herrno ~= 200 then
- logger.trace("查询充值失败.errno %s", herrno)
- return
- end
- -- info 解码
- local order = cjson.decode(info)
- if order.erron ~= 0 then
- logger.trace("查询充值失败 %s", stringify(order))
- return
- end
- list.rcg_player = order.data.day_player or 0
- list.rcg_money = order.data.day_recharge or 0
- list.rcg_money30 = order.data.month_recharge or 0
- if list.create > 0 then
- list.keep = myfloor(list.keep/list.create)
- list.keep3 = myfloor(list.keep3/list.create)
- list.keep7 = myfloor(list.keep7/list.create)
- list.keep30 = myfloor(list.keep30/list.create)
- else
- list.keep = "NaN"
- list.keep3 = "NaN"
- list.keep7 = "NaN"
- list.keep30 = "NaN"
- end
- if list.rcg_player > 0 then
- list.arpu = list.rcg_money/list.rcg_player
- else
- list.arpu = "NaN"
- end
- db_list:hset(KEY_STR, time_key(tm), cjson.encode(list))
- return list
- end
- local function watchtime()
- skynet.fork(function()
- while(true) do
- if os.time() >= next_collect then
- collect(next_collect-DAY_SEC)
- check_next()
- end
- skynet.sleep(6000)
- end
- end)
- end
- local key_index = {
- "create",
- "dau",
- "wau",
- "mau",
- "lost",
- "login",
- "keep",
- "keep3",
- "keep7",
- "keep30",
- "all",
- "rcg_player",
- "rcg_money",
- "rcg_money30",
- "arpu",
- "ltv",
- }
- function CMD.get_statistics_data(time)
- local activitytime = skynet.localname(".activitytime")
- local open_time = skynet.call(activitytime, "lua", "query")
- local now = util.today()
- if not time then
- time = now
- end
- local start_time = util.month_one(time)
- local end_time = util.month_one(start_time+31*DAY_SEC)-DAY_SEC
- if start_time < open_time then
- start_time = util.today(open_time)
- end
- if end_time >= now then
- end_time = now - DAY_SEC
- end
- local ret = {}
- ret[1] = common_fun.scopy(key_index)
- table.insert(ret[1], 1, "date")
- for i = start_time, end_time, DAY_SEC do
- local key = time_key(i)
- local data
- if db_list:hexists(KEY_STR, key) == 1 then
- data = cjson.decode(db_list:hget(KEY_STR, key))
- else
- data = collect(i)
- end
- local temp = {key}
- for _, v in pairs(key_index) do
- local value = data and tostring(data[v])
- if not value or value == 'nil' then
- value = 'NaN'
- end
- table.insert(temp, value)
- end
- table.insert(ret, temp)
- end
- return ret
- end
- function CMD.start()
- init()
- watchtime()
- end
- skynet.init(function()
- skynet.register(".statistics")
- 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)
-
|