🐞 fix(幸运转盘优化): 修改保底

This commit is contained in:
zhangxk
2023-10-18 21:41:24 +08:00
committed by luying
parent fe55bf8da9
commit 850f6656c7
3 changed files with 99 additions and 75 deletions

View File

@@ -59,11 +59,11 @@ export class LuckyTurntableNewHandler {
let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); let costResult = await handleCost(roleId, sid, cost, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL);
if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH); if (!costResult) return resResult(STATUS.ROLE_MATERIAL_NOT_ENOUGH);
let { result, records, goodResult, pool, floorCount } = playerData.pull(roleName, count); let { result, records, goodResult, pool, floor } = playerData.pull(roleName, count);
await ActivityLuckyModel.updateData(serverId, activityId, roleId, playerData.roundIndex, { ...pick(playerData, ['todayCount', 'count', 'records', 'greatRewardCount']), refTodayCount: new Date() }); await ActivityLuckyModel.updateData(serverId, activityId, roleId, playerData.roundIndex, { ...pick(playerData, ['todayCount', 'count', 'records', 'floorRecord']), refTodayCount: new Date() });
await addItems(roleId, roleName, sid, goodResult, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL); await addItems(roleId, roleName, sid, goodResult, ITEM_CHANGE_REASON.ACT_TURNTABLE_PULL);
return resResult(STATUS.SUCCESS, { result, records, todayCount: playerData.todayCount, count: playerData.count, pool, floorCount }); return resResult(STATUS.SUCCESS, { result, records, todayCount: playerData.todayCount, count: playerData.count, pool, floor });
} }

View File

@@ -12,6 +12,14 @@ export class TurntableRecord {
count: number; count: number;
} }
export class FloorRecord {
@prop({ required: true })
id: number;
@prop({ required: true })
count: number;
}
/** /**
* 幸运转盘活动 * 幸运转盘活动
*/ */
@@ -19,55 +27,58 @@ export class TurntableRecord {
export default class Activity_Lucky_Rec extends BaseModel { export default class Activity_Lucky_Rec extends BaseModel {
@prop({ required: true }) @prop({ required: true })
activityId: number; // 活动id activityId: number; // 活动id
@prop({ required: true }) @prop({ required: true })
serverId: number; // 区id serverId: number; // 区id
@prop({ required: true }) @prop({ required: true })
roleId: string; // 用户id roleId: string; // 用户id
@prop({ required: true }) @prop({ required: true })
roundIndex: number; // 循环次数 roundIndex: number; // 循环次数
@prop({ required: true }) @prop({ required: true })
count: number; // 抽卡次数 count: number; // 抽卡次数
@prop({ required: true }) @prop({ required: true })
greatRewardCount: number; // 中头奖次数 greatRewardCount: number; // 中头奖次数
@prop({ required: true }) @prop({ required: true })
todayCount: number; // 本日抽卡 todayCount: number; // 本日抽卡
@prop({ required: true }) @prop({ required: true })
refTodayCount: Date; // 本日抽卡刷新时间 refTodayCount: Date; // 本日抽卡刷新时间
@prop({ required: true, type: TurntableRecord, _id: false }) @prop({ required: true, type: TurntableRecord, _id: false })
records: TurntableRecord[]; // 本日抽卡刷新时间 records: TurntableRecord[]; // 本日抽卡刷新时间
@prop({ required: true, type: Number }) @prop({ required: true, type: Number })
box: number[]; // 宝箱已领取次数 box: number[]; // 宝箱已领取次数
public static async findByActivityId(serverId: number, activityId: number, roleId: string, roundIndex: number) { @prop({ required: true, type: FloorRecord, _id: false })
let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOne({ roleId, activityId, serverId, roundIndex }).lean(); floorRecord: FloorRecord[]
return rec;
}
public static async updateData(serverId: number, activityId: number, roleId: string, roundIndex: number, update: ActivityLuckyModelTypeParam) { public static async findByActivityId(serverId: number, activityId: number, roleId: string, roundIndex: number) {
let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOneAndUpdate({ roleId, activityId, serverId, roundIndex }, { $set: update }, { upsert: true, new: true }).lean(); let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOne({ roleId, activityId, serverId, roundIndex }).lean();
return rec; return rec;
} }
public static async refreshTodayCount(serverId: number, activityId: number, roleId: string, roundIndex: number) { public static async updateData(serverId: number, activityId: number, roleId: string, roundIndex: number, update: ActivityLuckyModelTypeParam) {
let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOneAndUpdate({ roleId, activityId, serverId, roundIndex }, {$set: { todayCount: 0, refTodayCount: new Date() }}).lean(); let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOneAndUpdate({ roleId, activityId, serverId, roundIndex }, { $set: update }, { upsert: true, new: true }).lean();
return rec; return rec;
} }
public static async receiveBox(serverId: number, activityId: number, roleId: string, roundIndex: number, boxCount: number) { public static async refreshTodayCount(serverId: number, activityId: number, roleId: string, roundIndex: number) {
let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOneAndUpdate({ roleId, activityId, serverId, roundIndex }, {$addToSet: { box: boxCount }}, { new: true }).lean(); let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOneAndUpdate({ roleId, activityId, serverId, roundIndex }, { $set: { todayCount: 0, refTodayCount: new Date() } }).lean();
return rec; return rec;
} }
public static async receiveBox(serverId: number, activityId: number, roleId: string, roundIndex: number, boxCount: number) {
let rec: ActivityLuckyModelType = await ActivityLuckyModel.findOneAndUpdate({ roleId, activityId, serverId, roundIndex }, { $addToSet: { box: boxCount } }, { new: true }).lean();
return rec;
}
} }
export const ActivityLuckyModel = getModelForClass(Activity_Lucky_Rec); export const ActivityLuckyModel = getModelForClass(Activity_Lucky_Rec);

View File

@@ -3,7 +3,7 @@ import { ActivityModelType } from '../../db/Activity';
import { RewardInter } from '../../pubUtils/interface'; import { RewardInter } from '../../pubUtils/interface';
import { getRandEelmWithWeight, parseGoodStr } from '../../pubUtils/util'; import { getRandEelmWithWeight, parseGoodStr } from '../../pubUtils/util';
import { ActivityBase } from './activityField'; import { ActivityBase } from './activityField';
import { ActivityLuckyModelType, TurntableRecord } from '../../db/ActivityLuckyRec'; import { ActivityLuckyModelType, FloorRecord, TurntableRecord } from '../../db/ActivityLuckyRec';
/************** 在数据库中的格式 ***********/ /************** 在数据库中的格式 ***********/
@@ -17,7 +17,6 @@ interface TurntablePoolInDb {
interface TurntableFloorInDb { // 保底每sum次必出count个头奖头奖权重最低的一项 interface TurntableFloorInDb { // 保底每sum次必出count个头奖头奖权重最低的一项
sum: number; sum: number;
count: number;
id: number; id: number;
} }
@@ -81,18 +80,19 @@ export class LuckyData extends ActivityBase {
cost: string; // 抽1次的消耗 cost: string; // 抽1次的消耗
freeCount: number; // 免费次数 freeCount: number; // 免费次数
pool: LuckyPool[] = []; pool: LuckyPool[] = [];
// greateReward: LuckyPool; // 头奖weight最小的那一个
box: LuckyBox[] = []; box: LuckyBox[] = [];
floor: { // 保底 floor: { // 保底
sum: number; sum: number;
count: number;
id: number; id: number;
floorCount?: number;
}[]; }[];
todayCount: number = 0; // 今天抽了几次 todayCount: number = 0; // 今天抽了几次
count: number = 0; // 一共抽了几次 count: number = 0; // 一共抽了几次
records: TurntableRecord[] = []; // 奖励记录 records: TurntableRecord[] = []; // 奖励记录
greatRewardCount: number = 0; // 已抽次数,用于计算保底
floorRecord: FloorRecord[] = []; //
public getCost(count: number) { public getCost(count: number) {
if (this.todayCount < this.freeCount) { if (this.todayCount < this.freeCount) {
@@ -116,16 +116,22 @@ export class LuckyData extends ActivityBase {
let pool: LuckyPool[] = []; let pool: LuckyPool[] = [];
for (let obj of this.pool) { for (let obj of this.pool) {
let { gid, numLimit } = obj; let { gid, numLimit } = obj;
if (numLimit != -1 || numLimit > (gidMap.get(gid) || 0)) pool.push(obj); if (numLimit == -1 || numLimit > (gidMap.get(gid) || 0)) pool.push(obj);
} }
return pool; return pool;
} }
// 保底 // 保底
private getFloor(pool: LuckyPool[]) { private getFloor(pool: LuckyPool[]) {
let ret: TurntableFloorInDb = { sum: 0, count: 0, id: 0 }; let ret: TurntableFloorInDb = { sum: 0, id: 0 };
for (let { sum, count, id } of this.floor) { for (let { sum, id } of this.floor) {
if (this.greatRewardCount > (sum - count) && this.greatRewardCount <= sum) { let floorRecord = this.floorRecord.find(cur => cur.id == id);
if ((ret?.sum || 0) < sum) ret = { sum, count, id }; let count = 0;
if (floorRecord) count = floorRecord.count + 1;
if ((count == sum || count % sum == 0) && count != 0) {
if (sum > ret.sum) {
ret = { sum, id };
if (floorRecord) floorRecord.count = 0;
}
} }
} }
@@ -138,6 +144,23 @@ export class LuckyData extends ActivityBase {
return {}; return {};
} }
//获取保底
public getFloorCount() {
for (let obj of this.floor) {
let { sum, id } = obj;
let pool = this.pool.find(cur => cur.id == id)
if (!pool || pool.numLimit <= pool.getCnt) obj.floorCount = 0;
else {
let count = this.floorRecord.find(cur => cur.id == id)?.count || 0;
if (count % sum == 0) obj.floorCount = sum;
else {
obj.floorCount = sum - (count % sum);
}
}
}
return this.floor;
}
public pull(roleName: string, count: number) { public pull(roleName: string, count: number) {
let records: (string | number)[][] = []; let records: (string | number)[][] = [];
@@ -147,34 +170,26 @@ export class LuckyData extends ActivityBase {
// 1.次数上限 // 1.次数上限
let pool = this.getPoolByRecordNum(); let pool = this.getPoolByRecordNum();
// 2.保底 // 2.保底
this.greatRewardCount++;
let { newPool } = this.getFloor(pool); let { newPool } = this.getFloor(pool);
let randResult = newPool; let randResult = newPool;
if (newPool) { if (!newPool) {
let floor = this.floor.find(cur => cur.id == newPool.id) randResult = getRandEelmWithWeight(pool).dic;
if (floor && floor.sum == this.greatRewardCount) { }
this.greatRewardCount = 0; if (randResult) {
}
let tempPool = this.pool.find(cur => cur.id == randResult.id); let tempPool = this.pool.find(cur => cur.id == randResult.id);
if (tempPool) { if (tempPool) {
tempPool.getCnt = (tempPool.getCnt || 0) + 1; tempPool.getCnt = (tempPool.getCnt || 0) + 1;
} }
} for (let obj of this.floor) {
else { let floorRecord = this.floorRecord.find(cur => cur.id == obj.id);
randResult = getRandEelmWithWeight(pool).dic; if (obj.id != randResult.id) {
if (randResult) { if (!floorRecord) this.floorRecord.push({ id: obj.id, count: 1 });
let floor = this.floor.find(cur => cur.id == randResult.id); else floorRecord.count++;
let tempPool = this.pool.find(cur => cur.id == randResult.id); } else {
if (tempPool) { if (floorRecord) floorRecord.count = 0;
tempPool.getCnt = (tempPool.getCnt || 0) + 1;
} }
if (floor && floor.count <= tempPool.getCnt) {
this.greatRewardCount = 0;
}
} }
}
if (randResult) {
this.count++; this.count++;
this.todayCount++; this.todayCount++;
let record = { roleName, gid: randResult.gid, count: randResult.count }; let record = { roleName, gid: randResult.gid, count: randResult.count };
@@ -184,7 +199,7 @@ export class LuckyData extends ActivityBase {
goodResult.push({ id: randResult.gid, count: randResult.count }); goodResult.push({ id: randResult.gid, count: randResult.count });
} }
} }
return { result, records, goodResult, pool: this.pool.map(pool => pool.getShowResult()), floorCount: this.greatRewardCount }; return { result, records, goodResult, pool: this.pool.map(pool => pool.getShowResult()), floor: this.getFloorCount() };
} }
// 宝箱是否可以领取 // 宝箱是否可以领取
@@ -203,19 +218,20 @@ export class LuckyData extends ActivityBase {
public setPlayerRecords(playerData: ActivityLuckyModelType) { public setPlayerRecords(playerData: ActivityLuckyModelType) {
if (!playerData) return null if (!playerData) return null
let { todayCount, count, records, box, greatRewardCount } = playerData; let { todayCount, count, records, box, floorRecord = [] } = playerData;
this.todayCount = todayCount; this.todayCount = todayCount;
this.count = count; this.count = count;
this.records = records; this.records = records;
for (let boxData of this.box) { for (let boxData of this.box) {
boxData.setReceived(box); boxData.setReceived(box);
} }
this.greatRewardCount = greatRewardCount;
let gidMap = this.getGidMap(); let gidMap = this.getGidMap();
for (let obj of this.pool) { for (let obj of this.pool) {
obj.getCnt = (gidMap.get(obj.gid) || 0); obj.getCnt = (gidMap.get(obj.gid) || 0);
} }
this.floorRecord = floorRecord;
} }
public initData(data: string) { public initData(data: string) {
@@ -225,9 +241,6 @@ export class LuckyData extends ActivityBase {
for (let pool of dataObj.pool) { for (let pool of dataObj.pool) {
let poolObj = new LuckyPool(pool); let poolObj = new LuckyPool(pool);
this.pool.push(poolObj); this.pool.push(poolObj);
// if (!this.greateReward || this.greateReward.weight > poolObj.weight) {
// this.greateReward = poolObj;
// }
} }
for (let box of dataObj.box) { for (let box of dataObj.box) {
this.box.push(new LuckyBox(box)); this.box.push(new LuckyBox(box));
@@ -245,7 +258,7 @@ export class LuckyData extends ActivityBase {
box: this.box, box: this.box,
pool: this.pool.map(pool => pool.getShowResult()), pool: this.pool.map(pool => pool.getShowResult()),
records: this.records.map(record => [record.roleName, record.gid, record.count]), records: this.records.map(record => [record.roleName, record.gid, record.count]),
floorCount: this.greatRewardCount, floor: this.getFloorCount(),
} }
} }