feat,wip: 금,쌀 거래장 관련 로직 조정

This commit is contained in:
2022-06-09 01:21:21 +09:00
parent 3784aa09fc
commit f607350442
9 changed files with 572 additions and 190 deletions
+121 -22
View File
@@ -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;
}