local skynet = require "skynet" local redishelper = require "redishelper" local mongohelper = require "mongohelper" local keysutils = require "keysutils" local dateutils = require "dateutils" local utils = require "utils" local settings = require "settings" local cjson = require "cjson" local appname = settings.appname local skynet_node_name = ... require "skynet.manager" local CMD = {} local limit_cfg = { [1]=50, --入门 [2]=50, --初级 [3]=100,--中级 [4]=100,--高级 [5]=200,--大师 [6]=999999999,--巅峰 } local inc = 0 local workerId = settings.nodes[skynet_node_name].server_no local function getint() inc = inc + 1 local s = string.format("%d%06d",os.time(),inc) return checkint(s) end local season = {} --获取赛季配置 function CMD.getseasonconf() if not season.end_time or season.end_time < os.time() then season = mongohelper.findOne(settings.arena_season_key.tname, settings.arena_season_key.cname, {status=1}) end return season end --获取赛季编号 function CMD.getseasonno() local c = CMD.getseasonconf() return chechint(c.version) end local user_group_scritps = [[ local id = redis.call('get', ARGV[1]) if not id then id = redis.call('get', ARGV[2]) if not id then id = redis.call('incr', ARGV[2]) redis.call('expire', ARGV[2], tonumber(ARGV[5])) redis.call('set', ARGV[1], id, "ex", tonumber(ARGV[5])) local k = ARGV[3]..":"..tostring(id) redis.call('zadd', k, 0, ARGV[4]) else local k = ARGV[3]..":"..tostring(id) local n = redis.call('zcard', k) or 0 n = tonumber(n) if n >= tonumber(ARGV[6]) then id = redis.call('incr', ARGV[2]) redis.call('expire', ARGV[2], ARGV[5]) redis.call('set', ARGV[1], id, "ex", tonumber(ARGV[5])) local k = ARGV[3]..":"..tostring(id) redis.call('zadd', k, 0, ARGV[4]) redis.call('expire', k, ARGV[5]) else redis.call('set', ARGV[1], id, "ex", ARGV[5]) local k = ARGV[3]..":"..tostring(id) redis.call('zadd', k, 0, ARGV[4]) redis.call('expire', k, ARGV[5]) end end end return id ]] function CMD.getgroupid(uid) local k = keysutils.arena_usergroup_key(appname, uid, dateutils.get_weekno()) return redishelper.exec("get", uid, k) end --进行分组 --用户ID 服 竞技场等级 function CMD.joingroup(uid, server, level, week) week = week or dateutils.get_weekno() local k1 = keysutils.arena_usergroup_key(appname, uid, week) local k2 = keysutils.arena_groupid_key(appname, server, level, week) local k3 = keysutils.arena_groupbase_key(appname, server, level, week) local overtime = dateutils.oneweekend(os.time() + 7*86400) local ex = overtime - os.time() return redishelper.exec("eval", uid, user_group_scritps, 6, "k1", "k2", "k3", "uid", "ex", "limit", k1, k2, k3, uid, ex, limit_cfg[level]) end local scritps = [[ local score = redis.call('zscore', ARGV[1], ARGV[2]) or 0 score = tonumber(score) if score <= 0 or score < ARGV[3] then redis.call('zincrby', ARGV[1], -score, ARGV[2]) else redis.call('zincrby', ARGV[1], -ARGV[3], ARGV[2]) end return "ok" ]] local save_scritps = [[ local myscore = tonumber(ARGV[4]) if myscore > 0 then redis.call("zincrby", ARGV[1], myscore, ARGV[2]) else local score = redis.call('zscore', ARGV[1], ARGV[2]) or 0 score = tonumber(score) if score > 0 then if score <= 0 or score < -myscore then redis.call('zincrby', ARGV[1], -score, ARGV[2]) else redis.call('zincrby', ARGV[1], myscore, ARGV[2]) end end end local youscore = tonumber(ARGV[5]) if youscore > 0 then redis.call('zincrby', ARGV[1], youscore, ARGV[3]) else local score = redis.call('zscore', ARGV[1], ARGV[3]) or 0 score = tonumber(score) if score > 0 then if score <= 0 or score < -youscore then redis.call('zincrby', ARGV[1], -score, ARGV[3]) else redis.call('zincrby', ARGV[1], youscore, ARGV[3]) end end end return "ok" ]] --保存积分 function CMD.savescore(uid, userid, server, level, myscore, youscore) local groupid = CMD.joingroup(uid, server, level) local k = keysutils.arena_group_key(appname, server, level, dateutils.get_weekno(), groupid) local overtime = dateutils.oneweekend(os.time() + 7*86400) local ex = overtime - os.time() local ok = redishelper.exec("eval", uid, save_scritps, 5, "key", "my", "your", "myscore", "youscore", k, uid, userid, myscore, youscore) return ok end local rank_scritps = [[ local score = redis.call('zscore', ARGV[1], ARGV[2]) local rank = redis.call('zrank', ARGV[1], ARGV[2]) return {score, rank} ]] function CMD.loaduserscore(uid, server, level) local groupid = CMD.joingroup(uid, server, level) local k = keysutils.arena_group_key(appname, server, level, dateutils.get_weekno(), groupid) return redishelper.exec("eval", uid, rank_scritps, 2, "key", "uid", k, uid) end function CMD.loadrank(uid, server, level) local groupid = CMD.joingroup(uid, server, level) if not groupid then return nil end local k = keysutils.arena_group_key(appname, server, level, dateutils.get_weekno(), groupid) local res = redishelper.exec("zrevrange", uid, k, 0, -1, "WITHSCORES") return utils.redis_pack(res) end function CMD.loadlastweekrank(uid, server, level) local groupid = CMD.joingroup(uid, server, level, dateutils.get_weekno() - 1) if not groupid then return {} end local k = keysutils.arena_group_key(appname, server, level, dateutils.get_weekno(), groupid) local res = redishelper.exec("zrevrange", uid, k, 0, -1, "WITHSCORES") return utils.redis_pack(res) end function CMD.loadrandmousers(uid, server, level, min, max, rank) math.randomseed(tostring(os.time()):reverse():sub(1, 6)) local groupid = CMD.joingroup(uid, server, level) local k = keysutils.arena_group_key(appname, server, level, dateutils.get_weekno(), groupid) local res = redishelper.exec("zrevrangebyscore", uid, k, max, min, "WITHSCORES") local list = utils.redis_pack(res) local users = {} for k,v in pairs(list) do local userid = checkint(k) if uid ~= userid then table.insert(users, {uid=math.floor(k), score=math.floor(v)}) end end if #users > 0 then for i=1, 7 do users = table.shuffle(users) end end if #users <= 0 then if rank == 1 then return users end local res = redishelper.exec("zrange", uid, k, rank-1, rank-1, "WITHSCORES") local list = utils.redis_pack(res) local users = {} for k,v in pairs(list) do local userid = checkint(k) if uid ~= userid then table.insert(users, {uid=math.floor(k), score=math.floor(v)}) end end return users end if #users <= 4 then if #users > 0 then local overtime = dateutils.oneweekend(os.time() + 7*86400) local ex = overtime - os.time() local k = keysutils.arena_match_backup_key(appname, uid) redishelper.exec("set", uid, k, cjson.encode(users), "ex", ex) end return users end local s = math.random(1, #users - 4 + 1) local users = table.slice(users, s, 4) if #users > 0 then local overtime = dateutils.oneweekend(os.time() + 7*86400) local ex = overtime - os.time() local k = keysutils.arena_match_backup_key(appname, uid) redishelper.exec("set", uid, k, cjson.encode(users), "ex", ex) end return users end function CMD.loadbackupusers(uid, server, level, min, max, myrank) local k = keysutils.arena_match_backup_key(appname, uid) local result = redishelper.exec("get", uid, k) local ok, users = pcall(cjson.decode, result) if ok then return users end return CMD.loadrandmousers(uid, server, level, min, max, myrank) end function CMD.getbattlenum(uid) local k = keysutils.arena_battlenum_key(appname, uid, dateutils.getday()) return redishelper.exec("get", uid, k) or 0 end local battlenum_scripts = [[ redis.call('incr', ARGV[1]) redis.call('expire', ARGV[1], tonumber(ARGV[2])) return "ok" ]] function CMD.incrbattlenum(uid) local k = keysutils.arena_battlenum_key(appname, uid, dateutils.getday()) local overtime = dateutils.onedayover(os.time() + 86400) local ex = overtime - os.time() local ok = redishelper.exec("eval", uid, battlenum_scripts, 2, "key", "ex", k, ex) return ok end --获取刷新次数 function CMD.getrefreshnum(uid) local k = keysutils.arena_refreshnum_key(appname, uid) return redishelper.exec("get", uid, k) or 0 end function CMD.incrrefreshnum(uid) local k = keysutils.arena_refreshnum_key(appname, uid) return redishelper.exec("incr", uid, k) end function CMD.delrefreshnum(uid) local k = keysutils.arena_refreshnum_key(appname, uid) return redishelper.exec("del", uid, k) end function CMD.setdeflineup(uid, data) local k = keysutils.arena_deflineup_key(appname, uid) local overtime = dateutils.oneweekend(os.time() + 7*86400) local ex = overtime - os.time() return redishelper.exec("set", uid, k, data, "ex", ex) end function CMD.getdeflineup(uid) local k = keysutils.arena_deflineup_key(appname, uid) return redishelper.exec("get", uid, k) or {} end local score_scritps = [[ redis.call('hincrby', ARGV[1], KEYS[2], ARGV[2]) redis.call('expire', ARGV[1], ARGV[3]) return "ok" ]] --获取赛季通行证购买是否购买 function CMD.getuserarenapass(uid) return mongohelper.findOne(settings.user_arena_pass_key.tname, settings.user_arena_pass_key.cname, {uid=uid}) end function CMD.buyarenapass(data) return mongohelper.insert(settings.user_arena_pass_key.tname, settings.user_arena_pass_key.cname, data) end function CMD.incrarenapassscore(uid, score) local sea = CMD.getseasonconf() local ex = math.max(sea.end_time - os.time(), 0) local k = keysutils.arena_pass_key(appname, sea.no, uid) return redishelper.exec("eval", uid, score_scritps, 3, "key", "score", "ex", k, score, ex) end function CMD.getarenapass(uid) local k = keysutils.arena_pass_key(appname, no, uid) return redishelper.exec("hgetall", uid, k) end function CMD.saveearenapass(uid, data) local k = keysutils.arena_pass_key(appname, no, uid) return redishelper.exec("hmset", uid, k, data) end skynet.start(function() skynet.dispatch("lua", function(_, _, command, ...) DEBUG(" arenad cmd = ", command) local f = assert(CMD[command]) skynet.retpack(f(...)) end) skynet.register('.' .. SERVICE_NAME) end)