diff --git a/hwe/sammo/Auction.php b/hwe/sammo/Auction.php index e390cee5..c4fc69d6 100644 --- a/hwe/sammo/Auction.php +++ b/hwe/sammo/Auction.php @@ -17,7 +17,7 @@ use sammo\VO\InheritancePointType; class Auction { - private AuctionInfo $info; + protected AuctionInfo $info; public const LAST_AUCTION_ID_KEY = 'last_auction_id'; static public function genNextAuctionID(): int @@ -55,7 +55,7 @@ class Auction $auctionStor->setValue("id_{$auctionID}", $info->toArray()); } - public function getHighestBid(): AuctionBidItem + public function getHighestBid(): ?AuctionBidItem { $db = DB::db(); $rawHighestBid = $db->queryFirstRow( @@ -63,7 +63,7 @@ class Auction $this->info->id ); if(!$rawHighestBid){ - throw new \Exception('입찰이 없습니다.'); + return null; } return AuctionBidItem::fromArray($rawHighestBid); @@ -83,7 +83,7 @@ class Auction return AuctionBidItem::fromArray($rawMyPrevBid); } - public function __construct(private readonly int $auctionID, private General $general) + public function __construct(protected readonly int $auctionID, protected General $general) { $db = DB::db(); $auctionStor = KVStorage::getStorage($db, 'auction'); @@ -166,7 +166,11 @@ class Auction $this->general->setAuxVar('openedAuction', $openedAuction); } if ($isRollback) { - $this->refundBid($this->getHighestBid(), "{$this->info->title} 경매가 취소되었습니다."); + $highestBid = $this->getHighestBid(); + if($highestBid !== null){ + $this->refundBid($highestBid, "{$this->info->title} 경매가 취소되었습니다."); + } + } $auctionID = $this->info->id; $auctionStor->setValue("id_{$auctionID}", $this->info->toArray()); @@ -180,7 +184,7 @@ class Auction $general = $this->general; $highestBid = $this->getHighestBid(); - if ($amount <= $highestBid->amount) { + if ($highestBid !== null && $amount <= $highestBid->amount) { throw new \RuntimeException('현재입찰가보다 높게 입찰해야 합니다.'); } @@ -220,7 +224,7 @@ class Auction $general->increaseInheritancePoint(InheritanceKey::previous, -$morePoint); $general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, $morePoint); - if ($myPrevBid === null || $myPrevBid->id !== $highestBid->id) { + if ($myPrevBid === null || ($highestBid !== null && $myPrevBid->id !== $highestBid->id)) { $this->refundBid($highestBid, "{$auctionInfo->title} 경매에 상회입찰자가 나타났습니다."); } $general->applyDB($db); @@ -257,15 +261,8 @@ class Auction $db = DB::db(); - $rawHighestBid = $db->queryFirstRow( - 'SELECT * FROM ng_auction WHERE auction_id = %i ORDER BY `amount` DESC LIMIT 1', - $auctionInfo->id - ); - if (!$rawHighestBid) { - throw new \RuntimeException('최고 입찰가가 없습니다.'); - } - $highestBid = AuctionBidItem::fromArray($rawHighestBid); - if ($amount <= $highestBid->amount) { + $highestBid = $this->getHighestBid(); + if ($highestBid !== null && $amount <= $highestBid->amount) { throw new \RuntimeException('현재입찰가보다 높게 입찰해야 합니다.'); } @@ -300,7 +297,7 @@ class Auction $general->setVar($resType->value, $general->getVar($resType->value) - $morePoint); - if ($myPrevBid === null || $myPrevBid->id !== $highestBid->id) { + if ($myPrevBid === null || ($highestBid !== null && $myPrevBid->id !== $highestBid->id)) { $this->refundBid($highestBid, "{$auctionInfo->title} 경매에 상회입찰자가 나타났습니다."); } $general->applyDB($db); diff --git a/hwe/sammo/AuctionUniqueItem.php b/hwe/sammo/AuctionUniqueItem.php new file mode 100644 index 00000000..e52969d2 --- /dev/null +++ b/hwe/sammo/AuctionUniqueItem.php @@ -0,0 +1,95 @@ +getValue('obfuscatedNamePool'); + if($namePool === null){ + $rng = new RandUtil(new LiteHashDRBG(Util::simpleSerialize( + UniqueConst::$hiddenSeed, + ))); + $namePool = []; + foreach(GameConst::$randGenFirstName as $ch0){ + foreach(GameConst::$randGenMiddleName as $ch1){ + foreach(GameConst::$randGenLastName as $ch2){ + $namePool[] = "{$ch0}{$ch1}{$ch2}"; + } + } + } + $namePool = $rng->shuffle($namePool); + $gameStor->setValue('obfuscatedNamePool', $namePool); + } + + + $dupIdx = intdiv($id, count($namePool)); + $subIdx = $id % count($namePool); + if ($dupIdx == 0) { + return $namePool[$subIdx]; + } + return "{$namePool[$subIdx]}{$dupIdx}"; + } + + static public function openItemAuction(BaseItem $item, General $general, int $startAmount): ?string + { + if ($startAmount < GameConst::$inheritItemUniqueMinPoint) { + return '최소 경매 금액은 ' . GameConst::$inheritItemUniqueMinPoint . '입니다.'; + } + + if($general->getInheritancePoint(InheritanceKey::previous) < $startAmount){ + return '경매를 시작할 포인트가 부족합니다.'; + } + + $auctionID = static::genNextAuctionID(); + $now = new DateTimeImmutable(); + + $db = DB::db(); + $gameStor = KVStorage::getStorage($db, 'game_env'); + $turnTerm = $gameStor->getValue('turnterm'); + + $closeDate = $now->add(TimeUtil::secondsToDateInterval(24 * 60 * $turnTerm * 60)); + + $info = new AuctionInfo( + $auctionID, + static::genObfuscatedName($general->getID()), + $general->getID(), + $item->getRawClassName(), + "{$item->getName()} 경매", + false, + ResourceType::inheritancePoint, + $startAmount, + null, + $now, + $closeDate + ); + + $result = static::openAuction($info, $general); + if($result !== null){ + return $result; + } + $auction = new static($auctionID, $general); + try{ + $auction->bid($startAmount); + } + catch(\Exception $e){ + //실패해선 안된다. + $msg = $e->getMessage(); + $auction->closeAuction(); + return "경매를 시작했지만, 첫 입찰에 실패했습니다: {$msg}"; + } + + return null; + } +} diff --git a/hwe/sammo/DTO/AuctionInfo.php b/hwe/sammo/DTO/AuctionInfo.php index 6854ed37..c34dd50f 100644 --- a/hwe/sammo/DTO/AuctionInfo.php +++ b/hwe/sammo/DTO/AuctionInfo.php @@ -10,7 +10,7 @@ class AuctionInfo extends DTO { public function __construct( public int $id, - public int $openerName, + public string $openerName, public int $openerGeneralID, public string $type, public string $title,