2023-05-17 14:07:41 +08:00

245 lines
7.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const app = require('j7/app');
const utils = require('j7/utils');
const constant = require('../constant');
const Redis = require('../services/redis');
/**
* redis@3.1.2
*/
const RANKING_KEY = 'game2006api:'
const LAST_IDX = 'userLastIdx'
class Rankings {
async start() {
console.log('Rankings.start');
while (true) {
await this.doRanking();
// const sleepTime = 60*60*2
const sleepTime = 60*60*2
console.log('sleepTime:' + sleepTime, new Date(), sleepTime /60);
await utils.sleep(sleepTime * 1000);
}
}
async doRanking() {
//redis连接
// Redis.connect()
try {
const {err, conn} = await app.getDbConn("GameDb20060");
if (err){
throw err
}
if (await Redis.exists(RANKING_KEY + "account")){
await Redis.del(RANKING_KEY + 'account')
await this.calcRanking();
console.log("跟新rank榜单")
}else {
await this.calcRanking();
console.log("生成rank榜单")
}
}catch (err){
console.log(err);
}
//关闭redis连接
// Redis.quit()
}
//计算用户排行榜
async calcRanking() {
console.log("calc ranking...");
const {err, conn} = await app.getDbConn("GameDb20060");
if (err) {
throw err;
}
if (!err && conn) {
// 从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.recordsSort(sorted, result.records)
}
}
await this.pushResultToRedis(sorted);
// let rankList = await this.pushRankingResult(sorted);
// console.log(rankList);
//存储到redis中
// let listJson = JSON.stringify(rankList);
// Redis.set(RANKING_KEY + "rank",listJson);
console.log("calc ranking end");
}
}
//增加排名列
async pushResultToRedis(sorted) {
let rankingList = [];
await utils.serial(
sorted,
(value , index) =>{
value.ranking = index+1
Redis.hset(RANKING_KEY + "ranking",value.ranking,value.account_id)
Redis.hset(RANKING_KEY + "account",value.account_id,value.ranking)
}
)
}
//跟新用户榜单
async updateRankRecords(conn,data){
if (!data || data.length == 0){
return
}
for (let item of data) {
const {err, row} = await conn.execQueryOne(
'select idx,account_id,channel,convert(`name` using utf8) as name,head_id,head_frame,rank,history_best_rank,score,history_best_score,createtime, score_modifytime from t_user where account_id = ? and score_modifytime > ?',
[
item.account_id,
item.score_modifytime,
]
);
if (err){
throw err
}
if (row){
item.idx = row.idx
item.account_id = row.account_id
item.channel = row.channel
item.name = row.name
item.head_id = row.head_id
item.head_frame = row.head_frame
item.rank = row.rank
item.history_best_rank = row.history_best_rank
item.score = row.score
item.history_best_score = row.history_best_score
item.score_modifytime = row.score_modifytime
}
}
let sorted = [];
this.recordsSort(sorted,data)
let rankList = await this.pushRankingResult(sorted);
//更新redis中榜单
let newListJson = JSON.stringify(rankList);
Redis.set(RANKING_KEY + "rank",newListJson);
}
//获取数据库中最后一个自增id
async getDbLastIdx (conn){
const {err, row} = await conn.execQueryOne(
"select max(idx) as last_idx from t_user"
)
if (err) {
throw err;
}
return row.last_idx;
}
//追加新用户到榜单记录中
async pushNewUserRecords(conn,lastIdx,data){
while(lastIdx>=0) {
const result = await this.getRecords(conn, lastIdx, 1000);
lastIdx = result.lastIdx;
if (lastIdx != -1) {
this.recordsSort(data, result.records)
}
}
console.log("LAST_IDX : ",lastIdx)
let rankList = await this.pushRankingResult(data);
//存储到redis中
let listJson = JSON.stringify(rankList);
Redis.set(RANKING_KEY + "rank",listJson);
}
//获取用户记录
async getRecords(conn, lastIdx, limit) {
const {err, rows} = await conn.execQuery(
'select idx,account_id,channel,convert(`name` using utf8) as name,head_id,head_frame,rank,history_best_rank,score,history_best_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: []
};
}
// Redis.set(LAST_IDX,rows[rows.length-1].idx)
return {
lastIdx: rows[rows.length-1].idx,
records: rows
};
}
//给记录按分数排序
recordsSort(sorted, records) {
// 根据分数加入到排序表中
for (let element of records) {
if (element.score>0) {
if (sorted.length >= 20){
if (element.score >= sorted[sorted.length - 1].score){
sorted.pop()
this._recordsSort(sorted,element)
}
} else {
this._recordsSort(sorted,element)
}
}
}
// if (sorted.length>10000) {
// sorted.length = 10000;
// }
}
_recordsSort(sorted,element){
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;
});
}
//增加排名列
async pushRankingResult(sorted) {
let rankingList = [];
await utils.serial(
sorted,
(value , index) =>{
value.ranking = index+1
rankingList.push(value)
}
)
return rankingList;
}
}
function init() {
(new Rankings()).start();
}
exports.init = init;