diff --git a/hwe/js/select_general_from_pool.js b/hwe/js/select_general_from_pool.js
deleted file mode 100644
index 478acbfb..00000000
--- a/hwe/js/select_general_from_pool.js
+++ /dev/null
@@ -1,210 +0,0 @@
-var templateGeneralCard = '
\
-
<%generalName%>
\
-

\
- <%if(leadership){%>\
- <%leadership%> / <%strength%> / <%intel%>
\
- <%}%>\
- <%if(personalText){%><%personalText%>
<%}%>\
- <%if(specialDomesticText||specialWarText){%>\
- <%specialDomesticText%> / <%specialWarText%>
\
- <%}%>\
- <%if(dex){%>
\
- 보병: <%parseInt(dex[0]/1000)%>K
\
- 궁병: <%parseInt(dex[1]/1000)%>K
\
- 기병: <%parseInt(dex[2]/1000)%>K
\
- 귀병: <%parseInt(dex[3]/1000)%>K
\
- 차병: <%parseInt(dex[4]/1000)%>K
\
- <%}%>\
-
\
-
\
-
';
-
-var templateSpecial =
- '<%text%>\
- \
- <%info%>\
- \
-\
-';
-
-function pickGeneral() {
- $btn = $(this);
-
-
- if (hasGeneralID) {
- if (!confirm('이 장수를 선택할까요? : {0}'.format($btn.data('name')))) {
- return false;
- }
- $.post({
- url: 'j_update_picked_general.php',
- dataType: 'json',
- data: {
- pick: $btn.val()
- }
- }).then(function(result) {
- if (!result.result) {
- alert(result.reason);
- location.refresh();
- }
-
- alert('선택한 장수로 변경했습니다.');
- location.href = './';
- });
- return false;
- }
-
- currentGeneralInfo = cards[$btn.val()];
- var $card = $btn.closest('.general_card');
-
- var $leftPad = $('#left_pad');
- $leftPad.empty();
- $card.clone().appendTo($leftPad);
- initTooltip($leftPad);
-
- return false;
-}
-
-function buildGeneral() {
- if (!currentGeneralInfo) {
- alert('장수를 선택해주세요!');
- return false;
- }
- if (!confirm('이 장수로 생성할까요?')) {
- return false;
- }
- $.post({
- url: 'j_select_picked_general.php',
- dataType: 'json',
- data: {
- pick: currentGeneralInfo.uniqueName,
- use_own_picture: $('#use_own_picture').is(':checked'),
- leadership: parseInt($('#leadership').val()),
- strength: parseInt($('#leadership').val()),
- intel: parseInt($('#leadership').val()),
- personal: $('#selChar').val()
- }
- }).then(function(result) {
- if (!result.result) {
- alert(result.reason);
- location.refresh();
- }
-
- alert('선택한 장수로 생성했습니다.');
- location.href = './';
- });
- return false;
-}
-
-function updateOutdateTimer() {
- var $validUntilText = $('#valid_until_text');
- var now = Date.now();
- var validUntil = $validUntilText.data('until');
- if (validUntil <= 0) {
- return;
- } else if (validUntil < now) {
- $validUntilText.data('until', 0);
- $('#valid_until').hide();
- $('#outdate_token').show();
- return;
- } else if (validUntil - now <= 30000) {
- $validUntilText.css('color', "rgb(255, {0}, {0})".format(255 * (validUntil - now) / 30000));
- }
-
- setTimeout(updateOutdateTimer, 1000);
-}
-
-function printGenerals(value) {
- $('.card_holder').empty();
- $('#valid_until').show();
- $('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white');
- $('#outdate_token').hide();
-
- var pick = $.map(value.pick, function(value, key) {
- return value;
- });
-
- var emptyCard = {
- 'leadership': null,
- 'strength': null,
- 'intel': null,
- 'personalText': null,
- 'specialDomesticText': null,
- 'specialWarText': null,
- 'dex': null
- };
-
- $.each(pick, function(idx, cardData) {
- cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
- if (cardData.specialDomestic !== undefined) {
- cardData.specialDomesticText = TemplateEngine(templateSpecial, {
- text: cardData.specialDomesticName,
- info: cardData.specialDomesticInfo
- });
- cardData.specialWarText = '-';
- }
-
- if (cardData.specialWar !== undefined) {
- cardData.specialWarText = TemplateEngine(templateSpecial, {
- text: cardData.specialWarName,
- info: cardData.specialWarInfo
- });
- if (cardData.specialDomesticText === undefined) {
- cardData.specialDomesticText = '-';
- }
- }
-
- //FIXME: ego로 적었던것 같음!
- if (cardData.personal in characterInfo) {
- cardData.personalText = TemplateEngine(templateSpecial, {
- text: characterInfo[cardData.personal].name,
- info: characterInfo[cardData.personal].info
- });
- } else {
- cardData.personalText = cardData.personal;
- }
-
- cards[cardData.uniqueName] = cardData;
-
- var $card = $(TemplateEngine(templateGeneralCard, $.extend({}, emptyCard, cardData)));
-
- $('.card_holder').append($card);
- $card.find('.select_btn').click(pickGeneral);
- $card.find('.obj_tooltip').tooltip({
- title: function() {
- return $.trim($(this).find('.tooltiptext').html());
- },
- html: true
- });
- });
-
- updateOutdateTimer();
-}
-
-
-$(function($) {
- $.post('j_get_select_pool.php').then(function(value) {
- if (!value.result) {
- alert(value.reason);
- return;
- }
-
- console.log(value);
- printGenerals(value);
- });
-
- if (hasGeneralID) {
- $('#create_plate').hide();
- }
-
- $('#build_general').on('click', buildGeneral);
-
- $.each(validCustomOption, function(idx, value) {
- if (value == 'picture') {
- $('.custom_picture').show();
- } else if (value == 'ego') {
- $('.custom_personality').show();
- } else if (value == 'stat') {
- $('.custom_stat').show();
- }
- });
-});
\ No newline at end of file
diff --git a/hwe/select_general_from_pool.php b/hwe/select_general_from_pool.php
index 3886f16e..3a4b84ae 100644
--- a/hwe/select_general_from_pool.php
+++ b/hwe/select_general_from_pool.php
@@ -67,7 +67,7 @@ var validCustomOption = =Json::encode(GameConst::$generalPoolAllowOption)?>;
=WebUtil::printJS('dist_js/vendors.js')?>
=WebUtil::printJS('dist_js/common.js')?>
=WebUtil::printJS('dist_js/join.js')?>
-=WebUtil::printJS('js/select_general_from_pool.js')?>
+=WebUtil::printJS('dist_js/select_general_from_pool.js')?>
diff --git a/hwe/ts/select_general_from_pool.ts b/hwe/ts/select_general_from_pool.ts
new file mode 100644
index 00000000..4f531cc4
--- /dev/null
+++ b/hwe/ts/select_general_from_pool.ts
@@ -0,0 +1,285 @@
+import $ from 'jquery';
+import axios from 'axios';
+import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
+import { InvalidResponse } from './defs';
+import { getIconPath, initTooltip } from './common_legacy';
+import { convertFormData } from './util/convertFormData';
+import { unwrap_any } from './util/unwrap_any';
+import { unwrap } from './util/unwrap';
+import { TemplateEngine } from './util/TemplateEngine';
+
+type CardItem = {
+ uniqueName: string,
+
+ imgsvr: 0|1,
+ picture: string,
+ iconPath: string,
+ specialDomestic?: string,
+ specialDomesticName?: string,
+ specialDomesticInfo?: string,
+ specialDomesticText?: string,
+
+ specialWar?: string,
+ specialWarName?: string,
+ specialWarInfo?: string,
+ specialWarText?: string,
+
+ personal?: string,
+ personalText?: string,
+}
+
+type GeneralPoolResponse = {
+ result: true,
+ pick: CardItem[],
+ validUntil: string,
+}
+
+declare const characterInfo: Record;
+declare const hasGeneralID: number;
+declare let currentGeneralInfo: CardItem | undefined;
+declare const cards: Record;
+declare const validCustomOption: string[];
+
+const templateGeneralCard = '\
+
<%generalName%>
\
+

\
+ <%if(leadership){%>\
+ <%leadership%> / <%strength%> / <%intel%>
\
+ <%}%>\
+ <%if(personalText){%><%personalText%>
<%}%>\
+ <%if(specialDomesticText||specialWarText){%>\
+ <%specialDomesticText%> / <%specialWarText%>
\
+ <%}%>\
+ <%if(dex){%>
\
+ 보병: <%parseInt(dex[0]/1000)%>K
\
+ 궁병: <%parseInt(dex[1]/1000)%>K
\
+ 기병: <%parseInt(dex[2]/1000)%>K
\
+ 귀병: <%parseInt(dex[3]/1000)%>K
\
+ 차병: <%parseInt(dex[4]/1000)%>K
\
+ <%}%>\
+
\
+
\
+
';
+
+const templateSpecial =
+ '<%text%>\
+ \
+ <%info%>\
+ \
+\
+';
+
+function showPickedGeneral($btn: JQuery) {
+ currentGeneralInfo = cards[unwrap_any($btn.val())];
+ const $card = $btn.closest('.general_card');
+
+ const $leftPad = $('#left_pad');
+ $leftPad.empty();
+ $card.clone().appendTo($leftPad);
+ initTooltip($leftPad);
+}
+
+async function pickGeneral(this: HTMLElement, e: JQuery.Event) {
+ e.preventDefault();
+
+ const $btn = $(this);
+
+ if (!hasGeneralID) {
+ showPickedGeneral($btn);
+ return;
+ }
+
+ if (!confirm(`이 장수를 선택할까요? : ${$btn.data('name')}`)) {
+ return false;
+ }
+
+ let result: InvalidResponse;
+ try {
+ const response = await axios({
+ url: 'j_update_picked_general.php',
+ method: 'post',
+ responseType: 'json',
+ data: convertFormData({
+ pick: unwrap_any($btn.val())
+ })
+ });
+ result = response.data;
+ if (!result.result) {
+ throw result.reason;
+ }
+ }
+ catch (e) {
+ console.error(e);
+ alert(`실패했습니다: ${e}`);
+ location.reload();
+ return;
+ }
+ alert('선택한 장수로 변경했습니다.');
+ location.href = './';
+}
+
+async function buildGeneral(e: JQuery.Event) {
+ e.preventDefault();
+ if (!currentGeneralInfo) {
+ alert('장수를 선택해주세요!');
+ return;
+ }
+ if (!confirm('이 장수로 생성할까요?')) {
+ return;
+ }
+
+ let result: InvalidResponse;
+ try {
+ const response = await axios({
+ url: 'j_select_picked_general.php',
+ method: 'post',
+ responseType: 'json',
+ data: convertFormData({
+ pick: unwrap(currentGeneralInfo).uniqueName,
+ use_own_picture: $('#use_own_picture').is(':checked'),
+ leadership: parseInt(unwrap_any($('#leadership').val())),
+ strength: parseInt(unwrap_any($('#leadership').val())),
+ intel: parseInt(unwrap_any($('#leadership').val())),
+ personal: unwrap_any($('#selChar').val())
+ })
+ })
+ result = response.data;
+ if (!result.result) {
+ throw result.reason;
+ }
+ }
+ catch (e) {
+ console.error(e);
+ alert(`실패했습니다: ${e}`);
+ location.reload();
+ return;
+ }
+
+ alert('선택한 장수로 생성했습니다.');
+ location.href = './';
+}
+
+function updateOutdateTimer() {
+ const $validUntilText = $('#valid_until_text');
+ const now = Date.now();
+ const validUntil = $validUntilText.data('until');
+ if (validUntil <= 0) {
+ return;
+ } else if (validUntil < now) {
+ $validUntilText.data('until', 0);
+ $('#valid_until').hide();
+ $('#outdate_token').show();
+ return;
+ } else if (validUntil - now <= 30000) {
+ const colorVal = 255 * (validUntil - now) / 30000;
+ $validUntilText.css('color', `rgb(255, ${colorVal}, ${colorVal})`);
+ }
+
+ setTimeout(updateOutdateTimer, 1000);
+}
+
+function printGenerals(value: GeneralPoolResponse) {
+ $('.card_holder').empty();
+ $('#valid_until').show();
+ $('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white');
+ $('#outdate_token').hide();
+
+ const pick = value.pick.map(v => v);//XXX: 의도가 뭐였지? clone?
+
+ const emptyCard = {
+ 'leadership': null,
+ 'strength': null,
+ 'intel': null,
+ 'personalText': null,
+ 'specialDomesticText': null,
+ 'specialWarText': null,
+ 'dex': null
+ };
+
+ for (const cardData of pick) {
+ cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
+ if (cardData.specialDomestic !== undefined) {
+ cardData.specialDomesticText = TemplateEngine(templateSpecial, {
+ text: unwrap(cardData.specialDomesticName),
+ info: unwrap(cardData.specialDomesticInfo)
+ });
+ cardData.specialWarText = '-';
+ }
+
+ if (cardData.specialWar !== undefined) {
+ cardData.specialWarText = TemplateEngine(templateSpecial, {
+ text: unwrap(cardData.specialWarName),
+ info: unwrap(cardData.specialWarInfo)
+ });
+ if (cardData.specialDomesticText === undefined) {
+ cardData.specialDomesticText = '-';
+ }
+ }
+
+ //FIXME: ego로 적었던것 같음!
+ if (cardData.personal && cardData.personal in characterInfo) {
+ cardData.personalText = TemplateEngine(templateSpecial, {
+ text: unwrap(characterInfo[cardData.personal]).name,
+ info: unwrap(characterInfo[cardData.personal]).info
+ });
+ } else {
+ cardData.personalText = cardData.personal;
+ }
+
+ cards[cardData.uniqueName] = cardData;
+
+ const $card = $(TemplateEngine(templateGeneralCard, $.extend({}, emptyCard, cardData)));
+
+ $('.card_holder').append($card);
+ $card.find('.select_btn').on('click', pickGeneral);
+ $card.find('.obj_tooltip').tooltip({
+ title: function () {
+ return $.trim($(this).find('.tooltiptext').html());
+ },
+ html: true
+ });
+ }
+
+ updateOutdateTimer();
+}
+
+
+$(async function ($) {
+ setAxiosXMLHttpRequest();
+
+ let result: InvalidResponse | GeneralPoolResponse;
+ try {
+ const response = await axios({
+ url: 'j_get_select_pool.php',
+ method: 'post',
+ responseType: 'json',
+ });
+ result = response.data;
+ if (!result.result) {
+ throw result.reason;
+ }
+ }
+ catch (e) {
+ console.error(e);
+ alert(`실패했습니다: ${e}`);
+ return;
+ }
+
+ printGenerals(result);
+
+ if (hasGeneralID) {
+ $('#create_plate').hide();
+ }
+
+ $('#build_general').on('click', buildGeneral);
+
+ for (const value of validCustomOption) {
+ if (value == 'picture') {
+ $('.custom_picture').show();
+ } else if (value == 'ego') {
+ $('.custom_personality').show();
+ } else if (value == 'stat') {
+ $('.custom_stat').show();
+ }
+ }
+});
\ No newline at end of file
diff --git a/webpack.config.cjs b/webpack.config.cjs
index c4e693a5..18f5e69b 100644
--- a/webpack.config.cjs
+++ b/webpack.config.cjs
@@ -40,6 +40,7 @@ module.exports = (env, argv) => {
hallOfFame: '@/hallOfFame.ts',
history: '@/history.ts',
join: '@/join.ts',
+ select_general_from_pool: '@/select_general_from_pool.ts',
},
output: {
filename: '[name].js',