From 0f621b22a5b2147e5a1b9bd9a99cff0c2276fca2 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Mon, 25 Dec 2023 12:20:01 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20UserAction=20=EC=A1=B0=ED=9A=8C,=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../API/Command/GetReservedUserAction.php | 47 ++++++++++ hwe/sammo/API/Command/ReserveUserAction.php | 90 +++++++++++++++++++ hwe/sammo/DTO/UserAction.php | 25 ++++++ hwe/sammo/DTO/UserActionItem.php | 13 +++ hwe/ts/PageUserAction.vue | 20 ++++- hwe/ts/ReservedCommandForUserAction.vue | 58 +++++++----- hwe/ts/SammoAPI.ts | 3 +- hwe/ts/defs/API/Command.ts | 16 ++++ hwe/v_userAction.php | 13 ++- 9 files changed, 254 insertions(+), 31 deletions(-) create mode 100644 hwe/sammo/API/Command/GetReservedUserAction.php create mode 100644 hwe/sammo/API/Command/ReserveUserAction.php create mode 100644 hwe/sammo/DTO/UserAction.php create mode 100644 hwe/sammo/DTO/UserActionItem.php diff --git a/hwe/sammo/API/Command/GetReservedUserAction.php b/hwe/sammo/API/Command/GetReservedUserAction.php new file mode 100644 index 00000000..9b31837c --- /dev/null +++ b/hwe/sammo/API/Command/GetReservedUserAction.php @@ -0,0 +1,47 @@ +generalID; + + $userActionKey = 'user_action'; + + $rawUserActions = $db->queryFirstField('SELECT JSON_QUERY(`aux`, %s) FROM general WHERE no=%i', "$.{$userActionKey}", $generalID); + if($rawUserActions === null){ + $rawUserActions = '{}'; + } + + $userActions = UserAction::fromArray(Json::decode($rawUserActions)); + + return [ + 'result' => true, + 'userActions' => $userActions->toArray(), + ]; + } +} diff --git a/hwe/sammo/API/Command/ReserveUserAction.php b/hwe/sammo/API/Command/ReserveUserAction.php new file mode 100644 index 00000000..20824ceb --- /dev/null +++ b/hwe/sammo/API/Command/ReserveUserAction.php @@ -0,0 +1,90 @@ +args); + $v->rule('required', [ + 'turnIdx', + 'action' + ]) + ->rule('int', 'turnIdx') + ->rule('max', 'turnIdx', GameConst::$maxTurn) + ->rule('min', 'turnIdx', 0) + ->rule('lengthMin', 'action', 1); + if (!$v->validate()) { + return $v->errorStr(); + } + return null; + } + + public function getRequiredSessionMode(): int + { + return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY; + } + + public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType + { + $turnIdx = $this->args['turnIdx']; + $action = $this->args['action']; + + $userActionKey = 'user_action'; + + if($turnIdx < 0 || $turnIdx >= GameConst::$maxTurn){ + return '올바르지 않은 턴입니다.'; + } + + if(!in_array($action, Util::array_flatten(GameConst::$availableUserActionCommand))){ + return '사용할 수 없는 커맨드입니다.'; + } + + $db = DB::db(); + $generalID = $session->generalID; + $rawUserActions = $db->queryFirstField('SELECT JSON_QUERY(`aux`, %s) FROM general WHERE no=%i', "$.{$userActionKey}", $generalID); + if(!$rawUserActions){ + $rawUserActions = '{}'; + } + + $tmp = Json::decode($rawUserActions); + $userActions = UserAction::fromArray($tmp); + + + $gameStor = KVStorage::getStorage($db, 'game_env'); + $gameStor->cacheAll(); + $general = General::createObjFromDB($generalID); + + $item = buildUserActionCommandClass($action, $general, $gameStor->getAll()); + $userActions->reserved[$turnIdx] = new UserActionItem( + $item->getRawClassName(), + $item->getCommandDetailTitle(), + null, + ); + + $db->update('general', [ + 'aux' => $db->sqleval('JSON_SET(`aux`, %s, JSON_EXTRACT(%s, "$"))', "$.{$userActionKey}", Json::encode($userActions->toArray())), + ], 'no=%i', $generalID); + + return [ + 'result' => true, + ]; + } +} diff --git a/hwe/sammo/DTO/UserAction.php b/hwe/sammo/DTO/UserAction.php new file mode 100644 index 00000000..833105ca --- /dev/null +++ b/hwe/sammo/DTO/UserAction.php @@ -0,0 +1,25 @@ + $reserved + * */ + public function __construct( + + #[Convert(MapConverter::class, [UserActionItem::class])] + public ?array $reserved, + #[Convert(ArrayConverter::class, [UserActionItem::class])] + public ?array $active, + ) { + } +} diff --git a/hwe/sammo/DTO/UserActionItem.php b/hwe/sammo/DTO/UserActionItem.php new file mode 100644 index 00000000..81f630f9 --- /dev/null +++ b/hwe/sammo/DTO/UserActionItem.php @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/hwe/ts/ReservedCommandForUserAction.vue b/hwe/ts/ReservedCommandForUserAction.vue index e9a48a88..6edb9109 100644 --- a/hwe/ts/ReservedCommandForUserAction.vue +++ b/hwe/ts/ReservedCommandForUserAction.vue @@ -17,15 +17,15 @@
- +
{{ turnIdx + 1 }}
- - +
+
- +
-
+ + + + + + 휴식 + +
+
+
+
@@ -100,7 +112,6 @@ import { joinYearMonth } from "@util/joinYearMonth"; import { mb_strwidth } from "@util/mb_strwidth"; import { parseTime } from "@util/parseTime"; import { parseYearMonth } from "@util/parseYearMonth"; -import DragSelect from "@/components/DragSelect.vue"; import { SammoAPI } from "./SammoAPI"; import type { CommandItem, CommandTableResponse } from "@/defs"; import CommandSelectForm from "@/components/CommandSelectForm.vue"; @@ -110,7 +121,7 @@ import type { TurnObj } from "@/defs"; import type { Args } from "./processing/args"; import { getEmptyTurn } from "./util/QueryActionHelper"; import SimpleClock from "./components/SimpleClock.vue"; -import type { ReservedCommandResponse } from "./defs/API/Command"; +import type { ReservedCommandResponse, ReservedUserActionResponse, UserActionItem } from "./defs/API/Command"; import { unwrap } from "./util/unwrap"; defineExpose({ @@ -135,7 +146,6 @@ const nullCommand: CommandItem = { } const selectedCommand = ref(nullCommand); -const commandSelectForm = ref | null>(null); const invCommandMap = new Map(); async function updateCommandTable() { @@ -183,7 +193,7 @@ onMounted(() => { }); const reservedCommandList = ref(getEmptyTurn(maxTurn)); - +const reservedUserActionList = ref<(UserActionItem | undefined)[]>([]); const flippedMaxTurn = 14; const basicModeRowHeight = 34.4; @@ -209,8 +219,13 @@ const serverNow = ref(new Date()); async function reloadCommandList() { let result: ReservedCommandResponse; + let userActions: ReservedUserActionResponse; try { - result = await SammoAPI.Command.GetReservedCommand(); + [result, userActions] = await Promise.all([ + SammoAPI.Command.GetReservedCommand(), + SammoAPI.Command.GetReservedUserAction(), + ]); + } catch (e) { if (isString(e)) { toasts.danger({ @@ -265,13 +280,20 @@ async function reloadCommandList() { } serverNow.value = parseTime(result.date); + + const newReservedUserActionList: (UserActionItem | undefined)[] = []; + newReservedUserActionList.length = maxTurn; + for (const [idx, item] of Object.entries(userActions.userActions.reserved ?? {})) { + newReservedUserActionList[parseInt(idx)] = item; + } + reservedUserActionList.value = newReservedUserActionList; } async function reserveCommand() { const turnIdx = currentQuickReserveTarget.value; const commandName = selectedCommand.value.value; - if(turnIdx < 0) { + if (turnIdx < 0) { return; } @@ -333,14 +355,7 @@ onMounted(() => { width: 100%; display: grid; grid-template-columns: - minmax(20px, 0.8fr) minmax(75px, 2.4fr) minmax(40px, 0.9fr) 4.8fr minmax(28px, 0.8fr); - //30, 70, 37.65, 160 -} - -.commandTable.isEditMode { - width: 100%; - display: grid; - grid-template-columns: minmax(30px, 1fr) minmax(75px, 2.5fr) minmax(40px, 1fr) 5fr; + minmax(20px, 0.6fr) minmax(75px, 2.0fr) minmax(40px, 0.9fr) 4.0fr 3.2fr minmax(28px, 0.8fr); //30, 70, 37.65, 160 } @@ -388,11 +403,6 @@ onMounted(() => { } } -.isEditMode .month_pad:hover { - text-decoration: underline; - cursor: pointer; -} - .plain-center { background-color: black; } diff --git a/hwe/ts/SammoAPI.ts b/hwe/ts/SammoAPI.ts index 5d17fa69..bae610c4 100644 --- a/hwe/ts/SammoAPI.ts +++ b/hwe/ts/SammoAPI.ts @@ -15,7 +15,7 @@ import { export type { ValidResponse, InvalidResponse }; import { APIPathGen, NumVar, StrVar } from "./util/APIPathGen.js"; import type { BettingDetailResponse, BettingListResponse } from "./defs/API/Betting"; -import type { ReserveBulkCommandResponse, ReserveCommandResponse, ReservedCommandResponse } from "./defs/API/Command"; +import type { ReserveBulkCommandResponse, ReserveCommandResponse, ReservedCommandResponse, ReservedUserActionResponse } from "./defs/API/Command"; import type { ChiefResponse } from "./defs/API/NationCommand"; import type { inheritBuffType, InheritLogResponse } from "./defs/API/InheritAction"; import type { SetBlockWarResponse, GeneralListResponse as NationGeneralListResponse, NationInfoResponse } from "./defs/API/Nation"; @@ -109,6 +109,7 @@ const apiRealPath = { }, ReserveCommandResponse >, + GetReservedUserAction: GET as APICallT, ReserveBulkCommand: PUT as APICallT< { turnList: number[]; diff --git a/hwe/ts/defs/API/Command.ts b/hwe/ts/defs/API/Command.ts index fe3f6e16..a933d03a 100644 --- a/hwe/ts/defs/API/Command.ts +++ b/hwe/ts/defs/API/Command.ts @@ -20,3 +20,19 @@ export type ReserveBulkCommandResponse = { result: true, briefList: string[], } + +export type UserActionItem = { + command: string, + brief: string, + untilYearMonth?: number, +}; + +type UserAction = { + reserved?: Record, + active?: UserActionItem[], +} + +export type ReservedUserActionResponse = { + result: true, + userActions: UserAction, +} \ No newline at end of file diff --git a/hwe/v_userAction.php b/hwe/v_userAction.php index bc991ee4..49fcfa48 100644 --- a/hwe/v_userAction.php +++ b/hwe/v_userAction.php @@ -39,9 +39,18 @@ if ($limitState >= 2) { <?= UniqueConst::$serverName ?>: 개인 전략 - [ + [ + 'serverName' => UniqueConst::$serverName, + 'serverNick' => DB::prefix(), + 'serverID' => UniqueConst::$serverID, + 'mapName' => GameConst::$mapName, + 'unitSet' => GameConst::$unitSet, - ]]) ?> + 'maxTurn' => GameConst::$maxTurn, + 'serverNow' => TimeUtil::now(false), + ] + ], false) ?>