const app = require('j7/app'); const utils = require('j7/utils'); const metaFactory = require('../metadata/factory'); const constant = require('../constant'); class Season { seasonList = []; async start() { console.log("season ranking start1"); while (true) { await this.doRoutine(utils.getUtcTime()); const nowTime = utils.getUtcTime(); const daySeconds = utils.getDaySeconds(nowTime, constant.TIME_ZONE); const sleepTime = daySeconds + 3600 * 24 - nowTime; await utils.sleep(sleepTime*1000); } } async doRoutine(nowTime) { try { console.log("season ranking start2"); // 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",this.seasonList); 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) { return true; let c = this.getCurSeasonId(nowTime); if (!!c) { return (nowTime>c.end_time); } return false; } 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,createtime, score_modifytime 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) { let r = b.score - a.score; if (r==0) { r = a.score_modifytime - b.score_modifytime; } if (r==0) { r = a.idx - b.idx; } return r; }); } } 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', element.createtime], ['modifytime', element.score_modifytime], ] ) } ); } } function init() { (new Season()).start(); } exports.init = init;