diff --git a/hwe/_119_b.php b/hwe/_119_b.php index 9e18f21f..364d36af 100644 --- a/hwe/_119_b.php +++ b/hwe/_119_b.php @@ -50,9 +50,7 @@ switch ($btn) { $db->update('general', [ 'turntime' => $db->sqleval('DATE_SUB(turntime, INTERVAL %i MINUTE)', $minute) ], true); - $db->update('auction', [ - 'expire' => $db->sqleval('DATE_SUB(expire, INTERVAL %i MINUTE)', $minute) - ], true); + //TODO: 경매 시간도 모두 당겨야함 if ($locked) { unlock(); } @@ -78,9 +76,7 @@ switch ($btn) { $db->update('general', [ 'turntime' => $db->sqleval('DATE_ADD(turntime, INTERVAL %i MINUTE)', $minute) ], true); - $db->update('auction', [ - 'expire' => $db->sqleval('DATE_ADD(expire, INTERVAL %i MINUTE)', $minute) - ], true); + //TODO: 경매시간도 모두 뒤로 미뤄야함 if ($locked) { unlock(); } diff --git a/hwe/j_install.php b/hwe/j_install.php index 43301a3d..9a3124ba 100644 --- a/hwe/j_install.php +++ b/hwe/j_install.php @@ -4,8 +4,6 @@ namespace sammo; include "lib.php"; include "func.php"; -WebUtil::requireAJAX(); - $session = Session::requireLogin([])->setReadOnly(); if(!class_exists('\\sammo\\DB')){ diff --git a/hwe/sammo/API/Auction/GetActiveResourceAuctionList.php b/hwe/sammo/API/Auction/GetActiveResourceAuctionList.php index b3608e14..099fec0d 100644 --- a/hwe/sammo/API/Auction/GetActiveResourceAuctionList.php +++ b/hwe/sammo/API/Auction/GetActiveResourceAuctionList.php @@ -37,18 +37,32 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI $sellRiceList = []; /** @var AuctionInfo[] */ $auctions = array_map(fn ($raw) => AuctionInfo::fromArray($raw), $db->query( - 'SELECT * FROM `ng_auction` WHERE `type` IN %ls AND `finished` != 0 ORDER BY `close_date` DESC', + 'SELECT * FROM `ng_auction` WHERE `type` IN %ls AND `finished` = 0 ORDER BY `close_date` DESC', [ AuctionType::BuyRice->value, AuctionType::SellRice->value, ] )); + $recentLogs = getAuctionLogRecent(20); + + + if (!$auctions) { + return [ + 'result' => true, + 'buyRice' => $buyRiceList, + 'sellRice' => $sellRiceList, + 'recentLogs' => $recentLogs, + 'generalID' => $session->generalID, + ]; + } + $auctionIDList = []; foreach ($auctions as $auction) { $auctionIDList[] = $auction->id; } + $rawHighestBids = Util::convertArrayToDict($db->query( 'SELECT bid.* FROM `ng_auction_bid` bid INNER JOIN ( SELECT `auction_id`, MAX(`amount`) as `max_amount` @@ -87,7 +101,7 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI 'amount' => $highestBid->amount, 'date' => TimeUtil::format($highestBid->date, false), 'generalID' => $highestBid->generalID, - 'generalName' => $highestBid->data->generalName, + 'generalName' => $highestBid->aux->generalName, ]; } @@ -98,8 +112,6 @@ class GetActiveResourceAuctionList extends \sammo\BaseAPI } } - $recentLogs = getAuctionLogRecent(20); - return [ 'result' => true, 'buyRice' => $buyRiceList, diff --git a/hwe/sammo/API/Auction/GetUniqueItemAuctionDetail.php b/hwe/sammo/API/Auction/GetUniqueItemAuctionDetail.php index 5428e62d..2564995a 100644 --- a/hwe/sammo/API/Auction/GetUniqueItemAuctionDetail.php +++ b/hwe/sammo/API/Auction/GetUniqueItemAuctionDetail.php @@ -60,7 +60,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI $responseBid = []; foreach ($bidList as $bid) { $responseBid[] = [ - 'generalName' => $bid->data->generalName, + 'generalName' => $bid->aux->generalName, 'amount' => $bid->amount, 'isCallerHighestBidder' => $bid->generalID === $generalID, 'date' => $bid->date, @@ -74,7 +74,7 @@ class GetUniqueItemAuctionDetail extends \sammo\BaseAPI 'finished' => $auction->finished, 'title' => $auction->detail->title, 'target' => $auction->target, - 'isCallerHost' => $auction->openerGeneralID === $generalID, + 'isCallerHost' => $auction->hostGeneralID === $generalID, 'hostName' => $auction->detail->hostName, 'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt, 'availableLatestBidCloseDate' => $auction->detail->availableLatestBidCloseDate, diff --git a/hwe/sammo/API/Auction/GetUniqueItemAuctionList.php b/hwe/sammo/API/Auction/GetUniqueItemAuctionList.php index 47a3027d..0faaf0f8 100644 --- a/hwe/sammo/API/Auction/GetUniqueItemAuctionList.php +++ b/hwe/sammo/API/Auction/GetUniqueItemAuctionList.php @@ -69,12 +69,12 @@ class GetUniqueItemAuctionList extends \sammo\BaseAPI 'finished' => $auction->finished, 'title' => $auction->detail->title, 'target' => $auction->target, - 'isCallerHost' => $auction->openerGeneralID === $generalID, + 'isCallerHost' => $auction->hostGeneralID === $generalID, 'hostName' => $auction->detail->hostName, 'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt, 'availableLatestBidCloseDate' => $auction->detail->availableLatestBidCloseDate, 'highestBid' => [ - 'generalName' => $highestBid->data->generalName, + 'generalName' => $highestBid->aux->generalName, 'amount' => $highestBid->amount, 'isCallerHighestBidder' => $highestBid->generalID === $generalID, 'date' => $highestBid->date, diff --git a/hwe/sammo/Auction.php b/hwe/sammo/Auction.php index be771268..cef03db5 100644 --- a/hwe/sammo/Auction.php +++ b/hwe/sammo/Auction.php @@ -46,7 +46,7 @@ abstract class Auction { $db = DB::db(); - if($this->_highestBid !== false){ + if ($this->_highestBid !== false) { return $this->_highestBid; } @@ -75,11 +75,19 @@ abstract class Auction public function getMyPrevBid(): ?AuctionBidItem { $db = DB::db(); - $rawMyPrevBid = $db->queryFirstRow( - 'SELECT * FROM ng_auction_bid WHERE general_id = %i AND auction_id = %i ORDER BY `amount` DESC LIMIT 1', - $this->general->getID(), - $this->info->id - ); + if (!$this->info->detail->isReverse) { + $rawMyPrevBid = $db->queryFirstRow( + 'SELECT * FROM ng_auction_bid WHERE general_id = %i AND auction_id = %i ORDER BY `amount` DESC LIMIT 1', + $this->general->getID(), + $this->info->id + ); + } else { + $rawMyPrevBid = $db->queryFirstRow( + 'SELECT * FROM ng_auction_bid WHERE general_id = %i AND auction_id = %i ORDER BY `amount` ASC LIMIT 1', + $this->general->getID(), + $this->info->id + ); + } if (!$rawMyPrevBid) { return null; } @@ -89,13 +97,14 @@ abstract class Auction public function __construct(protected readonly int $auctionID, protected General $general) { $db = DB::db(); - $rawAuctionInfo = $db->query('SELECT * FROM ng_auction WHERE id = %i', $auctionID); - if ($rawAuctionInfo === null) { + $rawAuctionInfo = $db->queryFirstRow('SELECT * FROM `ng_auction` WHERE id = %i', $auctionID); + if (!$rawAuctionInfo) { throw new \RuntimeException("해당 경매가 없습니다: {$auctionID}"); } $this->info = AuctionInfo::fromArray($rawAuctionInfo); - if($this->info->type !== $this->auctionType){ - throw new \RuntimeException("잘못된 경매 타입입니다: {$this->info->type} != {$this->auctionType}"); + $thisAuctionType = static::$auctionType; + if ($this->info->type !== $thisAuctionType) { + throw new \RuntimeException("잘못된 경매 타입입니다: {$this->info->type->value} != {$thisAuctionType->value}"); } } @@ -104,8 +113,9 @@ abstract class Auction return $this->info; } - public function shrinkCloseDate(?DateTimeInterface $date): ?string{ - if($date === null){ + public function shrinkCloseDate(?DateTimeInterface $date): ?string + { + if ($date === null) { $date = new DateTimeImmutable(); } @@ -196,7 +206,7 @@ abstract class Auction if ($isRollback) { $highestBid = $this->getHighestBid(); if ($highestBid !== null) { - $this->refundBid($highestBid, "{$this->info->title} 경매가 취소되었습니다."); + $this->refundBid($highestBid, "{$this->info->id}번 {$this->info->detail->title} 경매가 취소되었습니다."); } $this->rollbackAuction(); } @@ -216,15 +226,10 @@ abstract class Auction return '현재입찰가보다 높게 입찰해야 합니다.'; } - $rawMyPrevBid = $db->queryFirstRow( - 'SELECT * FROM ng_auction_bid WHERE general_id = %i AND auction_id = %i ORDER BY `amount` DESC LIMIT 1', - $general->getID(), - $auctionInfo->id - ); - if ($rawMyPrevBid === null) { + $myPrevBid = $this->getMyPrevBid(); + if($myPrevBid !== null && $highestBid->no !== $myPrevBid->no){ + //이미 환불 받았으니 무효. $myPrevBid = null; - } else { - $myPrevBid = AuctionBidItem::fromArray($rawMyPrevBid); } $morePoint = $amount - ($myPrevBid ? $myPrevBid->amount : 0); @@ -269,8 +274,8 @@ abstract class Auction $general->increaseInheritancePoint(InheritanceKey::previous, -$morePoint); $general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, $morePoint); - if ($myPrevBid === null || ($highestBid !== null && $myPrevBid->id !== $highestBid->id)) { - $this->refundBid($highestBid, "{$auctionInfo->title} 경매에 상회입찰자가 나타났습니다."); + if ($highestBid !== null && $myPrevBid === null) { + $this->refundBid($highestBid, "{$auctionInfo->id}번 $auctionInfo->detail->title}에 상회입찰자가 나타났습니다."); } $general->applyDB($db); return null; @@ -326,6 +331,10 @@ abstract class Auction $myPrevBid = $this->getMyPrevBid(); + if($myPrevBid !== null && $highestBid->no !== $myPrevBid->no){ + //이미 환불 받았으니 무효. + $myPrevBid = null; + } $morePoint = $amount - ($myPrevBid ? $myPrevBid->amount : 0); $resType = $auctionInfo->reqResource; @@ -361,8 +370,8 @@ abstract class Auction $general->increaseVar($resType->value, -$morePoint); - if ($myPrevBid === null || ($highestBid !== null && $myPrevBid->id !== $highestBid->id)) { - $this->refundBid($highestBid, "{$auctionInfo->title} 경매에 상회입찰자가 나타났습니다."); + if ($highestBid !== null && $myPrevBid === null) { + $this->refundBid($highestBid, "{$auctionInfo->id}번 {$auctionInfo->detail->title}에 상회입찰자가 나타났습니다."); } $general->applyDB($db); return null; @@ -382,7 +391,7 @@ abstract class Auction return true; } - if ($highestBid->data->tryExtendCloseDate) { + if ($highestBid->aux->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 diff --git a/hwe/sammo/AuctionBasicResource.php b/hwe/sammo/AuctionBasicResource.php index 6fbf7420..4d647bad 100644 --- a/hwe/sammo/AuctionBasicResource.php +++ b/hwe/sammo/AuctionBasicResource.php @@ -45,7 +45,7 @@ abstract class AuctionBasicResource extends Auction $db = DB::db(); if (!($general instanceof DummyGeneral)) { $prevAuctionID = $db->queryFirstField( - 'SELECT id FROM ng_auction WHERE opener_general_id = %i AND finished = 0 AND `type` IN %ls', + 'SELECT id FROM ng_auction WHERE host_general_id = %i AND finished = 0 AND `type` IN %ls', $general->getID(), [AuctionType::BuyRice->value, AuctionType::SellRice->value], ); @@ -88,7 +88,7 @@ abstract class AuctionBasicResource extends Auction $general->increaseVarWithLimit($hostRes->value, -$amount, 0); $general->applyDB($db); - return new self($openResult, $general); + return new static($openResult, $general); } static public function genDummy(): DummyGeneral @@ -102,12 +102,12 @@ abstract class AuctionBasicResource extends Auction protected function rollbackAuction(): void { - if ($this->general->getID() === $this->info->openerGeneralID) { + if ($this->general->getID() === $this->info->hostGeneralID) { $auctionHost = $this->general; - } else if ($this->info->openerGeneralID == 0) { + } else if ($this->info->hostGeneralID == 0) { $auctionHost = $this->genDummy(); } else { - $auctionHost = General::createGeneralObjFromDB($this->info->openerGeneralID); + $auctionHost = General::createGeneralObjFromDB($this->info->hostGeneralID); } $hostRes = static::$hostRes; @@ -143,12 +143,12 @@ abstract class AuctionBasicResource extends Auction protected function finishAuction(AuctionBidItem $highestBid, General $bidder): ?string { - if ($this->general->getID() === $this->info->openerGeneralID) { + if ($this->general->getID() === $this->info->hostGeneralID) { $auctionHost = $this->general; - } else if ($this->info->openerGeneralID == 0) { + } else if ($this->info->hostGeneralID == 0) { $auctionHost = $this->genDummy(); } else { - $auctionHost = General::createGeneralObjFromDB($this->info->openerGeneralID); + $auctionHost = General::createGeneralObjFromDB($this->info->hostGeneralID); } $highestBid = $this->getHighestBid(); @@ -215,7 +215,7 @@ abstract class AuctionBasicResource extends Auction public function bid(int $amount, bool $tryExtendCloseDate = false): ?string { - if ($this->info->openerGeneralID === $this->general->getID()) { + if ($this->info->hostGeneralID === $this->general->getID()) { return '자신이 연 경매에 입찰할 수 없습니다.'; } $result = $this->_bid($amount, $tryExtendCloseDate); @@ -232,5 +232,7 @@ abstract class AuctionBasicResource extends Auction $date = (new DateTimeImmutable())->add(TimeUtil::secondsToDateInterval($turnTerm * 60)); $this->shrinkCloseDate($date); } + + return null; } } diff --git a/hwe/sammo/AuctionUniqueItem.php b/hwe/sammo/AuctionUniqueItem.php index 516f211e..4c0b4381 100644 --- a/hwe/sammo/AuctionUniqueItem.php +++ b/hwe/sammo/AuctionUniqueItem.php @@ -74,7 +74,7 @@ class AuctionUniqueItem extends Auction } $prevAuctionID = $db->queryFirstField( - 'SELECT id FROM ng_auction WHERE opener_general_id = %i AND finished = 0 AND `type` = %s', + 'SELECT id FROM ng_auction WHERE host_general_id = %i AND finished = 0 AND `type` = %s', $general->getID(), AuctionType::UniqueItem->value, ); diff --git a/hwe/sammo/DTO/AuctionBidItem.php b/hwe/sammo/DTO/AuctionBidItem.php index d4eecc84..d91d77f4 100644 --- a/hwe/sammo/DTO/AuctionBidItem.php +++ b/hwe/sammo/DTO/AuctionBidItem.php @@ -12,7 +12,7 @@ class AuctionBidItem extends DTO { public function __construct( #[NullIsUndefined] - public ?int $id, + public ?int $no, #[RawName('auction_id')] public int $auctionID, public ?int $owner, @@ -25,7 +25,7 @@ class AuctionBidItem extends DTO #[Convert(DateTimeConverter::class)] public \DateTimeImmutable $date, #[JsonString] - public AuctionBidItemData $data, + public AuctionBidItemData $aux, ) { } } diff --git a/hwe/sammo/DTO/AuctionInfo.php b/hwe/sammo/DTO/AuctionInfo.php index dc8a63f7..f8e1a385 100644 --- a/hwe/sammo/DTO/AuctionInfo.php +++ b/hwe/sammo/DTO/AuctionInfo.php @@ -20,7 +20,7 @@ class AuctionInfo extends DTO public ?string $target, #[RawName('host_general_id')] public int $hostGeneralID, - #[RawName('reqResource')] + #[RawName('req_resource')] public ResourceType $reqResource, #[RawName('open_date')] diff --git a/hwe/sql/reset.sql b/hwe/sql/reset.sql index c6464e56..1bb8ec24 100644 --- a/hwe/sql/reset.sql +++ b/hwe/sql/reset.sql @@ -68,4 +68,5 @@ DROP TABLE IF EXISTS ng_betting; DROP TABLE IF EXISTS vote; DROP TABLE IF EXISTS vote_comment; +DROP TABLE IF EXISTS `ng_auction`; DROP TABLE IF EXISTS `ng_auction_bid`; \ No newline at end of file diff --git a/hwe/templates/commandButton.php b/hwe/templates/commandButton.php index 13341621..12f163e4 100644 --- a/hwe/templates/commandButton.php +++ b/hwe/templates/commandButton.php @@ -16,5 +16,5 @@ '>감 찰 부 유산 관리 내 정보&설정 -거 래 장 +거 래 장 베 팅 장 \ No newline at end of file diff --git a/hwe/ts/PageAuction.vue b/hwe/ts/PageAuction.vue index 1f53efe3..43c77a1f 100644 --- a/hwe/ts/PageAuction.vue +++ b/hwe/ts/PageAuction.vue @@ -1,11 +1,32 @@ - + diff --git a/hwe/ts/build_exports.json b/hwe/ts/build_exports.json index 7c47de8c..20065ecc 100644 --- a/hwe/ts/build_exports.json +++ b/hwe/ts/build_exports.json @@ -22,6 +22,7 @@ "common": "common_deprecated.ts" }, "ingame_vue": { + "v_auction": "v_auction.ts", "v_inheritPoint": "v_inheritPoint.ts", "v_board": "v_board.ts", "v_cachedMap": "v_cachedMap", diff --git a/hwe/ts/components/AuctionResource.vue b/hwe/ts/components/AuctionResource.vue new file mode 100644 index 00000000..3c8d2cb2 --- /dev/null +++ b/hwe/ts/components/AuctionResource.vue @@ -0,0 +1,279 @@ + + + diff --git a/hwe/ts/components/AuctionUniqueItem.vue b/hwe/ts/components/AuctionUniqueItem.vue new file mode 100644 index 00000000..528108c0 --- /dev/null +++ b/hwe/ts/components/AuctionUniqueItem.vue @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/hwe/ts/v_auction.ts b/hwe/ts/v_auction.ts index 4bef455a..a17a0102 100644 --- a/hwe/ts/v_auction.ts +++ b/hwe/ts/v_auction.ts @@ -1,7 +1,7 @@ import "@scss/auction.scss"; import { createApp } from 'vue' import PageAuction from '@/PageAuction.vue'; -import BootstrapVue3 from 'bootstrap-vue-3' +import BootstrapVue3, { BToastPlugin } from 'bootstrap-vue-3' import { auto500px } from "./util/auto500px"; import { insertCustomCSS } from "./util/customCSS"; import { htmlReady } from "./util/htmlReady"; @@ -11,4 +11,4 @@ auto500px(); htmlReady(() => { insertCustomCSS(); }); -createApp(PageAuction).use(BootstrapVue3).mount('#app') \ No newline at end of file +createApp(PageAuction).use(BootstrapVue3).use(BToastPlugin).mount('#app') \ No newline at end of file diff --git a/hwe/v_auction.php b/hwe/v_auction.php index f9c26bae..2184eb43 100644 --- a/hwe/v_auction.php +++ b/hwe/v_auction.php @@ -18,7 +18,7 @@ $me = $db->queryFirstRow('SELECT no, nation, officer_level, permission, con, tur - <?= UniqueConst::$serverName ?>: <?= $boardName ?> + <?= UniqueConst::$serverName ?>: 경매장 diff --git a/src/sammo/APIHelper.php b/src/sammo/APIHelper.php index 2b74f7e4..8e1bca15 100644 --- a/src/sammo/APIHelper.php +++ b/src/sammo/APIHelper.php @@ -98,10 +98,10 @@ class APIHelper } Json::die($result, $setCache ? 0 : Json::NO_CACHE); } catch (\Exception $e) { - Json::dieWithReason($e->getMessage()); + Json::dieWithReason($e->getMessage()."\n".$e->getTraceAsString()); } catch (\Throwable $e) { logExceptionByCustomHandler($e, false); - Json::dieWithReason($e->getMessage()); + Json::dieWithReason($e->getMessage()."\n".$e->getTraceAsString()); } catch (mixed $e) { Json::dieWithReason(strval($e)); }