feat(WIP): 국가 베팅 '기능만' 구현
This commit is contained in:
@@ -1,18 +1,16 @@
|
|||||||
<div class="buttonPlate">
|
<?=$btnBegin??''?><a href="a_status.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">세력도</a><?=$btnEnd??''?>
|
||||||
<a href="a_status.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력도</button></a>
|
<?=$btnBegin??''?><a href="a_kingdomList.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">세력일람</a><?=$btnEnd??''?>
|
||||||
<a href="a_kingdomList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">세력일람</button></a>
|
<?=$btnBegin??''?><a href="a_genList.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">장수일람</a><?=$btnEnd??''?>
|
||||||
<a href="a_genList.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">장수일람</button></a>
|
<?=$btnBegin??''?><a href="a_bestGeneral.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">명장일람</a><?=$btnEnd??''?>
|
||||||
<a href="a_bestGeneral.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명장일람</button></a>
|
<?=$btnBegin??''?><a href="a_history.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">연감</a><?=$btnEnd??''?>
|
||||||
<a href="a_history.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">연감</button></a>
|
<?=$btnBegin??''?><a href="a_hallOfFame.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">명예의전당</a><?=$btnEnd??''?>
|
||||||
<a href="a_hallOfFame.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">명예의전당</button></a>
|
<?=$btnBegin??''?><a href="a_emperior.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">왕조일람</a><?=$btnEnd??''?>
|
||||||
<a href="a_emperior.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">왕조일람</button></a>
|
<?=$btnBegin??''?><a href="v_nationBetting.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">천통국 베팅</a><?=$btnEnd??''?>
|
||||||
<a href="a_traffic.php" target="_blank" class="open-window"><button type="button" class="toolbarButton">접속량정보</button></a>
|
<?=$btnBegin??''?><a href="/bbs/board" target="_blank" class="toolbarButton2 <?=$btnClass??""?>">삼모게시판</a><?=$btnEnd??''?>
|
||||||
<a href="/bbs/board" target="_blank"><button type="button" class="toolbarButton2">삼모게시판</button></a>
|
<?=$btnBegin??''?><a href="/bbs/tip" target="_blank" class="toolbarButton <?=$btnClass??""?>">팁/강좌</a><?=$btnEnd??''?>
|
||||||
<a href="/bbs/tip" target="_blank"><button type="button" class="toolbarButton">팁/강좌</button></a>
|
<?=$btnBegin??''?><a href="/bbs/news" target="_blank" class="toolbarButton <?=$btnClass??""?>">삼국 일보</a><?=$btnEnd??''?>
|
||||||
<a href="/bbs/news" target="_blank"><button type="button" class="toolbarButton">삼국 일보</button></a>
|
<?=$btnBegin??''?><a href="/bbs/history2" target="_blank" class="toolbarButton <?=$btnClass??""?>">개인 열전</a><?=$btnEnd??''?>
|
||||||
<a href="/bbs/history2" target="_blank"><button type="button" class="toolbarButton">개인 열전</button></a>
|
<?=$btnBegin??''?><a href="/bbs/history3" target="_blank" class="toolbarButton <?=$btnClass??""?>">국가 열전</a><?=$btnEnd??''?>
|
||||||
<a href="/bbs/history3" target="_blank"><button type="button" class="toolbarButton">국가 열전</button></a>
|
<?=$btnBegin??''?><a href="/bbs/patch" target="_blank" class="toolbarButton <?=$btnClass??""?>">패치 내역</a><?=$btnEnd??''?>
|
||||||
<a href="/bbs/patch" target="_blank"><button type="button" class="toolbarButton">패치 내역</button></a>
|
<?=$btnBegin??''?><a href="battle_simulator.php" target="_blank" class="toolbarButton <?=$btnClass??""?>">전투 시뮬레이터</a><?=$btnEnd??''?>
|
||||||
<a href="battle_simulator.php" target="_blank"><button type="button" class="toolbarButton">전투 시뮬레이터</button></a>
|
<?=$btnBegin??''?><a href="<?= $site ?>" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>"><?= $call ?></a><?=$btnEnd??''?>
|
||||||
<a href="<?=$site?>" target="_blank" class="open-window"><button type="button" class="toolbarButton"><?=$call?></button></a>
|
|
||||||
</div>
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace sammo\API\NationBetting;
|
namespace sammo\API\Betting;
|
||||||
|
|
||||||
use sammo\Session;
|
use sammo\Session;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use sammo\DB;
|
use sammo\DB;
|
||||||
use Sammo\DTO\BettingItem;
|
use sammo\DTO\BettingItem;
|
||||||
use sammo\Validator;
|
use sammo\Validator;
|
||||||
use sammo\Json;
|
use sammo\Json;
|
||||||
use sammo\DTO\BettingInfo;
|
use sammo\DTO\BettingInfo;
|
||||||
@@ -16,18 +16,18 @@ use sammo\Util;
|
|||||||
|
|
||||||
use function sammo\getAllNationStaticInfo;
|
use function sammo\getAllNationStaticInfo;
|
||||||
|
|
||||||
class BetNation extends \sammo\BaseAPI
|
class Bet extends \sammo\BaseAPI
|
||||||
{
|
{
|
||||||
public function validateArgs(): ?string
|
public function validateArgs(): ?string
|
||||||
{
|
{
|
||||||
$v = new Validator($this->args);
|
$v = new Validator($this->args);
|
||||||
$v->rule('required', [
|
$v->rule('required', [
|
||||||
'betting_id',
|
'bettingID',
|
||||||
'betting_type',
|
'bettingType',
|
||||||
'amount'
|
'amount'
|
||||||
])
|
])
|
||||||
->rule('integer', 'betting_id')
|
->rule('integer', 'bettingID')
|
||||||
->rule('integerArray', 'betting_type')
|
->rule('integerArray', 'bettingType')
|
||||||
->rule('integer', 'amount')
|
->rule('integer', 'amount')
|
||||||
->rule('min', 'amount', 1);
|
->rule('min', 'amount', 1);
|
||||||
|
|
||||||
@@ -47,10 +47,10 @@ class BetNation extends \sammo\BaseAPI
|
|||||||
$db = DB::db();
|
$db = DB::db();
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
$bettingID = $this->arg['betting_id'];
|
$bettingID = $this->args['bettingID'];
|
||||||
/** @var int[] */
|
|
||||||
$bettingType = $this->arg['betting_type'];
|
|
||||||
/** @var int[] */
|
/** @var int[] */
|
||||||
|
$bettingType = $this->args['bettingType'];
|
||||||
|
/** @var int */
|
||||||
$amount = $this->args['amount'];
|
$amount = $this->args['amount'];
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
@@ -75,7 +75,7 @@ class BetNation extends \sammo\BaseAPI
|
|||||||
$yearMonth = Util::joinYearMonth($year, $month);
|
$yearMonth = Util::joinYearMonth($year, $month);
|
||||||
|
|
||||||
|
|
||||||
if($bettingInfo->closeYearMonth > $yearMonth){
|
if($bettingInfo->closeYearMonth <= $yearMonth){
|
||||||
return '이미 마감된 베팅입니다';
|
return '이미 마감된 베팅입니다';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,15 +102,24 @@ class BetNation extends \sammo\BaseAPI
|
|||||||
}
|
}
|
||||||
|
|
||||||
$bettingTypeKey = Json::encode($bettingType);
|
$bettingTypeKey = Json::encode($bettingType);
|
||||||
$general = General::createGeneralObjFromDB($session->generalID, ['gold', 'aux'], 1);
|
|
||||||
|
$inheritStor = KVStorage::getStorage($db, "inheritance_{$session->userID}");
|
||||||
|
|
||||||
|
$prevBetAmount = $db->queryFirstField('SELECT sum(amount) FROM ng_betting WHERE betting_id = %i AND user_id = %i', $bettingID, $session->userID) ?? 0;
|
||||||
|
|
||||||
|
if($prevBetAmount + $amount > 1000){
|
||||||
|
return (1000 - $prevBetAmount).' 포인트까지만 베팅 가능합니다.';
|
||||||
|
}
|
||||||
|
|
||||||
if($bettingInfo->reqInheritancePoint){
|
if($bettingInfo->reqInheritancePoint){
|
||||||
if($general->getInheritancePoint('previous') < $amount){
|
$remainPoint = ($inheritStor->getValue('previous') ?? [0,0])[0];
|
||||||
|
if($remainPoint < $amount){
|
||||||
return '유산포인트가 충분하지 않습니다.';
|
return '유산포인트가 충분하지 않습니다.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if($general->getVar('gold') < GameConst::$generalMinimumGold + $amount){
|
$remainPoint = $db->queryFirstField('SELECT gold FROM general WHERE no = %i', $session->generalID)??0;
|
||||||
|
if($remainPoint < GameConst::$generalMinimumGold + $amount){
|
||||||
return '금이 부족합니다.';
|
return '금이 부족합니다.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,17 +135,17 @@ class BetNation extends \sammo\BaseAPI
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if($bettingInfo->reqInheritancePoint){
|
if($bettingInfo->reqInheritancePoint){
|
||||||
$general->increaseInheritancePoint('previous', -$amount);
|
$inheritStor->setValue('previous', [$remainPoint - $amount, null]);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
$general->increaseVar('gold', -$amount);
|
$db->update('general', [
|
||||||
|
'gold' => $db->sqleval('gold - %i', $amount)
|
||||||
|
], 'no = %i', $session->generalID);
|
||||||
}
|
}
|
||||||
$db->insertUpdate('ng_betting', $bettingItem->toArray());
|
$db->insertUpdate('ng_betting', $bettingItem->toArray());
|
||||||
if(!$db->affected_rows){
|
if(!$db->affected_rows){
|
||||||
$general->flushUpdateValues();
|
|
||||||
return '베팅을 실패했습니다.';
|
return '베팅을 실패했습니다.';
|
||||||
}
|
}
|
||||||
$general->applyDB($db);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'result'=>true
|
'result'=>true
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace sammo\API\NationBetting;
|
namespace sammo\API\Betting;
|
||||||
|
|
||||||
use sammo\Session;
|
use sammo\Session;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
@@ -8,6 +8,7 @@ use sammo\DB;
|
|||||||
use sammo\DTO\BettingInfo;
|
use sammo\DTO\BettingInfo;
|
||||||
use sammo\General;
|
use sammo\General;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
|
use sammo\Util;
|
||||||
use sammo\Validator;
|
use sammo\Validator;
|
||||||
|
|
||||||
use function sammo\increaseRefresh;
|
use function sammo\increaseRefresh;
|
||||||
@@ -39,7 +40,7 @@ class GetBettingDetail extends \sammo\BaseAPI
|
|||||||
|
|
||||||
increaseRefresh("국가베팅장", 1);
|
increaseRefresh("국가베팅장", 1);
|
||||||
/** @var int */
|
/** @var int */
|
||||||
$bettingID = $this->arg['betting_id'];
|
$bettingID = $this->args['betting_id'];
|
||||||
|
|
||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$bettingStor = KVStorage::getStorage($db, 'betting');
|
$bettingStor = KVStorage::getStorage($db, 'betting');
|
||||||
@@ -63,7 +64,7 @@ class GetBettingDetail extends \sammo\BaseAPI
|
|||||||
'SELECT betting_type, sum(amount) as sum_amount FROM ng_betting WHERE betting_id = %i GROUP BY betting_type',
|
'SELECT betting_type, sum(amount) as sum_amount FROM ng_betting WHERE betting_id = %i GROUP BY betting_type',
|
||||||
$bettingID
|
$bettingID
|
||||||
) as [$bettingType, $amount]) {
|
) as [$bettingType, $amount]) {
|
||||||
$bettingDetail[] = [$bettingType, $amount];
|
$bettingDetail[] = [$bettingType, Util::toInt($amount)];
|
||||||
}
|
}
|
||||||
|
|
||||||
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
|
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
|
||||||
@@ -73,20 +74,19 @@ class GetBettingDetail extends \sammo\BaseAPI
|
|||||||
'SELECT betting_type, sum(amount) as sum_amount FROM ng_betting WHERE betting_id = %i AND user_id = %i GROUP BY betting_type',
|
'SELECT betting_type, sum(amount) as sum_amount FROM ng_betting WHERE betting_id = %i AND user_id = %i GROUP BY betting_type',
|
||||||
$bettingID, $session->userID
|
$bettingID, $session->userID
|
||||||
) as [$bettingType, $amount]){
|
) as [$bettingType, $amount]){
|
||||||
$myBetting[] = [$bettingType, $amount];
|
$myBetting[] = [$bettingType, Util::toInt($amount)];
|
||||||
}
|
}
|
||||||
|
|
||||||
$general = General::createGeneralObjFromDB($session->generalID, ['gold', 'aux'], 1);
|
|
||||||
|
|
||||||
if($bettingInfo->reqInheritancePoint){
|
if($bettingInfo->reqInheritancePoint){
|
||||||
$remainPoint = $general->getInheritancePoint('previous');
|
$inheritStor = KVStorage::getStorage($db, "inheritance_{$session->userID}");
|
||||||
|
$remainPoint = ($inheritStor->getValue('previous') ?? [0,0])[0];
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
$remainPoint = $general->getVar('gold');
|
$remainPoint = $db->queryFirstField('SELECT gold FROM general WHERE no = %i', $session->generalID)??0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'result' => false,
|
'result' => true,
|
||||||
'bettingInfo' => $rawBettingInfo,
|
'bettingInfo' => $rawBettingInfo,
|
||||||
'bettingDetail' => $bettingDetail,
|
'bettingDetail' => $bettingDetail,
|
||||||
'myBetting' => $myBetting,
|
'myBetting' => $myBetting,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace sammo\API\NationBetting;
|
namespace sammo\API\Betting;
|
||||||
|
|
||||||
use sammo\Session;
|
use sammo\Session;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
@@ -42,6 +42,7 @@ class GetBettingList extends \sammo\BaseAPI
|
|||||||
$bettingList = [];
|
$bettingList = [];
|
||||||
foreach ($bettingStor->getAll() as $_key => $rawItem) {
|
foreach ($bettingStor->getAll() as $_key => $rawItem) {
|
||||||
$item = new BettingInfo($rawItem);
|
$item = new BettingInfo($rawItem);
|
||||||
|
unset($rawItem['candidates']);
|
||||||
$bettingList[$item->id] = $rawItem;
|
$bettingList[$item->id] = $rawItem;
|
||||||
$bettingList[$item->id]['totalAmount'] = 0;
|
$bettingList[$item->id]['totalAmount'] = 0;
|
||||||
}
|
}
|
||||||
@@ -61,7 +62,7 @@ class GetBettingList extends \sammo\BaseAPI
|
|||||||
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
|
[$year, $month] = $gameStor->getValuesAsArray(['year', 'month']);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'result' => false,
|
'result' => true,
|
||||||
'bettingList' => $bettingList,
|
'bettingList' => $bettingList,
|
||||||
'year' => $year,
|
'year' => $year,
|
||||||
'month' => $month,
|
'month' => $month,
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
namespace sammo\DTO;
|
namespace sammo\DTO;
|
||||||
|
|
||||||
use Sammo\DTO\SelectItem;
|
use sammo\DTO\SelectItem;
|
||||||
use Spatie\DataTransferObject\Attributes\CastWith;
|
use Spatie\DataTransferObject\Attributes\CastWith;
|
||||||
use Spatie\DataTransferObject\Attributes\Strict;
|
use Spatie\DataTransferObject\Attributes\Strict;
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
use Spatie\DataTransferObject\DataTransferObject;
|
||||||
|
use Spatie\DataTransferObject\Casters\ArrayCaster;
|
||||||
|
|
||||||
//https://json2dto.atymic.dev/
|
//https://json2dto.atymic.dev/
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Sammo\DTO;
|
namespace sammo\DTO;
|
||||||
|
|
||||||
use Spatie\DataTransferObject\Attributes\MapFrom;
|
use Spatie\DataTransferObject\Attributes\MapFrom;
|
||||||
|
use Spatie\DataTransferObject\Attributes\MapTo;
|
||||||
use Spatie\DataTransferObject\Attributes\Strict;
|
use Spatie\DataTransferObject\Attributes\Strict;
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
use Spatie\DataTransferObject\DataTransferObject;
|
||||||
|
|
||||||
@@ -10,14 +11,23 @@ use Spatie\DataTransferObject\DataTransferObject;
|
|||||||
class BettingItem extends DataTransferObject
|
class BettingItem extends DataTransferObject
|
||||||
{
|
{
|
||||||
#[MapFrom('id')]
|
#[MapFrom('id')]
|
||||||
|
#[MapTo('id')]
|
||||||
public null|int $rowID = null;
|
public null|int $rowID = null;
|
||||||
|
|
||||||
#[MapFrom('betting_id')]
|
#[MapFrom('betting_id')]
|
||||||
|
#[MapTo('betting_id')]
|
||||||
public int $bettingID;
|
public int $bettingID;
|
||||||
|
|
||||||
#[MapFrom('general_id')]
|
#[MapFrom('general_id')]
|
||||||
|
#[MapTo('general_id')]
|
||||||
public int $generalID;
|
public int $generalID;
|
||||||
|
|
||||||
#[MapFrom('user_id')]
|
#[MapFrom('user_id')]
|
||||||
|
#[MapTo('user_id')]
|
||||||
public null|int $userID;
|
public null|int $userID;
|
||||||
|
|
||||||
#[MapFrom('betting_type')]
|
#[MapFrom('betting_type')]
|
||||||
|
#[MapTo('betting_type')]
|
||||||
public string $bettingType;
|
public string $bettingType;
|
||||||
public int $amount;
|
public int $amount;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Sammo\DTO;
|
namespace sammo\DTO;
|
||||||
|
|
||||||
use Spatie\DataTransferObject\Attributes\Strict;
|
use Spatie\DataTransferObject\Attributes\Strict;
|
||||||
use Spatie\DataTransferObject\DataTransferObject;
|
use Spatie\DataTransferObject\DataTransferObject;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use \sammo\GameConst;
|
|||||||
use \sammo\Util;
|
use \sammo\Util;
|
||||||
use \sammo\DB;
|
use \sammo\DB;
|
||||||
use sammo\DTO\BettingInfo;
|
use sammo\DTO\BettingInfo;
|
||||||
use Sammo\DTO\SelectItem;
|
use sammo\DTO\SelectItem;
|
||||||
use sammo\Json;
|
use sammo\Json;
|
||||||
use sammo\KVStorage;
|
use sammo\KVStorage;
|
||||||
|
|
||||||
@@ -54,7 +54,12 @@ class OpenNationBetting extends \sammo\Event\Action
|
|||||||
/** @var \sammo\DTO\SelectItem[] */
|
/** @var \sammo\DTO\SelectItem[] */
|
||||||
$candidates = [];
|
$candidates = [];
|
||||||
|
|
||||||
foreach (getAllNationStaticInfo() as $nationRaw) {
|
$nations = getAllNationStaticInfo();
|
||||||
|
uasort($nations, function($lhs, $rhs){
|
||||||
|
return -($lhs['power'] <=> $rhs['power']);
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($nations as $nationRaw) {
|
||||||
$nationID = $nationRaw['nation'];
|
$nationID = $nationRaw['nation'];
|
||||||
$cityCnt = $citiesCnt[$nationID] ?? 0;
|
$cityCnt = $citiesCnt[$nationID] ?? 0;
|
||||||
$nationRaw['city_cnt'] = $cityCnt;
|
$nationRaw['city_cnt'] = $cityCnt;
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ class ResetHelper{
|
|||||||
$gameStor = KVStorage::getStorage($db, 'game_env');
|
$gameStor = KVStorage::getStorage($db, 'game_env');
|
||||||
$gameStor->resetValues();
|
$gameStor->resetValues();
|
||||||
$gameStor->next_season_idx = $seasonIdx;
|
$gameStor->next_season_idx = $seasonIdx;
|
||||||
|
$bettingStor = KVStorage::getStorage($db, 'betting');
|
||||||
|
$bettingStor->resetValues();
|
||||||
|
|
||||||
$lastExecuteStor = KVStorage::getStorage($db, 'next_execute');
|
$lastExecuteStor = KVStorage::getStorage($db, 'next_execute');
|
||||||
$lastExecuteStor->resetValues();
|
$lastExecuteStor->resetValues();
|
||||||
|
|||||||
@@ -63,3 +63,5 @@ CREATE TABLE `reserved_open` (
|
|||||||
)
|
)
|
||||||
DEFAULT CHARSET=utf8mb4
|
DEFAULT CHARSET=utf8mb4
|
||||||
ENGINE=Aria;
|
ENGINE=Aria;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS ng_betting;
|
||||||
+1
-1
@@ -680,7 +680,7 @@ DEFAULT CHARSET=utf8mb4
|
|||||||
ENGINE=Aria
|
ENGINE=Aria
|
||||||
;
|
;
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `ng_betting` (
|
CREATE TABLE `ng_betting` (
|
||||||
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
`id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
`betting_id` INT(11) NOT NULL,
|
`betting_id` INT(11) NOT NULL,
|
||||||
`general_id` INT(11) NOT NULL,
|
`general_id` INT(11) NOT NULL,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<?=$btnBegin??''?><a href="a_history.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">연감</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href="a_history.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">연감</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href="a_hallOfFame.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">명예의전당</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href="a_hallOfFame.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">명예의전당</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href="a_emperior.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">왕조일람</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href="a_emperior.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">왕조일람</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href="a_traffic.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">접속량정보</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href="v_nationBetting.php" target="_blank" class="open-window toolbarButton <?=$btnClass??""?>">천통국 베팅</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href="/bbs/board" target="_blank" class="toolbarButton2 <?=$btnClass??""?>">삼모게시판</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href="/bbs/board" target="_blank" class="toolbarButton2 <?=$btnClass??""?>">삼모게시판</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href="/bbs/tip" target="_blank" class="toolbarButton <?=$btnClass??""?>">팁/강좌</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href="/bbs/tip" target="_blank" class="toolbarButton <?=$btnClass??""?>">팁/강좌</a><?=$btnEnd??''?>
|
||||||
<?=$btnBegin??''?><a href="/bbs/news" target="_blank" class="toolbarButton <?=$btnClass??""?>">삼국 일보</a><?=$btnEnd??''?>
|
<?=$btnBegin??''?><a href="/bbs/news" target="_blank" class="toolbarButton <?=$btnClass??""?>">삼국 일보</a><?=$btnEnd??''?>
|
||||||
|
|||||||
@@ -0,0 +1,315 @@
|
|||||||
|
<template>
|
||||||
|
<MyToast v-model="toasts" />
|
||||||
|
<div id="container" class="pageNationBetting bg0">
|
||||||
|
<TopBackBar :title="title" />
|
||||||
|
<div v-if="bettingInfo !== undefined">
|
||||||
|
<template v-for="(info, idx) in [bettingInfo.bettingInfo]" :key="idx">
|
||||||
|
<div>
|
||||||
|
{{ info.name }}
|
||||||
|
<span v-if="info.finished">(종료)</span>
|
||||||
|
<span
|
||||||
|
v-else-if="(yearMonth ?? 0) <= info.closeYearMonth"
|
||||||
|
>({{ parseYearMonth(info.closeYearMonth)[0] }}년 {{ parseYearMonth(info.closeYearMonth)[1] }}월까지)</span>
|
||||||
|
<span v-else>(베팅 마감)</span>
|
||||||
|
(총액: {{ bettingAmount.toLocaleString() }})
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row bettingCandidates">
|
||||||
|
<div
|
||||||
|
class="col-4 col-md-2"
|
||||||
|
v-for="(candidate, idx) in bettingInfo.bettingInfo.candidates"
|
||||||
|
:key="idx"
|
||||||
|
@click="toggleCandidate(idx)"
|
||||||
|
>
|
||||||
|
<div>{{ candidate.title }}</div>
|
||||||
|
<div v-if="candidate.isHtml" v-html="candidate.info"></div>
|
||||||
|
<div>선택율: {{ ((partialBet.get(idx) ?? 0) / pureBettingAmount * 100).toFixed(1) }}%</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!info.finished && (yearMonth ?? 0) <= info.closeYearMonth" class="row">
|
||||||
|
<div
|
||||||
|
class="col-3"
|
||||||
|
>잔여 {{ info.reqInheritancePoint ? '포인트' : '금' }} : {{ bettingInfo.remainPoint.toLocaleString() }}</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<b-form-input type="number" v-model="betPoint" :min="10" :max="1000" :step="10"></b-form-input>
|
||||||
|
</div>
|
||||||
|
<div class="col-3">{{ getTypeStr(choosedBetTypeKey) }}</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<b-button @click="submitBet">베팅</b-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
배당 순위
|
||||||
|
<div class="row" v-for="[betType, amount] of detailBet" :key="betType">
|
||||||
|
<div
|
||||||
|
class="col-6 col-md-3"
|
||||||
|
:style="{
|
||||||
|
fontWeight: myBettings.has(betType) ? 'bold' : undefined
|
||||||
|
}"
|
||||||
|
>{{ getTypeStr(betType) }}</div>
|
||||||
|
<div class="col-3 col-md-6">{{ amount.toLocaleString() }}{{ myBettings.has(betType)?`(${myBettings.get(betType)?.toLocaleString()})`:'' }}</div>
|
||||||
|
<div class="col-3 col-md-3">{{ (bettingAmount / amount).toFixed(2) }}배</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div v-if="bettingList === undefined">로딩 중...</div>
|
||||||
|
<div class="bettingList" v-else>
|
||||||
|
<div
|
||||||
|
class="bettingItem"
|
||||||
|
v-for="info of Object.values(bettingList).reverse()"
|
||||||
|
:key="info.id"
|
||||||
|
@click="loadBetting(info.id)"
|
||||||
|
>
|
||||||
|
{{ info.name }}
|
||||||
|
<span v-if="info.finished">(종료)</span>
|
||||||
|
<span
|
||||||
|
v-else-if="(yearMonth ?? 0) <= info.closeYearMonth"
|
||||||
|
>({{ parseYearMonth(info.closeYearMonth)[0] }}년 {{ parseYearMonth(info.closeYearMonth)[1] }}월까지)</span>
|
||||||
|
<span v-else>(베팅 마감)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<BottomBar />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import MyToast from "@/components/MyToast.vue";
|
||||||
|
import TopBackBar from "@/components/TopBackBar.vue";
|
||||||
|
import BottomBar from "@/components/BottomBar.vue";
|
||||||
|
import { ToastType } from "@/defs";
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
import { SammoAPI, ValidResponse } from "./SammoAPI";
|
||||||
|
import { isString } from "lodash";
|
||||||
|
import { parseYearMonth } from "@/util/parseYearMonth";
|
||||||
|
import { joinYearMonth } from "./util/joinYearMonth";
|
||||||
|
|
||||||
|
type SelectItem = {
|
||||||
|
title: string;
|
||||||
|
info?: string;
|
||||||
|
isHtml?: boolean;
|
||||||
|
aux?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
type BettingInfo = {
|
||||||
|
id: number;
|
||||||
|
type: 'nationBetting',
|
||||||
|
name: string;
|
||||||
|
finished: boolean;
|
||||||
|
selectCnt: number;
|
||||||
|
reqInheritancePoint: boolean;
|
||||||
|
openYearMonth: number;
|
||||||
|
closeYearMonth: number;
|
||||||
|
candidates: SelectItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type BettingListResponse = ValidResponse & {
|
||||||
|
bettingList: Record<number, Omit<BettingInfo & { totalAmount: number }, 'candidates'>>,
|
||||||
|
year: number,
|
||||||
|
month: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
type BettingDetailResponse = ValidResponse & {
|
||||||
|
bettingInfo: BettingInfo;
|
||||||
|
bettingDetail: [string, number][];
|
||||||
|
myBetting: [string, number][];
|
||||||
|
remainPoint: number;
|
||||||
|
year: number;
|
||||||
|
month: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const toasts = ref<ToastType[]>([]);
|
||||||
|
const year = ref<number>();
|
||||||
|
const month = ref<number>();
|
||||||
|
const yearMonth = ref<number>();
|
||||||
|
const bettingList = ref<BettingListResponse['bettingList']>();
|
||||||
|
const bettingInfo = ref<BettingDetailResponse>();
|
||||||
|
|
||||||
|
const bettingAmount = ref<number>(0);
|
||||||
|
const pureBettingAmount = ref<number>(0);
|
||||||
|
|
||||||
|
const partialBet = ref(new Map<number, number>());
|
||||||
|
const detailBet = ref<[string, number][]>([]);
|
||||||
|
|
||||||
|
const typeMap = ref(new Map<string, string>());
|
||||||
|
function getTypeStr(type: string): string {
|
||||||
|
const typeResult = typeMap.value.get(type);
|
||||||
|
if (typeResult !== undefined) {
|
||||||
|
return typeResult;
|
||||||
|
}
|
||||||
|
const bettingSubTypes = JSON.parse(type) as number[];
|
||||||
|
if (bettingSubTypes[0] < -1) {
|
||||||
|
return 'Invalid';
|
||||||
|
}
|
||||||
|
|
||||||
|
const textBettingType = bettingSubTypes.map((idx) => {
|
||||||
|
return bettingInfo.value?.bettingInfo.candidates[idx].title;
|
||||||
|
}).join(', ');
|
||||||
|
typeMap.value.set(type, textBettingType);
|
||||||
|
return textBettingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const choosedBetType = ref(new Set<number>());
|
||||||
|
const choosedBetTypeKey = ref('[]');
|
||||||
|
|
||||||
|
const betPoint = ref(0);
|
||||||
|
const myBettings = ref(new Map<string, number>());
|
||||||
|
|
||||||
|
function toggleCandidate(idx: number) {
|
||||||
|
if (bettingInfo.value === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const selectCnt = bettingInfo.value.bettingInfo.selectCnt;
|
||||||
|
|
||||||
|
if (selectCnt == 1) {
|
||||||
|
choosedBetTypeKey.value = JSON.stringify([idx]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (choosedBetType.value.has(idx)) {
|
||||||
|
choosedBetType.value.delete(idx);
|
||||||
|
}
|
||||||
|
else if (choosedBetType.value.size < selectCnt) {
|
||||||
|
choosedBetType.value.add(idx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const typeArr = Array.from(choosedBetType.value.values());
|
||||||
|
choosedBetTypeKey.value = JSON.stringify(typeArr.sort());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadBetting(bettingID: number) {
|
||||||
|
try {
|
||||||
|
const result = await SammoAPI.Betting.GetBettingDetail<BettingDetailResponse>({
|
||||||
|
betting_id: bettingID
|
||||||
|
});
|
||||||
|
year.value = result.year;
|
||||||
|
month.value = result.month;
|
||||||
|
yearMonth.value = joinYearMonth(result.year, result.month);
|
||||||
|
bettingInfo.value = result;
|
||||||
|
|
||||||
|
partialBet.value.clear();
|
||||||
|
|
||||||
|
const betSort = new Map<string, number>();
|
||||||
|
|
||||||
|
|
||||||
|
let _bettingAmount = 0;
|
||||||
|
let adminBettingAmount = 0;
|
||||||
|
for (const [bettingType, amount] of result.bettingDetail) {
|
||||||
|
console.log(amount, typeof (amount));
|
||||||
|
let userBet = true;
|
||||||
|
const bettingSubTypes = JSON.parse(bettingType) as number[];
|
||||||
|
for (const bettingSubType of bettingSubTypes) {
|
||||||
|
if (bettingSubType < 0) {
|
||||||
|
userBet = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const oldValue = partialBet.value.get(bettingSubType) ?? 0;
|
||||||
|
partialBet.value.set(bettingSubType, oldValue + amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userBet) {
|
||||||
|
const oldValue = betSort.get(bettingType) ?? 0;
|
||||||
|
betSort.set(bettingType, oldValue + amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
_bettingAmount += amount;
|
||||||
|
if (!userBet) {
|
||||||
|
adminBettingAmount += amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(_bettingAmount);
|
||||||
|
bettingAmount.value = _bettingAmount;
|
||||||
|
pureBettingAmount.value = _bettingAmount - adminBettingAmount;
|
||||||
|
|
||||||
|
detailBet.value = Array.from(betSort.entries());
|
||||||
|
detailBet.value.sort(([, lhsVal], [, rhsVal]) => {
|
||||||
|
return rhsVal - lhsVal;
|
||||||
|
})
|
||||||
|
|
||||||
|
choosedBetType.value.clear();
|
||||||
|
choosedBetTypeKey.value = '[]';
|
||||||
|
myBettings.value.clear();
|
||||||
|
|
||||||
|
for(const [betType, amount] of result.myBetting){
|
||||||
|
myBettings.value.set(betType, amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
if (isString(e)) {
|
||||||
|
toasts.value.push({
|
||||||
|
title: "에러",
|
||||||
|
content: e,
|
||||||
|
type: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submitBet(): Promise<void> {
|
||||||
|
const info = bettingInfo.value;
|
||||||
|
if (info === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bettingID = info.bettingInfo.id;
|
||||||
|
const bettingType = JSON.parse(choosedBetTypeKey.value);
|
||||||
|
const amount = betPoint.value;
|
||||||
|
try {
|
||||||
|
await SammoAPI.Betting.Bet({
|
||||||
|
bettingID,
|
||||||
|
bettingType,
|
||||||
|
amount,
|
||||||
|
});
|
||||||
|
toasts.value.push({
|
||||||
|
title: '완료',
|
||||||
|
content: '베팅했습니다',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
await loadBetting(info.bettingInfo.id);
|
||||||
|
} catch (e) {
|
||||||
|
if (isString(e)) {
|
||||||
|
toasts.value.push({
|
||||||
|
title: "에러",
|
||||||
|
content: e,
|
||||||
|
type: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('시작!');
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const result = await SammoAPI.Betting.GetBettingList<BettingListResponse>();
|
||||||
|
year.value = result.year;
|
||||||
|
month.value = result.month;
|
||||||
|
yearMonth.value = joinYearMonth(result.year, result.month);
|
||||||
|
bettingList.value = result.bettingList;
|
||||||
|
console.log(result);
|
||||||
|
} catch (e) {
|
||||||
|
if (isString(e)) {
|
||||||
|
toasts.value.push({
|
||||||
|
title: "에러",
|
||||||
|
content: e,
|
||||||
|
type: "danger",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const title = '국가 베팅장';
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -13,6 +13,11 @@ async function done<ResultType extends ValidResponse, ErrorType extends InvalidR
|
|||||||
}
|
}
|
||||||
|
|
||||||
const apiRealPath = {
|
const apiRealPath = {
|
||||||
|
Betting:{
|
||||||
|
Bet: done,
|
||||||
|
GetBettingDetail: done,
|
||||||
|
GetBettingList: done,
|
||||||
|
},
|
||||||
Command: {
|
Command: {
|
||||||
GetReservedCommand: done,
|
GetReservedCommand: done,
|
||||||
PushCommand: done,
|
PushCommand: done,
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
"v_join": "v_join.ts",
|
"v_join": "v_join.ts",
|
||||||
"v_main": "v_main.ts",
|
"v_main": "v_main.ts",
|
||||||
"v_nationStratFinan": "v_nationStratFinan.ts",
|
"v_nationStratFinan": "v_nationStratFinan.ts",
|
||||||
"v_processing": "v_processing.ts"
|
"v_processing": "v_processing.ts",
|
||||||
|
"v_nationBetting": "v_nationBetting.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<span class="me-auto fw-bold">{{ toast.title }}</span>
|
<span class="me-auto fw-bold">{{ toast.title }}</span>
|
||||||
<CToastClose class="my-close" color="secondary" size="sm" />
|
<CToastClose class="my-close" color="secondary" size="sm" />
|
||||||
</CToastHeader>
|
</CToastHeader>
|
||||||
<CToastBody> {{ toast.content }} {{ toast.visible }} </CToastBody>
|
<CToastBody> {{ toast.content }} </CToastBody>
|
||||||
</CToast>
|
</CToast>
|
||||||
</template>
|
</template>
|
||||||
</CToaster>
|
</CToaster>
|
||||||
@@ -64,7 +64,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
doneMap.clear();
|
doneMap.clear();
|
||||||
toasts.value.length = 0;
|
toasts.value.length = 0;
|
||||||
emit("update:modelValue", toasts);
|
emit("update:modelValue", toasts.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(props.modelValue, (values) => {
|
watch(props.modelValue, (values) => {
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import "@scss/nationBetting.scss";
|
||||||
|
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
import PageNationBetting from '@/PageNationBetting.vue';
|
||||||
|
import BootstrapVue3 from 'bootstrap-vue-3';
|
||||||
|
import { auto500px } from './util/auto500px';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
auto500px();
|
||||||
|
createApp(PageNationBetting).use(BootstrapVue3).mount('#app');
|
||||||
@@ -20,7 +20,7 @@ $generalID = $session->generalID;
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=500" />
|
<meta name="viewport" content="width=500" />
|
||||||
<title><?= UniqueConst::$serverName ?>: 내무부</title>
|
<title><?= UniqueConst::$serverName ?>: 국가 베팅장</title>
|
||||||
<?= WebUtil::printStaticValues([
|
<?= WebUtil::printStaticValues([
|
||||||
'staticValues' => [
|
'staticValues' => [
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user