feat,wip: 경매장 API 작성
This commit is contained in:
@@ -90,8 +90,8 @@ function pushAuctionLog($log) {
|
|||||||
pushRawFileLog(__DIR__."/logs/".UniqueConst::$serverID."/_auctionlog.txt", $log);
|
pushRawFileLog(__DIR__."/logs/".UniqueConst::$serverID."/_auctionlog.txt", $log);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAuctionLogRecent(int $count) {
|
function getAuctionLogRecent(int $count): array {
|
||||||
return join('<br>', array_reverse(getFormattedFileLogRecent(__DIR__."/logs/".UniqueConst::$serverID."/_auctionlog.txt", $count, 300)));
|
return array_reverse(getRawFileLogRecent(__DIR__."/logs/".UniqueConst::$serverID."/_auctionlog.txt", $count, 300));
|
||||||
}
|
}
|
||||||
|
|
||||||
//DB-based
|
//DB-based
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\Auction;
|
||||||
|
|
||||||
|
use sammo\Session;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use sammo\AuctionBuyRice;
|
||||||
|
use sammo\AuctionUniqueItem;
|
||||||
|
use sammo\Validator;
|
||||||
|
use sammo\General;
|
||||||
|
|
||||||
|
class BidBuyRiceAuction extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
$v = new Validator($this->args);
|
||||||
|
$v->rule('required', [
|
||||||
|
'auctionID',
|
||||||
|
'amount',
|
||||||
|
])
|
||||||
|
->rule('int', 'amount')
|
||||||
|
->rule('int', 'auctionID');
|
||||||
|
|
||||||
|
if (!$v->validate()) {
|
||||||
|
return $v->errorStr();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_GAME_LOGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
$auctionID = $this->args['auctionID'];
|
||||||
|
$amount = $this->args['amount'];
|
||||||
|
|
||||||
|
$generalID = $session->generalID;
|
||||||
|
$general = General::createGeneralObjFromDB($generalID);
|
||||||
|
$auction = new AuctionBuyRice($auctionID, $general);
|
||||||
|
$result = $auction->bid($amount, true);
|
||||||
|
|
||||||
|
if (is_string($result)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\Auction;
|
||||||
|
|
||||||
|
use sammo\Session;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use sammo\AuctionSellRice;
|
||||||
|
use sammo\Validator;
|
||||||
|
use sammo\General;
|
||||||
|
|
||||||
|
class BidBuyRiceAuction extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
$v = new Validator($this->args);
|
||||||
|
$v->rule('required', [
|
||||||
|
'auctionID',
|
||||||
|
'amount',
|
||||||
|
])
|
||||||
|
->rule('int', 'amount')
|
||||||
|
->rule('int', 'auctionID');
|
||||||
|
|
||||||
|
if (!$v->validate()) {
|
||||||
|
return $v->errorStr();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_GAME_LOGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
$auctionID = $this->args['auctionID'];
|
||||||
|
$amount = $this->args['amount'];
|
||||||
|
|
||||||
|
$generalID = $session->generalID;
|
||||||
|
$general = General::createGeneralObjFromDB($generalID);
|
||||||
|
$auction = new AuctionSellRice($auctionID, $general);
|
||||||
|
$result = $auction->bid($amount, true);
|
||||||
|
|
||||||
|
if (is_string($result)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,22 +9,10 @@ use sammo\Validator;
|
|||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
|
|
||||||
use function sammo\buildItemClass;
|
|
||||||
|
|
||||||
class BidUniqueAuction extends \sammo\BaseAPI
|
class BidUniqueAuction extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
public function validateArgs(): ?string
|
public function validateArgs(): ?string
|
||||||
{
|
{
|
||||||
$availableItems = [];
|
|
||||||
foreach (GameConst::$allItems as $items) {
|
|
||||||
foreach ($items as $itemKey => $amount) {
|
|
||||||
if ($amount == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$availableItems[$itemKey] = $amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$v = new Validator($this->args);
|
$v = new Validator($this->args);
|
||||||
$v->rule('required', [
|
$v->rule('required', [
|
||||||
'auctionID',
|
'auctionID',
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\Auction;
|
||||||
|
|
||||||
|
use sammo\Session;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use sammo\AuctionSellRice;
|
||||||
|
use sammo\DB;
|
||||||
|
use sammo\DTO\AuctionBidItem;
|
||||||
|
use sammo\Enums\AuctionType;
|
||||||
|
use sammo\Validator;
|
||||||
|
use sammo\General;
|
||||||
|
use sammo\Json;
|
||||||
|
use sammo\TimeUtil;
|
||||||
|
use sammo\Util;
|
||||||
|
|
||||||
|
use function sammo\getAuctionLogRecent;
|
||||||
|
|
||||||
|
class GetActiveResourceAuctionList extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_GAME_LOGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
$db = DB::db();
|
||||||
|
|
||||||
|
$buyRiceList = [];
|
||||||
|
$sellRiceList = [];
|
||||||
|
$rawAuctions = $db->query(
|
||||||
|
'SELECT * FROM `ng_auction` WHERE `type` IN %ls AND `finished` != 0 ORDER BY `close_date` DESC',
|
||||||
|
[
|
||||||
|
AuctionType::BuyRice->value,
|
||||||
|
AuctionType::SellRice->value,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$auctionIDList = [];
|
||||||
|
foreach ($rawAuctions as $rawAuction) {
|
||||||
|
$auctionIDList[] = $rawAuction['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$rawHighestBids = Util::convertArrayToDict($db->query(
|
||||||
|
'SELECT bid.* FROM `ng_auction_bid` bid INNER JOIN (
|
||||||
|
SELECT `auction_id`, MAX(`amount`) as `max_amount`
|
||||||
|
FROM `ng_auction_bid`
|
||||||
|
WHERE `auction_id` IN %li
|
||||||
|
GROUP BY `auction_id`
|
||||||
|
ORDER BY `amount`
|
||||||
|
) AS max_bid
|
||||||
|
ON bid.`auction_id` = max_bid.`auction_id` AND bid.`amount` = max_bid.`max_amount`',
|
||||||
|
$auctionIDList,
|
||||||
|
) ?? [], 'auction_id');
|
||||||
|
/** @var array<int,AuctionBidItem> */
|
||||||
|
$highestBids = Util::mapWithKey(
|
||||||
|
fn ($auctionID, $bid) => AuctionBidItem::fromArray($bid),
|
||||||
|
$rawHighestBids
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($rawAuctions as $rawAuction) {
|
||||||
|
$detail = Json::decode($rawAuction['detail']);
|
||||||
|
unset($rawAuction['detail']);
|
||||||
|
$rawAuction = array_merge($rawAuction, $detail);
|
||||||
|
|
||||||
|
$highestBid = $highestBids[$rawAuction['id']] ?? null;
|
||||||
|
if($highestBid === null){
|
||||||
|
$rawAuction['highestBid'] = null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$rawAuction['hightestBid'] = [
|
||||||
|
'amount' => $highestBid->amount,
|
||||||
|
'date' => TimeUtil::format($highestBid->date, false),
|
||||||
|
'generalID' => $highestBid->generalID,
|
||||||
|
'generalName' => $highestBid->data->generalName,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($rawAuction['type'] == AuctionType::BuyRice->value) {
|
||||||
|
$buyRiceList[] = $rawAuction;
|
||||||
|
} else {
|
||||||
|
$sellRiceList[] = $rawAuction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$recentLogs = getAuctionLogRecent(20);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'result' => true,
|
||||||
|
'buyRice' => $buyRiceList,
|
||||||
|
'sellRice' => $sellRiceList,
|
||||||
|
'recentLogs' => $recentLogs
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,13 +4,11 @@ namespace sammo\API\Auction;
|
|||||||
|
|
||||||
use sammo\Session;
|
use sammo\Session;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use sammo\AuctionUniqueItem;
|
use sammo\AuctionBuyRice;
|
||||||
use sammo\Validator;
|
use sammo\Validator;
|
||||||
use sammo\GameConst;
|
use sammo\GameConst;
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
|
|
||||||
use function sammo\buildItemClass;
|
|
||||||
|
|
||||||
class OpenUniqueAuction extends \sammo\BaseAPI
|
class OpenUniqueAuction extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
public function validateArgs(): ?string
|
public function validateArgs(): ?string
|
||||||
@@ -27,12 +25,17 @@ class OpenUniqueAuction extends \sammo\BaseAPI
|
|||||||
|
|
||||||
$v = new Validator($this->args);
|
$v = new Validator($this->args);
|
||||||
$v->rule('required', [
|
$v->rule('required', [
|
||||||
'itemID',
|
'amount',
|
||||||
'amount'
|
'closeTurnCnt',
|
||||||
|
'startBidAmount',
|
||||||
|
'finishBidAmount',
|
||||||
])
|
])
|
||||||
->rule('int', 'amount')
|
->rule('int', 'amount')
|
||||||
->rule('min', 'amount', GameConst::$inheritItemUniqueMinPoint)
|
->rule('int', 'closeTurnCnt')
|
||||||
->rule('keyExists', 'itemID', $availableItems);
|
->rule('min', 'amount', 100)
|
||||||
|
->rule('max', 'amount', 10000)
|
||||||
|
->rule('int', 'startBidAmount')
|
||||||
|
->rule('int', 'finishBidAmount');
|
||||||
|
|
||||||
|
|
||||||
if (!$v->validate()) {
|
if (!$v->validate()) {
|
||||||
@@ -48,22 +51,34 @@ class OpenUniqueAuction extends \sammo\BaseAPI
|
|||||||
|
|
||||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
{
|
{
|
||||||
$itemID = $this->args['itemID'];
|
/** @var int */
|
||||||
$amount = $this->args['amount'];
|
$amount = $this->args['amount'];
|
||||||
|
/** @var int */
|
||||||
|
$closeTurnCnt = $this->args['closeTurnCnt'];
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
$startBidAmount = $this->args['startBidAmount'];
|
||||||
|
/** @var int */
|
||||||
|
$finishBidAmount = $this->args['finishBidAmount'];
|
||||||
$generalID = $session->generalID;
|
$generalID = $session->generalID;
|
||||||
|
|
||||||
$itemObj = buildItemClass($itemID);
|
|
||||||
$general = General::createGeneralObjFromDB($generalID);
|
$general = General::createGeneralObjFromDB($generalID);
|
||||||
|
|
||||||
$auctionResult = AuctionUniqueItem::openItemAuction($itemObj, $general, $amount);
|
$auctionResult = AuctionBuyRice::openResourceAuction(
|
||||||
|
$general,
|
||||||
|
$amount,
|
||||||
|
$closeTurnCnt,
|
||||||
|
$startBidAmount,
|
||||||
|
$finishBidAmount
|
||||||
|
);
|
||||||
|
|
||||||
if(is_string($auctionResult)) {
|
if (is_string($auctionResult)) {
|
||||||
return $auctionResult;
|
return $auctionResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'result' => true,
|
'result' => true,
|
||||||
'auctionID' => $auctionResult->id,
|
'auctionID' => $auctionResult->getInfo()->id,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace sammo\API\Auction;
|
||||||
|
|
||||||
|
use sammo\Session;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use sammo\AuctionSellRice;
|
||||||
|
use sammo\Validator;
|
||||||
|
use sammo\GameConst;
|
||||||
|
use sammo\General;
|
||||||
|
|
||||||
|
class OpenUniqueAuction extends \sammo\BaseAPI
|
||||||
|
{
|
||||||
|
public function validateArgs(): ?string
|
||||||
|
{
|
||||||
|
$availableItems = [];
|
||||||
|
foreach (GameConst::$allItems as $items) {
|
||||||
|
foreach ($items as $itemKey => $amount) {
|
||||||
|
if ($amount == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$availableItems[$itemKey] = $amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$v = new Validator($this->args);
|
||||||
|
$v->rule('required', [
|
||||||
|
'amount',
|
||||||
|
'closeTurnCnt',
|
||||||
|
'startBidAmount',
|
||||||
|
'finishBidAmount',
|
||||||
|
])
|
||||||
|
->rule('int', 'amount')
|
||||||
|
->rule('int', 'closeTurnCnt')
|
||||||
|
->rule('min', 'amount', 100)
|
||||||
|
->rule('max', 'amount', 10000)
|
||||||
|
->rule('int', 'startBidAmount')
|
||||||
|
->rule('int', 'finishBidAmount');
|
||||||
|
|
||||||
|
|
||||||
|
if (!$v->validate()) {
|
||||||
|
return $v->errorStr();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRequiredSessionMode(): int
|
||||||
|
{
|
||||||
|
return static::REQ_GAME_LOGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||||
|
{
|
||||||
|
/** @var int */
|
||||||
|
$amount = $this->args['amount'];
|
||||||
|
/** @var int */
|
||||||
|
$closeTurnCnt = $this->args['closeTurnCnt'];
|
||||||
|
|
||||||
|
/** @var int */
|
||||||
|
$startBidAmount = $this->args['startBidAmount'];
|
||||||
|
/** @var int */
|
||||||
|
$finishBidAmount = $this->args['finishBidAmount'];
|
||||||
|
$generalID = $session->generalID;
|
||||||
|
|
||||||
|
$general = General::createGeneralObjFromDB($generalID);
|
||||||
|
|
||||||
|
$auctionResult = AuctionSellRice::openResourceAuction(
|
||||||
|
$general,
|
||||||
|
$amount,
|
||||||
|
$closeTurnCnt,
|
||||||
|
$startBidAmount,
|
||||||
|
$finishBidAmount
|
||||||
|
);
|
||||||
|
|
||||||
|
if (is_string($auctionResult)) {
|
||||||
|
return $auctionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'result' => true,
|
||||||
|
'auctionID' => $auctionResult->getInfo()->id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,7 +63,7 @@ class OpenUniqueAuction extends \sammo\BaseAPI
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'result' => true,
|
'result' => true,
|
||||||
'auctionID' => $auctionResult->id,
|
'auctionID' => $auctionResult->getInfo()->id,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use DateTimeInterface;
|
|||||||
use sammo\DTO\AuctionBidItem;
|
use sammo\DTO\AuctionBidItem;
|
||||||
use sammo\DTO\AuctionBidItemData;
|
use sammo\DTO\AuctionBidItemData;
|
||||||
use sammo\DTO\AuctionInfo;
|
use sammo\DTO\AuctionInfo;
|
||||||
|
use sammo\Enums\AuctionType;
|
||||||
use sammo\Enums\InheritanceKey;
|
use sammo\Enums\InheritanceKey;
|
||||||
use sammo\Enums\RankColumn;
|
use sammo\Enums\RankColumn;
|
||||||
use sammo\Enums\ResourceType;
|
use sammo\Enums\ResourceType;
|
||||||
@@ -17,6 +18,8 @@ abstract class Auction
|
|||||||
|
|
||||||
protected AuctionInfo $info;
|
protected AuctionInfo $info;
|
||||||
|
|
||||||
|
static AuctionType $auctionType;
|
||||||
|
|
||||||
public const COEFF_AUCTION_CLOSE_MINUTES = 24;
|
public const COEFF_AUCTION_CLOSE_MINUTES = 24;
|
||||||
public const COEFF_EXTENSION_MINUTES_PER_BID = 1 / 6;
|
public const COEFF_EXTENSION_MINUTES_PER_BID = 1 / 6;
|
||||||
public const COEFF_EXTENSION_MINUTES_LIMIT_BY_BID = 1;
|
public const COEFF_EXTENSION_MINUTES_LIMIT_BY_BID = 1;
|
||||||
@@ -91,6 +94,9 @@ abstract class Auction
|
|||||||
throw new \RuntimeException("해당 경매가 없습니다: {$auctionID}");
|
throw new \RuntimeException("해당 경매가 없습니다: {$auctionID}");
|
||||||
}
|
}
|
||||||
$this->info = AuctionInfo::fromArray($rawAuctionInfo);
|
$this->info = AuctionInfo::fromArray($rawAuctionInfo);
|
||||||
|
if($this->info->type !== $this->auctionType){
|
||||||
|
throw new \RuntimeException("잘못된 경매 타입입니다: {$this->info->type} != {$this->auctionType}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInfo(): AuctionInfo
|
public function getInfo(): AuctionInfo
|
||||||
@@ -420,7 +426,7 @@ abstract class Auction
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract public function bid(int $amount, bool $tryExtendCloseDate = false): ?string;
|
abstract public function bid(int $amount, bool $tryExtendCloseDate): ?string;
|
||||||
|
|
||||||
abstract protected function rollbackAuction(): void;
|
abstract protected function rollbackAuction(): void;
|
||||||
abstract protected function finishAuction(AuctionBidItem $highestBid, General $bidder): ?string;
|
abstract protected function finishAuction(AuctionBidItem $highestBid, General $bidder): ?string;
|
||||||
|
|||||||
@@ -13,11 +13,10 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
{
|
{
|
||||||
const MIN_AUCTION_AMOUNT = 100;
|
const MIN_AUCTION_AMOUNT = 100;
|
||||||
const MAX_AUCTION_AMOUNT = 10000;
|
const MAX_AUCTION_AMOUNT = 10000;
|
||||||
static AuctionType $auctionType;
|
|
||||||
static ResourceType $hostRes;
|
static ResourceType $hostRes;
|
||||||
static ResourceType $bidderRes;
|
static ResourceType $bidderRes;
|
||||||
|
|
||||||
static public function openBuyRiceAuction(General $general, int $amount, int $closeTurnCnt, int $startBidAmount, int $finishBidAmount): self|string
|
static public function openResourceAuction(General $general, int $amount, int $closeTurnCnt, int $startBidAmount, int $finishBidAmount): self|string
|
||||||
{
|
{
|
||||||
if ($closeTurnCnt < 1 || $closeTurnCnt > 24) {
|
if ($closeTurnCnt < 1 || $closeTurnCnt > 24) {
|
||||||
return '종료기한은 1 ~ 24 턴 이어야 합니다.';
|
return '종료기한은 1 ~ 24 턴 이어야 합니다.';
|
||||||
@@ -44,15 +43,18 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
}
|
}
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$prevAuctionID = $db->queryFirstField(
|
if (!($general instanceof DummyGeneral)) {
|
||||||
'SELECT id FROM ng_auction WHERE opener_general_id = %i AND finished = 0 AND `type` IN %ls',
|
$prevAuctionID = $db->queryFirstField(
|
||||||
$general->getID(),
|
'SELECT id FROM ng_auction WHERE opener_general_id = %i AND finished = 0 AND `type` IN %ls',
|
||||||
[AuctionType::BuyRice->value, AuctionType::SellRice->value],
|
$general->getID(),
|
||||||
);
|
[AuctionType::BuyRice->value, AuctionType::SellRice->value],
|
||||||
if ($prevAuctionID !== null) {
|
);
|
||||||
return '아직 경매가 끝나지 않았습니다.';
|
if ($prevAuctionID !== null) {
|
||||||
|
return '아직 경매가 끝나지 않았습니다.';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$now = new \DateTimeImmutable();
|
$now = new \DateTimeImmutable();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$turnTerm = $gameStor->getValue('turnterm');
|
$turnTerm = $gameStor->getValue('turnterm');
|
||||||
@@ -89,10 +91,21 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
return new self($openResult, $general);
|
return new self($openResult, $general);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public function genDummy(): DummyGeneral
|
||||||
|
{
|
||||||
|
$dummyGeneral = new DummyGeneral(true);
|
||||||
|
$dummyGeneral->setVar('name', '상인');
|
||||||
|
$dummyGeneral->setVar('gold', static::MAX_AUCTION_AMOUNT * 10);
|
||||||
|
$dummyGeneral->setVar('rice', static::MAX_AUCTION_AMOUNT * 10);
|
||||||
|
return $dummyGeneral;
|
||||||
|
}
|
||||||
|
|
||||||
protected function rollbackAuction(): void
|
protected function rollbackAuction(): void
|
||||||
{
|
{
|
||||||
if ($this->general->getID() === $this->info->openerGeneralID) {
|
if ($this->general->getID() === $this->info->openerGeneralID) {
|
||||||
$auctionHost = $this->general;
|
$auctionHost = $this->general;
|
||||||
|
} else if ($this->info->openerGeneralID == 0) {
|
||||||
|
$auctionHost = $this->genDummy();
|
||||||
} else {
|
} else {
|
||||||
$auctionHost = General::createGeneralObjFromDB($this->info->openerGeneralID);
|
$auctionHost = General::createGeneralObjFromDB($this->info->openerGeneralID);
|
||||||
}
|
}
|
||||||
@@ -132,6 +145,8 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
{
|
{
|
||||||
if ($this->general->getID() === $this->info->openerGeneralID) {
|
if ($this->general->getID() === $this->info->openerGeneralID) {
|
||||||
$auctionHost = $this->general;
|
$auctionHost = $this->general;
|
||||||
|
} else if ($this->info->openerGeneralID == 0) {
|
||||||
|
$auctionHost = $this->genDummy();
|
||||||
} else {
|
} else {
|
||||||
$auctionHost = General::createGeneralObjFromDB($this->info->openerGeneralID);
|
$auctionHost = General::createGeneralObjFromDB($this->info->openerGeneralID);
|
||||||
}
|
}
|
||||||
@@ -174,7 +189,6 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
|
|
||||||
$josaYiHost = JosaUtil::pick($auctionHost->getName(), '이');
|
$josaYiHost = JosaUtil::pick($auctionHost->getName(), '이');
|
||||||
$josaYiBidder = JosaUtil::pick($bidder->getName(), '이');
|
$josaYiBidder = JosaUtil::pick($bidder->getName(), '이');
|
||||||
$josaRo = JosaUtil::pick($bidAmount, '로');
|
|
||||||
|
|
||||||
$auctionLog = [];
|
$auctionLog = [];
|
||||||
$auctionLog[] = "{$auctionID}번 {$hostResName} 경매 <C>성사</> : <Y>{$auctionHost->getName()}</>{$josaYiHost} {$hostResName} <C>{$auctionAmount}</> 판매, <Y>{$bidder->getName()}</>{$josaYiBidder} <C>{$bidAmount}</> 구매";
|
$auctionLog[] = "{$auctionID}번 {$hostResName} 경매 <C>성사</> : <Y>{$auctionHost->getName()}</>{$josaYiHost} {$hostResName} <C>{$auctionAmount}</> 판매, <Y>{$bidder->getName()}</>{$josaYiBidder} <C>{$bidAmount}</> 구매";
|
||||||
@@ -188,7 +202,7 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
|
|
||||||
pushAuctionLog(array_map(
|
pushAuctionLog(array_map(
|
||||||
fn ($log) =>
|
fn ($log) =>
|
||||||
$auctionHost->getLogger()->formatText($log, ActionLogger::EVENT_PLAIN),
|
$bidder->getLogger()->formatText($log, ActionLogger::EVENT_PLAIN),
|
||||||
$auctionLog
|
$auctionLog
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -199,18 +213,18 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bid(int $amount, bool $_tryExtendCloseDate = true): ?string
|
public function bid(int $amount, bool $tryExtendCloseDate = false): ?string
|
||||||
{
|
{
|
||||||
if ($this->info->openerGeneralID === $this->general->getID()) {
|
if ($this->info->openerGeneralID === $this->general->getID()) {
|
||||||
return '자신이 연 경매에 입찰할 수 없습니다.';
|
return '자신이 연 경매에 입찰할 수 없습니다.';
|
||||||
}
|
}
|
||||||
$result = $this->_bid($amount, true);
|
$result = $this->_bid($amount, $tryExtendCloseDate);
|
||||||
|
|
||||||
if(is_string($result)){
|
if (is_string($result)) {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($amount === $this->info->detail->finishBidAmount){
|
if ($amount === $this->info->detail->finishBidAmount) {
|
||||||
//즉구, 1턴 후 지급
|
//즉구, 1턴 후 지급
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
@@ -218,6 +232,5 @@ abstract class AuctionBasicResource extends Auction
|
|||||||
$date = (new DateTimeImmutable())->add(TimeUtil::secondsToDateInterval($turnTerm * 60));
|
$date = (new DateTimeImmutable())->add(TimeUtil::secondsToDateInterval($turnTerm * 60));
|
||||||
$this->shrinkCloseDate($date);
|
$this->shrinkCloseDate($date);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
namespace sammo;
|
namespace sammo;
|
||||||
|
|
||||||
use sammo\DTO\AuctionBidItem;
|
|
||||||
use sammo\DTO\AuctionInfo;
|
|
||||||
use sammo\DTO\AuctionInfoDetail;
|
|
||||||
use sammo\Enums\AuctionType;
|
use sammo\Enums\AuctionType;
|
||||||
use sammo\Enums\ResourceType;
|
use sammo\Enums\ResourceType;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ use sammo\RandUtil;
|
|||||||
|
|
||||||
class AuctionUniqueItem extends Auction
|
class AuctionUniqueItem extends Auction
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static AuctionType $auctionType = AuctionType::UniqueItem;
|
||||||
|
|
||||||
static public function genObfuscatedName(int $id): string
|
static public function genObfuscatedName(int $id): string
|
||||||
{
|
{
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
@@ -131,7 +134,7 @@ class AuctionUniqueItem extends Auction
|
|||||||
}
|
}
|
||||||
$auction = new static($auctionID, $general);
|
$auction = new static($auctionID, $general);
|
||||||
try {
|
try {
|
||||||
$auction->bid($startAmount);
|
$auction->bid($startAmount, false);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
//실패해선 안된다.
|
//실패해선 안된다.
|
||||||
$msg = $e->getMessage();
|
$msg = $e->getMessage();
|
||||||
@@ -147,7 +150,7 @@ class AuctionUniqueItem extends Auction
|
|||||||
// 유니크 옥션의 개최자는 운영자이므로 할 일이 없다.
|
// 유니크 옥션의 개최자는 운영자이므로 할 일이 없다.
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bid(int $amount, bool $tryExtendCloseDate = false): ?string
|
public function bid(int $amount, bool $tryExtendCloseDate): ?string
|
||||||
{
|
{
|
||||||
|
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
@@ -157,10 +160,21 @@ class AuctionUniqueItem extends Auction
|
|||||||
AuctionType::UniqueItem->value
|
AuctionType::UniqueItem->value
|
||||||
) ?? []);
|
) ?? []);
|
||||||
|
|
||||||
|
$auctionIDList = [];
|
||||||
|
foreach($openUniqueAuctions as $auction){
|
||||||
|
$auctionIDList[] = $auction->id;
|
||||||
|
}
|
||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
$rawHighestBids = Util::convertArrayToDict($db->queryFirstRow(
|
$rawHighestBids = Util::convertArrayToDict($db->query(
|
||||||
'SELECT * FROM ng_auction_bid WHERE auction_id IN %i ORDER BY `amount` DESC LIMIT 1',
|
'SELECT bid.* FROM `ng_auction_bid` bid INNER JOIN (
|
||||||
$this->info->id
|
SELECT `auction_id`, MAX(`amount`) as `max_amount`
|
||||||
|
FROM `ng_auction_bid`
|
||||||
|
WHERE `auction_id` IN %li
|
||||||
|
GROUP BY `auction_id`
|
||||||
|
ORDER BY `amount`
|
||||||
|
) AS max_bid
|
||||||
|
ON bid.`auction_id` = max_bid.`auction_id` AND bid.`amount` = max_bid.`max_amount`',
|
||||||
|
$auctionIDList,
|
||||||
) ?? [], 'auction_id');
|
) ?? [], 'auction_id');
|
||||||
/** @var array<int,AuctionBidItem> */
|
/** @var array<int,AuctionBidItem> */
|
||||||
$highestBids = Util::mapWithKey(
|
$highestBids = Util::mapWithKey(
|
||||||
|
|||||||
+1
-1
@@ -721,7 +721,7 @@ CREATE TABLE `ng_auction_bid` (
|
|||||||
PRIMARY KEY (`no`),
|
PRIMARY KEY (`no`),
|
||||||
UNIQUE INDEX `by_general` (`general_id`, `auction_id`, `amount`),
|
UNIQUE INDEX `by_general` (`general_id`, `auction_id`, `amount`),
|
||||||
UNIQUE INDEX `by_owner` (`owner`, `auction_id`, `amount`),
|
UNIQUE INDEX `by_owner` (`owner`, `auction_id`, `amount`),
|
||||||
INDEX `by_amount` (`auction_id`, `amount`, `date`),
|
UNIQUE INDEX `by_amount` (`auction_id`, `amount`),
|
||||||
CONSTRAINT `aux` CHECK (json_valid(`aux`))
|
CONSTRAINT `aux` CHECK (json_valid(`aux`))
|
||||||
)
|
)
|
||||||
COLLATE='utf8mb4_general_ci'
|
COLLATE='utf8mb4_general_ci'
|
||||||
|
|||||||
Reference in New Issue
Block a user