diff --git a/server/game2006service/metadata/RankSeason.js b/server/game2006service/metadata/RankSeason.js new file mode 100644 index 00000000..bdadcf77 --- /dev/null +++ b/server/game2006service/metadata/RankSeason.js @@ -0,0 +1,8 @@ +const utils = require('j7/utils'); +const basewrap = require('./basewrap'); + +class RankSeason extends basewrap.BaseWrap { + +} + +module.exports = RankSeason; diff --git a/server/game2006service/metadata/factory.js b/server/game2006service/metadata/factory.js index 2b7bd0f3..c97e13bd 100644 --- a/server/game2006service/metadata/factory.js +++ b/server/game2006service/metadata/factory.js @@ -84,7 +84,11 @@ function init() { '', 'GameDb2006' ); - + + registerMetaClass(configDir + 'rankSeason.json', + '', + 'RankSeason' + ); load(); { traverseMetaList('GameDb2006', (dbConf, idx) => { diff --git a/server/game2006service/tasks/season.js b/server/game2006service/tasks/season.js index 0da9c51c..907aaf54 100644 --- a/server/game2006service/tasks/season.js +++ b/server/game2006service/tasks/season.js @@ -5,6 +5,7 @@ const metaFactory = require('../metadata/factory'); const constant = require('../constant'); class Season { + seasonList = []; async start() { while (true) { await this.doRoutine(utils.getUtcTime()); @@ -17,12 +18,159 @@ class Season { async doRoutine(nowTime) { try { - + console.log("season ranking start"); + // console.time("season ranking"); + this.seasonList = []; + metaFactory.traverseMetaList("RankSeason", (config, idx) => { + this.seasonList.push({ + start_time: new Date(config.start_time+" GMT+0000").getTime()/1000, + end_time: new Date(config.end_time+" GMT+0000").getTime()/1000, + id: config.id + }); + return true; + }); + + console.log("season ranking"); + if (this.checkSeasonEnd(nowTime)) { + await this.calcRanking(nowTime); + } + + // console.timeLog("season ranking"); + // console.timeEnd("season ranking"); + + console.log("season ranking end"); } catch(err) { console.log(err); } } + + checkSeasonEnd(nowTime) { + let c = this.getCurSeasonId(nowTime); + return (nowTime>c.end_time); + } + + getCurSeasonId(nowTime) { + let s = this.seasonList[0]; + for( let c of this.seasonList) { + if (nowTime >= c.start_time) { + s = c; + } + } + return s; + } + + async calcRanking(nowTime) { + console.log("calc ranking..."); + + const {err, conn} = await app.getDbConn("GameDb20060"); + if (err) { + throw err; + } + if (!err && conn) { + // 检查是否本赛季已完成排名 + const seasonId = this.getCurSeasonId(nowTime).id; + if (!await this.alreadySorted(conn,seasonId)) { + // 从user表中遍历所有用户,每次取1000个用户,逐步加入到排序表中 + let sorted = []; + let lastIdx = 0; + while(lastIdx>=0) { + const result = await this.getRecords(conn, lastIdx, 1000); + lastIdx = result.lastIdx; + if (lastIdx != -1) { + this.insertNewRecords(sorted, result.records) + } + } + await this.pushRankingResult(conn, sorted, seasonId); + } + else { + console.log("already calc ranking, no need to calc"); + } + } + + console.log("calc ranking...done"); + } + + async alreadySorted(conn, seasonId) { + const {err, rows} = await conn.execQuery( + 'SELECT idx from t_season_ranking where season=? LIMIT 1', + [ + seasonId + ] + ); + if (err) { + throw err; + } + return rows.length>0; + } + + async getRecords(conn, lastIdx, limit) { + const {err, rows} = await conn.execQuery( + 'select idx,account_id,channel,rank,score from t_user where idx > ? order by idx LIMIT ?', + [ + lastIdx, + limit + ] + ); + if (err) { + throw err; + } + if (rows.length==0) { + return { + lastIdx: -1, + records: [] + }; + } + + return { + lastIdx: rows[rows.length-1].idx, + records: rows + }; + } + + insertNewRecords(sorted, records) { + // 根据分数加入到排序表中,始终保留钱10000名 + + // console.time("inserNewRecords"); + for (let element of records) { + if (element.score>0) { + sorted.push(element); + sorted.sort(function(a,b) { + return b.score - a.score; + }); + } + } + if (sorted.length>10000) { + sorted.length = 10000; + } + // console.timeLog("inserNewRecords"); + // console.timeEnd("inserNewRecords"); + } + + async pushRankingResult(conn, sorted, seasonId) { + // 计算排名并存入数据库 + // console.log(sorted); + const nowTime = utils.getUtcTime(); + + await utils.serial( + sorted, + async (element, index) => { + await conn.insert( + 't_season_ranking', + [ + ['account_id', element['account_id']], + ['channel', element['channel']], + ['rank', element['rank']], + ['score', element['score']], + ['ranking', index+1], + ['season', seasonId], + ['createtime', nowTime], + ['modifytime', nowTime], + ] + ) + } + ); + } } function init() {