refac: 변경한 DTO에 따라 코드 수정

- Spatie/DataTransferObject 대비
  - MapFrom,MapTo -> RawName
  - Strict -> 항상
     - 심지어 raw type도 더 까다롭게
  - array에 MapConverter 적용
  - NullIsUndefined 적용
  - 빈 nullable arg자리에 null 강제 지정
- Vue3에 v-model.number 지정
  - input type="number" 기준
This commit is contained in:
2022-05-22 22:39:28 +09:00
parent 43a5162a15
commit 78a55fb87a
24 changed files with 152 additions and 128 deletions
+6 -1
View File
@@ -383,10 +383,12 @@ function getDummyBettingInfo(string $tnmt_type): BettingInfo
name: $tnmt_type, name: $tnmt_type,
finished: true, finished: true,
selectCnt: 1, selectCnt: 1,
isExclusive: null,
reqInheritancePoint: false, reqInheritancePoint: false,
openYearMonth: 0, openYearMonth: 0,
closeYearMonth: 0, closeYearMonth: 0,
candidates: [] candidates: [],
winner: null,
); );
} }
@@ -425,6 +427,7 @@ function startBetting($type, $unit)
$candidates[$general['no']] = new \sammo\DTO\SelectItem( $candidates[$general['no']] = new \sammo\DTO\SelectItem(
title: $general['name'], title: $general['name'],
info: "{$statName}: {$general[$statKey]}", info: "{$statName}: {$general[$statKey]}",
isHtml: null,
aux: $general aux: $general
); );
} }
@@ -436,10 +439,12 @@ function startBetting($type, $unit)
name: $typeText, name: $typeText,
finished: false, finished: false,
selectCnt: 1, selectCnt: 1,
isExclusive: null,
reqInheritancePoint: false, reqInheritancePoint: false,
openYearMonth: $openYearMonth, openYearMonth: $openYearMonth,
closeYearMonth: $closeYearMonth, closeYearMonth: $closeYearMonth,
candidates: $candidates, candidates: $candidates,
winner: null,
)); ));
$betting = new Betting($bettingID); $betting = new Betting($bettingID);
+1 -1
View File
@@ -116,7 +116,7 @@ $lastVoteID = $gameStor->lastVote;
$lastVote = null; $lastVote = null;
if($lastVoteID){ if($lastVoteID){
$voteStor = KVStorage::getStorage($db, 'vote'); $voteStor = KVStorage::getStorage($db, 'vote');
$lastVote = new VoteInfo($voteStor->getValue("vote_{$lastVoteID}")); $lastVote = VoteInfo::fromArray($voteStor->getValue("vote_{$lastVoteID}"));
if($lastVote->endDate && $lastVote->endDate < TimeUtil::now()){ if($lastVote->endDate && $lastVote->endDate < TimeUtil::now()){
$lastVote = null; $lastVote = null;
} }
+1 -1
View File
@@ -47,7 +47,7 @@ class GetBettingDetail extends \sammo\BaseAPI
} }
try{ try{
$bettingInfo = new BettingInfo($rawBettingInfo); $bettingInfo = BettingInfo::fromArray($rawBettingInfo);
} }
catch(\Error $e){ catch(\Error $e){
return $e->getMessage(); return $e->getMessage();
+1 -1
View File
@@ -49,7 +49,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 = BettingInfo::fromArray($rawItem);
if ($reqType !== null && $item->type != $reqType) { if ($reqType !== null && $item->type != $reqType) {
continue; continue;
} }
+7 -5
View File
@@ -29,6 +29,7 @@ class AddComment extends \sammo\BaseAPI
if (!$v->validate()) { if (!$v->validate()) {
return $v->errorStr(); return $v->errorStr();
} }
$this->args['voteID'] = (int)$this->args['voteID'];
return null; return null;
} }
@@ -46,11 +47,12 @@ class AddComment extends \sammo\BaseAPI
$comment = new VoteComment( $comment = new VoteComment(
vote_id: $voteID, id: null,
general_id: $generalID, voteID: $voteID,
nation_id: $nationID, generalID: $generalID,
nation_name: $nationName, nationID: $nationID,
general_name: $generalName, nationName: $nationName,
generalName: $generalName,
text: $text, text: $text,
date: $date date: $date
); );
+4 -4
View File
@@ -40,7 +40,7 @@ class GetVoteDetail extends \sammo\BaseAPI
if (!$rawVote) { if (!$rawVote) {
return '설문조사가 없습니다.'; return '설문조사가 없습니다.';
} }
$voteInfo = new VoteInfo(...$rawVote); $voteInfo = VoteInfo::fromArray($rawVote);
$votes = array_map(fn ($arr) => [Json::decode($arr[0]), $arr[1]], $db->queryAllLists( $votes = array_map(fn ($arr) => [Json::decode($arr[0]), $arr[1]], $db->queryAllLists(
@@ -48,13 +48,13 @@ class GetVoteDetail extends \sammo\BaseAPI
$voteID $voteID
)); ));
$comments = VoteComment::arrayOf($db->query('SELECT * FROM vote_comment WHERE vote_id = %i ORDER BY `id` ASC', $voteID)); $comments = array_map(fn ($arr) => VoteComment::fromArray($arr), $db->query('SELECT * FROM vote_comment WHERE vote_id = %i ORDER BY `id` ASC', $voteID));
$myVote = null; $myVote = null;
if($session->isGameLoggedIn()){ if ($session->isGameLoggedIn()) {
$generalID = $session->generalID; $generalID = $session->generalID;
$rawMyVote = $db->queryFirstField('SELECT selection FROM vote WHERE vote_id = %i AND general_id = %i', $voteID, $generalID); $rawMyVote = $db->queryFirstField('SELECT selection FROM vote WHERE vote_id = %i AND general_id = %i', $voteID, $generalID);
if($rawMyVote){ if ($rawMyVote) {
$myVote = Json::decode($rawMyVote); $myVote = Json::decode($rawMyVote);
} }
} }
+1 -1
View File
@@ -33,7 +33,7 @@ class GetVoteList extends \sammo\BaseAPI
continue; continue;
} }
$voteID = (int)substr($voteKey, 5); $voteID = (int)substr($voteKey, 5);
$votes[$voteID] = new VoteInfo(...$rawVote); $votes[$voteID] = VoteInfo::fromArray($rawVote);
} }
return [ return [
+1 -1
View File
@@ -43,7 +43,7 @@ class NewVote extends \sammo\BaseAPI
if (!$rawLastVoteInfo) { if (!$rawLastVoteInfo) {
return; return;
} }
$lastVoteInfo = new VoteInfo(...$rawLastVoteInfo); $lastVoteInfo = VoteInfo::fromArray($rawLastVoteInfo);
if ($lastVoteInfo->endDate) { if ($lastVoteInfo->endDate) {
return; return;
} }
+1 -1
View File
@@ -58,7 +58,7 @@ class Vote extends \sammo\BaseAPI
if (!$rawVoteInfo) { if (!$rawVoteInfo) {
return '설문조사가 없습니다.'; return '설문조사가 없습니다.';
} }
$voteInfo = new VoteInfo(...$rawVoteInfo); $voteInfo = VoteInfo::fromArray($rawVoteInfo);
if ($voteInfo->endDate && $voteInfo->endDate < new \DateTimeImmutable()) { if ($voteInfo->endDate && $voteInfo->endDate < new \DateTimeImmutable()) {
return '설문조사가 종료되었습니다.'; return '설문조사가 종료되었습니다.';
+9 -8
View File
@@ -43,7 +43,7 @@ class Betting
if ($rawBettingInfo === null) { if ($rawBettingInfo === null) {
throw new \RuntimeException("해당 베팅이 없습니다: {$bettingID}"); throw new \RuntimeException("해당 베팅이 없습니다: {$bettingID}");
} }
$this->info = new BettingInfo($rawBettingInfo); $this->info = BettingInfo::fromArray($rawBettingInfo);
} }
private function _convertBettingKey(array $bettingType): string private function _convertBettingKey(array $bettingType): string
@@ -148,13 +148,14 @@ class Betting
} }
} }
$bettingItem = new BettingItem([ $bettingItem = new BettingItem(
'betting_id' => $this->bettingID, rowID: null,
'general_id' => $generalID, bettingID: $this->bettingID,
'user_id' => $userID, generalID: $generalID,
'betting_type' => $bettingTypeKey, userID: $userID,
'amount' => $amount bettingType: $bettingTypeKey,
]); amount: $amount
);
$db->insertUpdate( $db->insertUpdate(
'ng_betting', 'ng_betting',
+20 -21
View File
@@ -2,33 +2,32 @@
namespace sammo\DTO; namespace sammo\DTO;
use sammo\DTO\Attr\Convert;
use sammo\DTO\Converter\MapConverter;
use sammo\DTO\SelectItem; use sammo\DTO\SelectItem;
use Spatie\DataTransferObject\Attributes\CastWith;
use Spatie\DataTransferObject\Attributes\Strict;
use Spatie\DataTransferObject\DataTransferObject;
use Spatie\DataTransferObject\Casters\ArrayCaster;
//https://json2dto.atymic.dev/ //https://json2dto.atymic.dev/
class BettingInfo extends DTO
#[Strict]
class BettingInfo extends DataTransferObject
{ {
public int $id; public function __construct(
public string $type; public int $id,
public string $name; public string $type,
public bool $finished; public string $name,
public int $selectCnt; public bool $finished,
public ?bool $isExlusive; public int $selectCnt,
public bool $reqInheritancePoint; public ?bool $isExclusive,
public int $openYearMonth; public bool $reqInheritancePoint,
public int $closeYearMonth; public int $openYearMonth,
public int $closeYearMonth,
/** @var \sammo\DTO\SelectItem[] */
#[CastWith(ArrayCaster::class, itemType: SelectItem::class)] /** @var \sammo\DTO\SelectItem[] */
public array $candidates; #[Convert(MapConverter::class, [SelectItem::class])]
public ?array $winner; public array $candidates,
public ?array $winner,
) {
}
} }
+18 -22
View File
@@ -2,32 +2,28 @@
namespace sammo\DTO; namespace sammo\DTO;
use Spatie\DataTransferObject\Attributes\MapFrom; use sammo\DTO\Attr\NullIsUndefined;
use Spatie\DataTransferObject\Attributes\MapTo; use sammo\DTO\Attr\RawName;
use Spatie\DataTransferObject\Attributes\Strict;
use Spatie\DataTransferObject\DataTransferObject;
#[Strict] class BettingItem extends DTO
class BettingItem extends DataTransferObject
{ {
#[MapFrom('id')] public function __construct(
#[MapTo('id')] #[RawName('id')]
public null|int $rowID = null; #[NullIsUndefined]
public ?int $rowID,
#[MapFrom('betting_id')] #[RawName('betting_id')]
#[MapTo('betting_id')] public int $bettingID,
public int $bettingID;
#[MapFrom('general_id')] #[RawName('general_id')]
#[MapTo('general_id')] public int $generalID,
public int $generalID;
#[MapFrom('user_id')] #[RawName('user_id')]
#[MapTo('user_id')] public ?int $userID,
public null|int $userID;
#[MapFrom('betting_type')] #[RawName('betting_type')]
#[MapTo('betting_type')] public string $bettingType,
public string $bettingType; public int $amount,
public int $amount; ) {
}
} }
+11 -8
View File
@@ -2,14 +2,17 @@
namespace sammo\DTO; namespace sammo\DTO;
use Spatie\DataTransferObject\Attributes\Strict; use sammo\DTO\Attr\Convert;
use Spatie\DataTransferObject\DataTransferObject; use sammo\DTO\Converter\MapConverter;
#[Strict] class SelectItem extends DTO
class SelectItem extends DataTransferObject
{ {
public string $title; public function __construct(
public ?string $info; public string $title,
public ?bool $isHtml; public ?string $info,
public ?array $aux; public ?bool $isHtml,
#[Convert(MapConverter::class, ['string', 'int', 'float', 'array', 'null', 'bool'])]
public ?array $aux,
) {
}
} }
+20 -24
View File
@@ -2,37 +2,33 @@
namespace sammo\DTO; namespace sammo\DTO;
use Spatie\DataTransferObject\Attributes\MapFrom; use sammo\DTO\Attr\NullIsUndefined;
use Spatie\DataTransferObject\Attributes\MapTo; use sammo\DTO\Attr\RawName;
use Spatie\DataTransferObject\Attributes\Strict;
use Spatie\DataTransferObject\DataTransferObject;
#[Strict] class VoteComment extends DTO
class VoteComment extends DataTransferObject
{ {
public ?int $id; public function __construct(
#[NullIsUndefined]
public ?int $id,
#[MapFrom('vote_id')] #[RawName('vote_id')]
#[MapTo('vote_id')] public int $voteID,
public int $voteID;
#[MapFrom('general_id')] #[RawName('general_id')]
#[MapTo('general_id')] public int $generalID,
public int $generalID;
#[MapFrom('nation_id')] #[RawName('nation_id')]
#[MapTo('nation_id')] public int $nationID,
public int $nationID;
#[MapFrom('nation_name')] #[RawName('nation_name')]
#[MapTo('nation_name')] public string $nationName,
public string $nationName;
#[MapFrom('general_name')] #[RawName('general_name')]
#[MapTo('general_name')] public string $generalName,
public string $generalName;
public string $text; public string $text,
public string $date; public string $date,
) {
}
} }
+11 -16
View File
@@ -2,23 +2,18 @@
namespace sammo\DTO; namespace sammo\DTO;
use Spatie\DataTransferObject\Attributes\CastWith; class VoteInfo extends DTO
use Spatie\DataTransferObject\Attributes\Strict;
use Spatie\DataTransferObject\DataTransferObject;
use Spatie\DataTransferObject\Casters\ArrayCaster;
//https://json2dto.atymic.dev/
#[Strict]
class VoteInfo extends DataTransferObject
{ {
public int $id; public function __construct(
public string $title; public int $id,
public int $multipleOptions; public string $title,
public int $multipleOptions,
public string $startDate; public string $startDate,
public ?string $endDate; public ?string $endDate,
/** @var string[] */ /** @var string[] */
public array $options; public array $options,
) {
}
} }
+3 -1
View File
@@ -72,7 +72,7 @@ class OpenNationBetting extends \sammo\Event\Action
aux: $nationRaw, aux: $nationRaw,
); );
} }
$bettingID = \sammo\Betting::genNextBettingID(); $bettingID = \sammo\Betting::genNextBettingID();
Betting::openBetting(new BettingInfo( Betting::openBetting(new BettingInfo(
id: $bettingID, id: $bettingID,
@@ -80,10 +80,12 @@ class OpenNationBetting extends \sammo\Event\Action
name: "{$name} 예상", name: "{$name} 예상",
finished: false, finished: false,
selectCnt: $this->nationCnt, selectCnt: $this->nationCnt,
isExclusive: null,
reqInheritancePoint: true, reqInheritancePoint: true,
openYearMonth: $openYearMonth, openYearMonth: $openYearMonth,
closeYearMonth: $closeYearMonth, closeYearMonth: $closeYearMonth,
candidates: $candidates, candidates: $candidates,
winner: null,
)); ));
$db->insert('event', [ $db->insert('event', [
+1 -1
View File
@@ -3996,7 +3996,7 @@ class GeneralAI
if (!key_exists($chiefLevel, $this->chiefGenerals) && !key_exists($chiefLevel, $nextChiefs)) { if (!key_exists($chiefLevel, $this->chiefGenerals) && !key_exists($chiefLevel, $nextChiefs)) {
$newChiefProb = 1; $newChiefProb = 1;
} else { } else {
$newChiefProb = $this->rng->nextBool(0.1); $newChiefProb = $this->rng->nextBool(0.1)?1:0;
} }
if ($newChiefProb < 1 && !$this->rng->nextBool($newChiefProb)) { if ($newChiefProb < 1 && !$this->rng->nextBool($newChiefProb)) {
+1 -1
View File
@@ -155,7 +155,7 @@
<div class="col col-sm-6 f_tnum"> <div class="col col-sm-6 f_tnum">
<b-form-input <b-form-input
:id="`buff-${buffKey}`" :id="`buff-${buffKey}`"
v-model="inheritBuff[buffKey]" v-model.number="inheritBuff[buffKey]"
type="number" type="number"
:min="prevInheritBuff[buffKey] ?? 0" :min="prevInheritBuff[buffKey] ?? 0"
:max="maxInheritBuff" :max="maxInheritBuff"
+6 -6
View File
@@ -100,13 +100,13 @@
<small class="text-muted">//</small> <small class="text-muted">//</small>
</div> </div>
<div class="col col-md-2 col-3 align-self-center"> <div class="col col-md-2 col-3 align-self-center">
<input v-model="args.leadership" type="number" class="form-control" /> <input v-model.number="args.leadership" type="number" class="form-control" />
</div> </div>
<div class="col col-md-2 col-3 align-self-center"> <div class="col col-md-2 col-3 align-self-center">
<input v-model="args.strength" type="number" class="form-control" /> <input v-model.number="args.strength" type="number" class="form-control" />
</div> </div>
<div class="col col-md-2 col-3 align-self-center"> <div class="col col-md-2 col-3 align-self-center">
<input v-model="args.intel" type="number" class="form-control" /> <input v-model.number="args.intel" type="number" class="form-control" />
</div> </div>
</div> </div>
<div class="row" style="margin-top: 1em"> <div class="row" style="margin-top: 1em">
@@ -144,10 +144,10 @@
<div v-if="displayInherit" class="inherit-block"> <div v-if="displayInherit" class="inherit-block">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<NumberInputWithInfo v-model="inheritTotalPoint" title="보유한 유산 포인트" :readonly="true" /> <NumberInputWithInfo v-model.number="inheritTotalPoint" title="보유한 유산 포인트" :readonly="true" />
</div> </div>
<div class="col"> <div class="col">
<NumberInputWithInfo v-model="inheritRequiredPoint" title="필요 유산 포인트" :readonly="true" /> <NumberInputWithInfo v-model.number="inheritRequiredPoint" title="필요 유산 포인트" :readonly="true" />
</div> </div>
</div> </div>
<hr /> <hr />
@@ -174,7 +174,7 @@
<div class="row"> <div class="row">
<div class="col col-6 a-right align-self-center">도시</div> <div class="col col-6 a-right align-self-center">도시</div>
<div class="col col-6 align-self-center"> <div class="col col-6 align-self-center">
<select v-model="args.inheritCity" class="form-select form-inline" style="max-width: 20ch"> <select v-model.number="args.inheritCity" class="form-select form-inline" style="max-width: 20ch">
<option :value="undefined">사용안함</option> <option :value="undefined">사용안함</option>
<option v-for="city in availableInheritCity" :key="city.id" :value="city.id"> <option v-for="city in availableInheritCity" :key="city.id" :value="city.id">
{{ `[${city.region}] ${city.name}` }} {{ `[${city.region}] ${city.name}` }}
+1 -1
View File
@@ -39,7 +39,7 @@
<div class="col-6 col-md-3 align-self-center">대상: {{ getTypeStr(pickedBetTypeKey) }}</div> <div class="col-6 col-md-3 align-self-center">대상: {{ getTypeStr(pickedBetTypeKey) }}</div>
<div class="col-4 col-md-2 d-grid"> <div class="col-4 col-md-2 d-grid">
<!-- eslint-disable-next-line vue/max-attributes-per-line --> <!-- eslint-disable-next-line vue/max-attributes-per-line -->
<b-form-input v-model="betPoint" class="d-grid" type="number" :min="10" :max="1000" :step="10" /> <b-form-input v-model.number="betPoint" class="d-grid" type="number" :min="10" :max="1000" :step="10" />
</div> </div>
<div class="col-2 col-md-1 d-grid"> <div class="col-2 col-md-1 d-grid">
<b-button class="d-grid" @click="submitBet"> 베팅 </b-button> <b-button class="d-grid" @click="submitBet"> 베팅 </b-button>
+1 -1
View File
@@ -34,7 +34,7 @@
<div class="col mx-2"> <div class="col mx-2">
<div class="input-group my-0"> <div class="input-group my-0">
<span class="input-group-text py-1">병력</span> <span class="input-group-text py-1">병력</span>
<input v-model="amount" type="number" class="form-control py-1 f_tnum px-0 text-end" min="1" /> <input v-model.number="amount" type="number" class="form-control py-1 f_tnum px-0 text-end" min="1" />
<span class="input-group-text py-1 f_tnum">00</span> <span class="input-group-text py-1 f_tnum">00</span>
<span <span
class="input-group-text py-1 f_tnum" class="input-group-text py-1 f_tnum"
+1 -1
View File
@@ -112,7 +112,7 @@
<div class="input-group my-0"> <div class="input-group my-0">
<span class="input-group-text py-1">병력</span> <span class="input-group-text py-1">병력</span>
<input <input
v-model="amount" v-model.number="amount"
type="number" type="number"
class="form-control py-1 f_tnum px-0 text-end" class="form-control py-1 f_tnum px-0 text-end"
min="1" min="1"
+1 -1
View File
@@ -8,7 +8,7 @@
</b-button> </b-button>
<b-button v-if="maxAmount > 200" class="btn-sm" @click="amount = Math.max(amount - 100, minAmount)"> -백 </b-button> <b-button v-if="maxAmount > 200" class="btn-sm" @click="amount = Math.max(amount - 100, minAmount)"> -백 </b-button>
<input <input
v-model="amount" v-model.number="amount"
type="number" type="number"
class="form-control text-end" class="form-control text-end"
:max="maxAmount" :max="maxAmount"
+25
View File
@@ -4,6 +4,7 @@ use sammo\DTO\Attr\Convert;
use sammo\DTO\DTO; use sammo\DTO\DTO;
use sammo\DTO\Attr\JsonString; use sammo\DTO\Attr\JsonString;
use sammo\DTO\Attr\NullIsUndefined; use sammo\DTO\Attr\NullIsUndefined;
use sammo\DTO\Attr\RawName;
use sammo\DTO\Converter\ArrayConverter; use sammo\DTO\Converter\ArrayConverter;
use sammo\DTO\Converter\Converter; use sammo\DTO\Converter\Converter;
use sammo\DTO\Converter\MapConverter; use sammo\DTO\Converter\MapConverter;
@@ -141,6 +142,19 @@ class TypeNestedMap extends DTO
} }
} }
class TypeRawName extends DTO
{
public function __construct(
#[RawName('arg_name')]
public int $argName,
#[RawName('vID')]
public int $vID,
)
{
}
}
class DTOTest extends PHPUnit\Framework\TestCase class DTOTest extends PHPUnit\Framework\TestCase
{ {
public function testBasic() public function testBasic()
@@ -326,4 +340,15 @@ class DTOTest extends PHPUnit\Framework\TestCase
$this->assertEquals($rawType, $testType); $this->assertEquals($rawType, $testType);
} }
public function testRawName(){
$rawType = [
'arg_name' => 1,
'vID' => 2,
];
$obj = TypeRawName::fromArray($rawType);
$testType = $obj->toArray();
$this->assertEquals($rawType, $testType);
}
} }