From 9d9c66ba08c0071e3c761136d1a50f1962248524 Mon Sep 17 00:00:00 2001 From: hide_d Date: Thu, 18 Nov 2021 23:13:10 +0900 Subject: [PATCH 01/31] NationGeneralList --- hwe/sammo/API/List/NationGeneral.php | 237 +++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 hwe/sammo/API/List/NationGeneral.php diff --git a/hwe/sammo/API/List/NationGeneral.php b/hwe/sammo/API/List/NationGeneral.php new file mode 100644 index 00000000..4e188192 --- /dev/null +++ b/hwe/sammo/API/List/NationGeneral.php @@ -0,0 +1,237 @@ +args); + $v + ->rule('integer', 'req') + ->rule('boolean', 'force'); + + + if (!$v->validate()) { + return $v->errorStr(); + } + $this->reqType = $this->args['req'] ?? 1; + $this->reqForce = $this->args['force'] ?? false; + return null; + } + + public function getRequiredSessionMode(): int + { + return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY; + } + + private function getOfficerLevel($rawGeneral) + { + $level = $rawGeneral['officer_level']; + if ($level >= 5) { + return $level; + } + if ($this->permission > 1) { + return $level; + } + return 1; + } + + public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag) + { + increaseRefresh("세력장수", 1); + + $db = DB::db(); + + $me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID()); + $con = checkLimit($me['con']); + if ($con >= 2) { + return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'; + } + + $nationID = $me['nation']; + $this->permission = checkSecretPermission($me, true); + if ($this->reqForce && $this->reqType > $this->permission) { + return '권한이 부족합니다.'; + } + + $this->permission = min($this->reqType, $this->permission); + + $nationArr = getNationStaticInfo($nationID); + + $viewColumns = [ + 'no' => 0, + 'name' => 0, + 'owner_name' => 9, + 'nation' => 0, + 'city' => 1, + 'officer_level' => 2, + 'officer_city' => 2, + 'npc' => 0, + 'defence_train' => 2, + 'troop' => 2, + 'injury' => 0, + 'leadership' => 0, + 'strength' => 0, + 'intel' => 0, + 'experience' => 1, + 'explevel' => 0, + 'dedication' => 1, + 'dedlevel' => 0, + 'gold' => 0, + 'rice' => 0, + 'crewtype' => 2, + 'crew' => 2, + 'train' => 2, + 'atmos' => 2, + 'killturn' => 0, + 'turntime' => 2, + 'picture' => 0, + 'imgsvr' => 0, + 'age' => 0, + 'special' => 0, + 'special2' => 0, + 'personal' => 0, + 'belong' => 0, + 'horse' => 2, + 'weapon' => 2, + 'book' => 2, + 'item' => 2, + 'connect' => 0 + ]; + + $customViewColumns = [ + 'officerLevel' => 0, + 'officerLevelText' => 0, + 'lbonus' => 0, + 'ownerName' => 0, + 'honorText' => 0 + ]; + + + $specialViewFilter = [ + 'officerLevel' => function ($rawGeneral) { + return $this->getOfficerLevel($rawGeneral); + }, + 'special' => function ($rawGeneral) { + return getGeneralSpecialDomesticName($rawGeneral['special']); + }, + 'special2' => function ($rawGeneral) { + return getGeneralSpecialWarName($rawGeneral['special2']); + }, + 'personal' => function ($rawGeneral) { + return getGenChar($rawGeneral['personal']); + }, + 'lbonus' => function ($rawGeneral) use ($nationArr) { + return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']); + }, + 'ownerName' => function ($rawGeneral) { + if ($rawGeneral['npc'] != 1) { + return null; + } + return $rawGeneral['owner_name']; + }, + 'officerLevelText' => function ($rawGeneral) use ($nationArr) { + $level = $this->getOfficerLevel($rawGeneral); + return getOfficerLevelText($level, $nationArr['level']); + }, + 'honorText' => function ($rawGeneral) { + return getHonor($rawGeneral['experience']); + }, + 'dedLevelText' => function ($rawGeneral) { + return getDedLevelText($rawGeneral['dedLevel']); + }, + 'turntime' => function ($rawGeneral) { + //'0000-00-00 11:23'; + return substr($rawGeneral['turntime'], 11, 5); + } + + ]; + + [$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys($viewColumns), 1); + + $rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i', Util::formatListOfBackticks($queryColumns), $nationID), 'no'); + + $resultColumns = []; + foreach ($viewColumns as $column => $reqPermission) { + if ($reqPermission > $this->permission) { + continue; + } + $resultColumns[] = $column; + } + + foreach ($customViewColumns as $column => $reqPermission) { + if ($reqPermission > $this->permission) { + continue; + } + $resultColumns[] = $column; + } + + $generalList = []; + foreach ($rawGeneralList as $rawGeneral) { + //General 생성? + + $item = []; + foreach ($resultColumns as $column) { + if (key_exists($column, $specialViewFilter)) { + $value = $specialViewFilter[$column]($rawGeneral); + } else { + $value = $rawGeneral[$column]; + } + $item[] = $value; + } + + $generalList[] = $item; + } + + $result = [ + 'result' => true, + 'column' => $resultColumns, + 'list' => $generalList, + ]; + + + return $result; + } +} -- 2.54.0 From 29c3a933e97bbb4c75c4a0386c14442760445f86 Mon Sep 17 00:00:00 2001 From: hide_d Date: Fri, 19 Nov 2021 01:01:43 +0900 Subject: [PATCH 02/31] =?UTF-8?q?feat:=20GeneralList=EB=A5=BC=20API?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .phan/config.php | 3 +- hwe/j_get_general_list.php | 109 ----------- hwe/j_get_nation_general_list.php | 184 ------------------ hwe/sammo/API/Global/GeneralList.php | 165 ++++++++++++++++ .../GeneralList.php} | 22 +-- hwe/ts/select_npc.ts | 41 ++-- 6 files changed, 194 insertions(+), 330 deletions(-) delete mode 100644 hwe/j_get_general_list.php delete mode 100644 hwe/j_get_nation_general_list.php create mode 100644 hwe/sammo/API/Global/GeneralList.php rename hwe/sammo/API/{List/NationGeneral.php => Nation/GeneralList.php} (92%) diff --git a/.phan/config.php b/.phan/config.php index 95126d58..a01f9e30 100644 --- a/.phan/config.php +++ b/.phan/config.php @@ -101,8 +101,7 @@ return [ 'hwe/j_general_set_permission.php', 'hwe/j_get_basic_general_list.php', 'hwe/j_get_city_list.php', - 'hwe/j_get_general_list.php', - 'hwe/j_get_nation_general_list.php', + 'hwe/j_get_reserved_command.php', 'hwe/j_get_select_npc_token.php', 'hwe/j_get_select_pool.php', 'hwe/j_image_upload.php', diff --git a/hwe/j_get_general_list.php b/hwe/j_get_general_list.php deleted file mode 100644 index 9222ba15..00000000 --- a/hwe/j_get_general_list.php +++ /dev/null @@ -1,109 +0,0 @@ -isGameLoggedIn()){ - increaseRefresh("장수일람", 2); - - $me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID); - $con = checkLimit($me['con']); - if ($con >= 2) { - Json::die([ - 'result'=>false, - 'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.' - ]); - } -} -else{ - $availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00'; - $now = new \DateTimeImmutable(); - - if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){ - Json::die([ - 'result'=>false, - 'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall - ]); - } - - $availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s'); - $session->availableNextCallGetGeneralList = $availableNextCall; -} - -$session->setReadOnly(); - -$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general'); - -$ownerNameList = []; -if($gameStor->isunited){ - foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){ - $ownerNameList[$ownerID] = $ownerName; - } -} - -$generalList = []; -foreach($rawGeneralList as $rawGeneral){ - [$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral; - - if(key_exists($owner, $ownerNameList)){ - $ownerName = $ownerNameList[$owner]; - } - - $nationArr = getNationStaticInfo($nation); - $lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']); - - $generalList[] = [ - $no, - $picture, - $imgsvr, - $npc, - $age, - $nationArr['name'], - getGeneralSpecialDomesticName($special), - getGeneralSpecialWarName($special2), - getGenChar($personal), - $name, - $npc==1?$ownerName:null, - $injury, - $leadership, - $lbonus, - $strength, - $intel, - getExpLevel($experience), - getHonor($experience), - getDed($dedication), - getOfficerLevelText($officerLevel, $nationArr['level']), - $killturn, - $connectCnt - ]; -} - -$result = [ - 'result'=>'true', - 'list'=>$generalList, -]; - -if($withToken){ - $now = (new \DateTimeImmutable())->format('Y-m-d H:i:s'); - $tokens = []; - foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){ - $validUntil = $token['valid_until']; - - foreach(Json::decode($token['pick_result']) as $pickResult){ - $tokens[$pickResult['no']]=$pickResult['keepCnt']; - } - } - $result['token'] = $tokens; -} - -Json::die($result); diff --git a/hwe/j_get_nation_general_list.php b/hwe/j_get_nation_general_list.php deleted file mode 100644 index f5ad6fde..00000000 --- a/hwe/j_get_nation_general_list.php +++ /dev/null @@ -1,184 +0,0 @@ -setReadOnly(); -$userID = Session::getUserID(); - -$db = DB::db(); -$reqType = Util::getReq('req', 'int', 1); -$reqForce = Util::getReq('force', 'bool', false); -$gameStor = KVStorage::getStorage($db, 'game_env'); - -increaseRefresh("세력장수", 1); - -$me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $userID); -$con = checkLimit($me['con']); -if ($con >= 2) { - Json::die([ - 'result' => false, - 'reason' => '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.' - ]); -} - -$nationID = $me['nation']; -$permission = checkSecretPermission($me, true); -if ($reqForce && $reqType > $permission) { - Json::die([ - 'result' => false, - 'reason' => '권한이 부족합니다.' - ]); -} -$permission = min($reqType, $permission); -$nationArr = getNationStaticInfo($nationID); -$viewColumns = [ - 'no' => 0, - 'name' => 0, - 'owner_name' => 9, - 'nation' => 0, - 'city' => 1, - 'officer_level' => 2, - 'officer_city' => 2, - 'npc' => 0, - 'defence_train' => 2, - 'troop' => 2, - 'injury' => 0, - 'leadership' => 0, - 'strength' => 0, - 'intel' => 0, - 'experience' => 1, - 'explevel' => 0, - 'dedication' => 1, - 'dedlevel' => 0, - 'gold' => 0, - 'rice' => 0, - 'crewtype' => 2, - 'crew' => 2, - 'train' => 2, - 'atmos' => 2, - 'killturn' => 0, - 'turntime' => 2, - 'picture' => 0, - 'imgsvr' => 0, - 'age' => 0, - 'special' => 0, - 'special2' => 0, - 'personal' => 0, - 'belong' => 0, - 'horse' => 2, - 'weapon' => 2, - 'book' => 2, - 'item' => 2, - 'connect' => 0 -]; - -$customViewColumns = [ - 'officerLevel' => 0, - 'officerLevelText' => 0, - 'lbonus' => 0, - 'ownerName' => 0, - 'honorText' => 0 -]; - -function getOfficerLevel($rawGeneral) -{ - global $permission; - $level = $rawGeneral['officer_level']; - if ($level >= 5) { - return $level; - } - if ($permission > 1) { - return $level; - } - return 1; -} - -$specialViewFilter = [ - 'officerLevel' => function ($rawGeneral){ - return getOfficerLevel($rawGeneral); - }, - 'special' => function ($rawGeneral) { - return getGeneralSpecialDomesticName($rawGeneral['special']); - }, - 'special2' => function ($rawGeneral) { - return getGeneralSpecialWarName($rawGeneral['special2']); - }, - 'personal' => function ($rawGeneral) { - return getGenChar($rawGeneral['personal']); - }, - 'lbonus' => function ($rawGeneral) use ($nationArr) { - return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']); - }, - 'ownerName' => function ($rawGeneral) { - if ($rawGeneral['npc'] != 1) { - return null; - } - return $rawGeneral['owner_name']; - }, - 'officerLevelText' => function ($rawGeneral) use ($nationArr) { - $level = getOfficerLevel($rawGeneral); - return getOfficerLevelText($level, $nationArr['level']); - }, - 'honorText' => function ($rawGeneral) { - return getHonor($rawGeneral['experience']); - }, - 'dedLevelText' => function ($rawGeneral) { - return getDedLevelText($rawGeneral['dedLevel']); - }, - 'turntime' => function ($rawGeneral) { - //'0000-00-00 11:23'; - return substr($rawGeneral['turntime'], 11, 5); - } - -]; - -[$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys($viewColumns), 1); - -$rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i', Util::formatListOfBackticks($queryColumns), $nationID), 'no'); - -$resultColumns = []; -foreach ($viewColumns as $column => $reqPermission) { - if ($reqPermission > $permission) { - continue; - } - $resultColumns[] = $column; -} - -foreach ($customViewColumns as $column => $reqPermission) { - if ($reqPermission > $permission) { - continue; - } - $resultColumns[] = $column; -} - -$generalList = []; -foreach ($rawGeneralList as $rawGeneral) { - //General 생성? - - $item = []; - foreach ($resultColumns as $column) { - if (key_exists($column, $specialViewFilter)) { - $value = $specialViewFilter[$column]($rawGeneral); - } - else{ - $value = $rawGeneral[$column]; - } - $item[] = $value; - } - - $generalList[] = $item; -} - -$result = [ - 'result' => true, - 'column' => $resultColumns, - 'list' => $generalList, -]; - -Json::die($result); diff --git a/hwe/sammo/API/Global/GeneralList.php b/hwe/sammo/API/Global/GeneralList.php new file mode 100644 index 00000000..bf561ec9 --- /dev/null +++ b/hwe/sammo/API/Global/GeneralList.php @@ -0,0 +1,165 @@ +args); + $v + ->rule('boolean', 'with_token'); + if (!$v->validate()) { + return $v->errorStr(); + } + return null; + } + + public function getRequiredSessionMode(): int + { + return static::REQ_LOGIN; + } + + public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag) + { + $db = DB::db(); + $withToken = $this->args['with_token']??false; + $gameStor = KVStorage::getStorage($db, 'game_env'); + + $userID = $session->userID; + if ($session->isGameLoggedIn()) { + increaseRefresh("장수일람", 2); + $me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID); + $con = checkLimit($me['con']); + if ($con >= 2) { + return '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'; + } + } else { + $availableNextCall = $session->availableNextCallGetGeneralList ?? '2000-01-01 00:00:00'; + $now = new \DateTimeImmutable(); + + if ($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5) { + return "장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : " . $availableNextCall; + } + + $availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s'); + $session->availableNextCallGetGeneralList = $availableNextCall; + } + + $session->setReadOnly(); + + + $rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general'); + + $ownerNameList = []; + if ($gameStor->isunited) { + foreach (RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]) { + $ownerNameList[$ownerID] = $ownerName; + } + } + + $generalList = []; + foreach ($rawGeneralList as $rawGeneral) { + [$owner, $no, $picture, $imgsvr, $npc, $age, $nation, $special, $special2, $personal, $name, $ownerName, $injury, $leadership, $strength, $intel, $experience, $dedication, $officerLevel, $killturn, $connectCnt] = $rawGeneral; + + if (key_exists($owner, $ownerNameList)) { + $ownerName = $ownerNameList[$owner]; + } + + $nationArr = getNationStaticInfo($nation); + $lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']); + + $generalList[] = [ + $no, + $picture, + $imgsvr, + $npc, + $age, + $nationArr['name'], + getGeneralSpecialDomesticName($special), + getGeneralSpecialWarName($special2), + getGenChar($personal), + $name, + $npc == 1 ? $ownerName : null, + $injury, + $leadership, + $lbonus, + $strength, + $intel, + getExpLevel($experience), + getHonor($experience), + getDed($dedication), + getOfficerLevelText($officerLevel, $nationArr['level']), + $killturn, + $connectCnt + ]; + } + + $resultColumns = [ + 'no', + 'picture', + 'imgsvr', + 'npc', + 'age', + 'nationName', + 'special', + 'special2', + 'personal', + 'name', + 'ownerName', + 'injury', + 'leadership', + 'lbonus', + 'strength', + 'intel', + 'explevel', + 'honorText', + 'dedLevelText', + 'officerLevelText', + ]; + + $result = [ + 'result' => 'true', + 'column' => $resultColumns, + 'list' => $generalList, + ]; + + + if ($withToken) { + $now = (new \DateTimeImmutable())->format('Y-m-d H:i:s'); + $tokens = []; + foreach ($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token) { + $validUntil = $token['valid_until']; + + foreach (Json::decode($token['pick_result']) as $pickResult) { + $tokens[$pickResult['no']] = $pickResult['keepCnt']; + } + } + $result['token'] = $tokens; + } + return $result; + } +} diff --git a/hwe/sammo/API/List/NationGeneral.php b/hwe/sammo/API/Nation/GeneralList.php similarity index 92% rename from hwe/sammo/API/List/NationGeneral.php rename to hwe/sammo/API/Nation/GeneralList.php index 4e188192..f8962808 100644 --- a/hwe/sammo/API/List/NationGeneral.php +++ b/hwe/sammo/API/Nation/GeneralList.php @@ -1,31 +1,16 @@ { + const generalList: NPCPickPrintable[] = value.list.map((rawGeneral) => { const general: NPCPickPrintableR = { no: rawGeneral[0], picture: rawGeneral[1], @@ -317,7 +317,7 @@ function printGeneralList(value: GeneralListResponse) { } if (general.reserved == 1) { - general.nameAux += `
(${tokenList[general.no]}회)`; + general.nameAux += `
(${tokenList[general.no]}회)`; } @@ -369,7 +369,7 @@ function printGeneralList(value: GeneralListResponse) { _printGeneralList(true); } -function _printGeneralList(clear?:boolean) { +function _printGeneralList(clear?: boolean) { const $generalTable = $('#general_list'); if (clear) { $generalTable.empty(); @@ -438,20 +438,31 @@ $(function ($) { }, errUnknown); }); - $('#btn_load_general_list').click(function () { - $.post({ - url: 'j_get_general_list.php', - dataType: 'json', - data: { - with_token: true - } - }).then(function (result) { + $('#btn_load_general_list').click(async function () { + + let result: InvalidResponse | GeneralListResponse; + try { + const response = await axios({ + url: "api.php", + method: "post", + responseType: "json", + data: { + path: "Global/GeneralList", + args: { + with_token: true, + }, + }, + }); + result = response.data; if (!result.result) { - alert(result.reason); - return false; + throw result.reason; } - printGeneralList(result); - }, errUnknown); + } catch (e) { + console.error(e); + alert(`실패했습니다: ${e}`); + return; + } + printGeneralList(result); }); $('#btn_print_more').click(function () { -- 2.54.0 From 94acf876952679e0252c725ecbaebdb45406fc9e Mon Sep 17 00:00:00 2001 From: Hide_D Date: Sun, 27 Mar 2022 22:51:04 +0900 Subject: [PATCH 03/31] =?UTF-8?q?wip:=20=EC=84=B8=EB=A0=A5=20=EC=9E=A5?= =?UTF-8?q?=EC=88=98=20=EC=A4=80=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/scss/nationGeneral.scss | 30 +++++++++++++++++++++++++++ hwe/ts/PageNationGeneral.vue | 18 ++++++++++++++++ hwe/ts/build_exports.json | 3 ++- hwe/ts/v_nationGeneral.ts | 12 +++++++++++ hwe/v_nationGeneral.php | 40 ++++++++++++++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 hwe/scss/nationGeneral.scss create mode 100644 hwe/ts/PageNationGeneral.vue create mode 100644 hwe/ts/v_nationGeneral.ts create mode 100644 hwe/v_nationGeneral.php diff --git a/hwe/scss/nationGeneral.scss b/hwe/scss/nationGeneral.scss new file mode 100644 index 00000000..643047e0 --- /dev/null +++ b/hwe/scss/nationGeneral.scss @@ -0,0 +1,30 @@ +@import '@scss/common/bootstrap5.scss'; +@import "@scss/game_bg.scss"; +@import "@scss/util.scss"; + +#container{ + padding: 0; +} + +#app { + width: 100%; + overflow-x: hidden; +} + + +@include media-1000px { + #container { + width: 1000px; + margin: 0 auto; + position: relative; + } +} + +@include media-500px { + #container { + position: relative; + width: 500px; + margin: auto; + overflow-x: hidden; + } +} \ No newline at end of file diff --git a/hwe/ts/PageNationGeneral.vue b/hwe/ts/PageNationGeneral.vue new file mode 100644 index 00000000..065027ae --- /dev/null +++ b/hwe/ts/PageNationGeneral.vue @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/hwe/ts/build_exports.json b/hwe/ts/build_exports.json index c3f57482..6f4fb652 100644 --- a/hwe/ts/build_exports.json +++ b/hwe/ts/build_exports.json @@ -28,6 +28,7 @@ "v_main": "v_main.ts", "v_nationStratFinan": "v_nationStratFinan.ts", "v_processing": "v_processing.ts", - "v_nationBetting": "v_nationBetting.ts" + "v_nationBetting": "v_nationBetting.ts", + "v_nationGeneral": "v_nationGeneral.ts" } } \ No newline at end of file diff --git a/hwe/ts/v_nationGeneral.ts b/hwe/ts/v_nationGeneral.ts new file mode 100644 index 00000000..3364dad0 --- /dev/null +++ b/hwe/ts/v_nationGeneral.ts @@ -0,0 +1,12 @@ +import "@scss/nationGeneral.scss"; + +import { createApp } from 'vue' +import PageNationGeneral from '@/PageNationGeneral.vue'; +import { BootstrapVue3, BToastPlugin } from 'bootstrap-vue-3'; +import { auto500px } from './util/auto500px'; + + + + +auto500px(); +createApp(PageNationGeneral).use(BootstrapVue3).use(BToastPlugin).mount('#app'); \ No newline at end of file diff --git a/hwe/v_nationGeneral.php b/hwe/v_nationGeneral.php new file mode 100644 index 00000000..1bc2f726 --- /dev/null +++ b/hwe/v_nationGeneral.php @@ -0,0 +1,40 @@ +setReadOnly(); +$userID = Session::getUserID(); + +$db = DB::db(); +$gameStor = KVStorage::getStorage($db, 'game_env'); + +?> + + + + + + + + <?= UniqueConst::$serverName ?>: 세력 장수 + [ + 'serverNick' => DB::prefix(), + 'mapName' => GameConst::$mapName, + 'unitSet' => GameConst::$unitSet, + ] + ], false) ?> + + + + + + + +
+ + + \ No newline at end of file -- 2.54.0 From 3b4cbf68cad87d89b2a39d86cb0435d3435fb10f Mon Sep 17 00:00:00 2001 From: Hide_D Date: Mon, 28 Mar 2022 14:29:24 +0900 Subject: [PATCH 04/31] refac(WIP): SammoAPI, select_npc --- hwe/ts/SammoAPI.ts | 4 +++ hwe/ts/defs/index.ts | 50 +++++++++++++++++++++++------- hwe/ts/select_npc.ts | 72 ++++++++++++-------------------------------- 3 files changed, 62 insertions(+), 64 deletions(-) diff --git a/hwe/ts/SammoAPI.ts b/hwe/ts/SammoAPI.ts index ebad9a55..927720e6 100644 --- a/hwe/ts/SammoAPI.ts +++ b/hwe/ts/SammoAPI.ts @@ -13,6 +13,7 @@ import type { SetBlockWarResponse } from "./defs/API/Nation"; import type { UploadImageResponse } from "./defs/API/Misc"; import type { JoinArgs } from "./defs/API/General"; import type { GetConstResponse } from "./defs/API/Global"; +import type { GeneralListResponse } from "./defs"; const apiRealPath = { Betting: { @@ -49,6 +50,9 @@ const apiRealPath = { Join: POST as APICallT, }, Global: { + GeneralList: GET as APICallT<{ + with_token?: boolean + }, GeneralListResponse>, GetConst: GET as APICallT, }, InheritAction: { diff --git a/hwe/ts/defs/index.ts b/hwe/ts/defs/index.ts index 36527788..d7b8b0bf 100644 --- a/hwe/ts/defs/index.ts +++ b/hwe/ts/defs/index.ts @@ -1,5 +1,6 @@ import type { Args } from "@/processing/args"; import type { ValidResponse, InvalidResponse } from "@/util/callSammoAPI"; +import type { GameObjClassKey } from "./GameObj"; export type { ValidResponse, InvalidResponse }; export type BasicGeneralListResponse = { @@ -15,21 +16,48 @@ export type BasicGeneralListResponse = { }> } + +export type PublicGeneralItem = { + no: number, + picture: string, + imgsvr: 0 | 1, + npc: number, + age: number, + nation: string, + specialDomestic: GameObjClassKey, + specialWar: GameObjClassKey, + personal: GameObjClassKey, + name: string, + ownerName: string | null, + injury: number, + leadership: number, + lbonus: number, + strength: number, + intel: number, + explevel: number, + experienceStr: string, + dedicationStr: string, + officerLevelStr: string, + killturn: number, + connect: number, +} + + export type GeneralListResponse = { result: true, list: [ - number, - string, 0 | 1, - number, number, string, - string, string, string, - string, string | null, - number, - number, number, number, number, - number, - string, string, string, - number, number + PublicGeneralItem['no'], + PublicGeneralItem['picture'], PublicGeneralItem['imgsvr'], + PublicGeneralItem['npc'], PublicGeneralItem['age'], PublicGeneralItem['nation'], + PublicGeneralItem['specialDomestic'], PublicGeneralItem['specialWar'], PublicGeneralItem['personal'], + PublicGeneralItem['name'], PublicGeneralItem['ownerName'], + PublicGeneralItem['injury'], + PublicGeneralItem['leadership'], PublicGeneralItem['lbonus'], PublicGeneralItem['strength'], PublicGeneralItem['intel'], + PublicGeneralItem['explevel'], + PublicGeneralItem['experienceStr'], PublicGeneralItem['dedicationStr'], PublicGeneralItem['officerLevelStr'], + PublicGeneralItem['killturn'], PublicGeneralItem['connect'] ][], - token: Record, + token?: Record, } export type NationLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; diff --git a/hwe/ts/select_npc.ts b/hwe/ts/select_npc.ts index dfea1e56..c3d13e47 100644 --- a/hwe/ts/select_npc.ts +++ b/hwe/ts/select_npc.ts @@ -3,12 +3,14 @@ import { errUnknown } from '@/common_legacy'; import { getIconPath } from "@util/getIconPath"; import { TemplateEngine } from "@util/TemplateEngine"; import { getNpcColor } from '@/common_legacy'; -import type { GeneralListResponse, InvalidResponse } from '@/defs'; +import type { GeneralListResponse, InvalidResponse, PublicGeneralItem } from '@/defs'; import { convertFormData } from '@util/convertFormData'; import { unwrap_any } from '@util/unwrap_any'; import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest'; import { Tooltip } from 'bootstrap'; import { trim } from 'lodash'; +import { SammoAPI } from './SammoAPI'; +import { unwrap } from './util/unwrap'; setAxiosXMLHttpRequest(); @@ -40,29 +42,7 @@ type NPCPick = { personalText?: string, } -type NPCPickPrintableR = { - no: number, - picture: string, - imgsvr: 0 | 1, - npc: number, - age: number, - nation: string, - special: string, - special2: string, - personal: string, - name: string, - ownerName: string | null, - injury: number, - leadership: number, - lbonus: number, - strength: number, - intel: number, - explevel: number, - experience: string, - dedication: string, - officerLevel: string, - killturn: number, - connect: number, +type NPCPickPrintableR = PublicGeneralItem & { reserved: number, userCSS?: string, @@ -269,7 +249,7 @@ function printGenerals(value: NPCToken) { function printGeneralList(value: GeneralListResponse) { console.log(value); - const tokenList = value.token; + const tokenList = unwrap(value.token); const generalList: NPCPickPrintable[] = value.list.map((rawGeneral) => { const general: NPCPickPrintableR = { no: rawGeneral[0], @@ -278,8 +258,8 @@ function printGeneralList(value: GeneralListResponse) { npc: rawGeneral[3], age: rawGeneral[4], nation: rawGeneral[5], - special: rawGeneral[6], - special2: rawGeneral[7], + specialDomestic: rawGeneral[6], + specialWar: rawGeneral[7], personal: rawGeneral[8], name: rawGeneral[9], ownerName: rawGeneral[10], @@ -289,9 +269,9 @@ function printGeneralList(value: GeneralListResponse) { strength: rawGeneral[14], intel: rawGeneral[15], explevel: rawGeneral[16], - experience: rawGeneral[17], - dedication: rawGeneral[18], - officerLevel: rawGeneral[19], + experienceStr: rawGeneral[17], + dedicationStr: rawGeneral[18], + officerLevelStr: rawGeneral[19], killturn: rawGeneral[20], connect: rawGeneral[21], reserved: 0 @@ -325,13 +305,13 @@ function printGeneralList(value: GeneralListResponse) { general.iconPath = getIconPath(general.imgsvr, general.picture); general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, { - text: general.special, - info: specialInfo[general.special] + text: general.specialDomestic, + info: specialInfo[general.specialDomestic] }); general.specialWarWithTooltip = TemplateEngine(templateSpecial, { - text: general.special2, - info: specialInfo[general.special2] + text: general.specialWar, + info: specialInfo[general.specialWar] }); general.personalWithTooltip = TemplateEngine(templateSpecial, { @@ -438,34 +418,20 @@ $(function ($) { }, errUnknown); }); - $('#btn_load_general_list').click(async function () { - - let result: InvalidResponse | GeneralListResponse; + $('#btn_load_general_list').on('click', async function () { try { - const response = await axios({ - url: "api.php", - method: "post", - responseType: "json", - data: { - path: "Global/GeneralList", - args: { - with_token: true, - }, - }, + const result = await SammoAPI.Global.GeneralList({ + with_token: true, }); - result = response.data; - if (!result.result) { - throw result.reason; - } + printGeneralList(result); } catch (e) { console.error(e); alert(`실패했습니다: ${e}`); return; } - printGeneralList(result); }); - $('#btn_print_more').click(function () { + $('#btn_print_more').on('click', function () { _printGeneralList(); }) -- 2.54.0 From 988ba015b81debd8ca1e076aa79c0a278c4b3d68 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Mon, 28 Mar 2022 21:28:32 +0900 Subject: [PATCH 05/31] =?UTF-8?q?refac:=20sammoAPI=20=EC=A0=95=EC=9D=98=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EC=9D=BC=EB=B6=80=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?-=20defs/index.ts=EB=A1=9C=20=EB=B6=84=EB=A6=AC=20-=20API/Natio?= =?UTF-8?q?n/GeneralList=20=ED=98=B8=EC=B6=9C=20=EC=9E=AC=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/sammo/API/Nation/GeneralList.php | 51 ++++++++---------- hwe/ts/defs/API/Nation/index.ts | 81 ++++++++++++++++++++++++++++ hwe/ts/util/merge2DArrToObjectArr.ts | 20 +++++++ 3 files changed, 123 insertions(+), 29 deletions(-) create mode 100644 hwe/ts/defs/API/Nation/index.ts create mode 100644 hwe/ts/util/merge2DArrToObjectArr.ts diff --git a/hwe/sammo/API/Nation/GeneralList.php b/hwe/sammo/API/Nation/GeneralList.php index f8962808..ce93e391 100644 --- a/hwe/sammo/API/Nation/GeneralList.php +++ b/hwe/sammo/API/Nation/GeneralList.php @@ -22,24 +22,10 @@ use function sammo\increaseRefresh; class GeneralList extends \sammo\BaseAPI { - - private int $reqType; - private bool $reqForce; private int $permission; public function validateArgs(): ?string { - $v = new Validator($this->args); - $v - ->rule('integer', 'req') - ->rule('boolean', 'force'); - - - if (!$v->validate()) { - return $v->errorStr(); - } - $this->reqType = $this->args['req'] ?? 1; - $this->reqForce = $this->args['force'] ?? false; return null; } @@ -74,11 +60,6 @@ class GeneralList extends \sammo\BaseAPI $nationID = $me['nation']; $this->permission = checkSecretPermission($me, true); - if ($this->reqForce && $this->reqType > $this->permission) { - return '권한이 부족합니다.'; - } - - $this->permission = min($this->reqType, $this->permission); $nationArr = getNationStaticInfo($nationID); @@ -123,12 +104,19 @@ class GeneralList extends \sammo\BaseAPI 'connect' => 0 ]; + $columnRemap = [ + 'special' => 'specialDomestic', + 'special2' => 'specialWar', + ]; + $customViewColumns = [ 'officerLevel' => 0, 'officerLevelText' => 0, + 'specialDomesticTest' => 0, + 'specialWarText' => 0, 'lbonus' => 0, 'ownerName' => 0, - 'honorText' => 0 + 'honorText' => 0, ]; @@ -136,10 +124,14 @@ class GeneralList extends \sammo\BaseAPI 'officerLevel' => function ($rawGeneral) { return $this->getOfficerLevel($rawGeneral); }, - 'special' => function ($rawGeneral) { + 'officerLevelText' => function ($rawGeneral) use ($nationArr) { + $level = $this->getOfficerLevel($rawGeneral); + return getOfficerLevelText($level, $nationArr['level']); + }, + 'specialDomesticTest' => function ($rawGeneral) { return getGeneralSpecialDomesticName($rawGeneral['special']); }, - 'special2' => function ($rawGeneral) { + 'specialWarText' => function ($rawGeneral) { return getGeneralSpecialWarName($rawGeneral['special2']); }, 'personal' => function ($rawGeneral) { @@ -154,10 +146,6 @@ class GeneralList extends \sammo\BaseAPI } return $rawGeneral['owner_name']; }, - 'officerLevelText' => function ($rawGeneral) use ($nationArr) { - $level = $this->getOfficerLevel($rawGeneral); - return getOfficerLevelText($level, $nationArr['level']); - }, 'honorText' => function ($rawGeneral) { return getHonor($rawGeneral['experience']); }, @@ -180,7 +168,12 @@ class GeneralList extends \sammo\BaseAPI if ($reqPermission > $this->permission) { continue; } - $resultColumns[] = $column; + if(key_exists($column, $columnRemap)){ + $resultColumns[$columnRemap[$column]] = $column; + } + else{ + $resultColumns[$column] = $column; + } } foreach ($customViewColumns as $column => $reqPermission) { @@ -209,11 +202,11 @@ class GeneralList extends \sammo\BaseAPI $result = [ 'result' => true, - 'column' => $resultColumns, + 'permission' => $this->permission, + 'column' => array_keys($resultColumns), 'list' => $generalList, ]; - return $result; } } diff --git a/hwe/ts/defs/API/Nation/index.ts b/hwe/ts/defs/API/Nation/index.ts new file mode 100644 index 00000000..71b69f31 --- /dev/null +++ b/hwe/ts/defs/API/Nation/index.ts @@ -0,0 +1,81 @@ + +import type { GameObjType, ValuesOf } from "@/defs"; +import type { ValidResponse } from "@/SammoAPI"; + +export type GeneralListItemP0 = { + no: number, + name: string, + nation: number, + npc: number, + injury: number, + leadership: number, + strength: number, + intel: number, + explevel: number, + dedlevel: number, + gold: number, + rice: number, + killturn: number, + picture: string, + imgsvr: 0 | 1, + age: number, + special: GameObjType, + special2: GameObjType, + personal: GameObjType, + belong: number, + connect: number, + + officerLevel: number, //권한에따라 태수,군사,시종 노출 여부가 다름 + officerLevelText: string, + lbonus: number, + ownerName: string | null, //NPC 출력용에 따라 결과가 다름 + honorText: string, +} + +export type GeneralListItemP1 = { + city: number, + experience: number, + dedication: number, +} & GeneralListItemP0; + +export type GeneralListItemP2 = GeneralListItemP1 & { + officer_level: number, + officer_city: number, + +} +export type GeneralListItemP9 = GeneralListItemP2 & { + owner_name: string, +} + +export type GeneralListItem = +({permission : 0} & GeneralListItemP0) | +({permission : 1} & GeneralListItemP1) | +({permission : 2} & GeneralListItemP2) | +({permission : 9} & GeneralListItemP9); + + +export type RawGeneralListP0 = ValidResponse & { + permission: 0, + column: keyof GeneralListItemP0[], + list: ValuesOf[], +} + +export type RawGeneralListP1 = ValidResponse & { + permission: 1, + column: keyof GeneralListItemP1[], + list: ValuesOf[][], +} + +export type RawGeneralListP2 = ValidResponse & { + permission: 2, + column: keyof GeneralListItemP2[], + list: ValuesOf[][], +} + +export type RawGeneralListP9 = ValidResponse & { + permission: 9, + column: keyof GeneralListItemP9[], + list: ValuesOf[][], +} + +export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2 | RawGeneralListP9; diff --git a/hwe/ts/util/merge2DArrToObjectArr.ts b/hwe/ts/util/merge2DArrToObjectArr.ts new file mode 100644 index 00000000..a019d021 --- /dev/null +++ b/hwe/ts/util/merge2DArrToObjectArr.ts @@ -0,0 +1,20 @@ + +import type { ValuesOf } from "@/defs"; +import { zip } from "lodash"; + +export function merge2DArrToObjectArr>(column: (keyof T)[], list: ValuesOf[][]): T[]{ + const result: T[] = []; + for(const rawItem of list){ + const item: Record = {}; + + if(column.length != item.length){ + throw `column과 item의 길이가 같지 않습니다: ${column.length} != ${list.length}, ${JSON.stringify(item)}`; + } + + for(const [key, value] of zip(column, rawItem)){ + item[key as string] = value; + } + result.push(item as T); + } + return result; +} \ No newline at end of file -- 2.54.0 From 9eaaa0da07efdf752598e651bc939e7479720bd2 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Tue, 29 Mar 2022 02:33:10 +0900 Subject: [PATCH 06/31] misc: tabSize 2 --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 9d330958..98928fd3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,5 +28,6 @@ "cSpell.words": [ "josa", "sammo" - ] + ], + "editor.tabSize": 2 } \ No newline at end of file -- 2.54.0 From 73c3cc4983629120fc3015398309c3ba91e2389d Mon Sep 17 00:00:00 2001 From: Hide_D Date: Tue, 29 Mar 2022 02:36:28 +0900 Subject: [PATCH 07/31] =?UTF-8?q?feat(wip):=20=EC=84=B8=EB=A0=A5=20?= =?UTF-8?q?=EC=9E=A5=EC=88=98=20=EC=9E=91=EC=97=85=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/sammo/API/Nation/GeneralList.php | 4 +-- hwe/ts/PageNationGeneral.vue | 54 ++++++++++++++++++++++------ hwe/ts/components/GeneralList.vue | 19 ++++++++++ hwe/ts/defs/API/Nation/index.ts | 30 ++++++---------- hwe/ts/util/merge2DArrToObjectArr.ts | 2 +- 5 files changed, 77 insertions(+), 32 deletions(-) create mode 100644 hwe/ts/components/GeneralList.vue diff --git a/hwe/sammo/API/Nation/GeneralList.php b/hwe/sammo/API/Nation/GeneralList.php index ce93e391..729cd701 100644 --- a/hwe/sammo/API/Nation/GeneralList.php +++ b/hwe/sammo/API/Nation/GeneralList.php @@ -1,6 +1,6 @@ $this->permission) { continue; } - $resultColumns[] = $column; + $resultColumns[$column] = $column; } $generalList = []; diff --git a/hwe/ts/PageNationGeneral.vue b/hwe/ts/PageNationGeneral.vue index 065027ae..e9986766 100644 --- a/hwe/ts/PageNationGeneral.vue +++ b/hwe/ts/PageNationGeneral.vue @@ -1,18 +1,52 @@ + \ No newline at end of file +const title = "세력 장수"; + +onMounted(async () => { + try { + const { column, list, permission } = await SammoAPI.Nation.GeneralList(); + //XXX: 로직상 똑같은데.... + if (permission == 0) { + const rawGeneralList = merge2DArrToObjectArr(column, list); + generalList.value = new Map(rawGeneralList.map((v) => [v.no, { permission, ...v }])); + } else if (permission == 1) { + const rawGeneralList = merge2DArrToObjectArr(column, list); + generalList.value = new Map(rawGeneralList.map((v) => [v.no, { permission, ...v }])); + } else if ([2, 3, 4].includes(permission)) { + const rawGeneralList = merge2DArrToObjectArr(column, list); + generalList.value = new Map(rawGeneralList.map((v) => [v.no, { permission, ...v }])); + } else { + throw `?? ${permission}`; + } + + } catch (e) { + console.error(e); + throw e; + } +}); + diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue new file mode 100644 index 00000000..6e410b75 --- /dev/null +++ b/hwe/ts/components/GeneralList.vue @@ -0,0 +1,19 @@ + + + diff --git a/hwe/ts/defs/API/Nation/index.ts b/hwe/ts/defs/API/Nation/index.ts index 71b69f31..d5fbf43a 100644 --- a/hwe/ts/defs/API/Nation/index.ts +++ b/hwe/ts/defs/API/Nation/index.ts @@ -43,39 +43,31 @@ export type GeneralListItemP2 = GeneralListItemP1 & { officer_city: number, } -export type GeneralListItemP9 = GeneralListItemP2 & { - owner_name: string, -} + +export type RawGeneralListItem = GeneralListItemP0 | GeneralListItemP1 | GeneralListItemP2; export type GeneralListItem = -({permission : 0} & GeneralListItemP0) | -({permission : 1} & GeneralListItemP1) | -({permission : 2} & GeneralListItemP2) | -({permission : 9} & GeneralListItemP9); + ({ permission: 0 } & GeneralListItemP0) | + ({ permission: 1 } & GeneralListItemP1) | + ({ permission: 2 | 3 | 4 } & GeneralListItemP2); export type RawGeneralListP0 = ValidResponse & { permission: 0, - column: keyof GeneralListItemP0[], - list: ValuesOf[], + column: (keyof GeneralListItemP0)[], + list: ValuesOf[][], } export type RawGeneralListP1 = ValidResponse & { permission: 1, - column: keyof GeneralListItemP1[], + column: (keyof GeneralListItemP1)[], list: ValuesOf[][], } export type RawGeneralListP2 = ValidResponse & { - permission: 2, - column: keyof GeneralListItemP2[], + permission: 2 | 3 | 4, + column: (keyof GeneralListItemP2)[], list: ValuesOf[][], } -export type RawGeneralListP9 = ValidResponse & { - permission: 9, - column: keyof GeneralListItemP9[], - list: ValuesOf[][], -} - -export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2 | RawGeneralListP9; +export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2; diff --git a/hwe/ts/util/merge2DArrToObjectArr.ts b/hwe/ts/util/merge2DArrToObjectArr.ts index a019d021..bea7836a 100644 --- a/hwe/ts/util/merge2DArrToObjectArr.ts +++ b/hwe/ts/util/merge2DArrToObjectArr.ts @@ -7,7 +7,7 @@ export function merge2DArrToObjectArr>(column: for(const rawItem of list){ const item: Record = {}; - if(column.length != item.length){ + if(column.length != rawItem.length){ throw `column과 item의 길이가 같지 않습니다: ${column.length} != ${list.length}, ${JSON.stringify(item)}`; } -- 2.54.0 From 1a04e2c53b335326e586ff45a0242704ff091b2a Mon Sep 17 00:00:00 2001 From: Hide_D Date: Wed, 30 Mar 2022 03:24:28 +0900 Subject: [PATCH 08/31] =?UTF-8?q?feat(wip):=20=EC=9E=A5=EC=88=98=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EB=B7=B0=20=EC=9E=91=EC=97=85=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/scss/nationGeneral.scss | 2 - hwe/ts/components/GeneralList.vue | 180 +++++++++++++++++++++++++++++- hwe/ts/defs/API/Nation/index.ts | 4 +- 3 files changed, 177 insertions(+), 9 deletions(-) diff --git a/hwe/scss/nationGeneral.scss b/hwe/scss/nationGeneral.scss index 643047e0..df8b6b0a 100644 --- a/hwe/scss/nationGeneral.scss +++ b/hwe/scss/nationGeneral.scss @@ -8,7 +8,6 @@ #app { width: 100%; - overflow-x: hidden; } @@ -25,6 +24,5 @@ position: relative; width: 500px; margin: auto; - overflow-x: hidden; } } \ No newline at end of file diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index 6e410b75..0deb153e 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -1,14 +1,172 @@ + + diff --git a/hwe/ts/defs/API/Nation/index.ts b/hwe/ts/defs/API/Nation/index.ts index d5fbf43a..a89dab15 100644 --- a/hwe/ts/defs/API/Nation/index.ts +++ b/hwe/ts/defs/API/Nation/index.ts @@ -19,8 +19,8 @@ export type GeneralListItemP0 = { picture: string, imgsvr: 0 | 1, age: number, - special: GameObjType, - special2: GameObjType, + specialDomestic: GameObjType, + specialWar: GameObjType, personal: GameObjType, belong: number, connect: number, -- 2.54.0 From f3df6db60762e99a63841f875f82372ad79c83af Mon Sep 17 00:00:00 2001 From: Hide_D Date: Thu, 31 Mar 2022 01:50:24 +0900 Subject: [PATCH 09/31] =?UTF-8?q?feat(wip):=20=EC=9E=A5=EC=88=98=ED=8C=A8?= =?UTF-8?q?=EB=84=90=EC=97=90=20ag-grid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/ts/PageNationGeneral.vue | 22 ++- hwe/ts/components/GeneralList.vue | 249 ++++++++++++++++++++++-------- hwe/ts/v_nationGeneral.ts | 2 + package-lock.json | 30 ++++ package.json | 2 + 5 files changed, 233 insertions(+), 72 deletions(-) diff --git a/hwe/ts/PageNationGeneral.vue b/hwe/ts/PageNationGeneral.vue index e9986766..5e83e4b7 100644 --- a/hwe/ts/PageNationGeneral.vue +++ b/hwe/ts/PageNationGeneral.vue @@ -1,7 +1,7 @@ @@ -23,7 +23,7 @@ import { merge2DArrToObjectArr } from "./util/merge2DArrToObjectArr"; import type { GeneralListItem } from "./defs/API/Nation"; import GeneralList from "./components/GeneralList.vue"; -const generalList = ref(new Map()); +const generalList = ref([]); const title = "세력 장수"; @@ -33,13 +33,13 @@ onMounted(async () => { //XXX: 로직상 똑같은데.... if (permission == 0) { const rawGeneralList = merge2DArrToObjectArr(column, list); - generalList.value = new Map(rawGeneralList.map((v) => [v.no, { permission, ...v }])); + generalList.value = rawGeneralList.map((v) => {return { permission, ...v }}); } else if (permission == 1) { const rawGeneralList = merge2DArrToObjectArr(column, list); - generalList.value = new Map(rawGeneralList.map((v) => [v.no, { permission, ...v }])); + generalList.value = rawGeneralList.map((v) => {return { permission, ...v }}); } else if ([2, 3, 4].includes(permission)) { const rawGeneralList = merge2DArrToObjectArr(column, list); - generalList.value = new Map(rawGeneralList.map((v) => [v.no, { permission, ...v }])); + generalList.value = rawGeneralList.map((v) => {return { permission, ...v }}); } else { throw `?? ${permission}`; } @@ -50,3 +50,15 @@ onMounted(async () => { } }); + + \ No newline at end of file diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index 0deb153e..0860fd45 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -1,56 +1,88 @@ - + + + diff --git a/hwe/ts/v_nationGeneral.ts b/hwe/ts/v_nationGeneral.ts index 3364dad0..e877b3d5 100644 --- a/hwe/ts/v_nationGeneral.ts +++ b/hwe/ts/v_nationGeneral.ts @@ -1,4 +1,6 @@ import "@scss/nationGeneral.scss"; +import "ag-grid-community/dist/styles/ag-grid.css"; +import "ag-grid-community/dist/styles/ag-theme-balham-dark.css"; import { createApp } from 'vue' import PageNationGeneral from '@/PageNationGeneral.vue'; diff --git a/package-lock.json b/package-lock.json index 7e6936f4..3b81b866 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,8 @@ "@typescript-eslint/parser": "^5.14.0", "@vue/compiler-sfc": "^3.2.31", "@vue/eslint-config-typescript": "^10.0.0", + "ag-grid-community": "^27.1.0", + "ag-grid-vue3": "^27.1.0", "async-validator": "^4.0.7", "autoprefixer": "^10.4.2", "axios": "^0.26.1", @@ -3066,6 +3068,20 @@ "node": ">=0.4.0" } }, + "node_modules/ag-grid-community": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-27.1.0.tgz", + "integrity": "sha512-SWzIJTNa7C6Vinizelcoc1FAJQRt1pDn+A8XHQDO2GTQT+VjBnPL8fg94fLJy0EEvqaN5IhDybNS0nD07SKIQw==" + }, + "node_modules/ag-grid-vue3": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-27.1.0.tgz", + "integrity": "sha512-3kZCK4UiFc/jCGvMy7zXjNG130GLuLboqoo4jzdLnD9PNR4hzqYjKVnCFHAQVi9Zj3hRBAWDwEU18MHukZuwKA==", + "dependencies": { + "ag-grid-community": "~27.1.0", + "vue": "^3.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -12796,6 +12812,20 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==" }, + "ag-grid-community": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-27.1.0.tgz", + "integrity": "sha512-SWzIJTNa7C6Vinizelcoc1FAJQRt1pDn+A8XHQDO2GTQT+VjBnPL8fg94fLJy0EEvqaN5IhDybNS0nD07SKIQw==" + }, + "ag-grid-vue3": { + "version": "27.1.0", + "resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-27.1.0.tgz", + "integrity": "sha512-3kZCK4UiFc/jCGvMy7zXjNG130GLuLboqoo4jzdLnD9PNR4hzqYjKVnCFHAQVi9Zj3hRBAWDwEU18MHukZuwKA==", + "requires": { + "ag-grid-community": "~27.1.0", + "vue": "^3.0.0" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", diff --git a/package.json b/package.json index 5e5f9be9..c355febb 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,8 @@ "@typescript-eslint/parser": "^5.14.0", "@vue/compiler-sfc": "^3.2.31", "@vue/eslint-config-typescript": "^10.0.0", + "ag-grid-community": "^27.1.0", + "ag-grid-vue3": "^27.1.0", "async-validator": "^4.0.7", "autoprefixer": "^10.4.2", "axios": "^0.26.1", -- 2.54.0 From d4565042255ca38e27627141c8e70b823228914d Mon Sep 17 00:00:00 2001 From: Hide_D Date: Sun, 3 Apr 2022 23:42:52 +0900 Subject: [PATCH 10/31] =?UTF-8?q?feat(WIP):=20=EC=84=B8=EB=A0=A5=EC=9E=A5?= =?UTF-8?q?=EC=88=98=20=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/sammo/API/Nation/GeneralList.php | 8 +- hwe/templates/commandButton.php | 2 +- hwe/ts/PageNationGeneral.vue | 7 +- hwe/ts/SammoAPI.ts | 3 +- hwe/ts/components/GeneralList.vue | 434 +++++++++++++++++++-------- hwe/ts/defs/API/Nation.ts | 80 ++++- hwe/ts/defs/API/Nation/index.ts | 73 ----- 7 files changed, 397 insertions(+), 210 deletions(-) delete mode 100644 hwe/ts/defs/API/Nation/index.ts diff --git a/hwe/sammo/API/Nation/GeneralList.php b/hwe/sammo/API/Nation/GeneralList.php index 729cd701..62c9da17 100644 --- a/hwe/sammo/API/Nation/GeneralList.php +++ b/hwe/sammo/API/Nation/GeneralList.php @@ -11,6 +11,7 @@ use sammo\Validator; use function sammo\calcLeadershipBonus; use function sammo\checkLimit; use function sammo\checkSecretPermission; +use function sammo\getBillByLevel; use function sammo\getDedLevelText; use function sammo\getGenChar; use function sammo\getGeneralSpecialDomesticName; @@ -117,6 +118,8 @@ class GeneralList extends \sammo\BaseAPI 'lbonus' => 0, 'ownerName' => 0, 'honorText' => 0, + 'dedLevelText' => 0, + 'bill' => 0, ]; @@ -150,12 +153,13 @@ class GeneralList extends \sammo\BaseAPI return getHonor($rawGeneral['experience']); }, 'dedLevelText' => function ($rawGeneral) { - return getDedLevelText($rawGeneral['dedLevel']); + return getDedLevelText($rawGeneral['dedlevel']); }, 'turntime' => function ($rawGeneral) { //'0000-00-00 11:23'; return substr($rawGeneral['turntime'], 11, 5); - } + }, + 'bill' => fn($rawGeneral) => getBillByLevel($rawGeneral['dedlevel']) ]; diff --git a/hwe/templates/commandButton.php b/hwe/templates/commandButton.php index 4da7e7bb..834c55e4 100644 --- a/hwe/templates/commandButton.php +++ b/hwe/templates/commandButton.php @@ -10,7 +10,7 @@ 토 너 먼 트 '>세력 정보 '>세력 도시 -'>세력 장수 +'>세력 장수 중원 정보 현재 도시 '>감 찰 부 diff --git a/hwe/ts/PageNationGeneral.vue b/hwe/ts/PageNationGeneral.vue index 5e83e4b7..9c8b1d02 100644 --- a/hwe/ts/PageNationGeneral.vue +++ b/hwe/ts/PageNationGeneral.vue @@ -1,7 +1,12 @@ diff --git a/hwe/ts/SammoAPI.ts b/hwe/ts/SammoAPI.ts index 927720e6..1b87fd83 100644 --- a/hwe/ts/SammoAPI.ts +++ b/hwe/ts/SammoAPI.ts @@ -9,7 +9,7 @@ import type { BettingDetailResponse, BettingListResponse } from "./defs/API/Bett import type { ReserveBulkCommandResponse, ReserveCommandResponse, ReservedCommandResponse } from "./defs/API/Command"; import type { ChiefResponse } from "./defs/API/NationCommand"; import type { inheritBuffType } from "./defs/API/InheritAction"; -import type { SetBlockWarResponse } from "./defs/API/Nation"; +import type { SetBlockWarResponse, GeneralListResponse as NationGeneralListResponse } from "./defs/API/Nation"; import type { UploadImageResponse } from "./defs/API/Misc"; import type { JoinArgs } from "./defs/API/General"; import type { GetConstResponse } from "./defs/API/Global"; @@ -96,6 +96,7 @@ const apiRealPath = { }[], ReserveBulkCommandResponse>, }, Nation: { + GeneralList: GET as APICallT, SetNotice: PUT as APICallT<{ msg: string, }>, diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index 0860fd45..470153ff 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -8,6 +8,7 @@ , + type: String as PropType<"static" | "fill" | number | `${number}px` | `${number}%`>, required: false, - default: 'static', + default: "static", }, }); +//debug +console.log(`list`, props.list); + watch( () => props.list, () => { setTimeout(() => { + //debug + console.log(`list`, props.list); gridApi.value?.redrawRows(); }, 0); } @@ -50,7 +69,7 @@ watch( watch( () => props.height, (val) => { - if (val === 'static') { + if (val === "static") { gridApi.value?.setDomLayout("autoHeight"); } else { gridApi.value?.setDomLayout("normal"); @@ -63,76 +82,106 @@ const columnApi = ref(); const rowHeight = ref(28); +function getRowId(params: GetRowIdParams): string { + const genID = (params.data as GeneralListItem).no; + return `${genID}`; +} + function onGridReady(params: GridReadyEvent) { gridApi.value = params.api; columnApi.value = params.columnApi; - if (props.height === 'static') { + if (props.height === "static") { params.api.setDomLayout("autoHeight"); - } - else{ - params.api.setDomLayout('normal'); + } else { + params.api.setDomLayout("normal"); } setRowHeight(); - params.api.sizeColumnsToFit(); } function setRowHeight() { - if (!columnRawDefs.value.icon?.hide) { + if (!(columnRawDefs.value.icon as GenColDef | undefined)?.hide) { rowHeight.value = 64 + 4; return; } rowHeight.value = gridApi.value?.getSizesForCurrentTheme().rowHeight ?? 28; } -type headerInfo = { - title: string; - info?: string; - isEnum?: boolean; //default: false - sortable?: "asc" | "desc" | false | undefined | null; //default: false - searchable?: boolean; //default: false - type?: "both" | "display" | "filter" | "custom"; //default: both - converter?: (a: GeneralListItem) => string; - subType?: Partial>; //n행 표기 시 - style?: StyleValue; -}; - type headerType = - | keyof Omit + | keyof Omit | "stat" | "icon" | "goldRice" | "expDedLv" | "specials" - | "killturnAndConnect"; + | "killturnAndConnect" + | "years"; -type GenColDef = ColDef & { +interface GenValueParams extends BaseWithValueColDefParams { + data: GeneralListItem; +} + +interface GenValueGetterParams extends ValueGetterParams { + data: GeneralListItem; +} + +interface GenColDef extends ColDef { field?: headerType; -}; + valueFormatter?: string | ((params: GenValueParams) => string); + filterValueGetter?: string | ((params: GenValueGetterParams) => string); +} + +interface GenColGroupDef extends ColGroupDef { + children: (GenColDef | GenColGroupDef)[]; + groupId: headerType; +} interface GenCellClassParams extends CellClassParams { data: GeneralListItem; } +function naiveCheClassNameFilter(value: string): string { + const text = value.split("_").pop() ?? "None"; + if (text === "None") { + return "-"; + } + return text; +} + +function naiveCheClassNameFilterFromRow(key: keyof GeneralListItem) { + return (value: GenValueParams): string => { + return naiveCheClassNameFilter(value.data[key]?.toString() ?? "None"); + }; +} + +function numberFormatter(value: GenValueParams): string { + return (value.value as number).toLocaleString(); +} + +const defaultCellClass = ["cell-middle"]; +const centerCellClass = [...defaultCellClass, "cell-center"]; +const rightAlignClass = [...defaultCellClass, "cell-right"]; +const sortableNumber: GenColDef = { + sortable: true, + comparator: (a, b) => a - b, + sortingOrder: ["desc", "asc", null], + filter: "number", + cellClass: rightAlignClass, +}; const defaultColDef = ref({ resizable: true, headerClass: "default-cell-header", - cellClass: "cell-middle", + cellClass: centerCellClass, + floatingFilter: true, + width: 90, }); -const sortableNumber: GenColDef = { - sortable: true, - comparator: (a, b)=>a-b, - sortingOrder: ['desc', 'asc', null], - filter: 'number' -} - -const columnRawDefs = ref>>({ +const columnRawDefs = ref>>({ icon: { headerName: "아이콘", width: 64 + 24, suppressSizeToFit: true, resizable: false, - cellRenderer: (obj: { data: GeneralListItem }) => { + cellRenderer: (obj: GenValueParams) => { const { data: gen } = obj; return ``; }, @@ -144,7 +193,8 @@ const columnRawDefs = ref>>({ field: "name", pinned: "left", sortable: true, - sortingOrder: ['asc', 'desc', null], + width: 130, + sortingOrder: ["asc", "desc", null], lockPosition: true, cellStyle: (val: GenCellClassParams) => { const gen = val.data; @@ -153,117 +203,229 @@ const columnRawDefs = ref>>({ }; return style as CellStyle; }, + cellClass: defaultCellClass, filter: true, }, npc: { headerName: "NPC", field: "npc", hide: true }, - leadership: { headerName: '통솔', field: 'leadership', ...sortableNumber}, - strength: { headerName: '무력', field: 'strength', ...sortableNumber}, - intel: { headerName: '지력', field: 'intel', ...sortableNumber}, - explevel: { headerName: '명성Lv', field: 'explevel', ...sortableNumber}, - dedlevel: { headerName: '계급Lv', field: 'dedlevel', ...sortableNumber}, + stat: { + groupId: "stat", + openByDefault: false, + headerName: "능력치", + children: [ + { + headerName: "통|무|지", + width: 90, + + cellRenderer: (obj: GenValueParams) => { + const gen = obj.data; + return `${gen.leadership}|${gen.strength}|${gen.intel}`; + }, + columnGroupShow: "closed", + }, + { + headerName: "통솔", + field: "leadership", + ...sortableNumber, + columnGroupShow: "open", + width: 70, + type: "numericColumn", + }, + { + headerName: "무력", + field: "strength", + ...sortableNumber, + columnGroupShow: "open", + width: 70, + }, + { + headerName: "지력", + field: "intel", + ...sortableNumber, + columnGroupShow: "open", + width: 70, + }, + ], + }, + officerLevel: { + headerName: "관직", + field: "officerLevelText", + sortable: true, + comparator: (a, b, c, d) => c.data.officerLevel - d.data.officerLevel, + cellRenderer: ({ data }: GenValueParams) => { + if (data.permission == 2 && 2 <= data.officerLevel && 4 <= data.officerLevel) { + return `${data.officer_city} ${data.officerLevelText}`; + } + return data.officerLevelText; + }, + filter: true, + cellClass: centerCellClass, + width: 90, + }, + expDedLv: { + headerName: "명성", + groupId: "expDedLv", + width: 70, + children: [ + { + headerName: "/계급", + columnGroupShow: "closed", + width: 70, + cellRenderer: ({ data }: GenValueParams) => { + return `Lv ${data.explevel}
${data.dedLevelText}`; + }, + }, + { + headerName: "명성", + field: "explevel", + width: 75, + cellRenderer: ({ data }: GenValueParams) => { + return `Lv ${data.explevel}
(${data.honorText})`; + }, + ...sortableNumber, + columnGroupShow: "open", + }, + { + headerName: "계급", + field: "dedLevelText", + width: 75, + cellRenderer: ({ data }: GenValueParams) => { + return `${data.dedLevelText}
(${data.bill.toLocaleString()})`; + }, + ...sortableNumber, + cellClass: centerCellClass, + columnGroupShow: "open", + }, + ], + }, + gold: { headerName: "금", field: "gold", ...sortableNumber, valueFormatter: numberFormatter, width: 75 }, + rice: { headerName: "쌀", field: "rice", ...sortableNumber, valueFormatter: numberFormatter, width: 75 }, + + specials: { + headerName: "성격/내특/전특", + children: [ + { + headerName: "요약", + cellRenderer: ({ data }: GenValueParams) => { + const personal = naiveCheClassNameFilter(data.personal); + const specialDomestic = naiveCheClassNameFilter(data.specialDomestic); + const specialWar = naiveCheClassNameFilter(data.specialWar); + return `${personal}
${specialDomestic}
${specialWar}
`; + }, + width: 90, + columnGroupShow: "closed", + }, + { + headerName: "성격", + field: "personal", + valueFormatter: naiveCheClassNameFilterFromRow("personal"), + width: 70, + sortable: true, + filter: true, + columnGroupShow: "open", + }, + { + headerName: "내특", + field: "specialDomestic", + valueFormatter: naiveCheClassNameFilterFromRow("specialDomestic"), + width: 70, + sortable: true, + filter: true, + columnGroupShow: "open", + }, + { + headerName: "전특", + field: "specialWar", + valueFormatter: naiveCheClassNameFilterFromRow("specialWar"), + width: 70, + sortable: true, + filter: true, + columnGroupShow: "open", + }, + ], + }, + years: { + headerName: "연도", + children: [ + { + headerName: "요약", + cellRenderer: ({ data }: GenValueParams) => { + return `${data.age}세
${data.belong}년`; + }, + cellClass: centerCellClass, + columnGroupShow: "closed", + }, + { + headerName: "연령", + field: "age", + ...sortableNumber, + valueFormatter: (v: GenValueParams) => `${v.value}세`, + width: 70, + cellClass: centerCellClass, + columnGroupShow: "open", + }, + { + headerName: "사관", + field: "belong", + ...sortableNumber, + valueFormatter: (v: GenValueParams) => `${v.value}년`, + width: 70, + cellClass: centerCellClass, + columnGroupShow: "open", + }, + ], + }, + killturnAndConnect: { + headerName: "기타", + children: [ + { + headerName: "삭/벌", + cellRenderer: ({ data }: GenValueParams) => { + return `${data.killturn.toLocaleString()}턴
${data.connect.toLocaleString()}점`; + }, + cellClass: rightAlignClass, + columnGroupShow: "closed", + }, + { + headerName: "삭턴", + field: "killturn", + cellRenderer: ({ data }: GenValueParams) => { + return `${data.killturn.toLocaleString()}턴`; + }, + ...sortableNumber, + columnGroupShow: "open", + }, + { + headerName: "벌점", + field: "connect", + cellRenderer: ({ data }: GenValueParams) => { + return `${data.connect.toLocaleString()}점`; + }, + ...sortableNumber, + columnGroupShow: "open", + }, + ], + }, }); const columnDefs = ref([...Object.values(columnRawDefs.value)]); -const headerMap: Record = { - icon: { - title: "아이콘", - type: "display", - style: { - maxWidth: "64px", - }, - converter: (gen) => { - return ``; - }, - }, - name: { title: "장수명", searchable: true }, - nation: { title: "국가명", isEnum: true }, - npc: { title: "NPC", isEnum: true, type: "filter" }, - injury: { title: "부상", sortable: "asc" }, - leadership: { title: "통솔" }, - strength: { title: "무력" }, - intel: { title: "지력" }, - stat: { - title: "통/무/지", - type: "custom", - subType: { - leadership: { title: "통" }, - strength: { title: "무" }, - intel: { title: "지" }, - }, - }, - explevel: { title: "명성Lv" }, - dedlevel: { title: "계급Lv" }, - expDedLv: { - title: "명성/계급Lv", - subType: { - explevel: { title: "명성Lv" }, - dedlevel: { title: "계급Lv" }, - }, - }, - gold: { title: "금", sortable: "desc" }, - rice: { title: "쌀", sortable: "desc" }, - goldRice: { - title: "금/쌀", - type: "custom", - subType: { - gold: { title: "금", sortable: "desc" }, - rice: { title: "쌀", sortable: "desc" }, - }, - }, - age: { title: "연령" }, - specialDomestic: { title: "내특" }, - specialWar: { title: "전특" }, - specials: { - title: "성격/내특/전특", - subType: { - personal: { title: "성격", converter: (g) => g.personal.split("_").pop() as string }, - specialDomestic: { title: "내특", converter: (g) => g.specialDomestic.split("_").pop() as string }, - specialWar: { title: "전특", converter: (g) => g.specialWar.split("_").pop() as string }, - }, - }, - personal: { title: "성격" }, - belong: { title: "임관" }, - - killturnAndConnect: { - title: "삭턴/벌점", - subType: { - killturn: { title: "삭턴" }, - connect: { title: "벌점" }, - }, - }, - killturn: { title: "삭턴" }, - connect: { title: "벌점" }, - - officerLevel: { title: "관직" }, //권한에따라 태수,군사,시종 노출 여부가 다름 - ownerName: { title: "소유주" }, //NPC 출력용에 따라 결과가 다름 - honorText: { title: "명성" }, - - city: { title: "도시" }, - experience: { title: "명성" }, - dedication: { title: "계급" }, - - officer_level: { title: "관직" }, - officer_city: { title: "부임지" }, -} as const; - watch(columnRawDefs, (val) => { setRowHeight(); columnDefs.value = [...Object.values(val)]; }); - +/* let currentWidth = -1; window.addEventListener("resize", (e) => { setTimeout(() => { const newWidth = document.querySelector(".container")?.clientWidth ?? -1; if (currentWidth != newWidth) { currentWidth = newWidth; - gridApi.value?.sizeColumnsToFit(); + columnApi.value?.autoSizeAllColumns(); } }, 1); }); - +*/ diff --git a/hwe/ts/defs/API/Nation.ts b/hwe/ts/defs/API/Nation.ts index 6b4023c1..73dec09b 100644 --- a/hwe/ts/defs/API/Nation.ts +++ b/hwe/ts/defs/API/Nation.ts @@ -1,5 +1,79 @@ -import type { ValidResponse } from "@/defs"; +import type { ValuesOf, TurnObj } from "@/defs"; +import type { GameObjClassKey } from "@/defs/GameObj"; +import type { ValidResponse } from "@/SammoAPI"; export type SetBlockWarResponse = ValidResponse & { - availableCnt: number; - }; \ No newline at end of file + availableCnt: number; +}; + +export type GeneralListItemP0 = { + no: number, + name: string, + nation: number, + npc: number, + injury: number, + leadership: number, + strength: number, + intel: number, + explevel: number, + dedlevel: number, + gold: number, + rice: number, + killturn: number, + picture: string, + imgsvr: 0 | 1, + age: number, + specialDomestic: GameObjClassKey, + specialWar: GameObjClassKey, + personal: GameObjClassKey, + belong: number, + connect: number, + + officerLevel: number, //권한에따라 태수,군사,시종 노출 여부가 다름 + officerLevelText: string, + lbonus: number, + ownerName: string | null, //NPC 출력용에 따라 결과가 다름 + honorText: string, + dedLevelText: string, + bill: number, +} + +export type GeneralListItemP1 = { + city: number, + experience: number, + dedication: number, +} & GeneralListItemP0; + +export type GeneralListItemP2 = GeneralListItemP1 & { + officer_level: number, + officer_city: number, + +} + +export type RawGeneralListItem = GeneralListItemP0 | GeneralListItemP1 | GeneralListItemP2; + +export type GeneralListItem = + ({ permission: 0 } & GeneralListItemP0) | + ({ permission: 1 } & GeneralListItemP1) | + ({ permission: 2 | 3 | 4 } & GeneralListItemP2); + + +export type RawGeneralListP0 = ValidResponse & { + permission: 0, + column: (keyof GeneralListItemP0)[], + list: ValuesOf[][], +} + +export type RawGeneralListP1 = ValidResponse & { + permission: 1, + column: (keyof GeneralListItemP1)[], + list: ValuesOf[][], +} + +export type RawGeneralListP2 = ValidResponse & { + permission: 2 | 3 | 4, + column: (keyof GeneralListItemP2)[], + list: ValuesOf[][], +} + +export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2; diff --git a/hwe/ts/defs/API/Nation/index.ts b/hwe/ts/defs/API/Nation/index.ts deleted file mode 100644 index a89dab15..00000000 --- a/hwe/ts/defs/API/Nation/index.ts +++ /dev/null @@ -1,73 +0,0 @@ - -import type { GameObjType, ValuesOf } from "@/defs"; -import type { ValidResponse } from "@/SammoAPI"; - -export type GeneralListItemP0 = { - no: number, - name: string, - nation: number, - npc: number, - injury: number, - leadership: number, - strength: number, - intel: number, - explevel: number, - dedlevel: number, - gold: number, - rice: number, - killturn: number, - picture: string, - imgsvr: 0 | 1, - age: number, - specialDomestic: GameObjType, - specialWar: GameObjType, - personal: GameObjType, - belong: number, - connect: number, - - officerLevel: number, //권한에따라 태수,군사,시종 노출 여부가 다름 - officerLevelText: string, - lbonus: number, - ownerName: string | null, //NPC 출력용에 따라 결과가 다름 - honorText: string, -} - -export type GeneralListItemP1 = { - city: number, - experience: number, - dedication: number, -} & GeneralListItemP0; - -export type GeneralListItemP2 = GeneralListItemP1 & { - officer_level: number, - officer_city: number, - -} - -export type RawGeneralListItem = GeneralListItemP0 | GeneralListItemP1 | GeneralListItemP2; - -export type GeneralListItem = - ({ permission: 0 } & GeneralListItemP0) | - ({ permission: 1 } & GeneralListItemP1) | - ({ permission: 2 | 3 | 4 } & GeneralListItemP2); - - -export type RawGeneralListP0 = ValidResponse & { - permission: 0, - column: (keyof GeneralListItemP0)[], - list: ValuesOf[][], -} - -export type RawGeneralListP1 = ValidResponse & { - permission: 1, - column: (keyof GeneralListItemP1)[], - list: ValuesOf[][], -} - -export type RawGeneralListP2 = ValidResponse & { - permission: 2 | 3 | 4, - column: (keyof GeneralListItemP2)[], - list: ValuesOf[][], -} - -export type GeneralListResponse = RawGeneralListP0 | RawGeneralListP1 | RawGeneralListP2; -- 2.54.0 From b714c7dff10cf061fbe3d63310cacdd8664524d9 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Mon, 4 Apr 2022 00:19:45 +0900 Subject: [PATCH 11/31] feat(wip): gameConstStore inject --- hwe/ts/PageNationGeneral.vue | 23 ++++++++++++++++------- hwe/ts/components/GeneralList.vue | 7 ++++++- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/hwe/ts/PageNationGeneral.vue b/hwe/ts/PageNationGeneral.vue index 9c8b1d02..e243616e 100644 --- a/hwe/ts/PageNationGeneral.vue +++ b/hwe/ts/PageNationGeneral.vue @@ -1,12 +1,7 @@ @@ -22,16 +17,30 @@ import TopBackBar from "@/components/TopBackBar.vue"; import BottomBar from "@/components/BottomBar.vue"; import { BContainer } from "bootstrap-vue-3"; -import { onMounted, ref } from "vue"; +import { onMounted, provide, ref } from "vue"; import { SammoAPI } from "./SammoAPI"; import { merge2DArrToObjectArr } from "./util/merge2DArrToObjectArr"; import type { GeneralListItem } from "./defs/API/Nation"; import GeneralList from "./components/GeneralList.vue"; +import { type GameConstStore, getGameConstStore } from "./GameConstStore"; const generalList = ref([]); +const gameConstStore = ref(); +provide('gameConstStore', gameConstStore); + +const asyncReady = ref(false); + const title = "세력 장수"; +const storeP = getGameConstStore().then((store)=>{ + gameConstStore.value = store; +}); + +void Promise.all([storeP]).then(()=>{ + asyncReady.value = true; +}); + onMounted(async () => { try { const { column, list, permission } = await SammoAPI.Nation.GeneralList(); diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index 470153ff..e455b3ba 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -21,7 +21,7 @@ diff --git a/hwe/ts/gridCellRenderer/SimpleTooltipCell.vue b/hwe/ts/gridCellRenderer/SimpleTooltipCell.vue new file mode 100644 index 00000000..732485cc --- /dev/null +++ b/hwe/ts/gridCellRenderer/SimpleTooltipCell.vue @@ -0,0 +1,42 @@ + + + -- 2.54.0 From 09fb96d9b39410d6b6b9ffd5a3d0516b3eab1bfc Mon Sep 17 00:00:00 2001 From: Hide_D Date: Mon, 4 Apr 2022 21:26:01 +0900 Subject: [PATCH 14/31] =?UTF-8?q?feat(WIP):=20=EC=9E=A5=EC=88=98=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=86=92=EC=9D=B4=20=EC=9E=AC?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/ts/components/GeneralList.vue | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index d01e74e5..ee6d169b 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -9,7 +9,7 @@ style="width: 100%; height: 100%" class="ag-theme-balham-dark" :getRowId="getRowId" - :rowHeight="rowHeight" + :getRowHeight="getRowHeight" :columnDefs="columnDefs" :rowData="list" :defaultColDef="defaultColDef" @@ -111,6 +111,11 @@ function setRowHeight() { rowHeight.value = gridApi.value?.getSizesForCurrentTheme().rowHeight ?? 28; } + +function getRowHeight():number{ + return rowHeight.value; +} + type headerType = | keyof Omit | "stat" @@ -432,12 +437,14 @@ const columnRawDefs = ref ], }, }); +setRowHeight(); const columnDefs = ref([...Object.values(columnRawDefs.value)]); watch(columnRawDefs, (val) => { setRowHeight(); columnDefs.value = [...Object.values(val)]; + gridApi.value?.redrawRows(); }); /* -- 2.54.0 From c104fbcf5802a047a1bd8f0f294ea4b406ef013b Mon Sep 17 00:00:00 2001 From: Hide_D Date: Tue, 5 Apr 2022 00:29:45 +0900 Subject: [PATCH 15/31] =?UTF-8?q?feat(wip):=20=EC=84=B8=EB=A0=A5=EC=9E=A5?= =?UTF-8?q?=EC=88=98=EC=97=90=EC=84=9C=20=EC=95=94=ED=96=89=EB=B6=80,=20?= =?UTF-8?q?=EB=9E=AD=ED=81=AC=20=EA=B0=92=20=EB=AA=A8=EB=91=90=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/sammo/API/Nation/GeneralList.php | 256 +++++++++++++------- hwe/ts/PageNationGeneral.vue | 13 +- hwe/ts/components/GeneralList.vue | 24 +- hwe/ts/defs/API/Nation.ts | 29 +++ hwe/ts/gridCellRenderer/GridTooltipCell.vue | 2 - 5 files changed, 207 insertions(+), 117 deletions(-) diff --git a/hwe/sammo/API/Nation/GeneralList.php b/hwe/sammo/API/Nation/GeneralList.php index 0a0643a9..d29ab73d 100644 --- a/hwe/sammo/API/Nation/GeneralList.php +++ b/hwe/sammo/API/Nation/GeneralList.php @@ -25,8 +25,84 @@ class GeneralList extends \sammo\BaseAPI { private int $permission; + static $viewColumns = [ + 'no' => 0, + 'name' => 0, + 'nation' => 0, + 'npc' => 0, + 'injury' => 0, + 'leadership' => 0, + 'strength' => 0, + 'intel' => 0, + 'explevel' => 0, + 'dedlevel' => 0, + 'gold' => 0, + 'rice' => 0, + 'killturn' => 0, + 'picture' => 0, + 'imgsvr' => 0, + 'age' => 0, + 'special' => 0, + 'special2' => 0, + 'personal' => 0, + 'belong' => 0, + 'connect' => 0, + + + 'city' => 1, + 'experience' => 1, + 'dedication' => 1, + + 'officer_level' => 2, + 'officer_city' => 2, + 'defence_train' => 2, + 'troop' => 2, + 'crewtype' => 2, + 'crew' => 2, + 'train' => 2, + 'atmos' => 2, + 'turntime' => 2, + 'horse' => 2, + 'weapon' => 2, + 'book' => 2, + 'item' => 2, + + 'aux' => 2, + + + 'owner_name' => 9,//안씀. + + //RANK + 'warnum' => 2, + 'killnum' => 2, + 'deathnum' => 2, + 'killcrew' => 2, + 'deathcrew' => 2, + 'firenum' => 2, + ]; + + static $columnRemap = [ + 'special' => 'specialDomestic', + 'special2' => 'specialWar', + 'aux' => null, + ]; + + static $customViewColumns = [ + 'officerLevel' => 0, + 'officerLevelText' => 0, + 'lbonus' => 0, + 'ownerName' => 0, + 'honorText' => 0, + 'dedLevelText' => 0, + 'bill' => 0, + 'reservedCommand' => 2, + + 'autorun_limit' => 2, + ]; + public function validateArgs(): ?string { + //TODO: 장기적으로는 요청에 따라 반환해야... return null; } @@ -53,6 +129,9 @@ class GeneralList extends \sammo\BaseAPI $db = DB::db(); + $gameStor = \sammo\KVStorage::getStorage($db, 'game_env'); + $env = $gameStor->getValues(['year', 'month', 'turntime', 'turnterm']); + $me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $session->getUserID()); $con = checkLimit($me['con']); if ($con >= 2) { @@ -64,112 +143,99 @@ class GeneralList extends \sammo\BaseAPI $nationArr = getNationStaticInfo($nationID); - $viewColumns = [ - 'no' => 0, - 'name' => 0, - 'owner_name' => 9, - 'nation' => 0, - 'city' => 1, - 'officer_level' => 2, - 'officer_city' => 2, - 'npc' => 0, - 'defence_train' => 2, - 'troop' => 2, - 'injury' => 0, - 'leadership' => 0, - 'strength' => 0, - 'intel' => 0, - 'experience' => 1, - 'explevel' => 0, - 'dedication' => 1, - 'dedlevel' => 0, - 'gold' => 0, - 'rice' => 0, - 'crewtype' => 2, - 'crew' => 2, - 'train' => 2, - 'atmos' => 2, - 'killturn' => 0, - 'turntime' => 2, - 'picture' => 0, - 'imgsvr' => 0, - 'age' => 0, - 'special' => 0, - 'special2' => 0, - 'personal' => 0, - 'belong' => 0, - 'horse' => 2, - 'weapon' => 2, - 'book' => 2, - 'item' => 2, - 'connect' => 0 - ]; - - $columnRemap = [ - 'special' => 'specialDomestic', - 'special2' => 'specialWar', - ]; - - $customViewColumns = [ - 'officerLevel' => 0, - 'officerLevelText' => 0, - 'lbonus' => 0, - 'ownerName' => 0, - 'honorText' => 0, - 'dedLevelText' => 0, - 'bill' => 0, - ]; - $specialViewFilter = [ - 'officerLevel' => function ($rawGeneral) { - return $this->getOfficerLevel($rawGeneral); - }, - 'officerLevelText' => function ($rawGeneral) use ($nationArr) { - $level = $this->getOfficerLevel($rawGeneral); - return getOfficerLevelText($level, $nationArr['level']); - }, - 'lbonus' => function ($rawGeneral) use ($nationArr) { - return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']); - }, - 'ownerName' => function ($rawGeneral) { - if ($rawGeneral['npc'] != 1) { - return null; - } - return $rawGeneral['owner_name']; - }, - 'honorText' => function ($rawGeneral) { - return getHonor($rawGeneral['experience']); - }, - 'dedLevelText' => function ($rawGeneral) { - return getDedLevelText($rawGeneral['dedlevel']); - }, - 'turntime' => function ($rawGeneral) { - //'0000-00-00 11:23'; - return substr($rawGeneral['turntime'], 11, 5); - }, - 'bill' => fn($rawGeneral) => getBillByLevel($rawGeneral['dedlevel']) - - ]; - - [$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys($viewColumns), 1); + [$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys(static::$viewColumns), 1); $rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i', Util::formatListOfBackticks($queryColumns), $nationID), 'no'); + $reservedCommand = []; + if ($this->permission >= 2) { + $nonNPCGeneralIDList = []; + foreach ($rawGeneralList as $rawGeneral) { + if ($rawGeneral['npc'] < 2) { + $nonNPCGeneralIDList[] = $rawGeneral['no']; + } + } + + $rawTurnList = $db->query( + 'SELECT general_id, turn_idx, action, arg, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id asc, turn_idx asc', + $nonNPCGeneralIDList + ); + + foreach ($rawTurnList as $rawTurn) { + [ + 'general_id' => $generalID, + 'action' => $action, + 'arg' => $arg, + 'brief' => $brief, + ] = $rawTurn; + if (!key_exists($generalID, $reservedCommand)) { + $reservedCommand[$generalID] = []; + } + $reservedCommand[$generalID][] = [ + 'action' => $action, + 'arg' => $arg, + 'brief' => $brief + ]; + } + } + + $rankList = []; + if ($rankColumns) { + $rawRankList = $db->query('SELECT general_id, `type`, `value` FROM rank_data WHERE nation_id = %i AND `type` IN %ls', $nationID, $rankColumns); + foreach ($rawRankList as $rawRank) { + [ + 'general_id' => $generalID, + 'type' => $type, + 'value' => $value + ] = $rawRank; + + if (!key_exists($generalID, $rankList)) { + $rankList[$generalID] = []; + } + $rankList[$generalID][$type] = $value; + } + } + + $getRankVar = fn ($key) => (fn ($rawGeneral) => (($rankList[$rawGeneral['no']] ?? [])[$key] ?? 0)); + + + $specialViewFilter = [ + 'officerLevel' => fn ($rawGeneral) => $this->getOfficerLevel($rawGeneral), + 'officerLevelText' => fn ($rawGeneral) => getOfficerLevelText($this->getOfficerLevel($rawGeneral), $nationArr['level']), + 'lbonus' => fn ($rawGeneral) => calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']), + 'ownerName' => fn ($rawGeneral) => ($rawGeneral['npc'] != 1) ? null : $rawGeneral['owner_name'], + 'honorText' => fn ($rawGeneral) => getHonor($rawGeneral['experience']), + 'dedLevelText' => fn ($rawGeneral) => getDedLevelText($rawGeneral['dedlevel']), + //'0000-00-00 11:23'; + 'turntime' => fn ($rawGeneral) => substr($rawGeneral['turntime'], 0, 19), + 'bill' => fn ($rawGeneral) => getBillByLevel($rawGeneral['dedlevel']), + 'reservedCommand' => fn ($rawGeneral) => $reservedCommand[$rawGeneral['no']] ?? null, + 'autorun_limit' => fn ($rawGeneral) => ($rawGeneral['aux'] ?? [])['autorun_limit'] ?? 0, + ]; + + foreach ($rankColumns as $rankKey) { + $specialViewFilter[$rankKey] = $getRankVar($rankKey); + } + + $resultColumns = []; - foreach ($viewColumns as $column => $reqPermission) { + foreach (static::$viewColumns as $column => $reqPermission) { if ($reqPermission > $this->permission) { continue; } - if(key_exists($column, $columnRemap)){ - $resultColumns[$columnRemap[$column]] = $column; - } - else{ + if (key_exists($column, static::$columnRemap)) { + $newColumn = static::$columnRemap[$column]; + if($newColumn !== null){ + $resultColumns[$newColumn] = $column; + } + } else { $resultColumns[$column] = $column; } } - foreach ($customViewColumns as $column => $reqPermission) { + foreach (static::$customViewColumns as $column => $reqPermission) { if ($reqPermission > $this->permission) { continue; } @@ -179,6 +245,9 @@ class GeneralList extends \sammo\BaseAPI $generalList = []; foreach ($rawGeneralList as $rawGeneral) { //General 생성? + if (key_exists('aux', $rawGeneral)) { + $rawGeneral['aux'] = \sammo\JSON::decode($rawGeneral['aux']); + } $item = []; foreach ($resultColumns as $column) { @@ -198,6 +267,7 @@ class GeneralList extends \sammo\BaseAPI 'permission' => $this->permission, 'column' => array_keys($resultColumns), 'list' => $generalList, + 'env' => $env, ]; return $result; diff --git a/hwe/ts/PageNationGeneral.vue b/hwe/ts/PageNationGeneral.vue index e243616e..d5ac1313 100644 --- a/hwe/ts/PageNationGeneral.vue +++ b/hwe/ts/PageNationGeneral.vue @@ -1,7 +1,7 @@ @@ -20,11 +20,17 @@ import { BContainer } from "bootstrap-vue-3"; import { onMounted, provide, ref } from "vue"; import { SammoAPI } from "./SammoAPI"; import { merge2DArrToObjectArr } from "./util/merge2DArrToObjectArr"; -import type { GeneralListItem } from "./defs/API/Nation"; +import type { GeneralListItem, GeneralListResponse } from "./defs/API/Nation"; import GeneralList from "./components/GeneralList.vue"; import { type GameConstStore, getGameConstStore } from "./GameConstStore"; const generalList = ref([]); +const envVal = ref({ + year: 1, + month: 1, + turnterm: 1, + turntime: '2022-02-22 22:22:22.22222' +}); const gameConstStore = ref(); provide('gameConstStore', gameConstStore); @@ -43,7 +49,7 @@ void Promise.all([storeP]).then(()=>{ onMounted(async () => { try { - const { column, list, permission } = await SammoAPI.Nation.GeneralList(); + const { column, list, permission, env } = await SammoAPI.Nation.GeneralList(); //XXX: 로직상 똑같은데.... if (permission == 0) { const rawGeneralList = merge2DArrToObjectArr(column, list); @@ -57,6 +63,7 @@ onMounted(async () => { } else { throw `?? ${permission}`; } + envVal.value = env; } catch (e) { console.error(e); diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index ee6d169b..095a90fb 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -19,7 +19,7 @@ -- 2.54.0 From ad89dd0ffb93f47cfddb07d04c22b13b49268144 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Tue, 5 Apr 2022 01:20:54 +0900 Subject: [PATCH 16/31] =?UTF-8?q?feat:=20func=5Fconverter=20=EC=9D=BC?= =?UTF-8?q?=EB=B6=80=20=ED=95=AD=EB=AA=A9=20=EC=9D=B4=EC=8B=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/ts/defs/index.ts | 2 +- hwe/ts/utilGame/formatConnectScore.ts | 21 ++++++ hwe/ts/utilGame/formatDefenceTrain.ts | 17 +++++ hwe/ts/utilGame/formatDexLevel.ts | 50 ++++++++++++ hwe/ts/utilGame/formatHonor.ts | 25 ++++++ hwe/ts/utilGame/formatOfficerLevelText.ts | 92 +++++++++++++++++++++++ package-lock.json | 11 +++ package.json | 1 + 8 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 hwe/ts/utilGame/formatConnectScore.ts create mode 100644 hwe/ts/utilGame/formatDefenceTrain.ts create mode 100644 hwe/ts/utilGame/formatDexLevel.ts create mode 100644 hwe/ts/utilGame/formatHonor.ts create mode 100644 hwe/ts/utilGame/formatOfficerLevelText.ts diff --git a/hwe/ts/defs/index.ts b/hwe/ts/defs/index.ts index d7b8b0bf..5140102e 100644 --- a/hwe/ts/defs/index.ts +++ b/hwe/ts/defs/index.ts @@ -228,4 +228,4 @@ export const diplomacyStateInfo: Record = { 1: { name: '선포중', color: 'magenta' }, 2: { name: '통상' }, 7: { name: '불가침', color: 'green' }, -} +} \ No newline at end of file diff --git a/hwe/ts/utilGame/formatConnectScore.ts b/hwe/ts/utilGame/formatConnectScore.ts new file mode 100644 index 00000000..c027787f --- /dev/null +++ b/hwe/ts/utilGame/formatConnectScore.ts @@ -0,0 +1,21 @@ +import bs from 'binary-search'; + +const connectMap: [number, string][] = [ + [50, '안함'], + [100, '무관심'], + [400, '보통'], + [200, '가끔'], + [800, '자주'], + [1600, '열심'], + [3200, '중독'], + [6400, '폐인'], + [12800, '경고'], +] + +export function formatConnectScore(connect: number) { + const idx = bs(connectMap, connect, ([key], needle) => key - needle); + if(idx >= 0){ + return connectMap[idx][1]??'?'; + } + return connectMap[-(idx + 1)][1]??'?'; +} \ No newline at end of file diff --git a/hwe/ts/utilGame/formatDefenceTrain.ts b/hwe/ts/utilGame/formatDefenceTrain.ts new file mode 100644 index 00000000..cdbafe67 --- /dev/null +++ b/hwe/ts/utilGame/formatDefenceTrain.ts @@ -0,0 +1,17 @@ +import bs from 'binary-search'; + +const defenceMap: [number,string][] = [ + [0, "△"], + [60, "○"], + [80, "◎"], + [90, "☆"], + [999, "×"], +] + +export function formatDefenceTrain(defenceTrain: number): string { + const idx = bs(defenceMap, defenceTrain, ([defenceKey], needle) => defenceKey - needle); + if(idx >= 0){ + return defenceMap[idx][1]??'?'; + } + return defenceMap[-(idx + 1)][1]??'?'; +} \ No newline at end of file diff --git a/hwe/ts/utilGame/formatDexLevel.ts b/hwe/ts/utilGame/formatDexLevel.ts new file mode 100644 index 00000000..6a608044 --- /dev/null +++ b/hwe/ts/utilGame/formatDexLevel.ts @@ -0,0 +1,50 @@ +import bs from 'binary-search'; + +export const DexLevelMap: [number, string, string][] = [ + [0, 'navy', 'F-'], + [350, 'navy', 'F'], + [1375, 'navy', 'F+'], + [3500, 'skyblue', 'E-'], + [7125, 'skyblue', 'E'], + [12650, 'skyblue', 'E+'], + [20475, 'seagreen', 'D-'], + [31000, 'seagreen', 'D'], + [44625, 'seagreen', 'D+'], + [61750, 'teal', 'C-'], + [82775, 'teal', 'C'], + [108100, 'teal', 'C+'], + [138125, 'limegreen', 'B-'], + [173250, 'limegreen', 'B'], + [213875, 'limegreen', 'B+'], + [260400, 'darkorange', 'A-'], + [313225, 'darkorange', 'A'], + [372750, 'darkorange', 'A+'], + [439375, 'tomato', 'S-'], + [513500, 'tomato', 'S'], + [595525, 'tomato', 'S+'], + [685850, 'darkviolet', 'Z-'], + [784875, 'darkviolet', 'Z'], + [893000, 'darkviolet', 'Z+'], + [1010625, 'gold', 'EX-'], + [1138150, 'gold', 'EX'], + [1275975, 'white', 'EX+'], +]; + +export type DexInfo = { + level: number, + name: string, + color: string, +} + +export function formatDexLevel(dex: number): DexInfo { + const rawIdx = bs(DexLevelMap, dex, ([dexKey], needle) => dexKey - needle); + const level = rawIdx >= 0 ? rawIdx : -(rawIdx + 1); + + const [, color, name] = DexLevelMap[level]; + + return { + level, + name, + color + }; +} \ No newline at end of file diff --git a/hwe/ts/utilGame/formatHonor.ts b/hwe/ts/utilGame/formatHonor.ts new file mode 100644 index 00000000..3ea9399c --- /dev/null +++ b/hwe/ts/utilGame/formatHonor.ts @@ -0,0 +1,25 @@ +import bs from 'binary-search'; + +const hornorMap: [number, string][] = [ + [640, '전무'], + [2560, '무명'], + [5760, '신동'], + [10240, '약간'], + [16000, '평범'], + [23040, '지역적'], + [31360, '전국적'], + [40960, '세계적'], + [45000, '유명'], + [51840, '명사'], + [55000, '호걸'], + [64000, '효웅'], + [77440, '영웅'], +] + +export function formatHonor(experience: number): string { + const idx = bs(hornorMap, experience, ([experienceKey], needle) => experienceKey - needle); + if (idx >= 0) { + return hornorMap[idx][1] ?? '?'; + } + return hornorMap[-(idx + 1)][1] ?? '?'; +} \ No newline at end of file diff --git a/hwe/ts/utilGame/formatOfficerLevelText.ts b/hwe/ts/utilGame/formatOfficerLevelText.ts new file mode 100644 index 00000000..406a7776 --- /dev/null +++ b/hwe/ts/utilGame/formatOfficerLevelText.ts @@ -0,0 +1,92 @@ +export const OfficerLevelMapDefault: Record = { + 12: '군주', + 11: '참모', + 10: '제1장군', + 9: '제1모사', + 8: '제2장군', + 7: '제2모사', + 6: '제3장군', + 5: '제3모사', + 4: '태수', + 3: '군사', + 2: '종사', + 1: '일반', + 0: '재야', +} + +export const OfficerLevelMapByNationLevel: Record> = { + 7: { + 12: '황제', + 11: '승상', + 10: '표기장군', + 9: '사공', + 8: '거기장군', + 7: '태위', + 6: '위장군', + 5: '사도' + }, + + 6: { + 12: '왕', + 11: '광록훈', + 10: '좌장군', + 9: '상서령', + 8: '우장군', + 7: '중서령', + 6: '전장군', + 5: '비서령' + }, + + 5: { + 12: '공', + 11: '광록대부', + 10: '안국장군', + 9: '집금오', + 8: '파로장군', + 7: '소부' + }, + + 4: { + 12: '주목', + 11: '태사령', + 10: '아문장군', + 9: '낭중', + 8: '호군', + 7: '종사중랑' + }, + + 3: { + 12: '주자사', + 11: '주부', + 10: '편장군', + 9: '간의대부' + }, + + 2: { + 12: '군벌', + 11: '참모', + 10: '비장군', + 9: '부참모' + }, + + 1: { + 12: '영주', + 11: '참모' + }, + + 0: { + 12: '두목', + 11: '부두목' + }, +} +export function formatOfficerLevelText(officerLevel: number, nationLevel?: number) { + if (officerLevel < 5) { + return OfficerLevelMapDefault[officerLevel] ?? '???'; + } + + const nationMap = nationLevel === undefined + ? OfficerLevelMapDefault + : (OfficerLevelMapByNationLevel[nationLevel] ?? OfficerLevelMapDefault); + + return nationMap[officerLevel] ?? (OfficerLevelMapDefault[officerLevel] ?? '???'); +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 3b81b866..a519dc2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,6 +44,7 @@ "axios": "^0.26.1", "babel-plugin-lodash": "^3.3.4", "babel-preset-modern-browsers": "^15.0.2", + "binary-search": "^1.3.6", "bootstrap": "^5.1.3", "bootstrap-vue-3": "=0.1.8", "bootswatch": "^5.1.3", @@ -3453,6 +3454,11 @@ "node": "*" } }, + "node_modules/binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -13092,6 +13098,11 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, + "binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", diff --git a/package.json b/package.json index c355febb..4bfd6640 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "axios": "^0.26.1", "babel-plugin-lodash": "^3.3.4", "babel-preset-modern-browsers": "^15.0.2", + "binary-search": "^1.3.6", "bootstrap": "^5.1.3", "bootstrap-vue-3": "=0.1.8", "bootswatch": "^5.1.3", -- 2.54.0 From 0a3c98ec5adc2b6fbf8baf45fc5fcf6ef19e994c Mon Sep 17 00:00:00 2001 From: Hide_D Date: Tue, 5 Apr 2022 01:25:52 +0900 Subject: [PATCH 17/31] =?UTF-8?q?fix:=20ts=20format=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=95=98=ED=95=9C=EA=B0=92=20=EA=B8=B0=EC=A4=80=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/ts/utilGame/formatConnectScore.ts | 25 +++++++++++++------------ hwe/ts/utilGame/formatHonor.ts | 27 ++++++++++++++------------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/hwe/ts/utilGame/formatConnectScore.ts b/hwe/ts/utilGame/formatConnectScore.ts index c027787f..8b68ca13 100644 --- a/hwe/ts/utilGame/formatConnectScore.ts +++ b/hwe/ts/utilGame/formatConnectScore.ts @@ -1,21 +1,22 @@ import bs from 'binary-search'; const connectMap: [number, string][] = [ - [50, '안함'], - [100, '무관심'], - [400, '보통'], - [200, '가끔'], - [800, '자주'], - [1600, '열심'], - [3200, '중독'], - [6400, '폐인'], - [12800, '경고'], + [0, '안함'], + [50, '무관심'], + [100, '보통'], + [400, '가끔'], + [200, '자주'], + [800, '열심'], + [1600, '중독'], + [3200, '폐인'], + [6400, '경고'], + [12800, '헐...'], ] export function formatConnectScore(connect: number) { const idx = bs(connectMap, connect, ([key], needle) => key - needle); - if(idx >= 0){ - return connectMap[idx][1]??'?'; + if (idx >= 0) { + return connectMap[idx][1] ?? '?'; } - return connectMap[-(idx + 1)][1]??'?'; + return connectMap[-(idx + 1)][1] ?? '?'; } \ No newline at end of file diff --git a/hwe/ts/utilGame/formatHonor.ts b/hwe/ts/utilGame/formatHonor.ts index 3ea9399c..54215b12 100644 --- a/hwe/ts/utilGame/formatHonor.ts +++ b/hwe/ts/utilGame/formatHonor.ts @@ -1,19 +1,20 @@ import bs from 'binary-search'; const hornorMap: [number, string][] = [ - [640, '전무'], - [2560, '무명'], - [5760, '신동'], - [10240, '약간'], - [16000, '평범'], - [23040, '지역적'], - [31360, '전국적'], - [40960, '세계적'], - [45000, '유명'], - [51840, '명사'], - [55000, '호걸'], - [64000, '효웅'], - [77440, '영웅'], + [0, '전무'], + [640, '무명'], + [2560, '신동'], + [5760, '약간'], + [10240, '평범'], + [16000, '지역적'], + [23040, '전국적'], + [31360, '세계적'], + [40960, '유명'], + [45000, '명사'], + [51840, '호걸'], + [55000, '효웅'], + [64000, '영웅'], + [77440, '구세주'], ] export function formatHonor(experience: number): string { -- 2.54.0 From 35eafa36d60cd266d1d17f24968621dc84e487d0 Mon Sep 17 00:00:00 2001 From: Hide_D Date: Tue, 5 Apr 2022 03:16:09 +0900 Subject: [PATCH 18/31] =?UTF-8?q?feat(wip):=20=EC=84=B8=EB=A0=A5=EC=9E=A5?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80=EC=9E=91=EC=97=85,=20=EB=B3=91?= =?UTF-8?q?=EC=A2=85=20=EB=93=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/sammo/API/Global/GetConst.php | 14 +- hwe/ts/components/GeneralList.vue | 191 +++++++++++++++----- hwe/ts/defs/GameObj.ts | 2 +- hwe/ts/gridCellRenderer/GridTooltipCell.vue | 28 ++- 4 files changed, 176 insertions(+), 59 deletions(-) diff --git a/hwe/sammo/API/Global/GetConst.php b/hwe/sammo/API/Global/GetConst.php index b568905f..dd5eadbd 100644 --- a/hwe/sammo/API/Global/GetConst.php +++ b/hwe/sammo/API/Global/GetConst.php @@ -20,7 +20,7 @@ use function sammo\prepareDir; class GetConst extends \sammo\BaseAPI { /** 반환하는 StaticValues 타입이 달라지면 +1 */ - const CONST_API_VERSION = 1; + const CONST_API_VERSION = 2; const CACHE_KEY = 'JSConst'; private ?string $cacheKey = null; @@ -258,6 +258,18 @@ class GetConst extends \sammo\BaseAPI $iActionInfo[$mappedKey] = $actionInfo; } + + $crewtypeMap = []; + foreach(GameUnitConst::all() as $crewtypeObj){ + $crewtypeMap[$crewtypeObj->id] = [ + 'value'=>(string)$crewtypeObj->id, + 'name'=>$crewtypeObj->name, + 'info'=>$crewtypeObj->getInfo(), + ]; + } + $iActionInfo['crewtype'] = $crewtypeMap; + + return [ 'gameConst' => get_class_vars('\sammo\GameConst'), 'gameUnitConst' => GameUnitConst::all(), diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index 095a90fb..f122a5e3 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -38,8 +38,8 @@ import type { BaseWithValueColDefParams, ValueGetterParams } from "ag-grid-commu import type { GameConstStore } from "@/GameConstStore"; import { unwrap } from "@/util/unwrap"; import SimpleTooltipCell from "@/gridCellRenderer/SimpleTooltipCell.vue"; -import GridTooltipCell from "@/gridCellRenderer/GridTooltipCell.vue"; -import type { GameIActionInfo } from "@/defs/GameObj"; +import GridTooltipCell, { type GridCellInfo } from "@/gridCellRenderer/GridTooltipCell.vue"; +import { formatConnectScore } from "@/utilGame/formatConnectScore"; const props = defineProps({ list: { @@ -53,9 +53,9 @@ const props = defineProps({ default: "static", }, env: { - type: Object as PropType, + type: Object as PropType, required: true, - } + }, }); const gameConstStore = unwrap(inject>("gameConstStore")); @@ -111,8 +111,7 @@ function setRowHeight() { rowHeight.value = gridApi.value?.getSizesForCurrentTheme().rowHeight ?? 28; } - -function getRowHeight():number{ +function getRowHeight(): number { return rowHeight.value; } @@ -149,11 +148,13 @@ interface GenCellClassParams extends CellClassParams { data: GeneralListItem; } -type GridCellInfo = { - iActionMap?: Record; - info?: string; - target: keyof GeneralListItem; -}; +function naiveCheClassNameFilter(value: string): string { + const text = value.split("_").pop() ?? "None"; + if (text === "None") { + return "-"; + } + return text; +} function numberFormatter(value: GenValueParams): string { return (value.value as number).toLocaleString(); @@ -174,13 +175,13 @@ const defaultColDef = ref({ headerClass: "default-cell-header", cellClass: centerCellClass, floatingFilter: true, - width: 90, + width: 80, }); const columnRawDefs = ref>>({ icon: { headerName: "아이콘", - width: 64 + 24, + width: 64 + 16, suppressSizeToFit: true, resizable: false, cellRenderer: (obj: GenValueParams) => { @@ -195,7 +196,7 @@ const columnRawDefs = ref field: "name", pinned: "left", sortable: true, - width: 130, + width: 120, sortingOrder: ["asc", "desc", null], lockPosition: true, cellStyle: (val: GenCellClassParams) => { @@ -216,7 +217,7 @@ const columnRawDefs = ref children: [ { headerName: "통|무|지", - width: 90, + width: 88, cellRenderer: (obj: GenValueParams) => { const gen = obj.data; @@ -229,7 +230,7 @@ const columnRawDefs = ref field: "leadership", ...sortableNumber, columnGroupShow: "open", - width: 70, + width: 60, type: "numericColumn", }, { @@ -237,14 +238,14 @@ const columnRawDefs = ref field: "strength", ...sortableNumber, columnGroupShow: "open", - width: 70, + width: 60, }, { headerName: "지력", field: "intel", ...sortableNumber, columnGroupShow: "open", - width: 70, + width: 60, }, ], }, @@ -254,14 +255,28 @@ const columnRawDefs = ref sortable: true, comparator: (a, b, c, d) => c.data.officerLevel - d.data.officerLevel, cellRenderer: ({ data }: GenValueParams) => { - if (data.permission == 2 && 2 <= data.officerLevel && 4 <= data.officerLevel) { - return `${data.officer_city} ${data.officerLevelText}`; + if ([2, 3, 4].includes(data.permission)) { + const dataP2 = data as GeneralListItemP2; + if (2 <= dataP2.officerLevel && dataP2.officerLevel <= 4) { + const cityName = gameConstStore.value.cityConst[dataP2.officer_city].name; + return `${cityName}
${dataP2.officerLevelText}`; + } + } + return data.officerLevelText; + }, + filterValueGetter: ({ data }) => { + if ([2, 3, 4].includes(data.permission)) { + const dataP2 = data as GeneralListItemP2; + if (2 <= dataP2.officerLevel && dataP2.officerLevel <= 4) { + const cityName = gameConstStore.value.cityConst[dataP2.officer_city].name; + return `${cityName} ${dataP2.officerLevelText}`; + } } return data.officerLevelText; }, filter: true, cellClass: centerCellClass, - width: 90, + width: 70, }, expDedLv: { headerName: "명성", @@ -271,7 +286,7 @@ const columnRawDefs = ref { headerName: "/계급", columnGroupShow: "closed", - width: 70, + width: 60, cellRenderer: ({ data }: GenValueParams) => { return `Lv ${data.explevel}
${data.dedLevelText}`; }, @@ -279,17 +294,18 @@ const columnRawDefs = ref { headerName: "명성", field: "explevel", - width: 75, + width: 60, cellRenderer: ({ data }: GenValueParams) => { return `Lv ${data.explevel}
(${data.honorText})`; }, ...sortableNumber, + cellClass: centerCellClass, columnGroupShow: "open", }, { headerName: "계급", field: "dedLevelText", - width: 75, + width: 70, cellRenderer: ({ data }: GenValueParams) => { return `${data.dedLevelText}
(${data.bill.toLocaleString()})`; }, @@ -299,11 +315,37 @@ const columnRawDefs = ref }, ], }, - gold: { headerName: "금", field: "gold", ...sortableNumber, valueFormatter: numberFormatter, width: 75 }, - rice: { headerName: "쌀", field: "rice", ...sortableNumber, valueFormatter: numberFormatter, width: 75 }, - + gold: { headerName: "금", field: "gold", ...sortableNumber, valueFormatter: numberFormatter, width: 70 }, + rice: { headerName: "쌀", field: "rice", ...sortableNumber, valueFormatter: numberFormatter, width: 70 }, + crew: { + headerName: "보유 병력", + children: [ + { + headerName: "병종", + cellRenderer: GridTooltipCell, + cellRendererParams: { + cells: ((): GridCellInfo[][] => { + return [ + [{ target: "crewtype", iActionMap: gameConstStore.value.iActionInfo.crewtype }], + [{ target: "crew", converter: (value) => [`${value.crew.toLocaleString()}명`, undefined] }], + ]; + })(), + }, + }, + { + headerName: "훈/사", + width: 60, + cellRenderer: ({ data }: GenValueParams) => { + if (data.permission == 0 || data.permission == 1) { + return "?"; + } + return `${data.train}
${data.atmos}`; + }, + }, + ], + }, specials: { - headerName: "성격/내특/전특", + headerName: "특성", children: [ { headerName: "요약", @@ -319,7 +361,7 @@ const columnRawDefs = ref ]; })(), }, - width: 90, + width: 80, columnGroupShow: "closed", }, { @@ -329,7 +371,7 @@ const columnRawDefs = ref cellRendererParams: { iActionMap: gameConstStore.value.iActionInfo.personality, }, - width: 70, + width: 60, sortable: true, filter: true, columnGroupShow: "open", @@ -341,7 +383,7 @@ const columnRawDefs = ref cellRendererParams: { iActionMap: gameConstStore.value.iActionInfo.specialDomestic, }, - width: 70, + width: 60, sortable: true, filter: true, columnGroupShow: "open", @@ -353,7 +395,7 @@ const columnRawDefs = ref cellRendererParams: { iActionMap: gameConstStore.value.iActionInfo.specialWar, }, - width: 70, + width: 60, sortable: true, filter: true, columnGroupShow: "open", @@ -365,6 +407,7 @@ const columnRawDefs = ref children: [ { headerName: "요약", + width: 60, cellRenderer: ({ data }: GenValueParams) => { return `${data.age}세
${data.belong}년`; }, @@ -376,7 +419,7 @@ const columnRawDefs = ref field: "age", ...sortableNumber, valueFormatter: (v: GenValueParams) => `${v.value}세`, - width: 70, + width: 60, cellClass: centerCellClass, columnGroupShow: "open", }, @@ -385,12 +428,55 @@ const columnRawDefs = ref field: "belong", ...sortableNumber, valueFormatter: (v: GenValueParams) => `${v.value}년`, - width: 70, + width: 60, cellClass: centerCellClass, columnGroupShow: "open", }, ], }, + reservedCommand: { + headerName: "명령", + children: [ + { + headerName: "단축", + width: 70, + cellRenderer: ({ data }: GenValueParams) => { + if (data.npc >= 2) { + return "NPC 장수"; + } + const commandList = data.reservedCommand; + if (!commandList) { + return "???"; + } + return commandList.map(({ action }) => naiveCheClassNameFilter(action)).join("
"); + }, + cellStyle: { + lineHeight: "1em", + fontSize: "0.85em", + }, + columnGroupShow: "closed", + }, + { + headerName: "전체", + width: 120, + cellRenderer: ({ data }: GenValueParams) => { + if (data.npc >= 2) { + return "NPC 장수"; + } + const commandList = data.reservedCommand; + if (!commandList) { + return "???"; + } + return commandList.map(({ brief }) => brief).join("
"); + }, + cellStyle: { + lineHeight: "1em", + fontSize: "0.85em", + }, + columnGroupShow: "open", + }, + ], + }, killturnAndConnect: { headerName: "기타", children: [ @@ -401,6 +487,7 @@ const columnRawDefs = ref }, cellClass: rightAlignClass, columnGroupShow: "closed", + width: 70, }, { headerName: "삭턴", @@ -409,15 +496,17 @@ const columnRawDefs = ref return `${data.killturn.toLocaleString()}턴`; }, ...sortableNumber, + width: 70, columnGroupShow: "open", }, { headerName: "벌점", field: "connect", cellRenderer: ({ data }: GenValueParams) => { - return `${data.connect.toLocaleString()}점`; + return `${data.connect.toLocaleString()}점
(${formatConnectScore(data.connect)})`; }, ...sortableNumber, + width: 70, columnGroupShow: "open", }, ], @@ -433,18 +522,6 @@ watch(columnRawDefs, (val) => { gridApi.value?.redrawRows(); }); -/* -let currentWidth = -1; -window.addEventListener("resize", (e) => { - setTimeout(() => { - const newWidth = document.querySelector(".container")?.clientWidth ?? -1; - if (currentWidth != newWidth) { - currentWidth = newWidth; - columnApi.value?.autoSizeAllColumns(); - } - }, 1); -}); -*/ diff --git a/hwe/ts/defs/GameObj.ts b/hwe/ts/defs/GameObj.ts index 5da99a84..ad21e2c2 100644 --- a/hwe/ts/defs/GameObj.ts +++ b/hwe/ts/defs/GameObj.ts @@ -203,7 +203,7 @@ export type GameCityDefault = { path: Record; }; -export type GameIActionCategory = "nationType" | "specialDomestic" | "specialWar" | "personality" | "item"; +export type GameIActionCategory = "nationType" | "specialDomestic" | "specialWar" | "personality" | "item" | "crewtype"; export type GameIActionInfo = { value: string; diff --git a/hwe/ts/gridCellRenderer/GridTooltipCell.vue b/hwe/ts/gridCellRenderer/GridTooltipCell.vue index 9cfd0aab..1a189faa 100644 --- a/hwe/ts/gridCellRenderer/GridTooltipCell.vue +++ b/hwe/ts/gridCellRenderer/GridTooltipCell.vue @@ -6,10 +6,13 @@ v-if="colValue.iActionMap" v-b-tooltip.hover class="col" - :title="colValue.iActionMap[params.data[colValue.target ] as string ].info??''" + :title="colValue.iActionMap[params.data[colValue.target] as string ].info??''" > {{ colValue.iActionMap[params.data[colValue.target] as string ].name }}
+
+ {{colValue.converter(params.data)[0]}} +
{{params.data[colValue.target] as string}}
@@ -18,21 +21,26 @@ - + \ No newline at end of file + diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index f122a5e3..eeac4d8f 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -32,6 +32,7 @@ import type { GetRowIdParams, GridApi, GridReadyEvent, + RowNode, } from "ag-grid-community"; import { getNpcColor } from "@/common_legacy"; import type { BaseWithValueColDefParams, ValueGetterParams } from "ag-grid-community/dist/lib/entities/colDef"; @@ -40,6 +41,9 @@ import { unwrap } from "@/util/unwrap"; import SimpleTooltipCell from "@/gridCellRenderer/SimpleTooltipCell.vue"; import GridTooltipCell, { type GridCellInfo } from "@/gridCellRenderer/GridTooltipCell.vue"; import { formatConnectScore } from "@/utilGame/formatConnectScore"; +import { convertSearch초성 } from "@/util/convertSearch초성"; +import { isString } from "lodash"; +import { formatDefenceTrain } from "@/utilGame/formatDefenceTrain"; const props = defineProps({ list: { @@ -47,6 +51,11 @@ const props = defineProps({ required: true, }, + troops: { + type: Object as PropType>, + required: true, + }, + height: { type: String as PropType<"static" | "fill" | number | `${number}px` | `${number}%`>, required: false, @@ -82,6 +91,18 @@ watch( } ); +const generalByID = ref(new Map()); + +function refineGeneralList(list: GeneralListItem[]) { + const map = new Map(); + for (const general of list) { + map.set(general.no, general); + } + generalByID.value = map; +} +refineGeneralList(props.list); +watch(() => props.list, refineGeneralList); + const gridApi = ref(); const columnApi = ref(); @@ -133,10 +154,15 @@ interface GenValueGetterParams extends ValueGetterParams { data: GeneralListItem; } +interface GenRowNode extends RowNode { + data: GeneralListItem; +} + interface GenColDef extends ColDef { field?: headerType; valueFormatter?: string | ((params: GenValueParams) => string); - filterValueGetter?: string | ((params: GenValueGetterParams) => string); + filterValueGetter?: string | ((params: GenValueGetterParams) => unknown); + valueGetter?: string | ((params: GenValueGetterParams) => unknown); } interface GenColGroupDef extends ColGroupDef { @@ -156,8 +182,32 @@ function naiveCheClassNameFilter(value: string): string { return text; } -function numberFormatter(value: GenValueParams): string { - return (value.value as number).toLocaleString(); +function numberFormatter(unit?: string) { + if (unit) { + return (value: GenValueParams): string => { + const valueText = (value.value as number).toLocaleString(); + return `${valueText} ${unit}`; + }; + } + return (value: GenValueParams): string => { + return (value.value as number).toLocaleString(); + }; +} + +function extractTroopInfo(value: GeneralListItem): [string, GeneralListItemP2] | undefined { + if (value.permission == 0 || value.permission == 1) { + return undefined; + } + const troopID = value.troop; + if (!(troopID in props.troops)) { + return undefined; + } + const troopName = props.troops[troopID]; + const troopLeader = generalByID.value.get(troopID) as GeneralListItemP2 | undefined; + if (troopLeader === undefined) { + return undefined; + } + return [troopName, troopLeader]; } const defaultCellClass = ["cell-middle"]; @@ -206,6 +256,7 @@ const columnRawDefs = ref }; return style as CellStyle; }, + filterValueGetter: ({ data }) => convertSearch초성(data.name), cellClass: defaultCellClass, filter: true, }, @@ -269,10 +320,10 @@ const columnRawDefs = ref const dataP2 = data as GeneralListItemP2; if (2 <= dataP2.officerLevel && dataP2.officerLevel <= 4) { const cityName = gameConstStore.value.cityConst[dataP2.officer_city].name; - return `${cityName} ${dataP2.officerLevelText}`; + return convertSearch초성(`${cityName} ${dataP2.officerLevelText}`); } } - return data.officerLevelText; + return convertSearch초성(data.officerLevelText); }, filter: true, cellClass: centerCellClass, @@ -315,8 +366,116 @@ const columnRawDefs = ref }, ], }, - gold: { headerName: "금", field: "gold", ...sortableNumber, valueFormatter: numberFormatter, width: 70 }, - rice: { headerName: "쌀", field: "rice", ...sortableNumber, valueFormatter: numberFormatter, width: 70 }, + goldRice: { + headerName: "자금", + + children: [ + { + headerName: "금/쌀", + cellRenderer: ({ data }: GenValueParams) => { + return `${data.gold.toLocaleString()} 금
${data.rice.toLocaleString()} 쌀`; + }, + width: 80, + cellClass: rightAlignClass, + columnGroupShow: "closed", + sortable: true, + sortingOrder: ["desc", "asc", null], + comparator(_a, _b, { data: lhs }: GenRowNode, { data: rhs }: GenRowNode) { + const lhsAmount = lhs.gold + lhs.rice; + const rhsAmount = rhs.gold + rhs.rice; + return lhsAmount - rhsAmount; + }, + }, + { + headerName: "금", + field: "gold", + ...sortableNumber, + valueFormatter: numberFormatter("금"), + width: 70, + columnGroupShow: "open", + }, + { + headerName: "쌀", + field: "rice", + ...sortableNumber, + valueFormatter: numberFormatter("쌀"), + width: 70, + columnGroupShow: "open", + }, + ], + }, + + city: { + headerName: "도시", + field: "city", + valueGetter: ({ data }) => { + if (data.permission == 0 || data.permission == 1) { + return "-"; + } + return gameConstStore.value.cityConst[data.city].name; + }, + filter: true, + sortable: true, + width: 60, + filterValueGetter: ({ data }) => { + if (data.permission == 0 || data.permission == 1) { + return "-"; + } + return convertSearch초성(gameConstStore.value.cityConst[data.city].name); + }, + }, + + troop: { + headerName: "부대", + field: "troop", + valueGetter: ({ data }: GenValueGetterParams) => { + const troopInfo = extractTroopInfo(data); + if (troopInfo === undefined) { + return "-"; + } + + const [troopName, troopLeader] = troopInfo; + const cityName = gameConstStore.value.cityConst[troopLeader.city].name; + return [troopName, cityName]; + }, + cellRenderer: ({ value }: { value: [string, string] | string }) => { + if (isString(value)) { + return value; + } + const [troopName, cityName] = value; + return `${troopName}
[${cityName}]`; + }, + width: 90, + sortable: true, + comparator: (valX, valB, { data: lhs }: GenRowNode, { data: rhs }: GenRowNode) => { + const troopInfoLhs = extractTroopInfo(lhs); + const troopInfoRhs = extractTroopInfo(rhs); + console.log(troopInfoLhs, troopInfoRhs); + if (troopInfoLhs === troopInfoRhs) { + return 0; + } + if (troopInfoLhs === undefined) { + return 1; + } + if (troopInfoRhs === undefined) { + return -1; + } + + return troopInfoLhs[0].localeCompare(troopInfoRhs[0]); + }, + filter: true, + filterValueGetter: ({ data }) => { + const troopInfo = extractTroopInfo(data); + if (troopInfo === undefined) { + return "-"; + } + const [troopName, troopLeader] = troopInfo; + const cityName = gameConstStore.value.cityConst[troopLeader.city].name; + + return convertSearch초성(`${troopName}$${cityName}`); + }, + }, + crew: { headerName: "보유 병력", children: [ @@ -331,6 +490,7 @@ const columnRawDefs = ref ]; })(), }, + columnGroupShow: "closed", }, { headerName: "훈/사", @@ -341,6 +501,57 @@ const columnRawDefs = ref } return `${data.train}
${data.atmos}`; }, + columnGroupShow: "closed", + }, + { + headerName: "병종", + field: "crewtype", + cellRenderer: SimpleTooltipCell, + cellRendererParams: { + iActionMap: gameConstStore.value.iActionInfo.crewtype, + }, + sortable: true, + columnGroupShow: "open", + filter: true, + filterValueGetter: ({ data }) => { + if (data.permission == 0 || data.permission == 1) { + return "-"; + } + const name = gameConstStore.value.iActionInfo.crewtype[data.crewtype].name; + return convertSearch초성(name); + }, + }, + { + headerName: "병력", + field: "crew", + ...sortableNumber, + valueFormatter: numberFormatter("명"), + width: 70, + columnGroupShow: "open", + }, + { + headerName: "훈련", + field: "train", + ...sortableNumber, + valueFormatter: numberFormatter(), + width: 70, + columnGroupShow: "open", + }, + { + headerName: "병력", + field: "atmos", + ...sortableNumber, + valueFormatter: numberFormatter(), + width: 70, + columnGroupShow: "open", + }, + { + headerName: "수비", + field: "defence_train", + sortable: true, + sortingOrder: ["desc", "asc", null], + valueFormatter: ({ value }) => formatDefenceTrain(value as number), + width: 50, }, ], }, @@ -375,6 +586,10 @@ const columnRawDefs = ref sortable: true, filter: true, columnGroupShow: "open", + filterValueGetter: ({ data }) => { + const name = gameConstStore.value.iActionInfo.personality[data.personal].name; + return convertSearch초성(name); + }, }, { headerName: "내특", @@ -387,6 +602,10 @@ const columnRawDefs = ref sortable: true, filter: true, columnGroupShow: "open", + filterValueGetter: ({ data }) => { + const name = gameConstStore.value.iActionInfo.specialDomestic[data.specialDomestic].name; + return convertSearch초성(name); + }, }, { headerName: "전특", @@ -399,38 +618,10 @@ const columnRawDefs = ref sortable: true, filter: true, columnGroupShow: "open", - }, - ], - }, - years: { - headerName: "연도", - children: [ - { - headerName: "요약", - width: 60, - cellRenderer: ({ data }: GenValueParams) => { - return `${data.age}세
${data.belong}년`; + filterValueGetter: ({ data }) => { + const name = gameConstStore.value.iActionInfo.specialWar[data.specialWar].name; + return convertSearch초성(name); }, - cellClass: centerCellClass, - columnGroupShow: "closed", - }, - { - headerName: "연령", - field: "age", - ...sortableNumber, - valueFormatter: (v: GenValueParams) => `${v.value}세`, - width: 60, - cellClass: centerCellClass, - columnGroupShow: "open", - }, - { - headerName: "사관", - field: "belong", - ...sortableNumber, - valueFormatter: (v: GenValueParams) => `${v.value}년`, - width: 60, - cellClass: centerCellClass, - columnGroupShow: "open", }, ], }, @@ -477,6 +668,52 @@ const columnRawDefs = ref }, ], }, + turntime: { + headerName: "턴", + field: 'turntime', + width: 60, + valueFormatter: ({value, data}) => { + if(data.permission == 0 || data.permission == 1){ + return '-'; + } + const turntime = value as string; + return turntime.substring(14, 19); + }, + sortable: true, + cellClass: centerCellClass, + }, + years: { + headerName: "연도", + children: [ + { + headerName: "요약", + width: 60, + cellRenderer: ({ data }: GenValueParams) => { + return `${data.age}세
${data.belong}년`; + }, + cellClass: centerCellClass, + columnGroupShow: "closed", + }, + { + headerName: "연령", + field: "age", + ...sortableNumber, + valueFormatter: (v: GenValueParams) => `${v.value}세`, + width: 60, + cellClass: centerCellClass, + columnGroupShow: "open", + }, + { + headerName: "사관", + field: "belong", + ...sortableNumber, + valueFormatter: (v: GenValueParams) => `${v.value}년`, + width: 60, + cellClass: centerCellClass, + columnGroupShow: "open", + }, + ], + }, killturnAndConnect: { headerName: "기타", children: [ @@ -521,7 +758,6 @@ watch(columnRawDefs, (val) => { columnDefs.value = [...Object.values(val)]; gridApi.value?.redrawRows(); }); - diff --git a/hwe/ts/components/GeneralList.vue b/hwe/ts/components/GeneralList.vue index eeac4d8f..3d646989 100644 --- a/hwe/ts/components/GeneralList.vue +++ b/hwe/ts/components/GeneralList.vue @@ -1,4 +1,39 @@