diff --git a/.phan/config.php b/.phan/config.php
index a01f9e30..4c2b5fee 100644
--- a/.phan/config.php
+++ b/.phan/config.php
@@ -39,7 +39,6 @@ return [
'hwe/a_emperior.php',
'hwe/a_genList.php',
'hwe/a_hallOfFame.php',
- 'hwe/a_history.php',
'hwe/a_kingdomList.php',
'hwe/a_npcList.php',
'hwe/api.php',
@@ -108,7 +107,6 @@ return [
'hwe/j_install_db.php',
'hwe/j_install.php',
'hwe/j_load_scenarios.php',
- 'hwe/j_map_history.php',
'hwe/j_map.php',
'hwe/j_map_recent.php',
'hwe/j_msg_contact_list.php',
diff --git a/hwe/a_emperior.php b/hwe/a_emperior.php
index 8444f331..090f7b24 100644
--- a/hwe/a_emperior.php
+++ b/hwe/a_emperior.php
@@ -55,7 +55,7 @@ increaseRefresh("왕조일람", 1);
|
현재 (= $year ?>年 = $month ?>月)
-
+
|
@@ -75,7 +75,7 @@ increaseRefresh("왕조일람", 1);
-
+
diff --git a/hwe/a_history.php b/hwe/a_history.php
deleted file mode 100644
index 450f7cac..00000000
--- a/hwe/a_history.php
+++ /dev/null
@@ -1,231 +0,0 @@
-setReadOnly();
-$userID = Session::getUserID();
-
-$db = DB::db();
-$gameStor = KVStorage::getStorage($db, 'game_env');
-
-if (!$serverID) {
- $serverID = UniqueConst::$serverID;
-}
-
-if ($serverID === UniqueConst::$serverID) {
- increaseRefresh("연감", 1);
-}
-
-$admin = $gameStor->getValues(['startyear', 'year', 'month']);
-
-$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner = %i', $userID);
-
-$con = checkLimit($me['con']);
-if ($con >= 2) {
- printLimitMsg($me['turntime']);
- exit();
-}
-
-
-
-[$s_year, $s_month] = $db->queryFirstList('SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year ASC, month ASC LIMIT 1', $serverID);
-$s = Util::joinYearMonth($s_year, $s_month);
-
-if ($s_year === null) {
- echo '인자 에러';
- exit();
-}
-
-[$e_year, $e_month] = $db->queryFirstList('SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year DESC, month DESC LIMIT 1', $serverID);
-$e = Util::joinYearMonth($e_year, $e_month);
-
-if ($serverID !== UniqueConst::$serverID) {
- $mapName = $db->queryFirstField('SELECT map FROM ng_games WHERE server_id=%s', $serverID) ?: 'che';
-} else {
- $mapName = GameConst::$mapName;
-}
-
-//FIXME: $yearmonth가 올바르지 않을 경우에 처리가 필요.
-if ($serverID !== UniqueConst::$serverID && !$yearMonth) {
- $yearMonth = $s;
-} else if (!$yearMonth) {
- $yearMonth = Util::joinYearMonth($admin['year'], $admin['month']);
-} else {
- if ($btn == "◀◀ 이전달") {
- $yearMonth -= 1;
- } elseif ($btn == "다음달 ▶▶") {
- $yearMonth += 1;
- }
-}
-
-$isCurrent = false;
-if ($yearMonth < $s) {
- $yearMonth = $s;
-}
-if ($yearMonth > $e) {
- $isCurrent = true;
- $yearMonth = $e + 1;
-}
-
-[$year, $month] = Util::parseYearMonth($yearMonth);
-
-function getHistory($serverID, $year, $month):array{
- $db = DB::db();
- $history = $db->queryFirstRow('SELECT * FROM ng_history WHERE server_id = %s AND year = %i AND month = %i', $serverID, $year, $month);
- $history['global_history'] = Json::decode($history['global_history']);
- $history['global_action'] = Json::decode($history['global_action']);
- $history['nations'] = Json::decode($history['nations']);
- return $history;
-}
-
-
-if($isCurrent){
- $history = getCurrentHistory();
-}
-else{
- $history = getHistory($serverID, $year, $month);
-}
-
-$nations = $history['nations'];
-?>
-
-
-
-
-
-
-
- = UniqueConst::$serverName ?>: 연감
- = WebUtil::printJS('../d_shared/common_path.js') ?>
- = WebUtil::printJS("js/map/theme_{$mapName}.js") ?>
- = WebUtil::printCSS('../d_shared/common.css') ?>
-
- = WebUtil::printCSS('css/map.css') ?>
- = WebUtil::printCSS('css/history.css') ?>
- = WebUtil::printStaticValues([
- 'staticValues' => [
- 'startYear' => $s_year,
- 'startMonth' => $s_month,
- 'lastYear' => $e_year,
- 'lastMonth' => $e_month,
- 'selectYear' => $year,
- 'selectMonth' => $month,
- 'nations' => $nations ? $history['nations'] : [],
- 'serverNick' => DB::prefix(),
- 'serverID' => UniqueConst::$serverID,
- ]
- ])?>
- = WebUtil::printDist('ts', ['common', 'history']) ?>
-
-
-
-
-
-
- 연 감 = closeButton() ?> |
-
-
- |
-
- |
-
-
-
-
-
- | 중 원 지 도 |
-
-
-
-
- |
- = getMapHtml($mapName) ?>
- |
-
-
-
-
- | 국명 |
- 국력 |
- 장수 |
- 속령 |
-
-
-
-
-
- | ;background-color:= $nation['color'] ?>'>= $nation['name'] ?> |
- = number_format($nation['power']) ?> |
- = number_format($nation['gennum']) ?> |
- = number_format(count($nation['cities'] ?? [])) ?> |
-
-
-
-
-
- |
-
-
- | 중 원 정 세 |
-
-
- |
- = formatHistoryToHTML($history['global_history']) ?>
- |
-
-
- | 장 수 동 향 |
-
-
- |
- = formatHistoryToHTML($history['global_action']) ?>
- |
-
-
-
-
-
- | = closeButton() ?> |
-
-
- | = banner() ?> |
-
-
-
-
-
-
\ No newline at end of file
diff --git a/hwe/j_map_history.php b/hwe/j_map_history.php
deleted file mode 100644
index 11dd6064..00000000
--- a/hwe/j_map_history.php
+++ /dev/null
@@ -1,46 +0,0 @@
-false,
- 'reason'=>'Invalid Referer'
- ]);
-}
-
-if($year === null || !$month) {
- Json::die([
- 'result'=>false,
- 'reason'=>'year, month가 지정되지 않았습니다'
- ]);
-}
-
-
-if(!$serverID){
- $serverID = UniqueConst::$serverID;
-}
-
-//로그인 검사
-$session = Session::requireGameLogin([])->setReadOnly();
-
-$db = DB::db();
-
-$map = $db->queryFirstField('SELECT map FROM ng_history WHERE server_id=%s AND year=%i AND month=%i', $serverID, $year, $month);
-
-if(!$map){
- Json::die([
- 'result'=>false,
- 'reason'=>'해당하는 연월의 지도가 없습니다'
- ]);
-}
-
-Json::die($map, Json::PASS_THROUGH);
\ No newline at end of file
diff --git a/hwe/scss/history.scss b/hwe/scss/history.scss
new file mode 100644
index 00000000..e78a16eb
--- /dev/null
+++ b/hwe/scss/history.scss
@@ -0,0 +1,42 @@
+@import "./common/bootstrap5.scss";
+@import "./editor_component.scss";
+@import "./util.scss";
+
+@include media-1000px {
+ #container {
+ width: 1000px;
+ margin: 0 auto;
+ padding: 0;
+ }
+ .year-selector{
+ margin-left: 100%/24*5;
+ }
+
+ .map_position{
+ flex: 0 0 auto;
+ width: 700px;
+ }
+
+ .nation_position{
+ flex: 0 0 auto;
+ width: 300px;
+ }
+}
+
+@include media-500px {
+ #container {
+ width: 500px;
+ margin: 0 auto;
+ padding: 0;
+ }
+
+ .map_position{
+ flex: 0 0 auto;
+ width: 100%;
+ }
+
+ .nation_position{
+ flex: 0 0 auto;
+ width: 100%;
+ }
+}
diff --git a/hwe/templates/allButton.php b/hwe/templates/allButton.php
index 99c32bfd..8708f594 100644
--- a/hwe/templates/allButton.php
+++ b/hwe/templates/allButton.php
@@ -2,7 +2,7 @@
=$btnBegin??''?>">세력일람=$btnEnd??''?>
=$btnBegin??''?>">장수일람=$btnEnd??''?>
=$btnBegin??''?>">명장일람=$btnEnd??''?>
-=$btnBegin??''?>">연감=$btnEnd??''?>
+=$btnBegin??''?>">연감=$btnEnd??''?>
=$btnBegin??''?>">명예의전당=$btnEnd??''?>
=$btnBegin??''?>">왕조일람=$btnEnd??''?>
=$btnBegin??''?>">접속량정보=$btnEnd??''?>
diff --git a/hwe/ts/PageHistory.vue b/hwe/ts/PageHistory.vue
new file mode 100644
index 00000000..5e44f5de
--- /dev/null
+++ b/hwe/ts/PageHistory.vue
@@ -0,0 +1,188 @@
+
+
+
+
+
연월 선택:
+
◀ 이전달
+
+
+
+
다음달 ▶
+
+
+
+
+
+
+
+
diff --git a/hwe/ts/build_exports.json b/hwe/ts/build_exports.json
index 20a1c1ce..a2200c25 100644
--- a/hwe/ts/build_exports.json
+++ b/hwe/ts/build_exports.json
@@ -28,6 +28,7 @@
"v_NPCControl": "v_NPCControl.ts",
"v_join": "v_join.ts",
"v_main": "v_main.ts",
+ "v_history": "v_history.ts",
"v_nationStratFinan": "v_nationStratFinan.ts",
"v_processing": "v_processing.ts",
"v_nationBetting": "v_nationBetting.ts",
diff --git a/hwe/ts/components/BottomBar.vue b/hwe/ts/components/BottomBar.vue
index b3286818..afbb3611 100644
--- a/hwe/ts/components/BottomBar.vue
+++ b/hwe/ts/components/BottomBar.vue
@@ -1,6 +1,8 @@
-
+
diff --git a/hwe/ts/components/SimpleNationList.vue b/hwe/ts/components/SimpleNationList.vue
new file mode 100644
index 00000000..e5599653
--- /dev/null
+++ b/hwe/ts/components/SimpleNationList.vue
@@ -0,0 +1,72 @@
+
+
+
+
+ | 국명 |
+ 국력 |
+ 장수 |
+ 속령 |
+
+
+
+
+ |
+ {{ nation.name }}
+ |
+ {{ nation.power.toLocaleString() }} |
+ {{ nation.gennum.toLocaleString() }} |
+
+ {{ (nation.cities ?? []).length }}
+ |
+
+
+
+
+
+
+
+
+
diff --git a/hwe/ts/components/TopBackBar.vue b/hwe/ts/components/TopBackBar.vue
index af86e1d4..1826254d 100644
--- a/hwe/ts/components/TopBackBar.vue
+++ b/hwe/ts/components/TopBackBar.vue
@@ -1,6 +1,7 @@
-
-
+
@@ -94,7 +95,7 @@ function reload() {
margin-right: 2px;
}
-.teleport-zone{
+.teleport-zone {
height: 24pt;
}
diff --git a/hwe/ts/defs/index.ts b/hwe/ts/defs/index.ts
index fce1617c..d1cdd8b8 100644
--- a/hwe/ts/defs/index.ts
+++ b/hwe/ts/defs/index.ts
@@ -1,6 +1,6 @@
import type { Args } from "@/processing/args";
import type { ValidResponse, InvalidResponse } from "@/util/callSammoAPI";
-import type { GameObjClassKey } from "./GameObj";
+import type { GameIActionKey, GameObjClassKey } from "./GameObj";
export type { ValidResponse, InvalidResponse };
export type BasicGeneralListResponse = {
@@ -247,4 +247,17 @@ export type MapResult = {
theme?: string,
history?: string[],
+}
+
+
+export type SimpleNationObj = {
+ capital: number,
+ cities: string[],
+ color: string,
+ gennum: number,
+ level: number,
+ name: string,
+ nation: number,
+ power: number,
+ type: GameIActionKey
}
\ No newline at end of file
diff --git a/hwe/ts/utilGame/formatLog.ts b/hwe/ts/utilGame/formatLog.ts
new file mode 100644
index 00000000..3646b933
--- /dev/null
+++ b/hwe/ts/utilGame/formatLog.ts
@@ -0,0 +1,60 @@
+const regex = /<([RBGMCLSODYW]1?|1|\/)>/g;
+
+//TODO: 에서 더 확장해서, , 형태로 뒤에 타입을 지정할 수 있도록 한다.
+
+const convertMap: Record = {
+ "R": 'color: red;',
+ "B": 'color: blue;',
+ "G": 'color: green;',
+ "M": 'color: magenta;',
+ "C": 'color: cyan;',
+ "L": 'color: limegreen;',
+ "S": 'color: skyblue;',
+ "O": 'color: orangered;',
+ "D": 'color: orangered;',
+ "Y": 'color: yellow;',
+ "W": 'color: white;',
+ "1": 'font-size: 0.9em;',
+}
+
+const convertMap2: Record = {
+ "1": 'font-size: 0.9em;',
+}
+
+export function formatLog(text?: string): string {
+ if (!text) {
+ return '';
+ }
+
+ let matchRes;
+ let lastIndex = 0;
+ const result = [];
+ while ((matchRes = regex.exec(text)) !== null) {
+ const {
+ 0: partAll,
+ 1: subPart,
+ index,
+ } = matchRes;
+ if (lastIndex != index) {
+ result.push(text.slice(lastIndex, index));
+ }
+
+ if (subPart == '/') {
+ result.push(``);
+ }
+ else if (subPart.length == 2) {
+ result.push(``);
+ }
+ else {
+ result.push(``);
+ }
+
+ lastIndex = index + partAll.length;
+ }
+
+ if (lastIndex != text.length) {
+ result.push(text.slice(lastIndex));
+ }
+
+ return result.join('');
+}
\ No newline at end of file
diff --git a/hwe/ts/utilGame/techLevel.ts b/hwe/ts/utilGame/techLevel.ts
new file mode 100644
index 00000000..95b58444
--- /dev/null
+++ b/hwe/ts/utilGame/techLevel.ts
@@ -0,0 +1,22 @@
+
+import { clamp } from "lodash";
+
+export const TECH_LEVEL_YEAR_GAP = 5;
+export const TECH_LEVEL_STEP = 1000;
+
+export function isTechLimited(startYear: number, year: number, tech: number, maxTechLevel: number): boolean {
+ const relMaxTech = getMaxRelativeTechLevel(startYear, year, maxTechLevel);
+ const techLevel = convTechLevel(tech, maxTechLevel);
+
+ return techLevel >= relMaxTech;
+}
+
+export function convTechLevel(tech: number, maxTechLevel: number): number{
+ return clamp(Math.floor(tech / TECH_LEVEL_STEP), 0, maxTechLevel);
+}
+
+
+export function getMaxRelativeTechLevel(startYear: number, year: number, maxTechLevel: number): number {
+ const relYear = year - startYear;
+ return clamp(Math.floor(relYear / TECH_LEVEL_YEAR_GAP) + 1, 1, maxTechLevel);
+}
\ No newline at end of file
diff --git a/hwe/ts/v_history.ts b/hwe/ts/v_history.ts
new file mode 100644
index 00000000..507870c7
--- /dev/null
+++ b/hwe/ts/v_history.ts
@@ -0,0 +1,16 @@
+import "@scss/history.scss";
+import { createApp } from 'vue'
+import PageHistory from '@/PageHistory.vue';
+import { BootstrapVue3, BToastPlugin } from 'bootstrap-vue-3'
+import { setAxiosXMLHttpRequest } from '@util/setAxiosXMLHttpRequest';
+import { auto500px } from "./util/auto500px";
+import { htmlReady } from "./util/htmlReady";
+import { insertCustomCSS } from "./util/customCSS";
+
+setAxiosXMLHttpRequest();
+auto500px();
+
+htmlReady(() => {
+ insertCustomCSS();
+});
+createApp(PageHistory).use(BootstrapVue3).use(BToastPlugin).mount('#app');
\ No newline at end of file
diff --git a/hwe/v_history.php b/hwe/v_history.php
new file mode 100644
index 00000000..bcad74e6
--- /dev/null
+++ b/hwe/v_history.php
@@ -0,0 +1,62 @@
+setReadOnly();
+$userID = Session::getUserID();
+
+$db = DB::db();
+$gameStor = KVStorage::getStorage($db, 'game_env');
+
+$serverID = Util::getReq('serverID', 'string', null);
+if (!$serverID) {
+ $serverID = UniqueConst::$serverID;
+}
+if ($serverID !== UniqueConst::$serverID) {
+ $mapName = $db->queryFirstField('SELECT map FROM ng_games WHERE server_id=%s', $serverID) ?: 'che';
+} else {
+ $mapName = GameConst::$mapName;
+}
+
+[$f_year, $f_month] = $db->queryFirstList('SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year ASC, month ASC LIMIT 1', $serverID);
+[$l_year, $l_month] = $db->queryFirstList('SELECT year, month FROM ng_history WHERE server_id = %s ORDER BY year DESC, month DESC LIMIT 1', $serverID);
+[$currentYear, $currentMonth] = $gameStor->getValuesAsArray(['year', 'month']);
+
+$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner = %i', $userID);
+
+?>
+
+
+
+
+ = UniqueConst::$serverName ?>:연감
+
+
+
+ = WebUtil::printJS('../d_shared/common_path.js', true) ?>
+ = WebUtil::printJS("js/map/theme_{$mapName}.js") ?>
+
+ = WebUtil::printStaticValues([
+ 'staticValues' => [
+ 'fisrtYearMonth' => Util::joinYearMonth($f_year, $f_month),
+ 'lastYearMonth' => Util::joinYearMonth($l_year, $l_month),
+ 'currentYearMonth' => Util::joinYearMonth($currentYear, $currentMonth),
+ 'serverNick' => DB::prefix(),
+ 'serverID' => UniqueConst::$serverID,
+ ],
+ 'query' => [
+ 'serverID' => $serverID,
+ 'yearMonth' => Util::getReq('yearMonth', 'int'),
+ ],
+ ]) ?>
+ = WebUtil::printDist('vue', 'v_history', true) ?>
+
+
+
+
+
+
+
\ No newline at end of file