增加活动和挑战奖励的发放
This commit is contained in:
parent
de3d850c62
commit
bf6028c934
@ -97,7 +97,14 @@
|
|||||||
"timeLeft": 1, // 当局剩余时间
|
"timeLeft": 1, // 当局剩余时间
|
||||||
"gameResult": 0 // 当局的游戏结果, 单人的话和上一层gameResult相同
|
"gameResult": 0 // 当局的游戏结果, 单人的话和上一层gameResult相同
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"rewards": [{
|
||||||
|
coupon: '优惠券的id',
|
||||||
|
name: '优惠券名',
|
||||||
|
count: 1, //数量
|
||||||
|
couponUrl: '优惠券详情图的url',
|
||||||
|
ids: ['获取记录的短id']
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
### 3. 开始匹配
|
### 3. 开始匹配
|
||||||
|
@ -13,7 +13,8 @@ import {
|
|||||||
transformRecord,
|
transformRecord,
|
||||||
updateExamRank
|
updateExamRank
|
||||||
} from '../../services/GameLogic'
|
} from '../../services/GameLogic'
|
||||||
import { validShopId } from '../../models/shop/Shop'
|
import { Shop, validShopId } from '../../models/shop/Shop'
|
||||||
|
import { UserReward } from '../../models/UserReward'
|
||||||
|
|
||||||
class ExamController extends BaseController {
|
class ExamController extends BaseController {
|
||||||
@role('anon')
|
@role('anon')
|
||||||
@ -34,6 +35,11 @@ class ExamController extends BaseController {
|
|||||||
}
|
}
|
||||||
let params = {}
|
let params = {}
|
||||||
let results: any[] = []
|
let results: any[] = []
|
||||||
|
let shopData = await Shop.fetchByID(shop)
|
||||||
|
if (!shopData) {
|
||||||
|
throw new ZError(13, 'shop not found')
|
||||||
|
}
|
||||||
|
shop = shopData.id
|
||||||
let history = new PuzzleSession({ shop, level: 0})
|
let history = new PuzzleSession({ shop, level: 0})
|
||||||
if (record.source === 0) {
|
if (record.source === 0) {
|
||||||
if (record.qtypes && record.qtypes.length > 0) {
|
if (record.qtypes && record.qtypes.length > 0) {
|
||||||
@ -141,8 +147,23 @@ class ExamController extends BaseController {
|
|||||||
rspData.rankList = rankList
|
rspData.rankList = rankList
|
||||||
rspData.userRank = userRank
|
rspData.userRank = userRank
|
||||||
rspData.rankTotal = rankTotal
|
rspData.rankTotal = rankTotal
|
||||||
|
let examData = await ShopExam.findById(history.activityId)
|
||||||
|
let rewardList = []
|
||||||
|
if (!examData && examData.rewardInfo && examData.rewardInfo.length > 0) {
|
||||||
|
let rewards = examData.getReward(statMap.score)
|
||||||
|
for (let reward of rewards) {
|
||||||
|
let geted = await UserReward.examRewardGeted(history, accountid, reward.id)
|
||||||
|
if (geted) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const data = await UserReward.addOneRecord(history, accountid, reward.id, reward.coupon, reward.count)
|
||||||
|
rewardList.push(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rspData.rewords = rewardList
|
||||||
}
|
}
|
||||||
rspData.gameResult = gameResult
|
rspData.gameResult = gameResult
|
||||||
|
rspData.rewords = {}
|
||||||
return rspData
|
return rspData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import {
|
|||||||
updateSingleRank
|
updateSingleRank
|
||||||
} from '../../services/GameLogic'
|
} from '../../services/GameLogic'
|
||||||
import { Shop, validShopId } from '../../models/shop/Shop'
|
import { Shop, validShopId } from '../../models/shop/Shop'
|
||||||
|
import { ShopActivity } from '../../models/shop/ShopActivity'
|
||||||
|
|
||||||
|
|
||||||
class PuzzleController extends BaseController {
|
class PuzzleController extends BaseController {
|
||||||
@ -57,7 +58,7 @@ class PuzzleController extends BaseController {
|
|||||||
}
|
}
|
||||||
const cfg = fetchLevelCfg(level)
|
const cfg = fetchLevelCfg(level)
|
||||||
let params = {}
|
let params = {}
|
||||||
let typeArr = await fetchSinglePuzzleType({shopId: shop, levelCfg: cfg})
|
let { shopId, typeArr } = await fetchSinglePuzzleType({shopId: shop, levelCfg: cfg})
|
||||||
if (typeArr?.length > 0) {
|
if (typeArr?.length > 0) {
|
||||||
params = {$or: [{tag: {$in: typeArr}}, {sub_tag: {$in: typeArr}}]}
|
params = {$or: [{tag: {$in: typeArr}}, {sub_tag: {$in: typeArr}}]}
|
||||||
}
|
}
|
||||||
@ -65,7 +66,7 @@ class PuzzleController extends BaseController {
|
|||||||
let record2 = await Puzzle.randomQuestions(Object.assign(params, {quality: 2}), 5)
|
let record2 = await Puzzle.randomQuestions(Object.assign(params, {quality: 2}), 5)
|
||||||
let record3 = await Puzzle.randomQuestions(Object.assign(params, {quality: 3}), 5)
|
let record3 = await Puzzle.randomQuestions(Object.assign(params, {quality: 3}), 5)
|
||||||
const records = (record1.concat(record2)).concat(record3)
|
const records = (record1.concat(record2)).concat(record3)
|
||||||
let history = new PuzzleSession({ shop, level })
|
let history = new PuzzleSession({ shop: shopId, level })
|
||||||
history.members.set(accountid, new PuzzleStatusClass())
|
history.members.set(accountid, new PuzzleStatusClass())
|
||||||
for (let record of records) {
|
for (let record of records) {
|
||||||
history.questions.set(record.id, record.a1)
|
history.questions.set(record.id, record.a1)
|
||||||
@ -203,7 +204,7 @@ class PuzzleController extends BaseController {
|
|||||||
@role('anon')
|
@role('anon')
|
||||||
@router('post /api/:accountid/puzzle/match')
|
@router('post /api/:accountid/puzzle/match')
|
||||||
async joinMultipleGame(req, res) {
|
async joinMultipleGame(req, res) {
|
||||||
const { shop, aid, accountid, debug_begin_sec, debug_qcount } = req.params
|
let { shop, aid, accountid, debug_begin_sec, debug_qcount } = req.params
|
||||||
let data: any = { shop, maxTime: 3600, accountid }
|
let data: any = { shop, maxTime: 3600, accountid }
|
||||||
let beginSecond = (debug_begin_sec ? +debug_begin_sec : 20)
|
let beginSecond = (debug_begin_sec ? +debug_begin_sec : 20)
|
||||||
beginSecond = (Math.max(2, beginSecond)) * 1000
|
beginSecond = (Math.max(2, beginSecond)) * 1000
|
||||||
@ -213,12 +214,19 @@ class PuzzleController extends BaseController {
|
|||||||
* 如果没有人请求, 说明没人参加, 也没必要开启定时了
|
* 如果没有人请求, 说明没人参加, 也没必要开启定时了
|
||||||
* TODO:: 读取店铺活动配置
|
* TODO:: 读取店铺活动配置
|
||||||
*/
|
*/
|
||||||
let activityId = '1111111'
|
|
||||||
|
|
||||||
let roomId = ''
|
let roomId = ''
|
||||||
let sessionId = ''
|
let sessionId = ''
|
||||||
let sessionMatch = ''
|
let sessionMatch = ''
|
||||||
let beginTime = 0
|
let beginTime = 0
|
||||||
|
if (!aid) {
|
||||||
|
throw new ZError(12, 'params no match')
|
||||||
|
}
|
||||||
|
let activity = await ShopActivity.findById(aid)
|
||||||
|
let shopData = await Shop.fetchByID(shop)
|
||||||
|
shop = shopData.id
|
||||||
|
if (!activity) {
|
||||||
|
throw new ZError(13, 'activity not found')
|
||||||
|
}
|
||||||
let result = new RoomState().isLock(shop)
|
let result = new RoomState().isLock(shop)
|
||||||
try {
|
try {
|
||||||
await retry<Promise<string>>(async () => {
|
await retry<Promise<string>>(async () => {
|
||||||
@ -226,7 +234,7 @@ class PuzzleController extends BaseController {
|
|||||||
throw new RoomLockErr('')
|
throw new RoomLockErr('')
|
||||||
}
|
}
|
||||||
new RoomState().lock(shop)
|
new RoomState().lock(shop)
|
||||||
let history = await PuzzleSession.findOne({ shop, status: {$in: [0, 1]}, type: 1 })
|
let history = await PuzzleSession.findOne({ shop, status: {$in: [0, 1]}, type: 1, activityId: aid })
|
||||||
if (history) {
|
if (history) {
|
||||||
// if (history && !history.hasExpired()) {
|
// if (history && !history.hasExpired()) {
|
||||||
beginTime = history.begin
|
beginTime = history.begin
|
||||||
@ -261,6 +269,7 @@ class PuzzleController extends BaseController {
|
|||||||
roomId = rsp.data?.room?.roomId
|
roomId = rsp.data?.room?.roomId
|
||||||
sessionId = rsp.data?.sessionId
|
sessionId = rsp.data?.sessionId
|
||||||
history = new PuzzleSession({shop, status: 0, type: 1})
|
history = new PuzzleSession({shop, status: 0, type: 1})
|
||||||
|
history.activityId = aid
|
||||||
let memberData = new PuzzleStatusClass()
|
let memberData = new PuzzleStatusClass()
|
||||||
memberData.sessionId = sessionId
|
memberData.sessionId = sessionId
|
||||||
history.members.set(accountid, memberData)
|
history.members.set(accountid, memberData)
|
||||||
|
@ -10,6 +10,7 @@ import { customAlphabet, } from 'nanoid'
|
|||||||
import { Shop } from './shop/Shop'
|
import { Shop } from './shop/Shop'
|
||||||
import { Coupon } from './shop/Coupon'
|
import { Coupon } from './shop/Coupon'
|
||||||
import { getCouponUrl } from '../services/File'
|
import { getCouponUrl } from '../services/File'
|
||||||
|
import { PuzzleSessionClass } from './match/PuzzleSession'
|
||||||
|
|
||||||
const nanoid = customAlphabet('2345678abcdefghjkmnpqrstwxy', 10)
|
const nanoid = customAlphabet('2345678abcdefghjkmnpqrstwxy', 10)
|
||||||
|
|
||||||
@ -60,6 +61,9 @@ class UserRewardClass extends BaseModule {
|
|||||||
@prop()
|
@prop()
|
||||||
public coupon: string
|
public coupon: string
|
||||||
|
|
||||||
|
@prop()
|
||||||
|
public rewardId: string
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
* 0: 未使用
|
* 0: 未使用
|
||||||
@ -102,6 +106,50 @@ class UserRewardClass extends BaseModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public compactInfo() {
|
||||||
|
return {
|
||||||
|
id: this.sid,
|
||||||
|
couponUrl: getCouponUrl(this.sid, this.coupon),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async addOneRecord(history: PuzzleSessionClass, accountId: string, rewardId: string, coupon: string, count: number, ) {
|
||||||
|
let ids: string[] = []
|
||||||
|
let cdata = await Coupon.findById(coupon)
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
let record = new UserReward({
|
||||||
|
accountId,
|
||||||
|
shop: history.shop,
|
||||||
|
sessionId: history._id,
|
||||||
|
status: 0,
|
||||||
|
rewardId
|
||||||
|
})
|
||||||
|
if (history.type === 1) {
|
||||||
|
record.activityId = history.activityId
|
||||||
|
}
|
||||||
|
await record.save()
|
||||||
|
ids.push(record.sid)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
coupon,
|
||||||
|
name: cdata.name,
|
||||||
|
count,
|
||||||
|
couponUrl: getCouponUrl(history.shop, coupon),
|
||||||
|
ids
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查挑战的奖励是否已领取
|
||||||
|
* @param {PuzzleSessionClass} history
|
||||||
|
* @param {string} accountId
|
||||||
|
* @param rewardId
|
||||||
|
* @return {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
public static async examRewardGeted(history: PuzzleSessionClass, accountId: string, rewardId: string) {
|
||||||
|
let records = await UserReward.find({accountId, examId: history.activityId, rewardId, shop: history.shop}, {_id: 1}).limit(1)
|
||||||
|
return records.length > 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UserReward = getModelForClass(UserRewardClass, {existingConnection: UserRewardClass.db})
|
export const UserReward = getModelForClass(UserRewardClass, {existingConnection: UserRewardClass.db})
|
||||||
|
@ -9,8 +9,9 @@ import { noJson } from '../../decorators/nojson'
|
|||||||
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { GameEnv } from '../../config/GameEnv'
|
import { GameEnv } from '../../config/GameEnv'
|
||||||
|
import { Base } from '@typegoose/typegoose/lib/defaultClasses'
|
||||||
|
|
||||||
export class ActivityRewardClass {
|
export class ActivityRewardClass extends Base{
|
||||||
@prop()
|
@prop()
|
||||||
public id: number
|
public id: number
|
||||||
@prop()
|
@prop()
|
||||||
@ -172,6 +173,24 @@ export class ShopActivityClass extends BaseModule {
|
|||||||
result.next = getNextTime(record, result.current)
|
result.next = getNextTime(record, result.current)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据排名获取奖励
|
||||||
|
* @param {number} rank
|
||||||
|
* @return {null | {count: number, id: string}}
|
||||||
|
*/
|
||||||
|
public getReward(rank: number) {
|
||||||
|
if (!this.rewardInfo || this.rewardInfo.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
this.rewardInfo.sort((a, b) => a.rank - b.rank)
|
||||||
|
for (let reward of this.rewardInfo) {
|
||||||
|
if (rank < reward.rank || (reward.rankEnd && rank < reward.rankEnd)) {
|
||||||
|
return {id: reward._id + '', coupon:reward.coupon, count: reward.count}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShopActivity = getModelForClass(ShopActivityClass, { existingConnection: ShopActivityClass.db })
|
export const ShopActivity = getModelForClass(ShopActivityClass, { existingConnection: ShopActivityClass.db })
|
||||||
|
@ -8,6 +8,7 @@ import { BaseModule } from '../Base'
|
|||||||
import { noJson } from '../../decorators/nojson'
|
import { noJson } from '../../decorators/nojson'
|
||||||
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||||
import { Base } from '@typegoose/typegoose/lib/defaultClasses'
|
import { Base } from '@typegoose/typegoose/lib/defaultClasses'
|
||||||
|
import { UserReward } from '../UserReward'
|
||||||
|
|
||||||
export class ShopPuzzleClass extends Base{
|
export class ShopPuzzleClass extends Base{
|
||||||
@prop()
|
@prop()
|
||||||
@ -22,7 +23,7 @@ export class ShopPuzzleClass extends Base{
|
|||||||
public a4: string
|
public a4: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExamRewardClass {
|
export class ExamRewardClass extends Base{
|
||||||
@prop()
|
@prop()
|
||||||
public id: number
|
public id: number
|
||||||
@prop()
|
@prop()
|
||||||
@ -179,6 +180,19 @@ export class ShopExamClass extends BaseModule {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
public getReward(score: number) {
|
||||||
|
if (!this.rewardInfo || this.rewardInfo.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
this.rewardInfo.sort((a, b) => a.rank - b.rank)
|
||||||
|
let results = []
|
||||||
|
for (let reward of this.rewardInfo) {
|
||||||
|
if (score >= reward.rank) {
|
||||||
|
results.push({id: reward._id + '', coupon:reward.coupon, count: reward.count})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShopExam = getModelForClass(ShopExamClass, { existingConnection: ShopExamClass.db })
|
export const ShopExam = getModelForClass(ShopExamClass, { existingConnection: ShopExamClass.db })
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
beginGame,
|
beginGame,
|
||||||
endGame,
|
endGame, sendMsg,
|
||||||
sendQuestion,
|
sendQuestion,
|
||||||
updateRound,
|
updateRound,
|
||||||
updateScore
|
updateScore
|
||||||
@ -16,6 +16,7 @@ import { mission_vo } from '../config/parsers/mission_vo'
|
|||||||
import { ShopActivity } from '../models/shop/ShopActivity'
|
import { ShopActivity } from '../models/shop/ShopActivity'
|
||||||
import { getAccountRank, getRankCount, getRankList, updateRank } from './Rank'
|
import { getAccountRank, getRankCount, getRankList, updateRank } from './Rank'
|
||||||
import { PuzzleRank } from '../models/match/PuzzleRank'
|
import { PuzzleRank } from '../models/match/PuzzleRank'
|
||||||
|
import { UserReward } from '../models/UserReward'
|
||||||
|
|
||||||
|
|
||||||
export function transformRecord(records: any[]) {
|
export function transformRecord(records: any[]) {
|
||||||
@ -64,7 +65,12 @@ export function checkSubFinish(history: any, qid: string) {
|
|||||||
*/
|
*/
|
||||||
export async function startGame(roomId: string, sessionId: string) {
|
export async function startGame(roomId: string, sessionId: string) {
|
||||||
let history = await PuzzleSession.findById(sessionId)
|
let history = await PuzzleSession.findById(sessionId)
|
||||||
let records = await Puzzle.randomQuestions({status: 1, is_hide: 0, deleted: 0, dp: 1}, history.total)
|
let typeArr = await fetchPvpPuzzleType({shopId: history.shop, aid: history.activityId})
|
||||||
|
let params = {}
|
||||||
|
if (typeArr?.length > 0) {
|
||||||
|
params = {$or: [{tag: {$in: typeArr}}, {sub_tag: {$in: typeArr}}]}
|
||||||
|
}
|
||||||
|
let records = await Puzzle.randomQuestions(params, history.total)
|
||||||
await beginGame(roomId, {})
|
await beginGame(roomId, {})
|
||||||
for (let record of records) {
|
for (let record of records) {
|
||||||
history.questions.set(record.id, record.a1)
|
history.questions.set(record.id, record.a1)
|
||||||
@ -85,6 +91,8 @@ export async function sendOneQuestion(history: any) {
|
|||||||
history.status = 9
|
history.status = 9
|
||||||
await history.save()
|
await history.save()
|
||||||
await endGame(roomId, {closeTime: BaseConst.ROOM_AUTO_CLOSE_TIME})
|
await endGame(roomId, {closeTime: BaseConst.ROOM_AUTO_CLOSE_TIME})
|
||||||
|
//TODO:: 发送奖励
|
||||||
|
await sendReward(history)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const questions:string[] = Array.from(history.questions.keys())
|
const questions:string[] = Array.from(history.questions.keys())
|
||||||
@ -114,6 +122,31 @@ export async function sendOneQuestion(history: any) {
|
|||||||
}, history.scheduleKey)
|
}, history.scheduleKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送活动奖励
|
||||||
|
* @param history
|
||||||
|
* @return {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function sendReward(history: any) {
|
||||||
|
let activity = await ShopActivity.findById(history.activity)
|
||||||
|
if (activity.rewardInfo.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let members = []
|
||||||
|
for (let [ key, val ] of history.members) {
|
||||||
|
members.push({accountId: key, score: val.score, sessionId: val.sessionId})
|
||||||
|
}
|
||||||
|
members.sort((a, b) => a.score - b.score)
|
||||||
|
for (let i = 0, len = members.length; i < len; i++) {
|
||||||
|
const adata = activity.getReward(i)
|
||||||
|
if (!adata) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const data = await UserReward.addOneRecord(history, members[i].accountId, adata.id, adata.coupon, adata.count)
|
||||||
|
await sendMsg(history.room, members[i].sessionId, 'rewords', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function calcExamScore(time: number, combo: number) {
|
export function calcExamScore(time: number, combo: number) {
|
||||||
const cfg = new GameEnv()
|
const cfg = new GameEnv()
|
||||||
return cfg.pvpBaseScore + time / 100 * cfg.pvpTimeRate + combo * cfg.pvpComboRate
|
return cfg.pvpBaseScore + time / 100 * cfg.pvpTimeRate + combo * cfg.pvpComboRate
|
||||||
@ -281,7 +314,7 @@ export async function fetchSinglePuzzleType({shopId, levelCfg} : {shopId: string
|
|||||||
if (typeArr.length === 0 && levelCfg?.keyID) {
|
if (typeArr.length === 0 && levelCfg?.keyID) {
|
||||||
typeArr = levelCfg.keyID.split(':')
|
typeArr = levelCfg.keyID.split(':')
|
||||||
}
|
}
|
||||||
return typeArr
|
return {shopId: shop.id, typeArr}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user