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 mongoose from 'mongoose' import { ActivityUser } from 'models/ActivityUser' import { ScoreRecord } from 'models/ScoreRecord' import { ZRedisClient } from 'zutils' import { formatNumShow } from 'common/Utils' import { RANK_SCORE_SCALE } from 'common/Constants' import { InGameScoreRecord } from 'models/InGameScoreRecord' import { DeleteRecord } from 'models/DeleteRecord' import { Types } from 'mongoose' import { InGameStats } from 'models/InGameStats' import { NFTHolderRecord } from 'models/NFTHodlerRecord' let fs = require('fs') /** * 生成积分明细 */ mongoose.set('debug', false) const ACTIVITY = 'uaw_activity' const totalKey = 'uaw_activity:static:score' const gameTotalKey = 'uaw_activity:static:gamescore' const releationKey = `uaw_score_invite_rebate` const pageSize = 100 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) } }) }) } const saveScoreToRedis = async () => { let records = await ScoreRecord.aggregate([{ $group: { _id: '$user', count: { $sum: '$score' } } }]) let vals = [] for (let i = 0, l = records.length; i < l; i++) { if (records[i].count == 0) { continue } vals.push((records[i].count * RANK_SCORE_SCALE) | 0) vals.push(records[i]._id) if (i % 1000 === 0) { await updateRedis2(totalKey, vals) vals.length = 0 } } if (vals.length > 0) { await updateRedis2(totalKey, vals) } } const saveTypeScoreToRedis = async (type: string) => { const key = `uaw_score_${type}` await new ZRedisClient().del(key) let records = await ScoreRecord.aggregate([ { $match: { type } }, { $group: { _id: '$user', count: { $sum: '$score' } } }, ]) let vals = [] for (let i = 0, l = records.length; i < l; i++) { if (records[i].count == 0) { continue } vals.push((records[i].count * RANK_SCORE_SCALE) | 0) vals.push(records[i]._id) if (i % 1000 === 0) { await updateRedis2(key, vals) vals.length = 0 } } if (vals.length > 0) { await updateRedis2(key, vals) } } const generateScoreList = async (start: number) => { let end = start + pageSize const records = await new ZRedisClient().zrevrange(totalKey, start, end) let results = [] for (let i = 0; i < records.length; i += 2) { const id = records[i] let score = formatNumShow(parseInt(records[i + 1]) / RANK_SCORE_SCALE) const releatScore = await new ZRedisClient().zscore(releationKey, id) const releatScoreShow = formatNumShow(releatScore ? parseInt(releatScore + '') / RANK_SCORE_SCALE : 0) const user = await ActivityUser.findById(id) const rank = start + i / 2 + 1 results.push( `${rank}\t${user?.address}\t${score}\t${releatScoreShow}\t${holderMap.get(user?.address.toLowerCase()) || 1}\t${founderSet.has(user.address) ? 1 : 0}\t${explorerSet.has(user.address) ? 1 : 0}\t${badgeSet.has(user.address) ? 1 : 0}\t${candySet.has(user.address) ? 1 : 0}`, ) } fs.writeFileSync('outdatas/scorelist.txt', results.join('\n') + '\n', { flag: 'a+' }) } const saveGameScoreToRedis = async () => { let records = await InGameScoreRecord.aggregate([{ $group: { _id: '$user', count: { $sum: '$score' } } }]) let vals = [] for (let i = 0, l = records.length; i < l; i++) { if (records[i].count == 0) { continue } vals.push((records[i].count * 100) | 0) vals.push(records[i]._id) if (i % 1000 === 0) { await updateRedis2(gameTotalKey, vals) vals.length = 0 } } if (vals.length > 0) { await updateRedis2(gameTotalKey, vals) } } const generateGameScoreList = async (start: number) => { let end = start + pageSize // const records = await new ZRedisClient().zrevrange(gameTotalKey, start, end) const records = await InGameStats.find({ score: { $gt: 0 } }) .sort({ score: -1 }) .skip(start) .limit(pageSize) let results = [] for (let i = 0; i < records.length; i++) { let score = records[i].score if (score === 0) { continue } let address = '' const user = await ActivityUser.findById(records[i].user) if (!user) { const userDel = await DeleteRecord.findOne({ 'data._id': new Types.ObjectId(records[i].user) }) if (userDel) { address = userDel.data.address } } else { address = user.address } const rank = start + i + 1 results.push(`${rank}\t${address}\t${score}`) } fs.writeFileSync('outdatas/gameScorelist.txt', results.join('\n') + '\n', { flag: 'a+' }) } const generateWhiteList = async () => { let records = await ActivityUser.find({ whiteListNum: { $gt: 0 } }) let results = [] for (let i = 0; i < records.length; i++) { results.push(`${records[i].address} \t ${records[i].whiteListNum}`) } let records2 = await DeleteRecord.find({ 'data.whiteListNum': { $gt: 0 } }) for (let i = 0; i < records2.length; i++) { results.push(`${records2[i].data.address} \t ${records2[i].data.whiteListNum}`) } fs.writeFileSync('outdatas/whitelist.txt', results.join('\n') + '\n', { flag: 'a+' }) } const holders = [ ['explorer', '0x0cee888fa25810ca648d697099bc17a2c9e1dfbf', 1.5], ['candy', '0xefd4c863e73e7e9cc33d46fb30ce51510fcfdeb0', 1.5], ['badge', '0xd728de3d9ebed90e84abe84539280cbc5b18e304', 2], ['founder', '0xec23679653337d4c6390d0eeba682246a6067777', 3], ] const holderMap = new Map() let explorerSet = new Set() let candySet = new Set() let badgeSet = new Set() let founderSet = new Set() const queryHolder = async () => { for (let holder of holders) { const [name, contract] = holder let records = await NFTHolderRecord.find({ contract: contract + '' }) for (let i = 0; i < records.length; i++) { const uid = records[i].user let user = await ActivityUser.findById(uid) if (!user) { continue } let address = user.address.toLowerCase() if (name === 'explorer') { explorerSet.add(address) } else if (name === 'candy') { candySet.add(address) } else if (name === 'badge') { badgeSet.add(address) } else if (name === 'founder') { founderSet.add(address) } if (!holderMap.has(address)) { holderMap.set(address, 1) } holderMap.set(address, holderMap.get(address) * parseFloat(holder[2] + '')) } } } ;(async () => { try { let opts = { url: process.env.REDIS } new ZRedisClient(opts) await new ZRedisClient().del(totalKey) // await new ZRedisClient().del(gameTotalKey) console.time('update redis') await saveScoreToRedis() console.timeEnd('update redis') console.time('query holder info') await queryHolder() console.timeEnd('query holder info') console.time('update releation redis') await saveTypeScoreToRedis('invite_rebate') console.timeEnd('update releation redis') console.time('generate score list') const total = (await new ZRedisClient().zcard(totalKey)) as number for (let i = 0; i < total; i += pageSize) { await generateScoreList(i) } console.timeEnd('generate score list') // console.time('update game redis') // await saveGameScoreToRedis() // console.timeEnd('update game redis') // console.time('generate game score list') // const totalGame = (await new ZRedisClient().zcard(gameTotalKey)) as number // const totalGame = await InGameStats.countDocuments({ score: { $gt: 0 } }) // for (let i = 0; i < totalGame; i += pageSize) { // await generateGameScoreList(i) // } // console.timeEnd('generate game score list') // console.time('generate white list') // await generateWhiteList() // console.timeEnd('generate white list') } catch (e) { console.log(e) } console.log('end') process.exit(0) })()