feat,wip: 금,쌀 거래장 관련 로직 조정
This commit is contained in:
+121
-22
@@ -12,7 +12,7 @@ use sammo\Enums\InheritanceKey;
|
||||
use sammo\Enums\RankColumn;
|
||||
use sammo\Enums\ResourceType;
|
||||
|
||||
class Auction
|
||||
abstract class Auction
|
||||
{
|
||||
|
||||
protected AuctionInfo $info;
|
||||
@@ -26,22 +26,15 @@ class Auction
|
||||
public const MIN_EXTENSION_MINUTES_LIMIT_BY_BID = 5;
|
||||
public const MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY = 5;
|
||||
|
||||
static public function openAuction(AuctionInfo $info, General $general): int|string
|
||||
protected AuctionBidItem|null|false $_highestBid = false;
|
||||
|
||||
static protected function openAuction(AuctionInfo $info, General $general): int|string
|
||||
{
|
||||
$db = DB::db();
|
||||
if ($info->id !== null) {
|
||||
return 'id가 지정되어 있습니다.';
|
||||
}
|
||||
|
||||
$prevAuctionID = $db->queryFirstField(
|
||||
'SELECT id FROM ng_auction WHERE opener_general_id = %i AND finished = 0 AND `type` = %s',
|
||||
$general->getID(),
|
||||
$info->type
|
||||
);
|
||||
if ($prevAuctionID !== null) {
|
||||
return '아직 경매가 끝나지 않았습니다.';
|
||||
}
|
||||
|
||||
$db->insert('ng_auction', $info->toArray());
|
||||
return $db->insertId();
|
||||
}
|
||||
@@ -49,15 +42,31 @@ class Auction
|
||||
public function getHighestBid(): ?AuctionBidItem
|
||||
{
|
||||
$db = DB::db();
|
||||
$rawHighestBid = $db->queryFirstRow(
|
||||
'SELECT * FROM ng_auction_bid WHERE auction_id = %i ORDER BY `amount` DESC LIMIT 1',
|
||||
$this->info->id
|
||||
);
|
||||
|
||||
if($this->_highestBid !== false){
|
||||
return $this->_highestBid;
|
||||
}
|
||||
|
||||
if (!$this->info->detail->isReverse) {
|
||||
$rawHighestBid = $db->queryFirstRow(
|
||||
'SELECT * FROM ng_auction_bid WHERE auction_id = %i ORDER BY `amount` DESC LIMIT 1',
|
||||
$this->info->id
|
||||
);
|
||||
} else {
|
||||
$rawHighestBid = $db->queryFirstRow(
|
||||
'SELECT * FROM ng_auction_bid WHERE auction_id = %i ORDER BY `amount` ASC LIMIT 1',
|
||||
$this->info->id
|
||||
);
|
||||
}
|
||||
|
||||
if (!$rawHighestBid) {
|
||||
$this->_highestBid = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return AuctionBidItem::fromArray($rawHighestBid);
|
||||
$highestBid = AuctionBidItem::fromArray($rawHighestBid);
|
||||
$this->_highestBid = $highestBid;
|
||||
return $highestBid;
|
||||
}
|
||||
|
||||
public function getMyPrevBid(): ?AuctionBidItem
|
||||
@@ -89,6 +98,18 @@ class Auction
|
||||
return $this->info;
|
||||
}
|
||||
|
||||
public function shrinkCloseDate(?DateTimeInterface $date): ?string{
|
||||
if($date === null){
|
||||
$date = new DateTimeImmutable();
|
||||
}
|
||||
|
||||
$this->info->closeDate = $date;
|
||||
$db = DB::db();
|
||||
$db->update('ng_auction', $this->info->toArrayExcept('id'), 'id = %i', $this->info->id);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function extendCloseDate(DateTimeInterface $date, bool $force = false): ?string
|
||||
{
|
||||
if (!$force) {
|
||||
@@ -171,6 +192,7 @@ class Auction
|
||||
if ($highestBid !== null) {
|
||||
$this->refundBid($highestBid, "{$this->info->title} 경매가 취소되었습니다.");
|
||||
}
|
||||
$this->rollbackAuction();
|
||||
}
|
||||
|
||||
$db->update('ng_auction', $this->info->toArrayExcept('id'), 'id = %i', $this->info->id);
|
||||
@@ -248,7 +270,7 @@ class Auction
|
||||
return null;
|
||||
}
|
||||
|
||||
public function bid(int $amount, bool $tryExtendCloseDate = false): ?string
|
||||
protected function _bid(int $amount, bool $tryExtendCloseDate = false): ?string
|
||||
{
|
||||
$auctionInfo = $this->info;
|
||||
$general = $this->general;
|
||||
@@ -266,10 +288,17 @@ class Auction
|
||||
return '경매가 아직 시작되지 않았습니다.';
|
||||
}
|
||||
|
||||
if ($auctionInfo->buyImmediatelyAmount !== null && $auctionInfo->buyImmediatelyAmount < $amount) {
|
||||
return '즉시판매가보다 높을 수 없습니다.';
|
||||
if (!$auctionInfo->detail->isReverse) {
|
||||
if ($auctionInfo->buyImmediatelyAmount !== null && $auctionInfo->buyImmediatelyAmount < $amount) {
|
||||
return '즉시판매가보다 높을 수 없습니다.';
|
||||
}
|
||||
} else {
|
||||
if ($auctionInfo->buyImmediatelyAmount !== null && $auctionInfo->buyImmediatelyAmount > $amount) {
|
||||
return '즉시판매가보다 낮을 수 없습니다.';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($auctionInfo->reqResource === ResourceType::inheritancePoint) {
|
||||
return $this->bidInheritPoint($amount, $now, $tryExtendCloseDate);
|
||||
}
|
||||
@@ -279,10 +308,17 @@ class Auction
|
||||
$db = DB::db();
|
||||
|
||||
$highestBid = $this->getHighestBid();
|
||||
if ($highestBid !== null && $amount <= $highestBid->amount) {
|
||||
return '현재입찰가보다 높게 입찰해야 합니다.';
|
||||
if (!$auctionInfo->detail->isReverse) {
|
||||
if ($highestBid !== null && $amount <= $highestBid->amount) {
|
||||
return '현재입찰가보다 높게 입찰해야 합니다.';
|
||||
}
|
||||
} else {
|
||||
if ($highestBid !== null && $amount >= $highestBid->amount) {
|
||||
return '현재입찰가보다 낮게 입찰해야 합니다.';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$myPrevBid = $this->getMyPrevBid();
|
||||
|
||||
$morePoint = $amount - ($myPrevBid ? $myPrevBid->amount : 0);
|
||||
@@ -317,7 +353,7 @@ class Auction
|
||||
return '입찰에 실패했습니다: DB 오류';
|
||||
}
|
||||
|
||||
$general->setVar($resType->value, $general->getVar($resType->value) - $morePoint);
|
||||
$general->increaseVar($resType->value, -$morePoint);
|
||||
|
||||
if ($myPrevBid === null || ($highestBid !== null && $myPrevBid->id !== $highestBid->id)) {
|
||||
$this->refundBid($highestBid, "{$auctionInfo->title} 경매에 상회입찰자가 나타났습니다.");
|
||||
@@ -325,4 +361,67 @@ class Auction
|
||||
$general->applyDB($db);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function tryFinish(): ?bool
|
||||
{
|
||||
$now = new DateTimeImmutable();
|
||||
if ($now < $this->info->closeDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//경매를 닫아야한다.
|
||||
$highestBid = $this->getHighestBid();
|
||||
if ($highestBid === null) {
|
||||
$this->closeAuction(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($highestBid->data->tryExtendCloseDate) {
|
||||
//연장 요청이 있었다.
|
||||
$extendedCloseDate = $this->info->closeDate->add(TimeUtil::secondsToDateInterval(
|
||||
max(static::MIN_EXTENSION_MINUTES_BY_EXTENSION_QUERY, $this->info->turnTerm * static::COEFF_EXTENSION_MINUTES_BY_EXTENSION_QUERY) * 60
|
||||
));
|
||||
|
||||
if ($this->extendCloseDate($extendedCloseDate) === null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$bidder = General::createGeneralObjFromDB($highestBid->generalID);
|
||||
$failReason = $this->finishAuction($highestBid, $bidder);
|
||||
if ($failReason === null) {
|
||||
$this->closeAuction();
|
||||
return true;
|
||||
}
|
||||
|
||||
$staticNation = $bidder->getStaticNation();
|
||||
$src = new MessageTarget(0, '', 0, 'System', '#000000');
|
||||
$dest = new MessageTarget(
|
||||
$bidder->getID(),
|
||||
$bidder->getName(),
|
||||
$bidder->getNationID(),
|
||||
$staticNation['name'],
|
||||
$staticNation['color'],
|
||||
GetImageURL($bidder->getVar('imgsvr'), $bidder->getVar('picture'))
|
||||
);
|
||||
|
||||
//TODO: 전역 알림이 나타나야한다. 일반 메시지보다는 중요하고, 메시지보단 약하게..
|
||||
//TODO: 바로가기를 제공하는 편이 좋을 것 같다.
|
||||
$msg = new Message(
|
||||
Message::MSGTYPE_PRIVATE,
|
||||
$src,
|
||||
$dest,
|
||||
$failReason,
|
||||
new \DateTime(),
|
||||
new \DateTime('9999-12-31'),
|
||||
[]
|
||||
);
|
||||
$msg->send(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
abstract public function bid(int $amount, bool $tryExtendCloseDate = false): ?string;
|
||||
|
||||
abstract protected function rollbackAuction(): void;
|
||||
abstract protected function finishAuction(AuctionBidItem $highestBid, General $bidder): ?string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user