feat(拍卖行): 拍卖行最后10s延长15s

This commit is contained in:
luying
2023-06-20 14:47:47 +08:00
parent 2841625391
commit ef567db157
11 changed files with 143 additions and 49 deletions

View File

@@ -1,10 +1,10 @@
import { DividendModel, DividendType } from './../../../db/Dividend';
import { Application, BackendSession, ChannelService, HandlerService, pinus, } from "pinus";
import { AUCTION_STAGE, DEBUG_MAGIC_WORD, STATUS, CURRENCY_BY_TYPE, CURRENCY_TYPE, DATA_NAME, LOT_STATUS, CHANNEL_PREFIX, MAIL_TYPE, ITEM_CHANGE_REASON, TA_EVENT, ROLE_RECEIVE_STATUS, PUSH_ROUTE } from "../../../consts";
import { LotModel } from "../../../db/Lot";
import { AUCTION_STAGE, DEBUG_MAGIC_WORD, STATUS, CURRENCY_BY_TYPE, CURRENCY_TYPE, DATA_NAME, LOT_STATUS, CHANNEL_PREFIX, MAIL_TYPE, ITEM_CHANGE_REASON, TA_EVENT, ROLE_RECEIVE_STATUS, PUSH_ROUTE, AUCTION_BID_EXTEND_TIME } from "../../../consts";
import { LotModel, LotParam } from "../../../db/Lot";
import { ItemReward } from "../../../domain/dbGeneral";
import { genCode, resResult } from "../../../pubUtils/util";
import { auctionStage, calculateDividend, genAuction, sendUngotDividend, startGuildAuction, startWorldAuction, stopAuction, todayGuildBegin, getBasePrice, debugAuctionLots, officialAuctionLots, auctionBidStatus, getMaxPrice, guildBidStatus, getAuction, pushAuctionOver, pushAuctionUpdate, checkAuctionStage, processDividendFormat, processSingleDividendFormat, tomorrowGuildBegin, processLotsFormat, processSingleLotFormat, getAuctionRewardByPoolId } from "../../../services/auctionService";
import { auctionStage, calculateDividend, genAuction, sendUngotDividend, startGuildAuction, startWorldAuction, stopAuction, todayGuildBegin, getBasePrice, debugAuctionLots, officialAuctionLots, auctionBidStatus, getMaxPrice, guildBidStatus, getAuction, pushAuctionOver, pushAuctionUpdate, processDividendFormat, processSingleDividendFormat, tomorrowGuildBegin, processLotsFormat, processSingleLotFormat, getAuctionRewardByPoolId, getLotStatus, extendLotTime } from "../../../services/auctionService";
import { addItems, getGoldObject, handleCost } from '../../../services/role/rewardService';
import { getSimpleRoleInfo } from '../../../services/roleService';
import { getRoleOnlineInfo } from '../../../services/redisService';
@@ -76,12 +76,12 @@ export class AuctionHandler {
return resResult(STATUS.AUCTION_GUILD_MEMBER_ONLY);
}
if(!await checkAuctionStage(auctionStage, magicWord)) {
let { curBuyer, curPrice, prePrice, maxPrice, gid, count, bidRoles, watchingRoles, seq, begin, auctionStage: lotAuctionStage } = lot;
if (auctionStage != lotAuctionStage) {
res.releaseCallback();
return resResult(STATUS.AUCITON_STAGE_ERR);
}
let { curBuyer, curPrice, prePrice, maxPrice, gid, count, bidRoles, watchingRoles, seq, begin } = lot;
if (curBuyer === roleId && !max) {
res.releaseCallback();
return resResult(STATUS.LOT_OFFER_SERIAL);
@@ -117,7 +117,11 @@ export class AuctionHandler {
reportTAEvent(roleId, TA_EVENT.AUCTION_ITEM_GET, { item_name: dicGoods?.name, item_count: count, deel_price: newPrice }, ip);
}
bidRoles.push({ roleId, price: newPrice, time: new Date() });
const newLot = await LotModel.updateLot({ code, curBuyer: roleId, curPrice: newPrice, auctionStage, prePrice: curPrice, bidRoles, status: max ? LOT_STATUS.MAX : (maxFlag ? LOT_STATUS.SOLD : LOT_STATUS.ING), watchingRoles: Array.from(new Set([...watchingRoles, roleId])), seq: 0 });
let lotStatus = await getLotStatus(auctionStage, max, maxFlag)
let update: LotParam = { code, curBuyer: roleId, curPrice: newPrice, auctionStage, prePrice: curPrice, bidRoles, status: lotStatus, watchingRoles: Array.from(new Set([...watchingRoles, roleId])), seq: 0 };
if(lotStatus == LOT_STATUS.BIDDING) update.end = new Date(Date.now() + AUCTION_BID_EXTEND_TIME * 1000);
const newLot = await LotModel.updateLot(update);
await extendLotTime(newLot);
if(seq <= LOTS_KEEP_TO_WORLD_CNT && seq > 0) await LotModel.updateOne({ begin, gid, count, status: LOT_STATUS.DEFAULT, serverId, seq: { $gt: LOTS_KEEP_TO_WORLD_CNT } }, { $set: { seq }});
await pushAuctionOver(newLot); // 推送竞价超过标志
res.releaseCallback();

View File

@@ -1,5 +1,5 @@
import { DividendModel } from './../db/Dividend';
import { LOT_CODE_LEN, AUCTION_STAGE, AUCTION_TIME, DIVIDEND_CODE_LEN, DIVIDEND_STATUS, LOT_STATUS, MAIL_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_RECEIVE_STATUS, AUCTION_BID_STATUS, DEBUG_MAGIC_WORD, AUCTION_SOURCE, TA_EVENT, getAuctionSourceTypeName, PUSH_ROUTE, GUILD_JOB } from './../consts';
import { LOT_CODE_LEN, AUCTION_STAGE, AUCTION_TIME, DIVIDEND_CODE_LEN, DIVIDEND_STATUS, LOT_STATUS, MAIL_TYPE, CURRENCY_BY_TYPE, CURRENCY_TYPE, ROLE_RECEIVE_STATUS, AUCTION_BID_STATUS, DEBUG_MAGIC_WORD, AUCTION_SOURCE, TA_EVENT, getAuctionSourceTypeName, PUSH_ROUTE, GUILD_JOB, AUCTION_BID_TIME, AUCTION_BID_EXTEND_TIME } from './../consts';
import { DividendRec, } from "../domain/dbGeneral";
import { genCode, getRandEelmWithWeight, getRandSingleEelm } from '../pubUtils/util';
import Lot, { LotModel, LotParam, LotType } from '../db/Lot';
@@ -20,6 +20,8 @@ import { pick } from 'underscore';
import { AuctionRewardInter } from '../domain/battleField/auction';
import { CounterLotsModel } from '../db/CounterAuction';
import { isGoodsHidden } from './dataService';
import { scheduleJob } from 'node-schedule';
import { clearLotTimer, setLotTimer } from './memoryCache/auctionData';
// ! 获取底价,假数据
export function getBasePrice(gid: number, count: number) {
@@ -50,16 +52,9 @@ export async function debugAuctionLots(session: FrontendOrBackendSession, begin:
export async function officialAuctionLots(session: FrontendOrBackendSession, begin: Date) {
const serverId = session.get('serverId');
const guildCode = session.get('guildCode');
const stage = await auctionStage();
let lots: LotType[] = [];
if (stage === AUCTION_STAGE.DEFAULT || stage === AUCTION_STAGE.GUILD) {
lots = await LotModel.findGuildLotsByBegin(guildCode, begin);
} else if (stage === AUCTION_STAGE.WORLD) {
lots = await LotModel.findWorldLotsByBegin(serverId, begin);
}
return processLotsFormat(lots);
let guildLots = await LotModel.findGuildLotsByBegin(guildCode, begin);
let serverLots = await LotModel.findWorldLotsByBegin(serverId, begin);
return processLotsFormat([...guildLots, ...serverLots]);
}
// 拍卖行开始时间 今天20:20
@@ -342,7 +337,6 @@ export async function startWorldAuction() {
let lots = await LotModel.setLotSoldByBegin(begin, AUCTION_STAGE.GUILD); // 正在竞拍的拍品
await sendLotsRewardToMlail(lots);
lots = await LotModel.keepUnSoldLotsToWorld(begin);
let dividends = await DividendModel.updateDividendsStatus(begin, DIVIDEND_STATUS.END);
if(isDebugTime()) {
let day = getCurDay();
@@ -350,7 +344,7 @@ export async function startWorldAuction() {
pinus.app.rpc.guild.guildActivityRemote.setCurrentTime.broadcast(time);
await pushCurrentTime(time);
}
await pushAuctionUpdate(lots, dividends);
await pushAuctionUpdate(lots, []);
return true;
} catch (e) {
console.error('startWorldAuction err: ', e);
@@ -358,6 +352,14 @@ export async function startWorldAuction() {
}
}
export async function startDividend() {
console.log('schedule startDividend called:', new Date());
const begin = await todayGuildBegin();
console.log('begin', begin)
let dividends = await DividendModel.updateDividendsStatus(begin, DIVIDEND_STATUS.END);
await pushAuctionUpdate([], dividends);
}
export async function stopAuction() {
try {
console.log('schedule stopAuction called:', new Date());
@@ -492,35 +494,30 @@ export async function pushAuctionOver(lot: LotType) {
}
export async function pushAuctionUpdate(lots: LotType[], dividends: DividendType[]) {
const stage = await auctionStage();
if(stage === AUCTION_STAGE.DEFAULT || stage === AUCTION_STAGE.GUILD) {
let lotsResult = new Map<string, LotType[]>();
let lotsByGuild = new Map<string, LotType[]>();
let lotsByServer = new Map<number, LotType[]>();
for(let lot of lots) {
if(!lotsResult.has(lot.guildCode)) {
lotsResult.set(lot.guildCode, []);
for(let lot of lots) {
if(lot.auctionStage === AUCTION_STAGE.DEFAULT || lot.auctionStage === AUCTION_STAGE.GUILD) {
if(!lotsByGuild.has(lot.guildCode)) {
lotsByGuild.set(lot.guildCode, []);
}
lotsResult.get(lot.guildCode).push(lot);
}
for(let [guildCode, lots] of lotsResult) {
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.AUCTION_UPDATE, { lots: processLotsFormat(lots) });
}
} else {
let lotsResult = new Map<number, LotType[]>();
for(let lot of lots) {
if(!lotsResult.has(lot.serverId)) {
lotsResult.set(lot.serverId, []);
lotsByGuild.get(lot.guildCode).push(lot);
} else {
if(!lotsByServer.has(lot.serverId)) {
lotsByServer.set(lot.serverId, []);
}
lotsResult.get(lot.serverId).push(lot);
}
for(let [serverId, lots] of lotsResult) {
await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.AUCTION_UPDATE, { lots: processLotsFormat(lots) });
lotsByServer.get(lot.serverId).push(lot);
}
}
for(let [guildCode, lots] of lotsByGuild) {
await sendMessageToGuildWithSuc(guildCode, PUSH_ROUTE.AUCTION_UPDATE, { lots: processLotsFormat(lots) });
}
for(let [serverId, lots] of lotsByServer) {
await sendMessageToServerWithSuc(serverId, PUSH_ROUTE.AUCTION_UPDATE, { lots: processLotsFormat(lots) });
}
let dividendsResult = new Map<string, DividendType[]>();
for(let dividend of dividends) {
if(!dividendsResult.has(dividend.guildCode)) {
@@ -551,6 +548,45 @@ export async function checkAuctionStage(auctionStage: number, magicWord: string)
return true
}
export async function isAuctionBidding() {
const curTime = await getCurrentTimeWithSetDay();
const guildAuctionBeginTime = (await todayWorldBegin()).getTime();
return guildAuctionBeginTime - curTime <= AUCTION_BID_TIME * 1000;
}
/**
*
* @param max 玩家是否直接选择一口价
* @param maxFlag 竞拍是否达到一口价的价格了
* @param isBidding 是否在竞价时间重
*/
export async function getLotStatus(auctionStage: number, max: boolean, maxFlag: boolean) {
if(max) return LOT_STATUS.MAX;
if(maxFlag) return LOT_STATUS.SOLD;
if(auctionStage == AUCTION_STAGE.GUILD && await isAuctionBidding()) return LOT_STATUS.BIDDING;
return LOT_STATUS.ING
}
export async function extendLotTime(lot: LotType) {
if(lot.status != LOT_STATUS.BIDDING) {
clearLotTimer(lot.code);
} else {
let timer = setTimeout(async () => {
await sendSingleLot(lot.code);
}, lot.end.getTime() - Date.now());
setLotTimer(lot.code, timer);
}
}
export async function sendSingleLot(code: string) {
console.log('schedule sendSingleLot called:', new Date());
let lot = await LotModel.setLotSold(code, AUCTION_STAGE.GUILD); // 正在竞拍的拍品
await sendLotsRewardToMlail([lot]);
await pushAuctionOver(lot);
return true;
}
export function processSingleDividendFormat(dividend: DividendType) {
if(!dividend) return null;
let newDividend = { ...dividend, begin: getSeconds(dividend.begin)}
@@ -615,4 +651,8 @@ export function getAuctionRewardByPoolId(poolId: number) {
}
}
return rewards;
}
export function biddingLotTimeout() {
scheduleJob('', () => {})
}

View File

@@ -709,6 +709,7 @@ export async function setDicAuctionTime(startTime: number, endActivity: number,
let endGuildDate = new Date(startGuildDate.getTime() + endGuild * 1000);
let startWorldDate = new Date(endGuildDate.getTime() + startWorld * 1000);
let endWorldDate = new Date(startWorldDate.getTime() + endWorld * 1000);
let startDividendData = new Date(startWorldDate.getTime() + 3 * 60 * 1000)
// console.log('********* setDicAuctionTime', startGuildDate, endGuildDate, startWorldDate, endWorldDate);
@@ -719,6 +720,7 @@ export async function setDicAuctionTime(startTime: number, endActivity: number,
gameData.auctionTime.set(AUCTION_TIME.WORLD_PREVIEW, formatTime(endGuildDate));
gameData.auctionTime.set(AUCTION_TIME.WORLD_OPEN, formatTime(startWorldDate));
gameData.auctionTime.set(AUCTION_TIME.WORLD_CLOSE, formatTime(endWorldDate));
gameData.auctionTime.set(AUCTION_TIME.DIVIDEND_START, formatTime(startDividendData));
// console.log('*********** setDicAuctionTime', gameData.auctionTime)
}

View File

@@ -0,0 +1,21 @@
let auctionTimer = new Map<string, NodeJS.Timer>();
export function getLotTimer(code: string) {
return auctionTimer.get(code)
}
export function setLotTimer(code: string, timer: NodeJS.Timer) {
if(auctionTimer.has(code)) {
let originTimer = auctionTimer.get(code);
if(originTimer) clearTimeout(originTimer);
}
auctionTimer.set(code, timer);
}
export function clearLotTimer(code: string) {
let timer = getLotTimer(code);
if (timer) {
clearTimeout(timer);
auctionTimer.delete(code)
}
}

View File

@@ -10,7 +10,7 @@ import { pinus } from 'pinus';
import { settleGuildWeekly } from './guildService';
import { sendMailByContent, SendMailFun, sendMailsByGmMail, } from './mailService';
import { sendEndMsgToAllServer, sendGuildActivityStatus, setPreDayActiveData, incCurGuildActivityIndex } from './guildActivity/guildActivityService';
import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction } from './auctionService';
import { sendUngotDividendJob, startGuildAuction, startWorldAuction, stopAuction, startDividend } from './auctionService';
import { DicGuildActivity } from '../pubUtils/dictionary/DicGuildActivity';
import { dispatch } from '../pubUtils/dispatcher';
import { initMarquee, setServerMainten } from './gmService';
@@ -427,18 +427,21 @@ export async function raceActivitySeconds() {
let startGuildAuctionJobId: Job;
let startWorldAuctionJobId: Job;
let stopAuctionJobId: Job;
let startDividendJobId: Job;
export async function auctionSchedule() {
clearAuctionSchedule();
let guildOpen = gameData.auctionTime.get(AUCTION_TIME.GUILD_OPEN);
let worldOpen = gameData.auctionTime.get(AUCTION_TIME.WORLD_OPEN);
let worldClose = gameData.auctionTime.get(AUCTION_TIME.WORLD_CLOSE);
let dividendStart = gameData.auctionTime.get(AUCTION_TIME.DIVIDEND_START);
// console.log('***** auctionSchedule', guildOpen.hour, guildOpen.minute, guildOpen.seconds);
// console.log('***** auctionSchedule', worldOpen.hour, worldOpen.minute, worldOpen.seconds);
// console.log('***** auctionSchedule', worldClose.hour, worldClose.minute, worldClose.seconds);
startGuildAuctionJobId = scheduleJob('startGuildAuction', `${guildOpen.seconds} ${guildOpen.minute} ${guildOpen.hour} * * ?`, startGuildAuction);
startWorldAuctionJobId = scheduleJob('startWorldAuction', `${worldOpen.seconds} ${worldOpen.minute} ${worldOpen.hour} * * ?`, startWorldAuction);
startDividendJobId = scheduleJob('startDividend', `${dividendStart.seconds} ${dividendStart.minute} ${dividendStart.hour} * * ?`, startDividend);
stopAuctionJobId = scheduleJob('stopAuction', `${worldClose.seconds} ${worldClose.minute} ${worldClose.hour} * * ?`, stopAuction);
}

View File

@@ -138,6 +138,13 @@ export async function guild(session: Session, msg: any, app: Application, cb: (e
needDispatch = true;
rid = `${groupId}_${arg.body.cityId}`;
}
} else if ([
'guild.auctionHandler.offer'
].indexOf(arg.route) != -1) {
if(arg.body.code) {
needDispatch = true;
rid = arg.body.code;
}
}
}
}