feat(in-progress): 턴 조작기를 vue로 분리

This commit is contained in:
2021-11-27 15:40:31 +09:00
parent c493640dae
commit c7219eeb33
7 changed files with 354 additions and 62 deletions
+30
View File
@@ -461,6 +461,36 @@ function commandGroup($typename, $type = 0)
}
}
function getCommandTable(General $general){
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->turnOnCache();
$env = $gameStor->getAll();
$result = [];
foreach (GameConst::$availableGeneralCommand as $commandCategory => $commandList) {
$subList = [];
foreach ($commandList as $commandClassName) {
$commandObj = buildGeneralCommandClass($commandClassName, $general, $env);
if (!$commandObj->canDisplay()) {
continue;
}
$subList[Util::getClassNameFromObj($commandObj)] = [
'compansation'=>$commandObj->getCompensationStyle(),
'possible'=>$commandObj->hasMinConditionMet(),
'title'=>$commandObj->getCommandDetailTitle(),
];
}
$result[] = [
'category'=>$commandCategory,
'values'=>$subList
];
}
return $result;
}
function printCommandTable(General $generalObj)
{
$db = DB::db();
+13 -42
View File
@@ -104,6 +104,8 @@ $auctionCount = $db->queryFirstField('SELECT count(`no`) FROM auction');
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('dist_js/vendors.js') ?>
<?= WebUtil::printJS('d_shared/base_map.js') ?>
<?= WebUtil::printJS('dist_js/vendors_vue.js', true) ?>
<?= WebUtil::printJS('dist_js/v_main.js', true) ?>
<?= WebUtil::printJS('dist_js/main.js') ?>
<script>
window.serverNick = '<?= DB::prefix() ?>';
@@ -119,11 +121,18 @@ $auctionCount = $db->queryFirstField('SELECT count(`no`) FROM auction');
}, 5000);
});
</script>
<?= WebUtil::printCSS('../e_lib/bootstrap.min.css') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('css/common.css') ?>
<?= WebUtil::printCSS('dist_css/common_vue.css') ?>
<?= WebUtil::printCSS('dist_css/main.css') ?>
<?= WebUtil::printCSS('css/map.css') ?>
<?= WebUtil::printStaticValues([
'maxTurn'=>GameConst::$maxTurn,
'maxPushTurn'=>12,
'commandList'=>getCommandTable($generalObj),
'serverNow'=>TimeUtil::now(false),
'baseColor2'=>GameConst::$basecolor2,
])?>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Nanum+Gothic|Nanum+Myeongjo|Nanum+Pen+Script" rel="stylesheet">
@@ -233,49 +242,11 @@ $auctionCount = $db->queryFirstField('SELECT count(`no`) FROM auction');
</div>
</div>
<?php endif; ?>
<div id="map_view" >
<div id="map_view">
<div id="mapZone" class="view-item"><?= getMapHtml($mapTheme) ?></div>
<div class="view-item" id="reservedCommandList">
<table width="300" class="tb_layout b2">
<thead>
<tr height="24">
<td colspan="4" class="center bg0"><strong>- 명령 목록 - </strong><input value="<?= TimeUtil::now(false) ?>" type="text" id="clock" size="19" style="background-color:black;color:white;border-style:none;"></td>
</tr>
</thead>
<tbody class="center" style="font-weight:bold">
<?php for ($turnIdx = 0; $turnIdx < GameConst::$maxTurn; $turnIdx++) : ?>
<tr height='28' id="command_<?= $turnIdx ?>">
<td width="24" class='idx_pad center bg0'><?= $turnIdx + 1 ?></td>
<td height='24' class='month_pad center bg1' style='min-width:70px;white-space:nowrap;overflow:hidden;'></td>
<td width='42' class='time_pad center' style='background-color:black;white-space:nowrap;overflow:hidden;'></td>
<td width='165' class='turn_pad center bg2'><span class='turn_text'></span></td>
</tr>
<?php endfor; ?>
</tbody>
</table>
<div><?= turnTable() ?></div>
<div>
<span style="color:cyan"><b>←</b> Ctrl, Shift, 드래그로 복수선택 가능  반복&amp;수정<b>→</b></span>
<select id='repeatAmount' name=sel size=1 style=color:white;background-color:black;font-size:13px;>
<option value=1>1턴</option>
<option value=2>2턴</option>
<option value=3>3턴</option>
<option value=4>4턴</option>
<option value=5>5턴</option>
<option value=6>6턴</option>
<option value=7>7턴</option>
<option value=8>8턴</option>
<option value=9>9턴</option>
<option value=10>10턴</option>
<option value=11>11턴</option>
<option value=12>12턴</option>
</select><input type=button value='반복' id='repeatTurn' style='background-color:<?= GameConst::$basecolor2 ?>;color:white;width:70px;font-size:13px;margin-left:1ch;margin-right:2ch;'><input type=button value='▼미루기' id='pushTurn' style='background-color:<?= GameConst::$basecolor2 ?>;color:white;width:80px;font-size:13px;'><input type=button value='▲당기기' id='pullTurn' style='background-color:<?= GameConst::$basecolor2 ?>;color:white;width:80px;font-size:13px;'>
</div>
<div><?php printCommandTable($generalObj) ?>
<input type=button value='실 행' id="reserveTurn" style='background-color:<?= GameConst::$basecolor2 ?>;color:white;width:110px;font-size:13px;'><input type=button value='갱 신' id='refreshPage' style='background-color:<?= GameConst::$basecolor2 ?>;color:white;width:110px;font-size:13px;'><input type=button value='로비로' onclick="location.replace('../')" style=background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;font-size:13px;>
</div>
</div>
<div class="view-item" id="reservedCommandList"></div>
<div id="cityInfo" class="view-item" style="border:none;text-align:center;"><?= cityInfo($generalObj) ?></div>
<div id="routeButtons" class="view-item"><input type=button value='갱 신' id='refreshPage' style='background-color:<?= GameConst::$basecolor2 ?>;color:white;width:110px;font-size:13px;'><input type=button value='로비로' onclick="location.replace('../')" style="background-color:<?= GameConst::$basecolor2 ?>;color:white;width:160px;font-size:13px;"></div>
</div>
<div class="row">
<div class="col-lg-6"><?php myNationInfo($generalObj); ?></div>
+52 -12
View File
@@ -9,19 +9,22 @@ body {
border-color: gray;
background-position: center;
background-repeat: repeat-y;
overflow-x: hidden;
}
@include media-breakpoint-up(lg) {
@include media-breakpoint-up(md) {
#container {
width: 1000px;
margin: 0 auto;
}
}
@include media-breakpoint-down(lg) {
@include media-breakpoint-down(md) {
body{
overflow-x: hidden;
}
#container {
width: 100%;
width: 500px;
margin: 0 auto;
}
}
@@ -33,10 +36,10 @@ body {
}
@include media-breakpoint-up(lg) {
@include media-breakpoint-up(md) {
#map_view {
grid-template-columns: 700px 300px;
grid-template-rows: 520px auto;
grid-template-rows: 520px 130px auto;
}
#mapZone {
@@ -54,14 +57,24 @@ body {
grid-row-end: 3;
}
#routeButtons{
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 3;
grid-row-end: 4;
text-align: center;
}
#reservedCommandList {
width: 300px;
grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 3;
grid-row-end: 4;
}
.buttonPlate {
display: grid;
grid-template-columns: repeat(10, 1fr);
@@ -87,7 +100,7 @@ body {
}
}
@include media-breakpoint-down(lg) {
@include media-breakpoint-down(md) {
.buttonPlate {
display: grid;
grid-template-columns: repeat(5, 1fr);
@@ -111,6 +124,37 @@ body {
margin: 0;
display: block;
}
#mapZone {
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 1;
grid-row-end: 2;
}
#reservedCommandList {
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 2;
grid-row-end: 3;
}
#routeButtons{
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 3;
grid-row-end: 4;
}
#cityInfo {
grid-column-start: 1;
grid-column-end: 2;
grid-row-start: 4;
grid-row-end: 5;
}
}
.toolbarButton {
@@ -171,10 +215,6 @@ body {
transform: translateY(-50%);
}
#sidebar button {
/*width:100px;*/
}
.turn_pad {
white-space: nowrap;
font-weight: lighter;
+239
View File
@@ -0,0 +1,239 @@
<template>
<table width="300" class="tb_layout b2">
<thead>
<tr height="24">
<td colspan="4" class="center bg0">
<strong>- 명령 목록 - </strong
><input
:value="serverNow"
type="text"
id="clock"
size="19"
style="background-color: black; color: white; border-style: none"
/>
</td>
</tr>
<tr>
<td colspan="4">
<div class="row gx-1">
<div class="col d-grid">
<b-dropdown right split text="당기기">
<b-dropdown-item v-for="turnIdx in maxPushTurn" :key="turnIdx"
>{{ turnIdx }}
</b-dropdown-item>
</b-dropdown>
</div>
<div class="col d-grid">
<b-dropdown right split @click="selectAll" text="전체선택">
<b-dropdown-item @click="selectAll(true)"
>모든턴</b-dropdown-item
>
<b-dropdown-item @click="selectStep(0, 2)"
>홀수턴</b-dropdown-item
>
<b-dropdown-item @click="selectStep(1, 2)"
>짝수턴</b-dropdown-item
>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-text
v-for="spanIdx in [3, 4, 5, 6, 7]"
:key="spanIdx"
>
{{ spanIdx }} 간격<br />
<b-button-group>
<b-button
class="ignoreMe"
v-for="beginIdx in spanIdx"
:key="beginIdx"
@click="selectStep(beginIdx - 1, spanIdx)"
>{{ beginIdx }}</b-button
>
</b-button-group>
</b-dropdown-text>
</b-dropdown>
</div>
<div class="col d-grid">
<b-dropdown right text="반복">
<b-dropdown-item v-for="turnIdx in maxPushTurn" :key="turnIdx"
>{{ turnIdx }}
</b-dropdown-item>
</b-dropdown>
</div>
</div>
</td>
</tr>
</thead>
<tbody class="center" style="font-weight: bold">
<tr
v-for="turnIdx in Math.min(maxTurn, viewMaxTurn)"
:key="turnIdx"
height="28"
:id="`command_${turnIdx - 1}`"
:class="pressed[turnIdx - 1] ? 'pressed' : ''"
>
<td width="32" class="idx_pad center bg0 d-grid" @click="clickTurn(turnIdx - 1)">
<b-button
size="sm"
:variant="pressed[turnIdx - 1] ? 'info' : 'primary'"
>{{ turnIdx }}</b-button
>
</td>
<td @click="clickTurn(turnIdx - 1)"
height="24"
class="month_pad center bg1"
style="min-width: 70px; white-space: nowrap; overflow: hidden"
></td>
<td @click="clickTurn(turnIdx - 1)"
width="38"
class="time_pad center"
style="background-color: black; white-space: nowrap; overflow: hidden"
></td>
<td width="160" class="turn_pad center bg2">
<span class="turn_text"></span>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<div class="row gx-1">
<div class="col-4 d-grid">
<b-dropdown right split text="미루기">
<b-dropdown-item v-for="turnIdx in maxPushTurn" :key="turnIdx"
>{{ turnIdx }}
</b-dropdown-item>
</b-dropdown>
</div>
<div class="col-8 d-grid"><b-button @click="toggleViewMaxTurn">{{flippedMaxTurn==viewMaxTurn?'펼치기':'접기'}}</b-button></div>
</div>
</td>
</tr>
</tfoot>
</table>
<div class="row gx-0">
<div class="col-10 d-grid">
<b-form-select v-model="selectedCommand"
><b-form-select-option-group
v-for="cgroup in commandList"
:key="cgroup['category']"
:label="cgroup['category']"
><b-form-select-option v-for="(citem, ckey) in cgroup['values']" :value="ckey" :key="ckey">{{citem.title}}{{citem.possible?'':'(불가)'}}</b-form-select-option>
</b-form-select-option-group
></b-form-select></div>
<div class="col-2 d-grid">
<b-button>실행</b-button></div>
</div>
</template>
<script lang="ts">
import addMilliseconds from "date-fns/esm/addMilliseconds/index.js";
import { range } from "lodash";
import { defineComponent, ref } from "vue";
import { formatTime } from "./util/formatTime";
import { parseTime } from "./util/parseTime";
type commandItem = {
title: string;
compensation: number;
possible: boolean;
};
declare const maxTurn: number;
declare const maxPushTurn: number;
declare const commandList: {
category: string;
values: Record<string, commandItem>[];
}[];
declare const serverNow: string;
export default defineComponent({
name: "ReservedCommand",
methods: {
updateNow() {
const clientNow = addMilliseconds(new Date(), this.timeDiff);
this.serverNow = formatTime(clientNow, false);
setTimeout(() => {
this.updateNow();
}, 250);
},
clickTurn(turnIdx: number) {
this.pressed[turnIdx] = !this.pressed[turnIdx];
},
selectAll(e: Event | true) {
//NOTE: split 구현에 버그가 있어서, 수동으로 구분해야함
if (e !== true) {
if (!e.target) {
return;
}
if (
(e.target as HTMLElement).classList.contains("dropdown-item") ||
(e.target as HTMLElement).classList.contains(
"dropdown-toggle-split"
) ||
(e.target as HTMLElement).classList.contains("ignoreMe")
) {
return;
}
}
let pressedCnt = 0;
for (const pressed of this.pressed) {
if (pressed) {
pressedCnt += 1;
}
}
if (pressedCnt * 3 > this.maxTurn) {
this.pressed.fill(false);
} else {
this.pressed.fill(true);
}
},
selectStep(begin: number, step: number) {
for (const idx of range(0, maxTurn)) {
if ((idx - begin) % step == 0) {
this.pressed[idx] = true;
} else {
this.pressed[idx] = false;
}
}
},
toggleViewMaxTurn(){
if(this.viewMaxTurn == this.flippedMaxTurn){
this.viewMaxTurn = this.maxTurn;
}
else{
this.viewMaxTurn = this.flippedMaxTurn;
}
}
},
data() {
const serverNowObj = parseTime(serverNow);
const clientNowObj = new Date();
const timeDiff = serverNowObj.getTime() - clientNowObj.getTime();
setTimeout(() => {
this.updateNow();
}, 250);
const pressed = Array.from<boolean>({ length: maxTurn }).fill(false);
pressed[0] = true;
const selectedCommand = ref<string>("휴식");
return {
maxTurn,
flippedMaxTurn: 18,
viewMaxTurn: 18,
maxPushTurn,
commandList,
serverNow,
timeDiff,
pressed,
selectedCommand,
};
},
});
</script>
+4 -3
View File
@@ -13,7 +13,6 @@
"bossInfo": "bossInfo.ts",
"myPage": "myPage.ts",
"extExpandCity": "extExpandCity.ts",
"main": "main.ts",
"dipcenter": "dipcenter.ts",
"diplomacy": "diplomacy.ts",
"currentCity": "currentCity.ts",
@@ -21,12 +20,14 @@
"history": "history.ts",
"select_general_from_pool": "select_general_from_pool.ts",
"extKingdoms": "extKingdoms.ts",
"common": "common_deprecated.ts"
"common": "common_deprecated.ts",
"main": "main.ts"
},
"ingame_vue": {
"v_inheritPoint": "v_inheritPoint.ts",
"v_board": "v_board.ts",
"v_NPCControl": "v_NPCControl.ts",
"v_join": "v_join.ts"
"v_join": "v_join.ts",
"v_main": "v_main.ts"
}
}
+7 -5
View File
@@ -15,6 +15,9 @@ import { exportWindow } from './util/exportWindow';
import {stringifyUrl} from 'query-string';
import { joinYearMonth } from './util/joinYearMonth';
import { parseYearMonth } from './util/parseYearMonth';
exportWindow($, '$');
import '../scss/main.scss';
@@ -40,9 +43,8 @@ type ReservedTurnResponse = {
autorun_limit: number|null,
}
$(function ($) {
setAxiosXMLHttpRequest();
$(function ($) {
$('#refreshPage').click(function () {
document.location.reload();
return false;
@@ -218,8 +220,8 @@ $(function ($) {
window.open(href);
});
setInterval(myclock, 500);
reloadCommandList();
//setInterval(myclock, 500);
//reloadCommandList();
activateFlip();
initTooltip();
});
});
+9
View File
@@ -0,0 +1,9 @@
import { createApp } from 'vue'
import ReservedCommand from './ReservedCommand.vue';
import BootstrapVue3 from 'bootstrap-vue-3'
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
setAxiosXMLHttpRequest();
createApp(ReservedCommand).use(BootstrapVue3).mount('#reservedCommandList')