增加修复数据的脚本
This commit is contained in:
parent
2dc526796d
commit
f2da3f1b57
1033
initdatas/chest_id.txt
Normal file
1033
initdatas/chest_id.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,9 @@
|
|||||||
"lint": "eslint --ext .ts src/**",
|
"lint": "eslint --ext .ts src/**",
|
||||||
"format": "eslint --ext .ts src/** --fix",
|
"format": "eslint --ext .ts src/** --fix",
|
||||||
"initdata": "ts-node src/initdata.ts",
|
"initdata": "ts-node src/initdata.ts",
|
||||||
|
"repairdata": "ts-node -r tsconfig-paths/register src/repairdata.ts",
|
||||||
|
"repairdata2": "ts-node -r tsconfig-paths/register src/repairdata2.ts",
|
||||||
|
"repairredis": "ts-node -r tsconfig-paths/register src/repairredis.ts",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
|
@ -375,7 +375,17 @@ class GameController extends BaseController {
|
|||||||
// updateData['$inc']['maxNoChestCount'] = step
|
// updateData['$inc']['maxNoChestCount'] = step
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
await ActivityGame.updateOne({ user: user.id, activity: user.activity }, updateData)
|
let saveRes = await ActivityGame.findOneAndUpdate(
|
||||||
|
{ user: user.id, activity: user.activity, tickets: { $gte: step } },
|
||||||
|
updateData,
|
||||||
|
{
|
||||||
|
new: false,
|
||||||
|
upsert: false,
|
||||||
|
includeResultMetadata: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// TODO:: check saveRes
|
||||||
|
console.log(saveRes)
|
||||||
await updateRankScore({
|
await updateRankScore({
|
||||||
user: user.id,
|
user: user.id,
|
||||||
score: score,
|
score: score,
|
||||||
|
20
src/models/DeleteRecord.ts
Normal file
20
src/models/DeleteRecord.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { dbconn } from 'decorators/dbconn'
|
||||||
|
import { getModelForClass, index, modelOptions, mongoose, prop } from '@typegoose/typegoose'
|
||||||
|
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||||
|
import { BaseModule } from './Base'
|
||||||
|
/**
|
||||||
|
* 宝箱券
|
||||||
|
*/
|
||||||
|
@dbconn()
|
||||||
|
@index({ type: 1 }, { unique: false })
|
||||||
|
@modelOptions({
|
||||||
|
schemaOptions: { collection: 'delete_record', timestamps: true },
|
||||||
|
options: { allowMixed: Severity.ALLOW },
|
||||||
|
})
|
||||||
|
export class DeleteRecordClass extends BaseModule {
|
||||||
|
@prop()
|
||||||
|
public type: string
|
||||||
|
@prop({ type: mongoose.Schema.Types.Mixed })
|
||||||
|
public data: any
|
||||||
|
}
|
||||||
|
export const DeleteRecord = getModelForClass(DeleteRecordClass, { existingConnection: DeleteRecordClass['db'] })
|
96
src/repairdata.ts
Normal file
96
src/repairdata.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import mongoose from 'mongoose'
|
||||||
|
import * as dotenv from 'dotenv'
|
||||||
|
|
||||||
|
const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development'
|
||||||
|
dotenv.config({ path: envFile })
|
||||||
|
console.log(process.env.DB_MAIN)
|
||||||
|
import { ActivityChest } from 'models/ActivityChest'
|
||||||
|
import { VoucherRecord } from 'models/VoucherRecord'
|
||||||
|
import { NFTHolderRecord } from 'models/NFTHodlerRecord'
|
||||||
|
import { TicketRecord } from 'models/TicketRecord'
|
||||||
|
const db = mongoose.connection
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
try {
|
||||||
|
await mongoose.connect(process.env.DB_MAIN)
|
||||||
|
let chests = await ActivityChest.find({})
|
||||||
|
// 过滤掉箱子码开出来的箱子
|
||||||
|
console.log('箱子总数: ', chests.length)
|
||||||
|
let voucherChestSet = new Set()
|
||||||
|
let voucherRecords = await VoucherRecord.find({ status: 9 })
|
||||||
|
for (let record of voucherRecords) {
|
||||||
|
if (record.chests.length > 0) {
|
||||||
|
voucherChestSet.add(record.chests[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let chestsLeft = []
|
||||||
|
for (let chest of chests) {
|
||||||
|
if (!voucherChestSet.has(chest.id)) {
|
||||||
|
chestsLeft.push(chest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('过滤掉箱子码开出来的箱子: ', voucherChestSet.size, '剩余: ', chestsLeft.length)
|
||||||
|
// 过滤掉正常合作伙伴nft holeder的箱子
|
||||||
|
let nftHolderRecords = await NFTHolderRecord.find({})
|
||||||
|
let nftHolderChestSet = new Set()
|
||||||
|
for (let record of nftHolderRecords) {
|
||||||
|
if (record.rewards.length > 0) {
|
||||||
|
nftHolderChestSet.add(record.rewards[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let chestsLeft2 = []
|
||||||
|
for (let chest of chestsLeft) {
|
||||||
|
if (!nftHolderChestSet.has(chest.id)) {
|
||||||
|
chestsLeft2.push(chest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('过滤掉正常NFT holder记录的箱子: ', nftHolderChestSet.size, '剩余: ', chestsLeft2.length)
|
||||||
|
// 根据探索记录时间和箱子生成时间过滤正常的箱子
|
||||||
|
let ticketRecords = await TicketRecord.find({ score: { $lt: 0 } })
|
||||||
|
let exploreChestSet = new Set()
|
||||||
|
for (let ticketRecord of ticketRecords) {
|
||||||
|
// query chest createAt between ticketRecord.createAt and ticketRecord.createAt - 1 second
|
||||||
|
let total = Math.abs(ticketRecord.score)
|
||||||
|
let chestArr = []
|
||||||
|
for (let chest of chestsLeft2) {
|
||||||
|
if (
|
||||||
|
chest.user === ticketRecord.user &&
|
||||||
|
// @ts-ignore
|
||||||
|
chest.createdAt < ticketRecord.createdAt &&
|
||||||
|
// @ts-ignore
|
||||||
|
chest.createdAt > ticketRecord.createdAt - 1000
|
||||||
|
) {
|
||||||
|
chestArr.push(chest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 有限保留已开过和品质高的箱子
|
||||||
|
chestArr.sort((a, b) => {
|
||||||
|
return b.status - a.status
|
||||||
|
})
|
||||||
|
let count = 0
|
||||||
|
for (let chest of chestArr) {
|
||||||
|
if (count >= total) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
exploreChestSet.add(chest.id)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let chestsLeft3 = []
|
||||||
|
for (let chest of chestsLeft2) {
|
||||||
|
if (!exploreChestSet.has(chest.id)) {
|
||||||
|
chestsLeft3.push(chest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(chestsLeft3.length)
|
||||||
|
console.log('过滤掉探索获得的箱子: ', exploreChestSet.size, '剩余: ', chestsLeft3.length)
|
||||||
|
let file = require('fs')
|
||||||
|
let ids = chestsLeft3.map(chest => chest.id)
|
||||||
|
file.writeFileSync('initdatas/chest_id.txt', ids.join('\n'))
|
||||||
|
|
||||||
|
console.log('Finished repair box data in the database')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
process.exit(0)
|
||||||
|
})()
|
123
src/repairdata2.ts
Normal file
123
src/repairdata2.ts
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import mongoose from 'mongoose'
|
||||||
|
import * as dotenv from 'dotenv'
|
||||||
|
|
||||||
|
const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development'
|
||||||
|
dotenv.config({ path: envFile })
|
||||||
|
console.log(process.env.DB_MAIN)
|
||||||
|
import { ActivityChest } from 'models/ActivityChest'
|
||||||
|
import { ScoreRecord } from 'models/ScoreRecord'
|
||||||
|
import { DeleteRecord } from 'models/DeleteRecord'
|
||||||
|
import { rankKey, updateRank, updateRankInvite } from 'services/rank.svr'
|
||||||
|
import { ZRedisClient } from 'zutils'
|
||||||
|
import { RANK_SCORE_SCALE } from 'common/Constants'
|
||||||
|
const db = mongoose.connection
|
||||||
|
|
||||||
|
const updateRedis = async (activity, user, score) => {
|
||||||
|
const key = rankKey(activity)
|
||||||
|
await updateRank(key, score, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateRedisInvite = async (activity, sourceUser, user, score) => {
|
||||||
|
const keyInvite = `${activity}:invite`
|
||||||
|
await updateRankInvite(keyInvite, parseInt(score * RANK_SCORE_SCALE + ''), `${sourceUser}_${user}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
try {
|
||||||
|
return false
|
||||||
|
let fs = require('fs')
|
||||||
|
let ids = fs.readFileSync('initdatas/chest_id.txt', 'utf-8').split('\n')
|
||||||
|
let ids2 = []
|
||||||
|
for (let i = 0; i < ids.length; i++) {
|
||||||
|
if (ids[i].trim()) {
|
||||||
|
ids2.push(ids[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let chests = await ActivityChest.find({ _id: { $in: ids2 } })
|
||||||
|
const activity = 'uaw_activity'
|
||||||
|
console.time('delete')
|
||||||
|
let opts = { url: process.env.REDIS }
|
||||||
|
new ZRedisClient(opts)
|
||||||
|
for (let chest of chests) {
|
||||||
|
if (chest.status === 1) {
|
||||||
|
// 未开启
|
||||||
|
// 处理助力分数
|
||||||
|
if (chest.bonusUsers.length > 0) {
|
||||||
|
for (let user of chest.bonusUsers) {
|
||||||
|
let record = await ScoreRecord.findOne({ user: user, activity: chest.activity, type: 'enhance_chest_gift' })
|
||||||
|
console.log('助力分数: ', record.score)
|
||||||
|
await updateRedis(activity, user, -record.score)
|
||||||
|
let dRecord = new DeleteRecord({
|
||||||
|
type: 'enhance_chest_gift',
|
||||||
|
data: record,
|
||||||
|
})
|
||||||
|
await dRecord.save()
|
||||||
|
await ScoreRecord.deleteOne({ _id: record.id })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (chest.status === 9) {
|
||||||
|
// 已开启
|
||||||
|
// 处理助力分数
|
||||||
|
if (chest.bonusUsers.length > 0) {
|
||||||
|
for (let user of chest.bonusUsers) {
|
||||||
|
let record = await ScoreRecord.findOne({ user: user, activity: chest.activity, type: 'enhance_chest_gift' })
|
||||||
|
console.log('助力分数: ', record.score)
|
||||||
|
// update redis
|
||||||
|
await updateRedis(activity, user, -record.score)
|
||||||
|
let dRecord = new DeleteRecord({
|
||||||
|
type: 'enhance_chest_gift',
|
||||||
|
data: record,
|
||||||
|
})
|
||||||
|
await dRecord.save()
|
||||||
|
await ScoreRecord.deleteOne({ _id: record.id })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理已开箱所得分数
|
||||||
|
let record = await ScoreRecord.findOne({
|
||||||
|
'data.chestId': chest.id,
|
||||||
|
user: chest.user,
|
||||||
|
activity: chest.activity,
|
||||||
|
type: 'open_chest',
|
||||||
|
})
|
||||||
|
console.log('开箱所得分数: ', record.score)
|
||||||
|
// update redis
|
||||||
|
await updateRedis(activity, chest.user, -record.score)
|
||||||
|
let dRecord = new DeleteRecord({
|
||||||
|
type: 'open_chest',
|
||||||
|
data: record,
|
||||||
|
})
|
||||||
|
await dRecord.save()
|
||||||
|
await ScoreRecord.deleteOne({ _id: record.id })
|
||||||
|
// 处理邀请者所得分数
|
||||||
|
let subRecords = await ScoreRecord.find({
|
||||||
|
'data.fromUser': record.user,
|
||||||
|
'data.chestId': chest.id,
|
||||||
|
type: 'invite_rebate',
|
||||||
|
})
|
||||||
|
for (let subRecord of subRecords) {
|
||||||
|
console.log('邀请者所得分数: ', subRecord.score, subRecord.id)
|
||||||
|
// update redis
|
||||||
|
await updateRedis(activity, subRecord.user, -record.score)
|
||||||
|
await updateRedisInvite(activity, record.user, subRecord.user, -record.score)
|
||||||
|
let dRecord = new DeleteRecord({
|
||||||
|
type: 'invite_rebate',
|
||||||
|
data: subRecord,
|
||||||
|
})
|
||||||
|
await dRecord.save()
|
||||||
|
await ScoreRecord.deleteOne({ _id: subRecord.id })
|
||||||
|
}
|
||||||
|
// 移除当前箱子
|
||||||
|
}
|
||||||
|
let dRecordChest = new DeleteRecord({
|
||||||
|
type: 'chest',
|
||||||
|
data: chest,
|
||||||
|
})
|
||||||
|
await dRecordChest.save()
|
||||||
|
await ActivityChest.deleteOne({ _id: chest.id })
|
||||||
|
}
|
||||||
|
console.timeEnd('delete')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
process.exit(0)
|
||||||
|
})()
|
94
src/repairredis.ts
Normal file
94
src/repairredis.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import mongoose from 'mongoose'
|
||||||
|
import * as dotenv from 'dotenv'
|
||||||
|
|
||||||
|
const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development'
|
||||||
|
dotenv.config({ path: envFile })
|
||||||
|
console.log(process.env.DB_MAIN)
|
||||||
|
import { ActivityChest } from 'models/ActivityChest'
|
||||||
|
import { ScoreRecord } from 'models/ScoreRecord'
|
||||||
|
import { DeleteRecord } from 'models/DeleteRecord'
|
||||||
|
import { rankKey, updateRank, updateRankInvite } from 'services/rank.svr'
|
||||||
|
import { ZRedisClient } from 'zutils'
|
||||||
|
import { RANK_SCORE_SCALE } from 'common/Constants'
|
||||||
|
const db = mongoose.connection
|
||||||
|
|
||||||
|
const totalKey = 'uaw_activity:score'
|
||||||
|
const keyInvite = `uaw_activity:invite`
|
||||||
|
|
||||||
|
const updateRedis = async (activity, user, score) => {
|
||||||
|
await updateRank(totalKey, score, user)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateRedisInvite = async (activity, sourceUser, user, score) => {
|
||||||
|
await updateRankInvite(keyInvite, parseInt(score * RANK_SCORE_SCALE + ''), `${sourceUser}_${user}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateRedis2 = (key, vals) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
new ZRedisClient().pub.zadd(key, vals, function (err, res) {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
} else {
|
||||||
|
resolve(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
return false
|
||||||
|
try {
|
||||||
|
let records = await ScoreRecord.aggregate([{ $group: { _id: '$user', count: { $sum: '$score' } } }])
|
||||||
|
console.time('first')
|
||||||
|
// _id, count
|
||||||
|
console.log('records: ', records.length)
|
||||||
|
let opts = { url: process.env.REDIS }
|
||||||
|
new ZRedisClient(opts)
|
||||||
|
let vals = []
|
||||||
|
for (let i = 0, l = records.length; i < l; i++) {
|
||||||
|
vals.push(records[i].count * 100 + 1 - Date.now() / 1000 / 10000000000)
|
||||||
|
vals.push(records[i]._id)
|
||||||
|
if (i++ % 1000 === 0) {
|
||||||
|
await updateRedis2(totalKey, vals)
|
||||||
|
vals.length = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vals.length > 0) {
|
||||||
|
await updateRedis2(totalKey, vals)
|
||||||
|
}
|
||||||
|
console.timeEnd('first')
|
||||||
|
let records2 = await ScoreRecord.aggregate([
|
||||||
|
{ $match: { type: 'invite_rebate' } },
|
||||||
|
{
|
||||||
|
$group: {
|
||||||
|
_id: {
|
||||||
|
user: '$user',
|
||||||
|
from: '$data.fromUser',
|
||||||
|
},
|
||||||
|
count: { $sum: '$score' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
console.time('second')
|
||||||
|
// _id, count
|
||||||
|
console.log('records2: ', records2.length)
|
||||||
|
let vals2 = []
|
||||||
|
for (let i = 0, l = records.length; i < l; i++) {
|
||||||
|
vals2.push(records[i].count * 100)
|
||||||
|
vals2.push(`${records[i]._id.from}_${records[i]._id.user}`)
|
||||||
|
if (i++ % 1000 === 0) {
|
||||||
|
await updateRedis2(keyInvite, vals2)
|
||||||
|
vals2.length = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vals2.length > 0) {
|
||||||
|
await updateRedis2(keyInvite, vals2)
|
||||||
|
}
|
||||||
|
console.timeEnd('second')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
console.log('end')
|
||||||
|
process.exit(0)
|
||||||
|
})()
|
@ -68,7 +68,7 @@ export const updateRankScore = async ({
|
|||||||
* @param score
|
* @param score
|
||||||
* @param member
|
* @param member
|
||||||
*/
|
*/
|
||||||
const updateRank = async (key: string, score: number, member: string) => {
|
export const updateRank = async (key: string, score: number, member: string) => {
|
||||||
let scoreSaved = (await new ZRedisClient().zscore(key, member)) + ''
|
let scoreSaved = (await new ZRedisClient().zscore(key, member)) + ''
|
||||||
if (scoreSaved) {
|
if (scoreSaved) {
|
||||||
scoreSaved = scoreSaved.substring(0, scoreSaved.indexOf('.'))
|
scoreSaved = scoreSaved.substring(0, scoreSaved.indexOf('.'))
|
||||||
@ -76,10 +76,12 @@ const updateRank = async (key: string, score: number, member: string) => {
|
|||||||
let scoreOld = parseInt(scoreSaved || '0')
|
let scoreOld = parseInt(scoreSaved || '0')
|
||||||
score = score * RANK_SCORE_SCALE + scoreOld
|
score = score * RANK_SCORE_SCALE + scoreOld
|
||||||
const scoreToSave = score + 1 - Date.now() / 1000 / 10000000000
|
const scoreToSave = score + 1 - Date.now() / 1000 / 10000000000
|
||||||
|
let vals = ['1', '2']
|
||||||
|
new ZRedisClient().pub.zadd(...vals)
|
||||||
await new ZRedisClient().zadd(key, scoreToSave, member)
|
await new ZRedisClient().zadd(key, scoreToSave, member)
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateRankInvite = async (key: string, score: number, member: string) => {
|
export const updateRankInvite = async (key: string, score: number, member: string) => {
|
||||||
await new ZRedisClient().zincrby(key, score, member)
|
await new ZRedisClient().zincrby(key, score, member)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user