Merge remote-tracking branch 'origin/bugfix' into bugfix

This commit is contained in:
dy 2023-12-28 18:19:52 +08:00
commit cc6aad7223

View File

@ -1,6 +1,5 @@
import { rankType, ResOpen } from '../../shared/protocols/rank/PtlOpen';
import { rankInfo } from '../../shared/protocols/type';
import { player } from '../../shared/protocols/user/type';
import { Queue } from '../../shared/public/queue';
import { RankClslCross } from './rank_clsl';
//import { RankHbzbJfsCross, RankHbzbJfsLocal, RankHbzbZbsCross } from './rank_hbzb_jfs';
@ -12,21 +11,17 @@ import { RankTujian } from './rank_tujian';
import { RankWzryCross } from './rank_wzry';
import { RankXszm } from './rank_xszm';
import { RankZccg } from './rank_zccg';
import { sortEd } from '../../module/redis'
import * as util from 'util'
import { RankKfjs } from "./rank_kfjs";
import { clusterRunOnce } from '../../clusterUtils';
export abstract class Rank {
static list: Partial<{
qjzzd: RankQjzzd;
zhanli: RankPower;
tanxian: RankTanXian;
//hbzbLocal: RankHbzbJfsLocal;
// hbzbCross: RankHbzbJfsCross;
// hbzbZbsCross: RankHbzbZbsCross;
slzd1: RankSlzd1;
slzd2: RankSlzd2;
slzd3: RankSlzd3;
@ -41,17 +36,12 @@ export abstract class Rank {
kfjs: RankKfjs
}> = {};
// list: rankInfo[];
queue = new Queue();
findKey = 'uid';
countMaxNum = 50;
utimeTTL = 60;
abstract getType(): rankType;
// abstract compare(other: rankInfo, cur: rankInfo): boolean;
// abstract compareSort(a: rankInfo, b: rankInfo): number;
// abstract getRankList(uid: string, obj?: {gud?:player, min?: number, max?:number}): Promise<ResOpen['']>;
// abstract getValArr(info: rankInfo): number|string; // 运算后的积分值,排名依据
// 获取rank数据, 注可能重写具体根据type类型判断
async getRankList(uid: string, { min, max }): Promise<{ rankList: rankInfo[]; myRank: rankInfo; }> {
@ -70,7 +60,12 @@ export abstract class Rank {
};
}
// 积分, 排名依据, 可能重写具体根据type类型判断
/**
* RankInfo数据
* type类型判断
* @param info
* @returns
*/
getValArr(info: rankInfo): number | string {
return info?.valArr[0] || 0
}
@ -85,9 +80,13 @@ export abstract class Rank {
return b.valArr[0] - a.valArr[0];
}
// 页码转换为minmax
static pageToMin (page, offset) {
/**
* page和offset转换出min和max
* @param page
* @param offset
* @returns
*/
static pageToMin(page: number, offset: number) {
let res = {
min: page * offset,
max: page * offset + offset
@ -95,9 +94,16 @@ export abstract class Rank {
return res
}
/**
* DB连接对象
*/
get db() {
return G.mongodb.collection('rankList');
}
/**
*
*/
get type() {
return this.getType();
}
@ -107,10 +113,16 @@ export abstract class Rank {
this.cotr();
}
/**
* typeredis Data的key
*/
get getRedisKey() {
return util.format('rank:%s:data', this.getType())
}
/**
* typeredis Sort的key
*/
get getRedisKeySort() {
return util.format('rank:%s:sort', this.getType())
}
@ -119,8 +131,18 @@ export abstract class Rank {
async cotr() {
clusterRunOnce(async () => {
// redis已存在则不初始化
if(await this.getRankLen() > 0) return
this.db.find({ type: this.type }).toArray().then(listArr => {
//if(await this.getRankLen() > 0) return
//将db里的数据写入到 rank:xxx:sort里
//写入的单条数据为: {uid:score}
this.db.find({ type: this.type }, {
projection: {
"idKey": 1,
"type": 1,
"data.valArr": 1,
"utime": 1
}
}).toArray().then(listArr => {
// 写入初始化数据
listArr = listArr || [];
listArr.forEach(item => {
@ -128,50 +150,83 @@ export abstract class Rank {
})
});
})
this.getRankListRange();
}
// 更新数据与排名
async setRankData(idKey: string, data: rankInfo) {
let key = this.getRedisKey
/**
*
* @param uid uidrank里通常保存于idKey这个字段
* @param data data.valArr字段
* @returns
*/
async setRankData(uid: string, data: rankInfo) {
let keySort = this.getRedisKeySort
data.utime = G.time
// data
G.redis.hSet(key, idKey, data)
// sort
let valArr = await this.getValArr(data)
G.redis.zAdd(keySort, <sortEd>{value: idKey, score: valArr})
// let key = this.getRedisKey
// G.redis.hSet(key, idKey, data)
/**积分 */
let score = await this.getValArr(data)
//G.redis.zAdd(keySort, <sortEd>{value: idKey, score: valArr})
await G.ioredis.zadd(keySort, score, uid)
return
}
// 获取单个用户的数据
async getRankData(idKey: string) {
let key = this.getRedisKey
let data = await G.redis.hGet(key, idKey)
if(!data || data.utime < (G.time - this.utimeTTL)) {
let type = this.getType()
let res = await this.db.findOne({isKey: idKey, type})
if(res) {
data = G.mongodb.conversionIdObj(res)
this.setRankData(idKey, data.data)
/**
*
* @param uid uid
* @returns
*/
async getRankData(uid: string) {
let data: rankInfo;
let res = await this.db.findOne({ "idKey": uid, "type": this.getType() })
if (res?.data && res.data.utime + 60 > G.time) {
data = (G.mongodb.conversionIdObj(res)).data;
} else if (res?.data) {
let player = await G.mongodb.collection("user").findOne({ uid: uid }, { projection: { _id: 0 } });
data = Object.assign(res.data, { player: player });
this.db.updateOne({ idKey: uid, type: this.getType() }, { $set: { "data.player": data.player, "data.utime": G.time } });
}
}
if(data) return data
return undefined || {}
return data;
// let key = this.getRedisKey
// let data = await G.redis.hGet(key, idKey)
// if(!data || data.utime < (G.time - this.utimeTTL)) {
// let type = this.getType()
// let res = await this.db.findOne({isKey: idKey, type}) //<--isKey意味着整个rank从来不会更新res永远是空
// if(res) {
// data = G.mongodb.conversionIdObj(res)
// this.setRankData(idKey, data.data)
// }
// }
// if(data) return data
// return undefined || {}
}
// 获取单个用户的分数
async getRankScore(idKey:string): Promise<number> {
let score = await G.redis.zScore(this.getRedisKeySort, idKey)
/**
*
* @param uid
* @returns
*/
async getRankScore(uid: string): Promise<number> {
let score = await G.redis.zScore(this.getRedisKeySort, uid)
return score || 0
}
// 获取单个用户的排名 *降序
async getRankSortByOne(idKey: string):Promise<number> {
let rank = await G.redis.zRevRank(this.getRedisKeySort, idKey)
/**
* redis中获取单个用户的排名 *
* @param uid
* @returns
*/
async getRankSortByOne(uid: string): Promise<number> {
let rank = await G.redis.zRevRank(this.getRedisKeySort, uid)
return rank === 0 || rank > 0 ? rank : -1;
}
// 获取单个指定排名的用户数据 *降序
// 从redis中获取单个指定排名的用户数据 *降序
async getRankSortDataByOne(rank: number): Promise<rankInfo> {
let rankList: rankInfo[] = await this.getRankListRange(rank, rank + 1)
let rankInfo = rankList && rankList.length > 0 ? rankList[0] : {} as rankInfo
@ -179,73 +234,152 @@ export abstract class Rank {
}
// 获取排名长度
async getRankLen() {
return await G.redis.hLen(this.getRedisKey)
// async getRankLen() {
// return await G.redis.hLen(this.getRedisKey)
// }
/**
* *
* @param min
* @param max
* @returns
*/
async getRankListRange(min: number = 0, max: number = 50): Promise<rankInfo[]> {
let uids = await this.getRankListIdKeyRange(min, max)
if (uids && uids.length > 0) {
let res = await this.db.find({ idKey: { $in: uids }, type: this.getType() }).toArray()
switch (this.getType()) {
case "slzd1":
case "slzd2":
case "slzd3":
case "slzd4":
case "slzd5":
case "slzd6":
let ghid = [];
res = res.map(item => {
if (!item.data?.player?.ghid || item.data.utime + 60 < G.time) {
ghid.push(G.mongodb.conversionId(item.idKey));
}
return item;
})
if(ghid.length > 0){
(await G.mongodb.collection("gonghui").find(
{ _id: { $in: ghid } }, { projection: { name: 1 } }
)).forEach(item => {
let index = res.findIndex(x => x.idKey == item._id.toHexString());
res[index].data.player.ghName = item.name;
this.db.updateOne({ idKey: item._id.toHexString(), type: this.getType() }, { $set: { "data.player.ghName": item.name } });
})
}
break;
default: // 排行数据更新逻辑 默认更新playerInfo
let updateUids = [];
res = res.map(item => {
// 没有player 或者 player 过期
if (!item.data?.player || item.data.utime + 60 < G.time) {
updateUids.push(item.idKey);
}
return item;
});
let newUserArr = await G.mongodb.collection('user').find(
{ uid: { $in: updateUids } }, { projection: { _id: 0 } }
).toArray();
newUserArr.forEach(item => {
// 每次遍历查找?
let index = res.findIndex(x => x.idKey == item.uid);
res[index].data.player = item;
this.db.updateOne({ idKey: item.uid, type: this.getType() }, { $set: { "data.player": item } });
// 跟新redis score
// this.setRankData(item.uid, res[index].data as any);
})
}
// 获取指定排名范围的数据 *降序
async getRankListRange(min:number = 0, max:number = 50): Promise<rankInfo[]> {
let idKeys = await this.getRankListIdKeyRange(min, max)
if(idKeys && idKeys.length > 0) {
let res = await G.redis.hmGet(this.getRedisKey, idKeys)
res = await this.checkData(res)
return res.map(ele => ele.data).sort(this.compareSort) as any;
}
return []
}
/**
* redis中获取指定排名范围的uid集合 *
* @param min
* @param max
* @returns uid集合数组
*/
async getRankListIdKeyRange(min: number = 0, max: number = 50): Promise<string[]> {
let uids = await G.redis.zRevRange(this.getRedisKeySort, min, max - 1)
return uids || []
}
/**
* rank列表,
* @returns
*/
async getRankListAll(): Promise<rankInfo[]> {
// let res = await G.redis.hGetAll(this.getRedisKey)
let res = (await this.db.find({ type: this.getType() }).toArray()).map(ele => ele.data);
if (res) {
// 如果是用户数据则比对utime更新数据
// res = await this.checkData(res)
return res.sort(this.compareSort)
}
return []
}
// 获取指定排名范围的idKey *降序
async getRankListIdKeyRange(min:number = 0, max: number = 50): Promise<string[]> {
let idKeys = await G.redis.zRevRange(this.getRedisKeySort, min, max - 1)
return idKeys || []
}
// 获取指定类型的全部rank列表,返回为积分排序后的数组
async getRankListAll(): Promise<rankInfo[]> {
let res = await G.redis.hGetAll(this.getRedisKey)
if(res) {
// 如果是用户数据则比对utime更新数据
// res = await this.checkData(res)
return Object.values(res).sort(this.compareSort)
}
return []
}
// 按排名获取全部的idKey
/**
* idKey
* @returns
*/
async getRankListIdKeyAll(): Promise<string[]> {
let res = this.getRankListIdKeyRange(0, -1)
return res
}
// 验证数据的过期时间,更新数据
async checkData(rankList: rankInfo[]): Promise<rankInfo[]> {
let updateUid = []
rankList.forEach((value,key) => {
// 仅针对用户表,公会表暂不考虑
if(rankList[key].player?.uid && (rankList[key].utime || 0) < (G.time - this.utimeTTL)) {
// 更新数据
updateUid.push(rankList[key].player.uid)
}
})
if(updateUid.length > 0) {
let newUserArr = await G.mongodb.collection('user').find({uid:{$in: updateUid}}).toArray()
// let newUserArr = await G.redis.gets('user', ...updateUid.map(uid => [uid] as [string]))
// async checkData(rankList: rankInfo[]): Promise<rankInfo[]> {
// let updateUid = []
// rankList.forEach((value,key) => {
// // 仅针对用户表,公会表暂不考虑
// if(rankList[key].player?.uid && (rankList[key].utime || 0) < (G.time - this.utimeTTL)) {
// // 更新数据
// updateUid.push(rankList[key].player.uid)
// }
// })
// if(updateUid.length > 0) {
// let newUserArr = await G.mongodb.collection('user').find({uid:{$in: updateUid}}).toArray()
newUserArr.forEach(item => {
let index = rankList.findIndex( x => x.player.uid == item.uid);
rankList[index].player = item;
this.setRankData(item.uid, rankList[index]);
})
}
return rankList
}
// // let newUserArr = await G.redis.gets('user', ...updateUid.map(uid => [uid] as [string]))
// // let newUserArr = await G.mongodb.collection('user').find({uid:{$in: updateUid}}).toArray()
// newUserArr.forEach(item => {
// let index = rankList.findIndex( x => x.player.uid == item.uid);
// rankList[index].player = item;
// this.setRankData(item.uid, rankList[index]);
// })
// }
// return rankList
// }
/**
* idk的排名数据
* @param idKey
* @returns
*/
async delRankData(idKey: string) {
G.redis.hDel(this.getRedisKey, idKey)
G.redis.zRem(this.getRedisKeySort, idKey)
// G.redis.hDel(this.getRedisKey, idKey)
G.redis.zRem(this.getRedisKeySort, idKey);
this.db.updateOne({ idKey: idKey, type: this.getType() }, {
$set: { idKey: `del_${idKey}` }
});
}
// 原逻辑前50(countMaxNum)名才更新数据(上榜),多余的数据会删除。
/**
* 50(countMaxNum)
* @param info
* @returns
*/
async addNew(info: rankInfo) {
//this.queue.enqueue(async () => {
await this.setRankData(info.player[this.findKey], info)
@ -259,12 +393,13 @@ export abstract class Rank {
//});
}
// 清空相关rank数据
async clear() {
this.queue.enqueue(async () => {
// G.redis.rawDel(this.getRedisKey)
G.redis.rawDel(this.getRedisKeySort);
await this.db.deleteMany({ type: this.type });
G.redis.rawDel(this.getRedisKey)
G.redis.rawDel(this.getRedisKeySort)
});
}
}