diff --git a/game-server/app/servers/battle/handler/auctionHandler.ts b/game-server/app/servers/battle/handler/auctionHandler.ts index ed115c0f2..3dd2b50e3 100644 --- a/game-server/app/servers/battle/handler/auctionHandler.ts +++ b/game-server/app/servers/battle/handler/auctionHandler.ts @@ -1,8 +1,13 @@ +import { DividendModel } from './../../../db/Dividend'; import { Application, BackendSession, ChannelService } from "pinus"; -import { DEBUG_MAGIC_WORD, STATUS } from "../../../consts"; +import { AUCTION_STAGE, DEBUG_MAGIC_WORD, STATUS, OFFER_RATIO, CURRENCY_BY_TYPE, CURRENCY_TYPE } from "../../../consts"; +import { LotModel } from "../../../db/Lot"; import { ItemReward } from "../../../domain/dbGeneral"; import { resResult } from "../../../pubUtils/util"; -import { genAuction } from "../../../services/auctionService"; +import { auctionBegin, auctionStage, genAuction } from "../../../services/auctionService"; +import { addItems, handleCost } from '../../../services/rewardService'; +import { getSimpleRoleInfo } from '../../../services/roleService'; +import { getRoleOnlineInfo } from '../../../services/redisService'; export default function (app: Application) { return new AuctionHandler(app); @@ -15,11 +20,51 @@ export class AuctionHandler { } async getAuction(msg: {}, session: BackendSession) { - return resResult(STATUS.SUCCESS); + const guildCode = session.get('guildCode'); + const serverId = session.get('serverId'); + if (!guildCode) return resResult(STATUS.GUILD_NOT_FOUND); + const begin = auctionBegin(); + const stage = auctionStage(); + let lots = []; + 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); + } + const dividends = await DividendModel.findGuildDividendsByBegin(guildCode, begin); + return resResult(STATUS.SUCCESS, { lots, dividends }); } - async offer(msg: { max: boolean }, session: BackendSession) { - return resResult(STATUS.SUCCESS); + async offer(msg: { code: string, max: boolean }, session: BackendSession) { + const { code, max } = msg; + let maxFlag = max; + const lot = await LotModel.findLot(code); + if (!lot) return resResult(STATUS.GUILD_LOT_NOT_FOUND); + const roleId = session.get('roleId'); + const roleName = session.get('roleName'); + const sid = session.get('sid'); + const { curBuyer, curPrice, maxPrice, gid, count, bidRoles } = lot; + if (curBuyer === roleId) return resResult(STATUS.LOT_OFFER_SERIAL); + let newPrice = parseInt((curPrice * OFFER_RATIO).toFixed(0)); + if (newPrice >= maxPrice) { + newPrice = maxPrice; + maxFlag = true; + } + const costRes = await handleCost(roleId, sid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: newPrice }]); + if (!costRes) return resResult(STATUS.ROLE_COIN_NOT_ENOUGH); + const { roleName: buyerName } = await getSimpleRoleInfo(curBuyer); + const { sid: buyerSid } = await getRoleOnlineInfo(buyerName); + await addItems(curBuyer, buyerName, buyerSid, [{ id: CURRENCY_BY_TYPE.get(CURRENCY_TYPE.GOLD), count: curPrice }]); + // TODO 元宝返还纪录 + if (maxFlag) { + newPrice = maxPrice; + await addItems(roleId, roleName, sid, [{ id: gid, count }]); + } + bidRoles.push({roleId, price: newPrice, time: new Date()}); + const newLot = await LotModel.updateLot({ code, curBuyer: roleId, curPrice: newPrice, bidRoles}); + + // TODO 更新分红 + return resResult(STATUS.SUCCESS, { lot: newLot }); } async watchLot(msg: { code: string }, session: BackendSession) { diff --git a/game-server/app/services/auctionService.ts b/game-server/app/services/auctionService.ts index 369a64d98..047f81bca 100644 --- a/game-server/app/services/auctionService.ts +++ b/game-server/app/services/auctionService.ts @@ -3,7 +3,7 @@ import { LOT_CODE_LEN, AUCTION_STAGE, AUCTION_TIME, DIVIDEND_CODE_LEN, DIVIDEND_ import { DividendRec, ItemReward } from "../domain/dbGeneral"; import { genCode } from '../pubUtils/util'; import { LotModel, LotParam } from '../db/Lot'; -import { getNextTime } from '../pubUtils/timeUtil'; +import { getNextTime, getTodayZeroDate } from '../pubUtils/timeUtil'; import { getGoodById } from '../pubUtils/data'; import { DividendParam, DividendType } from '../db/Dividend'; @@ -19,6 +19,25 @@ function getMaxPrice(gid: number, count: number) { return (good ? good.quality * 200 : 200) * count; } +export function auctionStage() { + const curTime = new Date().getTime(); + const todayGuildBegin = getNextTime(getTodayZeroDate(), AUCTION_TIME.GUILD_BEGIN_HOUR, AUCTION_TIME.GUILD_BEGIN_MIN).getTime(); + const todayWorldBegin = getNextTime(getTodayZeroDate(), AUCTION_TIME.WORLD_BEGIN_HOUR, AUCTION_TIME.WORLD_BEGIN_MIN).getTime(); + const todayWorldEnd = getNextTime(getTodayZeroDate(), AUCTION_TIME.WORLD_END_HOUR, AUCTION_TIME.WORLD_END_MIN).getTime(); + if (curTime < todayGuildBegin) return AUCTION_STAGE.DEFAULT; + if (curTime < todayWorldBegin && curTime > todayGuildBegin) return AUCTION_STAGE.GUILD; + if (curTime > todayWorldBegin && curTime < todayWorldEnd) return AUCTION_STAGE.WORLD; + if (curTime > todayWorldEnd) return AUCTION_STAGE.END; +} + +export function auctionBegin() { + return getNextTime(new Date(), AUCTION_TIME.GUILD_BEGIN_HOUR, AUCTION_TIME.GUILD_BEGIN_MIN); +} + +export function auctionEnd() { + return getNextTime(new Date(), AUCTION_TIME.WORLD_END_HOUR, AUCTION_TIME.WORLD_END_MIN); +} + /** * @description 生成拍卖数据 * @export @@ -29,8 +48,8 @@ function getMaxPrice(gid: number, count: number) { * @param {ItemReward[]} rewards */ export async function genAuction(guildCode: string, sourceType: number, sourceCode: string, serverId: number, rewards: ItemReward[]) { - const begin = getNextTime(new Date(), AUCTION_TIME.GUILD_BEGIN_HOUR, AUCTION_TIME.GUILD_BEGIN_MIN); - const end = getNextTime(new Date(), AUCTION_TIME.WORLD_END_HOUR, AUCTION_TIME.WORLD_END_MIN); + const begin = auctionBegin(); + const end = auctionEnd(); const lotsData: LotParam[] = rewards.map(reward => { const { id, count } = reward; const code = genCode(LOT_CODE_LEN); @@ -43,7 +62,7 @@ export async function genAuction(guildCode: string, sourceType: number, sourceCo const lots = await LotModel.createRecs(lotsData); const dividendCode = genCode(DIVIDEND_CODE_LEN); const dividendData: DividendParam = { - guildCode, sourceType, sourceCode, serverId, code: dividendCode, lots: [], dividends: [], totalPrice: 0, end + guildCode, sourceType, sourceCode, serverId, code: dividendCode, lots: [], dividends: [], totalPrice: 0, begin }; const dividend = await DividendModel.createDividend(dividendData); return { lots, dividend }; @@ -81,7 +100,7 @@ function weekendDividend(totalPrice: number, roleNum: number, date: Date) { } export async function calculateDividend(dividend: DividendType) { - const { code, guildCode, sourceType, sourceCode, lots, totalPrice, status, end } = dividend; + const { code, guildCode, sourceType, sourceCode, lots, totalPrice, status, begin } = dividend; if (status === DIVIDEND_STATUS.SENT) return null; const calcuTotalPrice = lots.reduce((acc, lot) => { return acc + lot.price }, 0); if (calcuTotalPrice !== totalPrice) { @@ -94,7 +113,7 @@ export async function calculateDividend(dividend: DividendType) { const roleNum = participantsData.length; const baseNum = baseDividend(calcuTotalPrice, roleNum); const posNum = posDividend(calcuTotalPrice, roleNum, position); - const weekendNum = weekendDividend(calcuTotalPrice, roleNum, end); + const weekendNum = weekendDividend(calcuTotalPrice, roleNum, begin); return { roleId, baseNum, // 基础分红 diff --git a/game-server/app/services/rewardService.ts b/game-server/app/services/rewardService.ts index 018c97872..d8ed1026f 100644 --- a/game-server/app/services/rewardService.ts +++ b/game-server/app/services/rewardService.ts @@ -102,6 +102,7 @@ function sortConsumes(goods: Array, bags: Array, currencys return true; } +// TODO: sid 在方法内部获取,且不一定存在 export async function addItems(roleId: string, roleName: string, sid: string, goods: Array) { let showItems: Array = []; let currencysMap: any = {}; diff --git a/game-server/test/auction.test.ts b/game-server/test/auction.test.ts index 3348078ef..b4c818b9b 100644 --- a/game-server/test/auction.test.ts +++ b/game-server/test/auction.test.ts @@ -71,15 +71,15 @@ describe('拍卖行测试', function() { }); it('出价', function(done) { - pinusClient.request('battle.auctionHandler.offer', { max: false }, (res) => { - checkSuccessResponse(res, false); + pinusClient.request('battle.auctionHandler.offer', { code: '', max: false }, (res) => { + // checkSuccessResponse(res, false); done(); }); }); it('出一口价', function(done) { - pinusClient.request('battle.auctionHandler.offer', { max: true }, (res) => { - checkSuccessResponse(res, false); + pinusClient.request('battle.auctionHandler.offer', { code: '', max: true }, (res) => { + // checkSuccessResponse(res, false); done(); }); }); diff --git a/shared/consts/constModules/auctionConst.ts b/shared/consts/constModules/auctionConst.ts index b9b39023c..e36d78459 100644 --- a/shared/consts/constModules/auctionConst.ts +++ b/shared/consts/constModules/auctionConst.ts @@ -34,3 +34,5 @@ export const DIVIDEND_STATUS = { END: 2, // 2:已结束 SENT: 3, // 3:已发放 }; + +export const OFFER_RATIO = 1.1; diff --git a/shared/consts/statusCode.ts b/shared/consts/statusCode.ts index 8b88fccaa..014827be6 100644 --- a/shared/consts/statusCode.ts +++ b/shared/consts/statusCode.ts @@ -191,6 +191,10 @@ export const STATUS = { GUILD_TRAIN_BOX_IS_OVER_TIME: { code: 20971, simStr: '军团宝箱超时' }, GUILD_TRAIN_BOX_INDEX_IS_GOT:{ code: 20972, simStr: '该位置试炼宝箱已经领取过,请重新选择' }, GUILD_TRAIN_BOX_IS_GOT: { code: 20973, simStr: '玩家已经领取该试炼宝箱' }, + + // 军团拍卖 + GUILD_LOT_NOT_FOUND: { code: 21001, simStr: '拍品未找到' }, + LOT_OFFER_SERIAL: { code: 21002, simStr: '不能连续出价' }, // 通用 30000 - 30099 DIC_DATA_NOT_FOUND: { code: 30000, simStr: '数据表未找到' }, ROLE_MATERIAL_NOT_ENOUGH: { code: 30001, simStr: '材料数量不足' }, diff --git a/shared/db/Dividend.ts b/shared/db/Dividend.ts index 353464020..dd8ccc229 100644 --- a/shared/db/Dividend.ts +++ b/shared/db/Dividend.ts @@ -8,7 +8,8 @@ import { genCode } from '../pubUtils/util'; **/ @modelOptions({ schemaOptions: { id: false } }) @index({ code: 1 }) -@index({ guildCode: 1 }) +@index({ begin: -1, guildCode: 1 }) +@index({ begin: -1, serverId: 1}) export default class Dividend extends BaseModel { @prop({ required: true, default: 0 }) serverId: number; // 区服编号 @@ -29,7 +30,7 @@ export default class Dividend extends BaseModel { @prop({ required: true, default: 0 }) status: number; // 0:未开始;1:进行中;2:已结束;3:已发放 @prop({ required: true }) - end: Date; + begin: Date; public static async createDividend(data: DividendParam) { const code = genCode(8); @@ -43,6 +44,16 @@ export default class Dividend extends BaseModel { return result; } + public static async findWorldDividendsByBegin(serverId: number, begin: Date) { + const results = await DividendModel.find({ serverId, begin }).select('-_id -__v').lean(); + return results; + } + + public static async findGuildDividendsByBegin(guildCode: string, begin: Date) { + const results = await DividendModel.find({ guildCode, begin }).select('-_id -__v').lean(); + return results; + } + public static async updateDividend(code: string, update: DividendParam) { const result = await DividendModel.findOneAndUpdate({ code }, { ...update }, { new: true }).select('-_id -__v').lean(); return result; diff --git a/shared/db/Lot.ts b/shared/db/Lot.ts index e2ad1a6c3..4b98ef808 100644 --- a/shared/db/Lot.ts +++ b/shared/db/Lot.ts @@ -8,7 +8,7 @@ import { genCode } from '../pubUtils/util'; **/ @modelOptions({ schemaOptions: { id: false } }) @index({ code: 1 }) -@index({ guildCode: 1, createdAt: -1 }) +@index({ guildCode: 1, begin: -1 }) export default class Lot extends BaseModel { @prop({ required: true, default: 0 }) auctionStage: number; // 0:初始添加,1:军团拍卖,2:世界拍卖,3:拍卖结束 @@ -56,10 +56,21 @@ export default class Lot extends BaseModel { return result; } - public static async findGuildLotsByTime(guildCode: string, sourceType: number, time: Date) { - const results = await LotModel.find({ guildCode, sourceType, createdAt: { $gte: time } }).select('-_id -__v').lean(); + public static async findGuildLotsByBegin(guildCode: string, time: Date) { + const results = await LotModel.find({ guildCode, begin: { $eq: time } }).select('-_id -__v').lean(); return results; } + + public static async findWorldLotsByBegin(serverId: number, time: Date) { + const results = await LotModel.find({ serverId, begin: { $eq: time } }).select('-_id -__v').lean(); + return results; + } + + public static async updateLot(data: LotParam) { + const code = data.code!; + const result: LotType = await LotModel.findOneAndUpdate({ code }, { ...data }, { new: true }).select('-_id -__v').lean(); + return result; + } } export const LotModel = getModelForClass(Lot);