feat,refac: 경매장 재설계, 유니크 경매장 구현 (#221)
- 경매장을 모든 입찰 기록이 남는 새로운 경매장 로직으로 변경
- ng_auction, ng_auction_bid
- DTO 사용
- 상회입찰 시 개인메시지로 알림
- 기존의 '배경에서 조용히 이루어지는' 유니크 입찰을 공개된 유니크 경매장으로 변경
- 종료 기간 명시
- 종료 기간에 가까워질때 입찰하면 자동 연장
- 최대 연장기간 있음
- 유니크 제한인 경우 24턴 연장
- 중원정세에서 '보물수배'로 알림
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/221
This commit was merged in pull request #221.
This commit is contained in:
@@ -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 BidSellRiceAuction 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Auction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\AuctionUniqueItem;
|
||||
use sammo\Validator;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
|
||||
class BidUniqueAuction extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('required', [
|
||||
'auctionID',
|
||||
'amount',
|
||||
])
|
||||
->rule('int', 'amount')
|
||||
->rule('int', 'auctionID')
|
||||
->rule('boolean', 'extendCloseDate');
|
||||
|
||||
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'];
|
||||
$tryExtendCloseDate = $this->arg['extendCloseDate'] ?? false;
|
||||
|
||||
$generalID = $session->generalID;
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
$auction = new AuctionUniqueItem($auctionID, $general);
|
||||
$result = $auction->bid($amount, $tryExtendCloseDate);
|
||||
|
||||
if (is_string($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Auction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\AuctionSellRice;
|
||||
use sammo\DB;
|
||||
use sammo\DTO\AuctionBidItem;
|
||||
use sammo\DTO\AuctionInfo;
|
||||
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 = [];
|
||||
/** @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` ASC',
|
||||
[
|
||||
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`
|
||||
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 ($auctions as $auction) {
|
||||
$rawAuction = [
|
||||
'id' => $auction->id,
|
||||
'type' => $auction->type->value,
|
||||
'hostGeneralID' => $auction->hostGeneralID,
|
||||
'hostName' => $auction->detail->hostName,
|
||||
'openDate' => TimeUtil::format($auction->openDate, false),
|
||||
'closeDate' => TimeUtil::format($auction->closeDate, false),
|
||||
'amount' => $auction->detail->amount,
|
||||
'startBidAmount' => $auction->detail->startBidAmount,
|
||||
'finishBidAmount' => $auction->detail->finishBidAmount,
|
||||
];
|
||||
|
||||
$highestBid = $highestBids[$rawAuction['id']] ?? null;
|
||||
if ($highestBid === null) {
|
||||
$rawAuction['highestBid'] = null;
|
||||
} else {
|
||||
$rawAuction['highestBid'] = [
|
||||
'amount' => $highestBid->amount,
|
||||
'date' => TimeUtil::format($highestBid->date, false),
|
||||
'generalID' => $highestBid->generalID,
|
||||
'generalName' => $highestBid->aux->generalName,
|
||||
];
|
||||
}
|
||||
|
||||
if ($rawAuction['type'] == AuctionType::BuyRice->value) {
|
||||
$buyRiceList[] = $rawAuction;
|
||||
} else {
|
||||
$sellRiceList[] = $rawAuction;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => true,
|
||||
'buyRice' => $buyRiceList,
|
||||
'sellRice' => $sellRiceList,
|
||||
'recentLogs' => $recentLogs,
|
||||
'generalID' => $session->generalID,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Auction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\AuctionUniqueItem;
|
||||
use sammo\DB;
|
||||
use sammo\DTO\AuctionBidItem;
|
||||
use sammo\DTO\AuctionInfo;
|
||||
use sammo\Enums\AuctionType;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\Validator;
|
||||
|
||||
class GetUniqueItemAuctionDetail extends \sammo\BaseAPI
|
||||
{
|
||||
public function validateArgs(): ?string
|
||||
{
|
||||
$v = new Validator($this->args);
|
||||
$v->rule('required', [
|
||||
'auctionID',
|
||||
])
|
||||
->rule('integer', 'auctionID');
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
$this->args['auctionID'] = (int)$this->args['auctionID'];
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
return static::REQ_GAME_LOGIN;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||
{
|
||||
$db = DB::db();
|
||||
|
||||
$generalID = $session->generalID;
|
||||
$auctionID = $this->args['auctionID'];
|
||||
|
||||
$rawAuction = $db->queryFirstRow(
|
||||
'SELECT * FROM `ng_auction` WHERE `type` = %s AND `id` = %i',
|
||||
AuctionType::UniqueItem->value,
|
||||
$auctionID
|
||||
);
|
||||
|
||||
if (!$rawAuction) {
|
||||
return '선택한 경매가 없습니다.';
|
||||
}
|
||||
|
||||
$auction = AuctionInfo::fromArray($rawAuction);
|
||||
|
||||
/** @var AuctionBidItem[] */
|
||||
$bidList = array_map(fn ($raw) => AuctionBidItem::fromArray($raw), $db->query(
|
||||
'SELECT * FROM `ng_auction_bid` WHERE `auction_id` = %s ORDER BY `amount` DESC',
|
||||
$auctionID
|
||||
) ?? []);
|
||||
|
||||
$responseBid = [];
|
||||
foreach ($bidList as $bid) {
|
||||
$responseBid[] = [
|
||||
'generalName' => $bid->aux->generalName,
|
||||
'amount' => $bid->amount,
|
||||
'isCallerHighestBidder' => $bid->generalID === $generalID,
|
||||
'date' => TimeUtil::format($bid->date, false),
|
||||
];
|
||||
}
|
||||
|
||||
$obfuscatedName = AuctionUniqueItem::genObfuscatedName($generalID);
|
||||
|
||||
return [
|
||||
'result' => true,
|
||||
'auction' => [
|
||||
'id' => $auction->id,
|
||||
'finished' => $auction->finished,
|
||||
'title' => $auction->detail->title,
|
||||
'target' => $auction->target,
|
||||
'isCallerHost' => $auction->hostGeneralID === $generalID,
|
||||
'hostName' => $auction->detail->hostName,
|
||||
'closeDate' => TimeUtil::format($auction->closeDate, false),
|
||||
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
||||
'availableLatestBidCloseDate' => TimeUtil::format($auction->detail->availableLatestBidCloseDate, false),
|
||||
],
|
||||
'bidList' => $responseBid,
|
||||
'obfuscatedName' => $obfuscatedName,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Auction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\AuctionUniqueItem;
|
||||
use sammo\DB;
|
||||
use sammo\DTO\AuctionBidItem;
|
||||
use sammo\DTO\AuctionInfo;
|
||||
use sammo\Enums\AuctionType;
|
||||
use sammo\TimeUtil;
|
||||
use sammo\Util;
|
||||
|
||||
class GetUniqueItemAuctionList 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();
|
||||
|
||||
$generalID = $session->generalID;
|
||||
|
||||
/** @var AuctionInfo[] */
|
||||
$auctions = array_map(fn($raw)=>AuctionInfo::fromArray($raw), $db->query(
|
||||
'SELECT * FROM `ng_auction` WHERE `type` = %s ORDER BY `close_date` ASC',
|
||||
AuctionType::UniqueItem->value
|
||||
) ?? []);
|
||||
|
||||
$obfuscatedName = AuctionUniqueItem::genObfuscatedName($generalID);
|
||||
|
||||
if(!$auctions){
|
||||
return [
|
||||
'result' => true,
|
||||
'list' => [],
|
||||
'obfuscatedName' => $obfuscatedName,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
$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`
|
||||
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
|
||||
);
|
||||
|
||||
$response = [];
|
||||
foreach ($auctions as $auction) {
|
||||
$auctionID = $auction->id;
|
||||
$highestBid = $highestBids[$auctionID] ?? null;
|
||||
if($highestBid === null){
|
||||
continue;
|
||||
}
|
||||
|
||||
$response[] = [
|
||||
'id' => $auctionID,
|
||||
'finished' => $auction->finished,
|
||||
'title' => $auction->detail->title,
|
||||
'target' => $auction->target,
|
||||
'isCallerHost' => $auction->hostGeneralID === $generalID,
|
||||
'hostName' => $auction->detail->hostName,
|
||||
'closeDate' => TimeUtil::format($auction->closeDate, false),
|
||||
'remainCloseDateExtensionCnt' => $auction->detail->remainCloseDateExtensionCnt,
|
||||
'availableLatestBidCloseDate' => TimeUtil::format($auction->detail->availableLatestBidCloseDate, false),
|
||||
'highestBid' => [
|
||||
'generalName' => $highestBid->aux->generalName,
|
||||
'amount' => $highestBid->amount,
|
||||
'isCallerHighestBidder' => $highestBid->generalID === $generalID,
|
||||
'date' => $highestBid->date,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => true,
|
||||
'list' => $response,
|
||||
'obfuscatedName' => $obfuscatedName,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Auction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\AuctionBuyRice;
|
||||
use sammo\DB;
|
||||
use sammo\Validator;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Util;
|
||||
|
||||
class OpenBuyRiceAuction 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);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
[$initYear, $initMonth, $year, $month] = $gameStor->getValuesAsArray(['init_year', 'init_month', 'year', 'month']);
|
||||
$initYearMonth = Util::joinYearMonth($initYear, $initMonth);
|
||||
$yearMonth = Util::joinYearMonth($year, $month);
|
||||
|
||||
if($yearMonth <= $initYearMonth + 3){
|
||||
return '시작 후 3개월이 지나야 경매를 열 수 있습니다.';
|
||||
}
|
||||
|
||||
$auctionResult = AuctionBuyRice::openResourceAuction(
|
||||
$general,
|
||||
$amount,
|
||||
$closeTurnCnt,
|
||||
$startBidAmount,
|
||||
$finishBidAmount
|
||||
);
|
||||
|
||||
if (is_string($auctionResult)) {
|
||||
return $auctionResult;
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => true,
|
||||
'auctionID' => $auctionResult->getInfo()->id,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Auction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\AuctionSellRice;
|
||||
use sammo\DB;
|
||||
use sammo\Validator;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Util;
|
||||
|
||||
class OpenSellRiceAuction 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);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
[$initYear, $initMonth, $year, $month] = $gameStor->getValuesAsArray(['init_year', 'init_month', 'year', 'month']);
|
||||
$initYearMonth = Util::joinYearMonth($initYear, $initMonth);
|
||||
$yearMonth = Util::joinYearMonth($year, $month);
|
||||
|
||||
if($yearMonth <= $initYearMonth + 3){
|
||||
return '시작 후 3개월이 지나야 경매를 열 수 있습니다.';
|
||||
}
|
||||
|
||||
$auctionResult = AuctionSellRice::openResourceAuction(
|
||||
$general,
|
||||
$amount,
|
||||
$closeTurnCnt,
|
||||
$startBidAmount,
|
||||
$finishBidAmount
|
||||
);
|
||||
|
||||
if (is_string($auctionResult)) {
|
||||
return $auctionResult;
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => true,
|
||||
'auctionID' => $auctionResult->getInfo()->id,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\Auction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\AuctionUniqueItem;
|
||||
use sammo\DB;
|
||||
use sammo\Validator;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\Util;
|
||||
|
||||
use function sammo\buildItemClass;
|
||||
|
||||
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', [
|
||||
'itemID',
|
||||
'amount'
|
||||
])
|
||||
->rule('int', 'amount')
|
||||
->rule('min', 'amount', GameConst::$inheritItemUniqueMinPoint)
|
||||
->rule('keyExists', 'itemID', $availableItems);
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
$itemID = $this->args['itemID'];
|
||||
$amount = $this->args['amount'];
|
||||
$generalID = $session->generalID;
|
||||
|
||||
$itemObj = buildItemClass($itemID);
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
|
||||
$db = DB::db();
|
||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||
[$initYear, $initMonth, $year, $month] = $gameStor->getValuesAsArray(['init_year', 'init_month', 'year', 'month']);
|
||||
$initYearMonth = Util::joinYearMonth($initYear, $initMonth);
|
||||
$yearMonth = Util::joinYearMonth($year, $month);
|
||||
|
||||
if($yearMonth <= $initYearMonth + 3){
|
||||
return '시작 후 3개월이 지나야 경매를 열 수 있습니다.';
|
||||
}
|
||||
|
||||
$auctionResult = AuctionUniqueItem::openItemAuction($itemObj, $general, $amount);
|
||||
|
||||
if(is_string($auctionResult)) {
|
||||
return $auctionResult;
|
||||
}
|
||||
|
||||
return [
|
||||
'result' => true,
|
||||
'auctionID' => $auctionResult->getInfo()->id,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace sammo\API\General;
|
||||
|
||||
use Ds\Set;
|
||||
use sammo\DB;
|
||||
use sammo\Validator;
|
||||
|
||||
@@ -9,6 +10,7 @@ use sammo\Session;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\JosaUtil;
|
||||
use sammo\KVStorage;
|
||||
|
||||
class DropItem extends \sammo\BaseAPI
|
||||
{
|
||||
@@ -56,12 +58,13 @@ class DropItem extends \sammo\BaseAPI
|
||||
$logger->pushGeneralActionLog("<C>{$itemName}</>{$josaUl} 버렸습니다.");
|
||||
|
||||
$nationName = $me->getStaticNation()['name'];
|
||||
$db = DB::db();
|
||||
if (!$item->isBuyable()) {
|
||||
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
|
||||
$logger->pushGlobalHistoryLog("<R><b>【망실】</b></><D><b>{$nationName}</b></>의 <Y>{$generalName}</>{$josaYi} <C>{$itemName}</>{$josaUl} 잃었습니다!");
|
||||
}
|
||||
|
||||
$me->applyDB(DB::db());
|
||||
$me->applyDB($db);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace sammo\API\InheritAction;
|
||||
|
||||
use sammo\Session;
|
||||
use DateTimeInterface;
|
||||
use sammo\DB;
|
||||
use sammo\Enums\RankColumn;
|
||||
use sammo\GameConst;
|
||||
use sammo\General;
|
||||
use sammo\KVStorage;
|
||||
use sammo\UserLogger;
|
||||
use sammo\Validator;
|
||||
|
||||
use function sammo\buildItemClass;
|
||||
|
||||
class BuySpecificUnique 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', [
|
||||
'item',
|
||||
'amount',
|
||||
])
|
||||
->rule('int', 'amount')
|
||||
->rule('min', 'amount', GameConst::$inheritItemUniqueMinPoint)
|
||||
->rule('keyExists', 'item', $availableItems);
|
||||
|
||||
if (!$v->validate()) {
|
||||
return $v->errorStr();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getRequiredSessionMode(): int
|
||||
{
|
||||
//KVStrorage, General.aux 모두 쓰므로 lock;
|
||||
return static::REQ_GAME_LOGIN;
|
||||
}
|
||||
|
||||
public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag)
|
||||
{
|
||||
$itemKey = $this->args['item'];
|
||||
$amount = $this->args['amount'];
|
||||
|
||||
$userID = $session->userID;
|
||||
$generalID = $session->generalID;
|
||||
|
||||
$general = General::createGeneralObjFromDB($generalID);
|
||||
if ($userID != $general->getVar('owner')) {
|
||||
return '로그인 상태가 이상합니다. 다시 로그인해 주세요.';
|
||||
}
|
||||
|
||||
$itemTrials = $general->getAuxVar('inheritUniqueTrial') ?? [];
|
||||
if (key_exists($itemKey, $itemTrials)) {
|
||||
return '이미 입찰한 아이템입니다. 다음 턴에 시도해 주세요.';
|
||||
}
|
||||
|
||||
foreach(GameConst::$allItems as $itemType => $items){
|
||||
if(!key_exists($itemKey, $items)){
|
||||
continue;
|
||||
}
|
||||
|
||||
$prevItem = $general->getItem($itemType);
|
||||
if(!$prevItem->isBuyable()){
|
||||
return '이미 같은 자리에 유니크를 보유하고 있습니다.';
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$db = DB::db();
|
||||
$inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}");
|
||||
$trialStor = KVStorage::getStorage($db, "ut_{$itemKey}");
|
||||
$previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0];
|
||||
if ($previousPoint < $amount) {
|
||||
return '충분한 유산 포인트를 가지고 있지 않습니다.';
|
||||
}
|
||||
|
||||
$itemObj = buildItemClass($itemKey);
|
||||
$userLogger = new UserLogger($userID);
|
||||
$userLogger->push("{$amount} 포인트로 유니크 {$itemObj->getName()} 구입 시도", "inheritPoint");
|
||||
$userLogger->flush();
|
||||
|
||||
$itemTrials[$itemKey] = $amount;
|
||||
$general->setAuxVar('inheritUniqueTrial', $itemTrials);
|
||||
$inheritStor->setValue('previous', [$previousPoint - $amount, null]);
|
||||
$general->increaseRankVar(RankColumn::inherit_point_spent_dynamic, $amount);
|
||||
$trialStor->setValue("u{$userID}", [$userID, $generalID, $amount]);
|
||||
$general->applyDB($db);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user