From 43ff417a2cdcd0bda29805b26db18d60a4cb0dae Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:07:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8A=A9=E5=8A=9B=E5=92=8C?= =?UTF-8?q?=E7=AD=BE=E5=88=B0=E6=8E=A5=E5=8F=A3=E4=B8=80=E4=BA=9B=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/uaw.md | 18 +++++++- package.json | 1 + src/checkredis.ts | 67 +++++++++++++++++++++++++++++ src/common/Utils.ts | 5 +++ src/controllers/chest.controller.ts | 3 +- src/controllers/game.controller.ts | 39 ++++++++++++----- src/repairredis.ts | 5 +-- 7 files changed, 123 insertions(+), 15 deletions(-) create mode 100644 src/checkredis.ts diff --git a/docs/uaw.md b/docs/uaw.md index b1f7293..ebc4f4e 100644 --- a/docs/uaw.md +++ b/docs/uaw.md @@ -55,6 +55,11 @@ #### 20240416 1. 增加接口: 兑换宝箱激活码(30) +#### 20240423 +1. 签到列表接口(11)增加返回字段: 是否已领取奖励 +1. 检查签到并领取奖励(23), 增加post参数, 可以领取指定天数的奖励 +1. 宝箱助力(18), 增加返回scoreBonus, 表示当前宝箱已得到的助力积分 + ### 1. 钱包预登录 #### Request @@ -387,7 +392,8 @@ query param "day": "20240105", // 格式化后签到日期, 时区按SG(UTC+8) "time": 1704436745, // 具体的签到时间 "count": 0, //连签天数 - "total": 10 //累计签到天数 + "total": 10, //累计签到天数 + "claimed": true, // 当日签到奖励是否已领取 }, ] ``` @@ -587,6 +593,7 @@ body: ```js { score: 100, // 自己获得的积分 + scoreBonus: 1 //当前箱子已助力积分 } ``` @@ -693,6 +700,15 @@ body: - 头部: - Authorization: Bearer JWT_token +body: + +```js +{ + "day": "20240418" //需要领取的天数, 该字段为空的话, 领取当日的 +} + +``` + #### Response ```js diff --git a/package.json b/package.json index 878caff..64293f9 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "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", + "checkredis": "ts-node -r tsconfig-paths/register src/checkredis.ts", "test:watch": "jest --watch", "test": "jest" }, diff --git a/src/checkredis.ts b/src/checkredis.ts new file mode 100644 index 0000000..9e734ee --- /dev/null +++ b/src/checkredis.ts @@ -0,0 +1,67 @@ +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 () => { + 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++) { + const score = parseInt(records[i].count * 100 + '') + let totalScoreStr = await new ZRedisClient().zscore(totalKey, records[i]._id) + let totalScore = parseInt(totalScoreStr + '') + if (score != totalScore) { + if (Math.abs(score - totalScore) > 1) { + console.log(`user: ${records[i]._id}, score: ${score}, redis: ${totalScore}`) + await new ZRedisClient().zincrby(totalKey, score - totalScore, records[i]._id) + } + } + if (i % 1000 === 0) { + console.log(i) + } + } + console.timeEnd('first') + } catch (e) { + console.log(e) + } + console.log('end') + process.exit(0) +})() diff --git a/src/common/Utils.ts b/src/common/Utils.ts index 961313d..bcfbfae 100644 --- a/src/common/Utils.ts +++ b/src/common/Utils.ts @@ -15,6 +15,11 @@ export const isValidVoucherCode = (str: string) => { let reg = new RegExp(`^[${BASE52_ALPHABET}]{12}$`) return reg.test(str) } +// check if a string is a valid day tag, like 20240408 +export const isValidDayTag = (str: string) => { + return /^[0-9]{8}$/.test(str) +} + export const formatNumShow = (num: number) => { if (num >= 10) { return Math.round(num) + '' diff --git a/src/controllers/chest.controller.ts b/src/controllers/chest.controller.ts index c584995..75d6880 100644 --- a/src/controllers/chest.controller.ts +++ b/src/controllers/chest.controller.ts @@ -249,7 +249,7 @@ class BoxController extends BaseController { throw new ZError(16, 'user enhance times exceed') } const score = chest.bounsCfg[chest.bonusUsers.length] || chest.bounsCfg[chest.bounsCfg.length - 1] - await ActivityChest.updateOne( + let doc = await ActivityChest.findOneAndUpdate( { _id: chest.id }, { $inc: { scoreBonus: score }, @@ -278,6 +278,7 @@ class BoxController extends BaseController { }) return { score: ENHANCE_CHEST_GIFT, + scoreBonus: doc.scoreBonus, } // const chestsForUser = await ActivityChest.find({ user: uid, activity: user.activity }) // 如果用户没有宝箱, 则说明用户是新用户, 生成一个宝箱 diff --git a/src/controllers/game.controller.ts b/src/controllers/game.controller.ts index 63d14f5..d6e4cf1 100644 --- a/src/controllers/game.controller.ts +++ b/src/controllers/game.controller.ts @@ -11,7 +11,7 @@ import { ExploreRecord } from 'models/ExploreRecord' import { isObjectId } from 'zutils/utils/string.util' import { GeneralScription } from 'models/chain/GeneralScription' import { CheckIn } from 'models/chain/CheckIn' -import { formatNumShow } from 'common/Utils' +import { formatNumShow, isValidDayTag } from 'common/Utils' import logger from 'logger/logger' /** @@ -27,14 +27,26 @@ class GameController extends BaseController { logger.db('checkin', req) const user = req.user const { address } = user - const dateTag = formatDate(new Date()) + let { day } = req.params + if (day) { + if (!isValidDayTag(day)) { + throw new ZError(11, 'invalid day') + } + } + const dateTag = day || formatDate(new Date()) + const ticketRecordExists = await TicketRecord.findOne({ + user: user.id, + activity: user.activity, + type: DAILY_SIGN, + 'data.dataTag': dateTag, + }) + if (ticketRecordExists) { + throw new ZError(12, 'already claimed') + } const gameRecord = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {}) if (MANUAL_OPEN_GAME && gameRecord.status === 0) { throw new ZError(11, 'map not open') } - if (dateTag === gameRecord.lastSignDay) { - throw new ZError(12, 'already claimed') - } const record = await checkInToday(address, dateTag) if (!record) { throw new ZError(13, 'had not check in') @@ -43,13 +55,10 @@ class GameController extends BaseController { user: user.id, activity: user.activity, type: DAILY_SIGN, - data: {}, + data: { dataTag: dateTag }, score: 1, }) - await ActivityGame.updateOne( - { user: user.id, activity: user.activity }, - { lastSignDay: dateTag, $inc: { tickets: 1 } }, - ) + await ActivityGame.updateOne({ user: user.id, activity: user.activity }, { $inc: { tickets: 1 } }) await ticketRecord.save() return { ticket: 1 } } @@ -73,6 +82,16 @@ class GameController extends BaseController { days = Math.floor((now - start) / 86400000) } const res = await queryCheckInList(user.address.toLowerCase(), days, 0) + const ticketRecords = await TicketRecord.find({ user: user.id, activity: user.activity, type: DAILY_SIGN }) + const claimedSet = new Set() + ticketRecords.forEach(record => { + // @ts-ignore + let dateTag = record.data?.dateTag || formatDate(record.createdAt) + claimedSet.add(dateTag) + }) + for (let record of res) { + record.claimed = claimedSet.has(record.day) + } return res } /** diff --git a/src/repairredis.ts b/src/repairredis.ts index 2210ac7..2b33711 100644 --- a/src/repairredis.ts +++ b/src/repairredis.ts @@ -36,7 +36,6 @@ const updateRedis2 = (key, vals) => { } ;(async () => { - return false try { let records = await ScoreRecord.aggregate([{ $group: { _id: '$user', count: { $sum: '$score' } } }]) console.time('first') @@ -48,7 +47,7 @@ const updateRedis2 = (key, 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) { + if (i % 1000 === 0) { await updateRedis2(totalKey, vals) vals.length = 0 } @@ -77,7 +76,7 @@ const updateRedis2 = (key, vals) => { 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) { + if (i % 1000 === 0) { await updateRedis2(keyInvite, vals2) vals2.length = 0 }