Compare commits

...
158 Commits
Author SHA1 Message Date
Hide_D 923cac5408 전략 턴 버그 수정. 글로벌 쿨 9턴으로 변경 2020-07-17 00:16:48 +09:00
Hide_D 23505326c7 격노 추가 향상 2020-07-16 02:57:37 +09:00
Hide_D 5f1a48f523 아이템 짝 안맞는 것 수정 2020-07-16 02:38:40 +09:00
Hide_D a607d39030 아이템 수정 2020-07-16 02:31:18 +09:00
Hide_D 96d108729e 위압 사기버그 수정 2020-07-15 11:55:35 +09:00
Hide_D ef15adaaf8 저격 약간 더 강화 2020-07-15 02:56:31 +09:00
Hide_D f190b74a7e 필살 조금 더 강화 2020-07-15 02:52:14 +09:00
Hide_D edbc2b88b6 버그 수정 2020-07-15 02:43:00 +09:00
Hide_D dc000cecf1 전특 대 개편 2020-07-15 02:33:21 +09:00
Hide_D 7c95a483df 기본 스탯 향상 2020-07-13 23:25:33 +09:00
Hide_D 27e5d73da1 전략별 쿨타임 적용 2020-07-13 23:21:21 +09:00
Hide_D 6306dae92d 전략 사용 방식 변경 2020-07-13 21:54:32 +09:00
Hide_D a427ddff83 수동 토너먼트 버그 수정 2020-07-07 15:24:48 +09:00
Hide_D b62ee6e820 버그 수정 2020-06-26 23:33:39 +09:00
Hide_D 3c18666080 로그인 form draw 예시 2020-06-26 23:31:45 +09:00
Hide_D 40968b301a file_cache_준비 2020-06-26 21:24:24 +09:00
Hide_D 05904d31fd webp 지원 2020-06-26 02:43:46 +09:00
Hide_D 75aeaf4ee7 후방워프 버그 수정 2020-06-26 02:30:35 +09:00
Hide_D ff4e67a9f6 중립턴, 내정워프 수정 2020-06-26 02:26:59 +09:00
Hide_D 5f672d5bd1 몰수 기준 완화 2020-06-26 00:16:56 +09:00
Hide_D 5cb39eba8b 전특 초기화에서 '쿨'을 감안함 2020-06-25 23:45:09 +09:00
Hide_D 4d8c3c75d6 새 금쌀 구매 로직 2020-06-25 23:43:35 +09:00
Hide_D 8bdd19fc06 버그 수정 2020-06-21 17:07:03 +09:00
Hide_D 0ec99d8ba1 서버 커스터마이징 가능 2020-06-21 17:03:32 +09:00
Hide_D 929d2db5a5 유저장 구출 버그 수정 예상 2020-06-20 21:43:28 +09:00
Hide_D a7ad77f433 최근 전투 페이즈 계산 버그 수정 2020-06-20 15:09:35 +09:00
Hide_D 9cd47d5deb recent_war 표기 방식 변경경 2020-06-19 20:24:50 +09:00
Hide_D 3cb5691aae 수비 기호 표시 추가 2020-06-18 01:05:34 +09:00
Hide_D dce63919fa 부대유저장발령 코드 일부 수정 2020-06-17 03:39:22 +09:00
Hide_D 1cdbedcb96 도시 치료 결과가 이상하게 뜨는 버그 수정 2020-06-16 00:26:45 +09:00
Hide_D 1586712ce5 버그 수정 2020-06-12 22:11:19 +09:00
Hide_D f059186494 구출 발령 활성화 안된 버그 수정 2020-06-12 22:08:56 +09:00
Hide_D 0af0be57b0 전방 발령 버그 수정 2020-06-12 21:16:37 +09:00
Hide_D dad2b03212 ExistsDestNation 버그 수정 2020-06-12 20:39:31 +09:00
Hide_D b6e307660f warning 수정 2020-06-12 20:28:50 +09:00
Hide_D c21c14825a 오타 수정 2020-06-11 03:28:10 +09:00
Hide_D 39f9c986e9 버그 수정 2020-06-11 03:21:26 +09:00
Hide_D 393683aebc 버그 수정 2020-06-11 03:14:12 +09:00
Hide_D a87fcb44a6 전투 시뮬레이터 장수 불러오기 완성 2020-06-11 03:13:02 +09:00
Hide_D 0a6496ddfb 관직 비우기 안되는 것 수정 2020-06-11 00:29:36 +09:00
Hide_D fa2841fac6 원조 버그 수정 2020-06-11 00:20:08 +09:00
Hide_D 861e45419b 포상 검사 로직 빠진 부분 수정 2020-06-09 20:50:57 +09:00
Hide_D 15fd943456 전쟁장 판단 기준 임시 수정, 사망 대비 장수에겐 포상안함 2020-06-09 20:32:49 +09:00
Hide_D b538bfc27e Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2020-06-09 20:30:41 +09:00
Hide_D e0f32eddc4 전쟁장 판별 코드 임시 수정 2020-06-09 20:30:34 +09:00
Hide_D 75a704c196 저격시 아이템이 무조건 소모되는 버그 수정 2020-06-09 01:45:52 +09:00
Hide_D 6565fdbe7e 무장 신산 가능 2020-06-09 01:25:35 +09:00
Hide_D 6248d72852 홀짝 버그 수정 2020-06-09 01:10:21 +09:00
Hide_D 00d1797b96 내특 동작 안하는 버그 수정 2020-06-09 01:03:58 +09:00
Hide_D 911194eba8 찐유저무쌍 비급판 2020-06-07 16:08:04 +09:00
Hide_D 0fad3ae31d 유지비를 깎고 세수를 계산하도록 수정 2020-06-06 19:21:51 +09:00
Hide_D b6988d866a 선포 동안에는 초토화 가능하도록 수정 2020-06-06 15:43:29 +09:00
Hide_D e30959a656 숙련전환 효율 향상 2020-06-06 14:33:21 +09:00
Hide_D 52eeff3466 환약 사용 여부가 안보이는 버그 수정 2020-06-06 13:45:31 +09:00
Hide_D a06ded552d 유저장은 자동 사령턴 켬끔 가능 2020-06-06 13:20:01 +09:00
Hide_D e9b8a84243 전방 발령에 공백지 배제 2020-06-06 12:55:34 +09:00
Hide_D 1fc3cfd1f2 중립 인탐 확률 감소 2020-06-06 03:07:00 +09:00
Hide_D 188b57ed7a 랜덤 임관 버그 수정 2020-06-05 18:13:21 +09:00
Hide_D c8620390ac 중립 커맨드 2020-06-05 02:25:44 +09:00
Hide_D b3f8ed2335 지도 기반 선택 버그 수정 2020-06-05 01:14:49 +09:00
Hide_D 54bf504eb4 명령 입력턴에 select2 적용 2020-06-05 01:02:33 +09:00
Hide_D c6f3bf856b select2 업그레이드 2020-06-04 23:21:47 +09:00
Hide_D 8b33a7926e 오호 장군 수정 2020-06-04 21:31:26 +09:00
Hide_D a38cb90cbf 천지비급 시나리오를 설명에 맞게 수정 2020-06-03 22:17:22 +09:00
Hide_D 1500e8e54f 서버가 닫힌 경우 리다이렉트하도록 2020-06-03 01:51:31 +09:00
Hide_D 94fd8d5e9d 세력도시 암행부 연동 버그 수정 2020-06-02 01:24:25 +09:00
Hide_D 373e0a2155 버그 수정 시도2 2020-06-02 01:06:00 +09:00
Hide_D 267298f341 사령부 공백이어도 사령턴은 보임 2020-06-02 00:24:44 +09:00
Hide_D 359d46e94d 천지비급 디버그 풀기 2020-06-02 00:08:52 +09:00
Hide_D 11f5540099 composer 반영 2020-06-01 21:14:50 +09:00
Hide_D 680e1afcfd 버그 수정 2020-06-01 02:34:56 +09:00
Hide_D e4322e60cc 환약 사용 기준 추가 2020-06-01 02:31:46 +09:00
Hide_D 82f2eecfe8 내 설정 페이지 동작 방식 일단 수정 2020-06-01 02:17:20 +09:00
Hide_D 3e3c3c559d 소모성 아이템 소비 2020-05-31 23:11:17 +09:00
Hide_D 65f5e8e964 setResultTurn 버그 수정 2020-05-31 17:21:51 +09:00
Hide_D c5fbe93890 버그 수정 2020-05-31 04:43:15 +09:00
Hide_D 307d8b6165 버그 수정 2020-05-31 04:42:11 +09:00
Hide_D bf08eb2f8b 버그 수정 2020-05-31 04:32:46 +09:00
Hide_D a569c1dfaf 버그 수정 2020-05-31 04:25:36 +09:00
Hide_D e48db0d231 장수 목록 json 버그 수정 2020-05-31 04:12:42 +09:00
Hide_D 1a5b5dbb45 격노 1회만 2020-05-31 01:47:44 +09:00
Hide_D 56f21cabe5 격노 발동은 1회만 2020-05-31 01:44:44 +09:00
Hide_D 7ac5afe05b 이벤트 특기 버그 수정 2020-05-30 22:50:48 +09:00
Hide_D b3db97f4a8 이중특기 테스트 2020-05-30 16:31:03 +09:00
Hide_D 6d1a06a9d9 긴급 쌀 시 병량패퇴를 당하지 않기 위해 강제 회피 2020-05-30 04:48:33 +09:00
Hide_D 088643df6c 워프 버그 수정 2020-05-30 04:41:47 +09:00
Hide_D fc00a0a363 의병모집, 소형b 초기 m장, 작위보상금쌀
의병모집 -> 초기 금쌀 1000
작위보상 -> 작위에 따라 금쌀*1000
소형b -> 초기 m장 10 추가
2020-05-30 04:36:42 +09:00
Hide_D 7a48fdd246 멸망시 임관 확률을 변경 가능하도록 설정 2020-05-30 03:18:23 +09:00
Hide_D 89be493882 인재탐색 변경. 영입 불가, 재야 가능 2020-05-30 03:09:48 +09:00
Hide_D 5947abf83d 대인 사살, 점령률 추가 2020-05-30 03:05:03 +09:00
Hide_D 962db6821f 대인살상률, 점령수 준비 2020-05-30 02:29:46 +09:00
Hide_D f6a3df7858 수비 켬끔 다양화 2020-05-30 02:08:16 +09:00
Hide_D 090aaed3f4 숙련 전환 효율 향상 2020-05-30 01:56:31 +09:00
Hide_D 71cb5aa9e4 성벽에 닳는 내정을 1/2 2020-05-29 19:16:24 +09:00
Hide_D 043b29ef33 격노 회피 시도 캔슬 2020-05-28 01:39:14 +09:00
Hide_D d81cf4aec3 소집해제 위치 이동 2020-05-28 01:33:27 +09:00
Hide_D 7cb46eeb82 Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2020-05-26 21:44:22 +09:00
Hide_D c3b4d54414 내정 워프 버그 수정 2020-05-26 21:44:03 +09:00
Hide_D 8b9acf2d3d 실패 메시지 수정 2020-05-26 10:44:55 +09:00
Hide_D 08548181ed 첩보 가격이 저렴한 버그 수정 2020-05-26 00:47:42 +09:00
Hide_D 45f883c98b 징병창 병력 키보드 입력 버그 2020-05-25 23:28:16 +09:00
Hide_D 5f39229e47 치안강화 만땅 채우기 2020-05-24 22:52:56 +09:00
Hide_D 8c5bdc2a4b 사망시 수명 계산 버그 2020-05-24 13:41:52 +09:00
Hide_D 7b7602bce2 사령부 확실히 엔터 2020-05-23 17:21:07 +09:00
Hide_D a145792fac 헌납 비율 수정 2020-05-23 16:35:33 +09:00
Hide_D 667a550f4c 조사 수정 2020-05-23 16:30:10 +09:00
Hide_D 53e1ad8991 헌납 메시지 수정 2020-05-23 16:28:21 +09:00
Hide_D 429c949d1f AI 치안 버그 수정 2020-05-23 16:24:18 +09:00
Hide_D 1548577d65 주민선정을 매우 열심히 합니다. 2020-05-23 15:33:10 +09:00
Hide_D 82e59b297f 증축 버그 수정 2020-05-23 11:12:10 +09:00
Hide_D 1f9c994425 사령부 시간 표기 문제 2020-05-22 00:24:52 +09:00
Hide_D fc0c7a5004 호황, 풍작 색상 변경 2020-05-22 00:17:24 +09:00
Hide_D a2d0309c79 내특 중복 버그 수정 2020-05-21 12:52:00 +09:00
Hide_D 6d01fbb6e8 generalCommand 생성이 preprecessCommand보다 빠른 문제 수정 2020-05-21 12:14:46 +09:00
Hide_D be270df088 요양 입력하면 템치료 무효화 2020-05-21 02:16:20 +09:00
Hide_D 88fd94e1cc 왕조일람 국가 타입 버그 수정 2020-05-20 01:35:11 +09:00
Hide_D e460392368 인사부 임명시 색상 2020-05-20 01:31:26 +09:00
Hide_D 249cda99f4 랜덤임관에 긍정적인 메시지 추가 2020-05-20 01:26:28 +09:00
Hide_D 327fce822a Merge branch 'devel' of ssh://storage.hided.net:2525/devsam/core into devel 2020-05-20 01:11:41 +09:00
Hide_D 58931354a4 NPC 포상룰 변경 2020-05-20 01:11:35 +09:00
Hide_D c8993e9832 암해부 정렬 버그 2020-05-19 16:53:20 +09:00
Hide_D 4ee2e023aa 버그 수정 2020-05-19 10:07:24 +09:00
Hide_D 22fa1b121e 수정시도2 2020-05-19 00:32:52 +09:00
Hide_D cbc6e526c3 수정시도2 2020-05-19 00:32:40 +09:00
Hide_D 96041faefd 수정시도1 2020-05-19 00:30:55 +09:00
Hide_D 894c912e19 수정시도 1 2020-05-19 00:29:24 +09:00
Hide_D 7b406a945f 버그 수정 2020-05-19 00:25:41 +09:00
Hide_D 6ff5cc90f1 버그 수정 2020-05-19 00:18:45 +09:00
Hide_D f66e56f4b5 보궁기귀 전특 중 '통장'에 타 능력치 금지 추가 2020-05-19 00:08:50 +09:00
Hide_D 8f09aab0ea NPC 자원 기준 대폭 변경 2020-05-18 23:49:13 +09:00
Hide_D b248b9ca2c 불가침 하나만 있어도 계략이 안들어가는 버그 수정 2020-05-18 23:25:53 +09:00
Hide_D 5a6a31fefa 정착장려, 주민선정 색상 문제 2020-05-18 23:24:17 +09:00
Hide_D 1e485a3883 onCalcNationalIncome 버그 2020-05-18 23:17:16 +09:00
Hide_D fed3246c84 계략 성공시 대미지 없는 문제 수정 2020-05-18 20:12:57 +09:00
Hide_D daff4a9786 징병시 부상을 무시하는 버그 수정 2020-05-18 19:35:41 +09:00
Hide_D 6e88b0c701 로그에 도시 추가 2020-05-18 14:30:39 +09:00
Hide_D 808f674173 버그 수정? 2020-05-18 09:55:00 +09:00
Hide_D ba377c9aac 등용 UI 버그 수정 2020-05-17 20:07:09 +09:00
Hide_D bb8909f552 등용 UI 버그 수정 2020-05-17 20:05:47 +09:00
Hide_D 5a4d9ffcfc 등용장 버그 수정
등용장 초반에도 보낼 수 있도록,
리스트에서 optgroup 작성 실수
2020-05-17 20:00:06 +09:00
Hide_D 5ed24a98cb npc 정책 UI 수정 2020-05-17 19:48:20 +09:00
Hide_D 6d17675ee7 npc 정책 UI
?가 아니라 본체를 선택해도 보이도록
2020-05-17 19:45:18 +09:00
Hide_D e0b8bfdeae 버그 수정 2020-05-17 18:15:02 +09:00
Hide_D 0db2009e65 NPC 생성시 스케일러 제거 2020-05-17 13:47:28 +09:00
Hide_D 5f016d74a1 버그 수정 2020-05-17 03:03:04 +09:00
Hide_D 02b9832750 npcMax 추가 감소 2020-05-16 21:12:09 +09:00
Hide_D 18a888b9d4 인탐, 의병모집 수정, npcMin, npcTotal 추가 2020-05-16 18:59:10 +09:00
Hide_D 7f20e981d2 오호장군 표기기준 버그 수정 2020-05-16 18:16:52 +09:00
Hide_D d64e08f3c4 부대장후방발령버그 2020-05-16 16:24:45 +09:00
Hide_D 8bb5324896 출병 경로 설정 메시지 버그 수정 2020-05-16 14:14:13 +09:00
Hide_D 8f2ebc6409 인재탐색 연령버그 수정 2020-05-16 12:37:13 +09:00
Hide_D 371318f62f 버그 수정 2020-05-15 21:59:10 +09:00
Hide_D 6e94403dc6 수치 버그 수정 2020-05-15 21:51:29 +09:00
Hide_D c35f6905bb 초토화 배율 변경 2020-05-15 21:50:11 +09:00
Hide_D 4eebbb3e81 초토화에 전 장수 배신 1호 추가, 반환 금액 입력 2020-05-15 21:25:01 +09:00
Hide_D 8ddfc8fb4a 한계징병 2020-05-15 12:36:01 +09:00
Hide_D 14d2661be8 npc 조작 권한 안내 2020-05-15 00:38:26 +09:00
Hide_D ec71bf29b8 애니 집결 수정 2020-05-15 00:30:14 +09:00
353 changed files with 43025 additions and 27409 deletions
+52 -50
View File
@@ -1,50 +1,52 @@
.vscode/* .vscode/*
!.vscode/settings.json !.vscode/settings.json
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json
# 체섭 ignore # 체섭 ignore
*.log *.log
logs/*.txt logs/*.txt
d_log/*.txt d_log/*.txt
d_log/*.zip d_log/*.zip
sess_* sess_*
*/logs/*.txt */logs/*.txt
*/logs/*/*.txt */logs/*/*.txt
*/logs/preserved */logs/preserved
err.txt err.txt
che/.htaccess che/.htaccess
kwe/.htaccess kwe/.htaccess
pwe/.htaccess pwe/.htaccess
twe/.htaccess twe/.htaccess
hwe/.htaccess hwe/.htaccess
d_shared d_shared
d_pic/*.jpg d_pic/*.jpg
d_pic/*.gif d_pic/*.gif
d_pic/*.png d_pic/*.png
d_pic/uploaded_image d_pic/uploaded_image
d_setting/*.php d_setting/*.php
*/d_setting/*.php */d_setting/*.php
*/d_setting/templates/*.php */d_setting/templates/*.php
**/old/* */data/file_cache
test.php
**/old/*
/che test.php
/kwe
/pwe /che
/nya /kwe
/pya /pwe
/twe /nya
/pya
phpinfo.php /twe
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3 phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
+2 -2
View File
@@ -51,10 +51,8 @@ return [
'hwe/b_tournament.php', 'hwe/b_tournament.php',
'hwe/b_troop.php', 'hwe/b_troop.php',
'hwe/c_auction.php', 'hwe/c_auction.php',
'hwe/c_die_immediately.php',
'hwe/c_dipcenter.php', 'hwe/c_dipcenter.php',
'hwe/c_tournament.php', 'hwe/c_tournament.php',
'hwe/c_vacation.php',
'hwe/c_vote.php', 'hwe/c_vote.php',
'hwe/func.php', 'hwe/func.php',
'hwe/func_auction.php', 'hwe/func_auction.php',
@@ -83,6 +81,7 @@ return [
'hwe/j_board_comment_add.php', 'hwe/j_board_comment_add.php',
'hwe/j_board_get_articles.php', 'hwe/j_board_get_articles.php',
'hwe/j_chief_turn.php', 'hwe/j_chief_turn.php',
'hwe/j_die_immediately.php',
'hwe/j_diplomacy_destroy_letter.php', 'hwe/j_diplomacy_destroy_letter.php',
'hwe/j_diplomacy_get_letter.php', 'hwe/j_diplomacy_get_letter.php',
'hwe/j_diplomacy_respond_letter.php', 'hwe/j_diplomacy_respond_letter.php',
@@ -115,6 +114,7 @@ return [
'hwe/j_set_general_command.php', 'hwe/j_set_general_command.php',
'hwe/j_simulate_battle.php', 'hwe/j_simulate_battle.php',
'hwe/j_troop.php', 'hwe/j_troop.php',
'hwe/j_vacation.php',
'hwe/lib.php', 'hwe/lib.php',
'hwe/process_war.php', 'hwe/process_war.php',
'hwe/select_npc.php', 'hwe/select_npc.php',
+23
View File
@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>닫혀 있습니다.</title>
<script>
setTimeout(function(){
window.location = window.location+'/../';
}, 5000);
</script>
<style>
html, body{
background-color:black;
color:yellow;
}
</style>
</head>
<body>
서버가 닫혀있습니다.<br>
잠시 뒤에 입구로 이동합니다.
</body>
</html>
+53 -51
View File
@@ -1,51 +1,53 @@
{ {
"name":"sammo-hid/sammo", "name":"sammo-hid/sammo",
"description":"삼국지 모의전투 HiDCHe", "description":"삼국지 모의전투 HiDCHe",
"license": [ "license": [
"MIT", "MIT",
"GPL-2.0-or-later", "GPL-2.0-or-later",
"proprietary" "proprietary"
], ],
"config": { "config": {
"platform": { "platform": {
"php": "7.3" "php": "7.3"
} }
}, },
"require": { "require": {
"brandonwamboldt/utilphp": "^1.1", "brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3", "sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3", "league/plates": "^3.3",
"guzzlehttp/guzzle": "^6.3", "guzzlehttp/guzzle": "^6.3",
"scssphp/scssphp": "^1.0", "scssphp/scssphp": "^1.0",
"monolog/monolog": "^1.23", "monolog/monolog": "^1.23",
"firephp/firephp-core": "^0.4.0", "firephp/firephp-core": "^0.4.0",
"vlucas/valitron": "^1.4", "vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1", "php-extended/php-tail": "^2.1",
"pguardiario/phpuri": "^1.0", "pguardiario/phpuri": "^1.0",
"symfony/lock": "^4.1", "symfony/lock": "^4.1",
"ezyang/htmlpurifier": "^4.10", "ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7", "xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5", "catfan/medoo": "^1.5",
"phan/phan": "^2.7" "phan/phan": "^2.7",
}, "erusev/parsedown-extra": "^0.8.1",
"autoload": { "nette/caching": "^3.0"
"psr-4": { },
"sammo\\": [ "autoload": {
"src/sammo" "psr-4": {
], "sammo\\": [
"kakao\\": [ "src/sammo"
"src/kakao" ],
] "kakao\\": [
}, "src/kakao"
"classmap": [ ]
"d_setting/" },
], "classmap": [
"exclude-from-classmap": [ "d_setting/"
"**/*.orig.php" ],
], "exclude-from-classmap": [
"files":[ "**/*.orig.php"
"f_config/config.php" ],
] "files":[
} "f_config/config.php"
]
} }
}
Generated
+300 -77
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "7343763bee946f23e755edecd14d6b2c", "content-hash": "ab1175c8592ba7f7756d5f02a3aa051c",
"packages": [ "packages": [
{ {
"name": "brandonwamboldt/utilphp", "name": "brandonwamboldt/utilphp",
@@ -215,13 +215,100 @@
"Xdebug", "Xdebug",
"performance" "performance"
], ],
"funding": [ "time": "2020-03-01T12:26:26+00:00"
},
{
"name": "erusev/parsedown",
"version": "1.7.4",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown.git",
"reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
"reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35"
},
"type": "library",
"autoload": {
"psr-0": {
"Parsedown": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{ {
"url": "https://packagist.com", "name": "Emanuil Rusev",
"type": "custom" "email": "hello@erusev.com",
"homepage": "http://erusev.com"
} }
], ],
"time": "2020-03-01T12:26:26+00:00" "description": "Parser for Markdown.",
"homepage": "http://parsedown.org",
"keywords": [
"markdown",
"parser"
],
"time": "2019-12-30T22:54:17+00:00"
},
{
"name": "erusev/parsedown-extra",
"version": "0.8.1",
"source": {
"type": "git",
"url": "https://github.com/erusev/parsedown-extra.git",
"reference": "91ac3ff98f0cea243bdccc688df43810f044dcef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/erusev/parsedown-extra/zipball/91ac3ff98f0cea243bdccc688df43810f044dcef",
"reference": "91ac3ff98f0cea243bdccc688df43810f044dcef",
"shasum": ""
},
"require": {
"erusev/parsedown": "^1.7.4"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35"
},
"type": "library",
"autoload": {
"psr-0": {
"ParsedownExtra": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Emanuil Rusev",
"email": "hello@erusev.com",
"homepage": "http://erusev.com"
}
],
"description": "An extension of Parsedown that adds support for Markdown Extra.",
"homepage": "https://github.com/erusev/parsedown-extra",
"keywords": [
"markdown",
"markdown extra",
"parsedown",
"parser"
],
"time": "2019-12-30T23:20:37+00:00"
}, },
{ {
"name": "ezyang/htmlpurifier", "name": "ezyang/htmlpurifier",
@@ -756,6 +843,213 @@
"description": "Map nested JSON structures onto PHP classes", "description": "Map nested JSON structures onto PHP classes",
"time": "2020-04-16T18:48:43+00:00" "time": "2020-04-16T18:48:43+00:00"
}, },
{
"name": "nette/caching",
"version": "v3.0.1",
"source": {
"type": "git",
"url": "https://github.com/nette/caching.git",
"reference": "b9ecbf920f240bd1ab14900d9a77876924ad7fb4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/caching/zipball/b9ecbf920f240bd1ab14900d9a77876924ad7fb4",
"reference": "b9ecbf920f240bd1ab14900d9a77876924ad7fb4",
"shasum": ""
},
"require": {
"nette/finder": "^2.4 || ^3.0",
"nette/utils": "^2.4 || ^3.0",
"php": ">=7.1"
},
"require-dev": {
"latte/latte": "^2.4",
"nette/di": "^v3.0",
"nette/tester": "^2.0",
"tracy/tracy": "^2.4"
},
"suggest": {
"ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause",
"GPL-2.0",
"GPL-3.0"
],
"authors": [
{
"name": "David Grudl",
"homepage": "https://davidgrudl.com"
},
{
"name": "Nette Community",
"homepage": "https://nette.org/contributors"
}
],
"description": "⏱ Nette Caching: library with easy-to-use API and many cache backends.",
"homepage": "https://nette.org",
"keywords": [
"cache",
"journal",
"memcached",
"nette",
"sqlite"
],
"time": "2019-11-19T18:41:40+00:00"
},
{
"name": "nette/finder",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/nette/finder.git",
"reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/finder/zipball/4ad2c298eb8c687dd0e74ae84206a4186eeaed50",
"reference": "4ad2c298eb8c687dd0e74ae84206a4186eeaed50",
"shasum": ""
},
"require": {
"nette/utils": "^2.4 || ^3.0",
"php": ">=7.1"
},
"conflict": {
"nette/nette": "<2.2"
},
"require-dev": {
"nette/tester": "^2.0",
"phpstan/phpstan": "^0.12",
"tracy/tracy": "^2.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.5-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause",
"GPL-2.0",
"GPL-3.0"
],
"authors": [
{
"name": "David Grudl",
"homepage": "https://davidgrudl.com"
},
{
"name": "Nette Community",
"homepage": "https://nette.org/contributors"
}
],
"description": "🔍 Nette Finder: find files and directories with an intuitive API.",
"homepage": "https://nette.org",
"keywords": [
"filesystem",
"glob",
"iterator",
"nette"
],
"time": "2020-01-03T20:35:40+00:00"
},
{
"name": "nette/utils",
"version": "v3.1.2",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
"reference": "488f58378bba71767e7831c83f9e0fa808bf83b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/utils/zipball/488f58378bba71767e7831c83f9e0fa808bf83b9",
"reference": "488f58378bba71767e7831c83f9e0fa808bf83b9",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"nette/tester": "~2.0",
"phpstan/phpstan": "^0.12",
"tracy/tracy": "^2.3"
},
"suggest": {
"ext-gd": "to use Image",
"ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
"ext-json": "to use Nette\\Utils\\Json",
"ext-mbstring": "to use Strings::lower() etc...",
"ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()",
"ext-xml": "to use Strings::length() etc. when mbstring is not available"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.1-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause",
"GPL-2.0-only",
"GPL-3.0-only"
],
"authors": [
{
"name": "David Grudl",
"homepage": "https://davidgrudl.com"
},
{
"name": "Nette Community",
"homepage": "https://nette.org/contributors"
}
],
"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
"homepage": "https://nette.org",
"keywords": [
"array",
"core",
"datetime",
"images",
"json",
"nette",
"paginator",
"password",
"slugify",
"string",
"unicode",
"utf-8",
"utility",
"validation"
],
"time": "2020-05-27T09:58:51+00:00"
},
{ {
"name": "pguardiario/phpuri", "name": "pguardiario/phpuri",
"version": "1.0", "version": "1.0",
@@ -1510,20 +1804,6 @@
], ],
"description": "Symfony Console Component", "description": "Symfony Console Component",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-30T11:42:42+00:00" "time": "2020-03-30T11:42:42+00:00"
}, },
{ {
@@ -1648,20 +1928,6 @@
"polyfill", "polyfill",
"portable" "portable"
], ],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00" "time": "2020-02-27T09:26:54+00:00"
}, },
{ {
@@ -1721,20 +1987,6 @@
"portable", "portable",
"shim" "shim"
], ],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00" "time": "2020-03-09T19:04:49+00:00"
}, },
{ {
@@ -1790,20 +2042,6 @@
"portable", "portable",
"shim" "shim"
], ],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00" "time": "2020-02-27T09:26:54+00:00"
}, },
{ {
@@ -1862,20 +2100,6 @@
"portable", "portable",
"shim" "shim"
], ],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00" "time": "2020-02-27T09:26:54+00:00"
}, },
{ {
@@ -2095,6 +2319,5 @@
"platform-dev": [], "platform-dev": [],
"platform-overrides": { "platform-overrides": {
"php": "7.3" "php": "7.3"
}, }
"plugin-api-version": "1.1.0"
} }
+131 -130
View File
@@ -1,131 +1,132 @@
body, html{ body,
height: 100%; html {
background-repeat: no-repeat; height: 100%;
} background-repeat: no-repeat;
}
.main{
margin-top: 70px; .main {
} margin-top: 70px;
}
h1.title {
font-size: 50px; h1.title {
font-family: 'Passion One', cursive; font-size: 50px;
font-weight: 400; font-family: 'Passion One', cursive;
} font-weight: 400;
}
hr{
width: 10%; hr {
/*color: #fff;*/ width: 10%;
} /*color: #fff;*/
}
.form-group{
margin-bottom: 15px; .form-group {
} margin-bottom: 15px;
}
label{
margin-bottom: 15px; label {
} margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder { input,
font-size: 11px; input::-webkit-input-placeholder {
padding-top: 3px; font-size: 11px;
} padding-top: 3px;
}
.main-login{
/*background-color: #fff;*/ .main-login {
/* shadows and rounded borders */ /*background-color: #fff;*/
-moz-border-radius: 2px; /* shadows and rounded borders */
-webkit-border-radius: 2px; -moz-border-radius: 2px;
border-radius: 2px; -webkit-border-radius: 2px;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); border-radius: 2px;
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
} }
.main-center{ .main-center {
margin-top: 30px; margin-top: 30px;
margin: 0 auto; margin: 0 auto;
max-width: 330px; max-width: 330px;
padding: 40px 40px; padding: 40px 40px;
}
}
.login_btn_group {
.login_btn_group{ margin-top: 5px;
margin-top: 5px; }
}
.login-register {
.login-register{ font-size: 11px;
font-size: 11px; text-align: center;
text-align: center; }
}
.col-form-label {
text-align: center;
.col-form-label{ }
text-align:center;
} .terms {
max-height: 200px;
.terms{ overflow-y: auto;
max-height: 200px; overflow-y: auto; }
}
.terms pre {
.terms pre{ width: 100%;
width:100%; white-space: pre-wrap;
white-space: pre-wrap; /* Since CSS 2.1 */ /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -moz-pre-wrap;
white-space: -pre-wrap; /* Opera 4-6 */ /* Mozilla, since 1999 */
white-space: -o-pre-wrap; /* Opera 7 */ white-space: -pre-wrap;
word-wrap: break-word; /* Internet Explorer 5.5+ */ /* Opera 4-6 */
} white-space: -o-pre-wrap;
/* Opera 7 */
.vertical-center { word-wrap: break-word;
min-height: 100%; /* Fallback for browsers do NOT support vh unit */ /* Internet Explorer 5.5+ */
min-height: 100vh; /* These two lines are counted as one :-) */ }
display: flex; .vertical-center {
align-items: center; min-height: 100%;
} /* Fallback for browsers do NOT support vh unit */
min-height: 100vh;
.full-content { /* These two lines are counted as one :-) */
position:fixed; display: flex;
left:0; align-items: center;
top:0; }
width:100%;
height:100%; #login_card {
margin:0; z-index: 801;
padding:0; }
z-index:800;
} #btn_kakao_login {
cursor: pointer;
#login_card{ height: 46px;
z-index:801; width: 116px;
} background-color: transparent;
color: transparent;
#btn_kakao_login{ border: 0;
cursor: pointer; background-size: 100%;
height:46px; /* To fill the dimensions of container (button), or */
width:116px; background-repeat: no-repeat;
background-color: transparent; background-position: bottom center;
color:transparent; margin-top: 5px;
border:0; background-image: url('../oauth_kakao/kakao_login_join.png');
background-size: 100%; /* To fill the dimensions of container (button), or */ }
background-repeat: no-repeat;
background-position: bottom center; #btn_kakao_login:hover {
margin-top:5px; background-image: url('../oauth_kakao/kakao_login_join_ov.png');
background-image:url('../oauth_kakao/kakao_login_join.png'); }
}
#bottom_box .container {
#btn_kakao_login:hover { text-align: center;
background-image:url('../oauth_kakao/kakao_login_join_ov.png'); }
}
.btn-group-xs>.btn,
#bottom_box{ .btn-xs {
position:fixed; padding: .25rem .4rem;
bottom:0; font-size: .875rem;
width:100%; line-height: .5;
left:0; border-radius: .2rem;
} }
#bottom_box .container{
text-align:center; #running_map {
margin-top: 20px;
} }
+2 -2
View File
@@ -1,3 +1,3 @@
/*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */ /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="너무 깁니다. "+t+" 글자 지워주세요.";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="너무 짧습니다. "+t+" 글자 더 입력해주세요.";return n},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(e){var t="최대 "+e.maximum+"개까지만 선택 가능합니다.";return t},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"}}}),{define:e.define,require:e.require}})(); !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(n){return"너무 깁니다. "+(n.input.length-n.maximum)+" 글자 지워주세요."},inputTooShort:function(n){return"너무 짧습니다. "+(n.minimum-n.input.length)+" 글자 더 입력해주세요."},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(n){return"최대 "+n.maximum+"개까지만 선택 가능합니다."},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"},removeAllItems:function(){return"모든 항목 삭제"}}}),n.define,n.require}();
+553 -188
View File
@@ -1,188 +1,553 @@
/* select2-bootstrap4 with Darkly */ /* select2-bootstrap4 with Darkly */
.select2-container--bootstrap4 { color: black; }
.select2-container--bootstrap4 {
.select2-container--bootstrap4 .select2-selection { background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; color: #495057; font-size: 1rem; outline: 0; } color: black;
}
.select2-container--bootstrap4 .select2-selection.form-control { border-radius: 0.25rem; }
.select2-container--bootstrap4 .select2-selection {
.select2-container--bootstrap4 .select2-search--dropdown .select2-search__field { background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; color: #495057; font-size: 1rem; } background-color: #fff;
border: 1px solid #ced4da;
.select2-container--bootstrap4 .select2-search__field { outline: 0; } border-radius: 0.25rem;
color: #495057;
.select2-container--bootstrap4 .select2-search__field::-webkit-input-placeholder { color: #6c757d; } font-size: 1rem;
outline: 0;
.select2-container--bootstrap4 .select2-search__field:-moz-placeholder { color: #6c757d; } }
.select2-container--bootstrap4 .select2-search__field::-moz-placeholder { color: #6c757d; opacity: 1; } .select2-container--bootstrap4 .select2-selection.form-control {
border-radius: 0.25rem;
.select2-container--bootstrap4 .select2-search__field:-ms-input-placeholder { color: #6c757d; } }
.select2-container--bootstrap4 .select2-results__option { padding: 0.75rem 0.375rem; font-size: 1rem; } .select2-container--bootstrap4 .select2-search--dropdown .select2-search__field {
background-color: #fff;
.select2-container--bootstrap4 .select2-results__option[role=group] { padding: 0; } border: 1px solid #ced4da;
border-radius: 0.25rem;
.select2-container--bootstrap4 .select2-results__option[aria-disabled=true] { color: #6c757d; cursor: not-allowed; } color: #495057;
font-size: 1rem;
.select2-container--bootstrap4 .select2-results__option[aria-selected=true] { background-color: #f8f9fa; color: #16181b; } }
.select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] { background-color: #007bff; color: #fff; } .select2-container--bootstrap4 .select2-search__field {
outline: 0;
.select2-container--bootstrap4 .select2-results__option .select2-results__option { padding: 0.75rem 0.375rem; } }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__group { padding-left: 0; } .select2-container--bootstrap4 .select2-search__field::-webkit-input-placeholder {
color: #6c757d;
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option { margin-left: -0.375rem; padding-left: 0.75rem; } }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -0.75rem; padding-left: 1.125rem; } .select2-container--bootstrap4 .select2-search__field:-moz-placeholder {
color: #6c757d;
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -1.125rem; padding-left: 1.5rem; } }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -1.5rem; padding-left: 1.875rem; } .select2-container--bootstrap4 .select2-search__field::-moz-placeholder {
color: #6c757d;
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { margin-left: -1.875rem; padding-left: 2.25rem; } opacity: 1;
}
.select2-container--bootstrap4 .select2-results__group { color: #6c757d; display: block; padding: 0.75rem 0.375rem; font-size: 75%; line-height: 1; white-space: nowrap; }
.select2-container--bootstrap4 .select2-search__field:-ms-input-placeholder {
.select2-container--bootstrap4.select2-container--focus .select2-selection, .select2-container--bootstrap4.select2-container--open .select2-selection { transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; border-color: #80bdff; } color: #6c757d;
}
@media screen and (prefers-reduced-motion: reduce) { .select2-container--bootstrap4.select2-container--focus .select2-selection, .select2-container--bootstrap4.select2-container--open .select2-selection { transition: none; } }
.select2-container--bootstrap4 .select2-results__option {
.select2-container--bootstrap4.select2-container--open .select2-selection .select2-selection__arrow b { border-color: transparent transparent #6c757d transparent; border-width: 0 0.25rem 0.25rem 0.25rem; } padding: 0.75rem 0.375rem;
font-size: 1rem;
.select2-container--bootstrap4.select2-container--open.select2-container--below .select2-selection { border-bottom-right-radius: 0; border-bottom-left-radius: 0; border-bottom-color: transparent; } }
.select2-container--bootstrap4.select2-container--open.select2-container--above .select2-selection { border-top-left-radius: 0; border-top-right-radius: 0; border-top-color: transparent; } .select2-container--bootstrap4 .select2-results__option[role=group] {
padding: 0;
.select2-container--bootstrap4 .select2-selection__clear { color: #6c757d; cursor: pointer; float: right; font-weight: bold; margin-right: 10px; } }
.select2-container--bootstrap4 .select2-selection__clear:hover { color: #343a40; } .select2-container--bootstrap4 .select2-results__option[aria-disabled=true] {
color: #6c757d;
.select2-container--bootstrap4.select2-container--disabled .select2-selection { border-color: #ced4da; } cursor: not-allowed;
}
.select2-container--bootstrap4.select2-container--disabled .select2-selection, .select2-container--bootstrap4.select2-container--disabled .select2-search__field { cursor: not-allowed; }
.select2-container--bootstrap4 .select2-results__option[aria-selected=true] {
.select2-container--bootstrap4.select2-container--disabled .select2-selection, .select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice { background-color: #e9ecef; } background-color: #f8f9fa;
color: #16181b;
.select2-container--bootstrap4.select2-container--disabled .select2-selection__clear, .select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove { display: none; } }
.select2-container--bootstrap4 .select2-dropdown { border-color: #80bdff; border-width: 1px; overflow-x: hidden; margin-top: -1px; } .select2-container--bootstrap4 .select2-results__option--highlighted[aria-selected] {
background-color: #007bff;
.select2-container--bootstrap4 .select2-dropdown--above { margin-top: 1px; } color: #fff;
}
.select2-container--bootstrap4 .select2-results > .select2-results__options { max-height: 200px; overflow-y: auto; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option {
.select2-container--bootstrap4 .select2-selection--single { height: calc(2.25rem + 2px); line-height: 1; padding: 0.75rem 1.125rem 0.75rem 0.375rem; } padding: 0.75rem 0.375rem;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow { position: absolute; bottom: 0; right: 0.375rem; top: 0; width: 0.25rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__group {
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { border-color: #6c757d transparent transparent transparent; border-style: solid; border-width: 0.25rem 0.25rem 0 0.25rem; height: 0; left: 0; margin-left: -0.25rem; margin-top: -0.125rem; position: absolute; top: 50%; width: 0; } padding-left: 0;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered { color: #495057; padding: 0; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option {
.select2-container--bootstrap4 .select2-selection--single .select2-selection__placeholder { color: #6c757d; } margin-left: -0.375rem;
padding-left: 0.75rem;
.select2-container--bootstrap4 .select2-selection--multiple { min-height: calc(2.25rem + 2px); padding: 0; height: auto; } }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered { box-sizing: border-box; display: block; line-height: 1; list-style: none; margin: 0; overflow: hidden; padding: 0.75rem 0.375rem 0 0.75rem; width: 100%; text-overflow: ellipsis; white-space: nowrap; } .select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -0.75rem;
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__placeholder { color: #6c757d; float: left; margin-top: 5px; } padding-left: 1.125rem;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { color: #495057; background: transparent; border: 1px solid #343a40; border-radius: 0.25rem; cursor: default; float: left; margin: -0.25rem 0 0 0.1875rem; padding: 0 0.75rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
.select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field { background: transparent; padding: 0 0.375rem; height: calc(2.25rem + 2px)-2; line-height: 1; margin-top: 0; min-width: 5em; } margin-left: -1.125rem;
padding-left: 1.5rem;
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove { color: #6c757d; cursor: pointer; display: inline-block; font-weight: bold; margin-right: 0.375rem; } }
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove:hover { color: #343a40; } .select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1.5rem;
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear { margin-top: 0.75rem; } padding-left: 1.875rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-sm, .input-group-sm .select2-container--bootstrap4 .select2-selection--single, .form-group-sm .select2-container--bootstrap4 .select2-selection--single { border-radius: 0.2rem; font-size: 75%; height: calc(1.8125rem + 2px); line-height: 1; padding: 0.5rem 1rem 0.5rem 0.25rem; }
.select2-container--bootstrap4 .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
.select2-container--bootstrap4 .select2-selection--single.input-sm .select2-selection__arrow b, .input-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b, .form-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { margin-left: -0.5rem; } margin-left: -1.875rem;
padding-left: 2.25rem;
.select2-container--bootstrap4 .select2-selection--multiple.input-sm, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple { min-height: calc(1.8125rem + 2px); border-radius: 0.2rem; } }
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__rendered, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered { padding: 0.5rem 0.25rem 0 0.5rem; } .select2-container--bootstrap4 .select2-results__group {
color: #6c757d;
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__choice, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { font-size: 75%; line-height: 1; margin: 0 0 0 0.125rem; padding: 0 0.5rem; } display: block;
padding: 0.75rem 0.375rem;
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field { padding: 0 0.25rem; font-size: 75%; height: calc(1.8125rem + 2px)-2; line-height: 1; } font-size: 75%;
line-height: 1;
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__clear, .input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear, .form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear { margin-top: 0.5rem; } white-space: nowrap;
}
.select2-container--bootstrap4 .select2-selection--single.input-lg, .input-group-lg .select2-container--bootstrap4 .select2-selection--single, .form-group-lg .select2-container--bootstrap4 .select2-selection--single { border-radius: 0.3rem; font-size: 1.25rem; height: calc(2.875rem + 2px); line-height: 1; padding: 1rem 1.4375rem 1rem 0.5rem; }
.select2-container--bootstrap4.select2-container--focus .select2-selection,
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow, .input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow, .form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow { width: 0.3125rem; } .select2-container--bootstrap4.select2-container--open .select2-selection {
transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow b, .input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b, .form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b { border-width: 0.3125rem 0.3125rem 0 0.3125rem; margin-left: -0.3125rem; margin-left: -1rem; margin-top: -0.15625rem; } border-color: #80bdff;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple { min-height: calc(2.875rem + 2px); border-radius: 0.3rem; }
@media screen and (prefers-reduced-motion: reduce) {
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__choice, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice { font-size: 1.25rem; line-height: 1; border-radius: 0.25rem; margin: 0rem 0 0 0.25rem; padding: 0 1rem; } .select2-container--bootstrap4.select2-container--focus .select2-selection,
.select2-container--bootstrap4.select2-container--open .select2-selection {
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field { padding: 0 0.5rem; font-size: 1.25rem; height: calc(2.875rem + 2px)-2; line-height: 1; } transition: none;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__clear, .input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear, .form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear { margin-top: 1rem; } }
.select2-container--bootstrap4 .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b { border-color: transparent transparent #6c757d transparent; border-width: 0 0.3125rem 0.3125rem 0.3125rem; } .select2-container--bootstrap4.select2-container--open .select2-selection .select2-selection__arrow b {
border-color: transparent transparent #6c757d transparent;
.input-group-lg .select2-container--bootstrap4 .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b { border-color: transparent transparent #6c757d transparent; border-width: 0 0.3125rem 0.3125rem 0.3125rem; } border-width: 0 0.25rem 0.25rem 0.25rem;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single { padding-left: 1.125rem; padding-right: 0.375rem; }
.select2-container--bootstrap4.select2-container--open.select2-container--below .select2-selection {
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__rendered { padding-right: 0; padding-left: 0; text-align: right; } border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__clear { float: left; } border-bottom-color: transparent;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow { left: 0.375rem; right: auto; }
.select2-container--bootstrap4.select2-container--open.select2-container--above .select2-selection {
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow b { margin-left: 0; } border-top-left-radius: 0;
border-top-right-radius: 0;
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-search--inline { float: right; } border-top-color: transparent;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice { margin-left: 0; margin-right: 0.1875rem; }
.select2-container--bootstrap4 .select2-selection__clear {
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { margin-left: 2px; margin-right: auto; } color: #6c757d;
cursor: pointer;
.has-warning .select2-dropdown, .has-warning .select2-selection { border-color: #ffc107; } float: right;
font-weight: bold;
.has-warning .select2-container--focus .select2-selection, .has-warning .select2-container--open .select2-selection { border-color: #d39e00; } margin-right: 10px;
}
.has-warning.select2-drop-active { border-color: #d39e00; }
.select2-container--bootstrap4 .select2-selection__clear:hover {
.has-warning.select2-drop-active.select2-drop.select2-drop-above { border-top-color: #d39e00; } color: #343a40;
}
.has-error .select2-dropdown, .has-error .select2-selection { border-color: #dc3545; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection {
.has-error .select2-container--focus .select2-selection, .has-error .select2-container--open .select2-selection { border-color: #bd2130; } border-color: #ced4da;
}
.has-error.select2-drop-active { border-color: #bd2130; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection,
.has-error.select2-drop-active.select2-drop.select2-drop-above { border-top-color: #bd2130; } .select2-container--bootstrap4.select2-container--disabled .select2-search__field {
cursor: not-allowed;
.has-success .select2-dropdown, .has-success .select2-selection { border-color: #28a745; } }
.has-success .select2-container--focus .select2-selection, .has-success .select2-container--open .select2-selection { border-color: #1e7e34; } .select2-container--bootstrap4.select2-container--disabled .select2-selection,
.select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice {
.has-success.select2-drop-active { border-color: #1e7e34; } background-color: #e9ecef;
}
.has-success.select2-drop-active.select2-drop.select2-drop-above { border-top-color: #1e7e34; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection__clear,
.input-group > .select2-hidden-accessible:first-child + .select2-container--bootstrap4 > .selection > .select2-selection, .input-group > .select2-hidden-accessible:first-child + .select2-container--bootstrap4 > .selection > .select2-selection.form-control { border-top-right-radius: 0; border-bottom-right-radius: 0; } .select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice__remove {
display: none;
.input-group > .select2-hidden-accessible:not(:first-child) + .select2-container--bootstrap4:not(:last-child) > .selection > .select2-selection, .input-group > .select2-hidden-accessible:not(:first-child) + .select2-container--bootstrap4:not(:last-child) > .selection > .select2-selection.form-control { border-radius: 0; } }
.input-group > .select2-hidden-accessible:not(:first-child):not(:last-child) + .select2-container--bootstrap4:last-child > .selection > .select2-selection, .input-group > .select2-hidden-accessible:not(:first-child):not(:last-child) + .select2-container--bootstrap4:last-child > .selection > .select2-selection.form-control { border-top-left-radius: 0; border-bottom-left-radius: 0; } .select2-container--bootstrap4 .select2-dropdown {
border-color: #80bdff;
.input-group > .select2-container--bootstrap4 { display: table; table-layout: fixed; position: relative; z-index: 2; width: 100%; margin-bottom: 0; } border-width: 1px;
overflow-x: hidden;
.input-group > .select2-container--bootstrap4 > .selection > .select2-selection.form-control { float: none; } margin-top: -1px;
}
.input-group > .select2-container--bootstrap4.select2-container--open, .input-group > .select2-container--bootstrap4.select2-container--focus { z-index: 3; }
.select2-container--bootstrap4 .select2-dropdown--above {
.input-group > .select2-container--bootstrap4, .input-group > .select2-container--bootstrap4 .input-group-btn, .input-group > .select2-container--bootstrap4 .input-group-btn .btn { vertical-align: top; } margin-top: 1px;
}
.form-control.select2-hidden-accessible { position: absolute !important; width: 1px !important; }
.select2-container--bootstrap4 .select2-results>.select2-results__options {
@media (min-width: 576px) { .form-inline .select2-container--bootstrap4 { display: inline-block; } } max-height: 200px;
overflow-y: auto;
}
.select2-container--bootstrap4 .select2-selection--single {
height: calc(2.25rem + 2px);
line-height: 1;
padding: 0.75rem 1.125rem 0.75rem 0.375rem;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow {
position: absolute;
bottom: 0;
right: 0.375rem;
top: 0;
width: 0.25rem;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b {
border-color: #6c757d transparent transparent transparent;
border-style: solid;
border-width: 0.25rem 0.25rem 0 0.25rem;
height: 0;
left: 0;
margin-left: -0.25rem;
margin-top: -0.125rem;
position: absolute;
top: 50%;
width: 0;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__rendered {
color: #495057;
padding: 0;
}
.select2-container--bootstrap4 .select2-selection--single .select2-selection__placeholder {
color: #6c757d;
}
.select2-container--bootstrap4 .select2-selection--multiple {
min-height: calc(2.25rem + 2px);
padding: 0;
height: auto;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
display: block;
line-height: 1;
list-style: none;
margin: 0;
overflow: hidden;
padding: 0.75rem 0.375rem 0 0.75rem;
width: 100%;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__placeholder {
color: #6c757d;
float: left;
margin-top: 5px;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice {
color: #495057;
background: transparent;
border: 1px solid #343a40;
border-radius: 0.25rem;
cursor: default;
float: left;
margin: -0.25rem 0 0 0.1875rem;
padding: 0 0.75rem;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field {
background: transparent;
padding: 0 0.375rem;
height: calc(2.25rem + 2px)-2;
line-height: 1;
margin-top: 0;
min-width: 5em;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove {
color: #6c757d;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 0.375rem;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #343a40;
}
.select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear {
margin-top: 0.75rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-sm,
.input-group-sm .select2-container--bootstrap4 .select2-selection--single,
.form-group-sm .select2-container--bootstrap4 .select2-selection--single {
border-radius: 0.2rem;
font-size: 75%;
height: calc(1.8125rem + 2px);
line-height: 1;
padding: 0.5rem 1rem 0.5rem 0.25rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-sm .select2-selection__arrow b,
.input-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b,
.form-group-sm .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b {
margin-left: -0.5rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple {
min-height: calc(1.8125rem + 2px);
border-radius: 0.2rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__rendered,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__rendered {
padding: 0.5rem 0.25rem 0 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__choice,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice {
font-size: 75%;
line-height: 1;
margin: 0 0 0 0.125rem;
padding: 0 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-search--inline .select2-search__field,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field {
padding: 0 0.25rem;
font-size: 75%;
height: calc(1.8125rem + 2px)-2;
line-height: 1;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-sm .select2-selection__clear,
.input-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear,
.form-group-sm .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear {
margin-top: 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-lg,
.input-group-lg .select2-container--bootstrap4 .select2-selection--single,
.form-group-lg .select2-container--bootstrap4 .select2-selection--single {
border-radius: 0.3rem;
font-size: 1.25rem;
height: calc(2.875rem + 2px);
line-height: 1;
padding: 1rem 1.4375rem 1rem 0.5rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow,
.input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow,
.form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow {
width: 0.3125rem;
}
.select2-container--bootstrap4 .select2-selection--single.input-lg .select2-selection__arrow b,
.input-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b,
.form-group-lg .select2-container--bootstrap4 .select2-selection--single .select2-selection__arrow b {
border-width: 0.3125rem 0.3125rem 0 0.3125rem;
margin-left: -0.3125rem;
margin-left: -1rem;
margin-top: -0.15625rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple {
min-height: calc(2.875rem + 2px);
border-radius: 0.3rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__choice,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__choice {
font-size: 1.25rem;
line-height: 1;
border-radius: 0.25rem;
margin: 0rem 0 0 0.25rem;
padding: 0 1rem;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-search--inline .select2-search__field,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-search--inline .select2-search__field {
padding: 0 0.5rem;
font-size: 1.25rem;
height: calc(2.875rem + 2px)-2;
line-height: 1;
}
.select2-container--bootstrap4 .select2-selection--multiple.input-lg .select2-selection__clear,
.input-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear,
.form-group-lg .select2-container--bootstrap4 .select2-selection--multiple .select2-selection__clear {
margin-top: 1rem;
}
.select2-container--bootstrap4 .select2-selection.input-lg.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #6c757d transparent;
border-width: 0 0.3125rem 0.3125rem 0.3125rem;
}
.input-group-lg .select2-container--bootstrap4 .select2-selection.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #6c757d transparent;
border-width: 0 0.3125rem 0.3125rem 0.3125rem;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single {
padding-left: 1.125rem;
padding-right: 0.375rem;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 0;
padding-left: 0;
text-align: right;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 0.375rem;
right: auto;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--single .select2-selection__arrow b {
margin-left: 0;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice,
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 0;
margin-right: 0.1875rem;
}
.select2-container--bootstrap4[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
.has-warning .select2-dropdown,
.has-warning .select2-selection {
border-color: #ffc107;
}
.has-warning .select2-container--focus .select2-selection,
.has-warning .select2-container--open .select2-selection {
border-color: #d39e00;
}
.has-warning.select2-drop-active {
border-color: #d39e00;
}
.has-warning.select2-drop-active.select2-drop.select2-drop-above {
border-top-color: #d39e00;
}
.has-error .select2-dropdown,
.has-error .select2-selection {
border-color: #dc3545;
}
.has-error .select2-container--focus .select2-selection,
.has-error .select2-container--open .select2-selection {
border-color: #bd2130;
}
.has-error.select2-drop-active {
border-color: #bd2130;
}
.has-error.select2-drop-active.select2-drop.select2-drop-above {
border-top-color: #bd2130;
}
.has-success .select2-dropdown,
.has-success .select2-selection {
border-color: #28a745;
}
.has-success .select2-container--focus .select2-selection,
.has-success .select2-container--open .select2-selection {
border-color: #1e7e34;
}
.has-success.select2-drop-active {
border-color: #1e7e34;
}
.has-success.select2-drop-active.select2-drop.select2-drop-above {
border-top-color: #1e7e34;
}
.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap4>.selection>.select2-selection,
.input-group>.select2-hidden-accessible:first-child+.select2-container--bootstrap4>.selection>.select2-selection.form-control {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap4:not(:last-child)>.selection>.select2-selection,
.input-group>.select2-hidden-accessible:not(:first-child)+.select2-container--bootstrap4:not(:last-child)>.selection>.select2-selection.form-control {
border-radius: 0;
}
.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap4:last-child>.selection>.select2-selection,
.input-group>.select2-hidden-accessible:not(:first-child):not(:last-child)+.select2-container--bootstrap4:last-child>.selection>.select2-selection.form-control {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.input-group>.select2-container--bootstrap4 {
display: table;
table-layout: fixed;
position: relative;
z-index: 2;
width: 100%;
margin-bottom: 0;
}
.input-group>.select2-container--bootstrap4>.selection>.select2-selection.form-control {
float: none;
}
.input-group>.select2-container--bootstrap4.select2-container--open,
.input-group>.select2-container--bootstrap4.select2-container--focus {
z-index: 3;
}
.input-group>.select2-container--bootstrap4,
.input-group>.select2-container--bootstrap4 .input-group-btn,
.input-group>.select2-container--bootstrap4 .input-group-btn .btn {
vertical-align: top;
}
.form-control.select2-hidden-accessible {
position: absolute !important;
width: 1px !important;
}
@media (min-width: 576px) {
.form-inline .select2-container--bootstrap4 {
display: inline-block;
}
}
+8 -11
View File
@@ -118,12 +118,14 @@
.select2-hidden-accessible { .select2-hidden-accessible {
border: 0 !important; border: 0 !important;
clip: rect(0 0 0 0) !important; clip: rect(0 0 0 0) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important; height: 1px !important;
margin: -1px !important;
overflow: hidden !important; overflow: hidden !important;
padding: 0 !important; padding: 0 !important;
position: absolute !important; position: absolute !important;
width: 1px !important; } width: 1px !important;
white-space: nowrap !important; }
.select2-container--default .select2-selection--single { .select2-container--default .select2-selection--single {
background-color: #fff; background-color: #fff;
@@ -186,16 +188,13 @@
width: 100%; } width: 100%; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered li { .select2-container--default .select2-selection--multiple .select2-selection__rendered li {
list-style: none; } list-style: none; }
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
color: #999;
margin-top: 5px;
float: left; }
.select2-container--default .select2-selection--multiple .select2-selection__clear { .select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer; cursor: pointer;
float: right; float: right;
font-weight: bold; font-weight: bold;
margin-top: 5px; margin-top: 5px;
margin-right: 10px; } margin-right: 10px;
padding: 1px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice { .select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4; background-color: #e4e4e4;
border: 1px solid #aaa; border: 1px solid #aaa;
@@ -214,7 +213,7 @@
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #333; } color: #333; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right; } float: right; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
@@ -420,9 +419,7 @@
color: #555; } color: #555; }
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
float: right; } float: right;
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px; margin-left: 5px;
margin-right: auto; } margin-right: auto; }
+583 -220
View File
@@ -1,11 +1,11 @@
/*! /*!
* Select2 4.0.5 * Select2 4.0.13
* https://select2.github.io * https://select2.github.io
* *
* Released under the MIT license * Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md * https://github.com/select2/select2/blob/master/LICENSE.md
*/ */
(function (factory) { ;(function (factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module. // AMD. Register as an anonymous module.
define(['jquery'], factory); define(['jquery'], factory);
@@ -574,10 +574,10 @@ S2.define('select2/utils',[
DecoratedClass.prototype = new ctr(); DecoratedClass.prototype = new ctr();
for (var m = 0; m < superMethods.length; m++) { for (var m = 0; m < superMethods.length; m++) {
var superMethod = superMethods[m]; var superMethod = superMethods[m];
DecoratedClass.prototype[superMethod] = DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod]; SuperClass.prototype[superMethod];
} }
var calledMethod = function (methodName) { var calledMethod = function (methodName) {
@@ -772,6 +772,70 @@ S2.define('select2/utils',[
$element.append($nodes); $element.append($nodes);
}; };
// Cache objects in Utils.__cache instead of $.data (see #4346)
Utils.__cache = {};
var id = 0;
Utils.GetUniqueElementId = function (element) {
// Get a unique element Id. If element has no id,
// creates a new unique number, stores it in the id
// attribute and returns the new id.
// If an id already exists, it simply returns it.
var select2Id = element.getAttribute('data-select2-id');
if (select2Id == null) {
// If element has id, use it.
if (element.id) {
select2Id = element.id;
element.setAttribute('data-select2-id', select2Id);
} else {
element.setAttribute('data-select2-id', ++id);
select2Id = id.toString();
}
}
return select2Id;
};
Utils.StoreData = function (element, name, value) {
// Stores an item in the cache for a specified element.
// name is the cache key.
var id = Utils.GetUniqueElementId(element);
if (!Utils.__cache[id]) {
Utils.__cache[id] = {};
}
Utils.__cache[id][name] = value;
};
Utils.GetData = function (element, name) {
// Retrieves a value from the cache by its key (name)
// name is optional. If no name specified, return
// all cache items for the specified element.
// and for a specified element.
var id = Utils.GetUniqueElementId(element);
if (name) {
if (Utils.__cache[id]) {
if (Utils.__cache[id][name] != null) {
return Utils.__cache[id][name];
}
return $(element).data(name); // Fallback to HTML5 data attribs.
}
return $(element).data(name); // Fallback to HTML5 data attribs.
} else {
return Utils.__cache[id];
}
};
Utils.RemoveData = function (element) {
// Removes all cached items for a specified element.
var id = Utils.GetUniqueElementId(element);
if (Utils.__cache[id] != null) {
delete Utils.__cache[id];
}
element.removeAttribute('data-select2-id');
};
return Utils; return Utils;
}); });
@@ -791,7 +855,7 @@ S2.define('select2/results',[
Results.prototype.render = function () { Results.prototype.render = function () {
var $results = $( var $results = $(
'<ul class="select2-results__options" role="tree"></ul>' '<ul class="select2-results__options" role="listbox"></ul>'
); );
if (this.options.get('multiple')) { if (this.options.get('multiple')) {
@@ -814,7 +878,7 @@ S2.define('select2/results',[
this.hideLoading(); this.hideLoading();
var $message = $( var $message = $(
'<li role="treeitem" aria-live="assertive"' + '<li role="alert" aria-live="assertive"' +
' class="select2-results__option"></li>' ' class="select2-results__option"></li>'
); );
@@ -907,7 +971,7 @@ S2.define('select2/results',[
$options.each(function () { $options.each(function () {
var $option = $(this); var $option = $(this);
var item = $.data(this, 'data'); var item = Utils.GetData(this, 'data');
// id needs to be converted to a string when comparing // id needs to be converted to a string when comparing
var id = '' + item.id; var id = '' + item.id;
@@ -948,11 +1012,16 @@ S2.define('select2/results',[
option.className = 'select2-results__option'; option.className = 'select2-results__option';
var attrs = { var attrs = {
'role': 'treeitem', 'role': 'option',
'aria-selected': 'false' 'aria-selected': 'false'
}; };
if (data.disabled) { var matches = window.Element.prototype.matches ||
window.Element.prototype.msMatchesSelector ||
window.Element.prototype.webkitMatchesSelector;
if ((data.element != null && matches.call(data.element, ':disabled')) ||
(data.element == null && data.disabled)) {
delete attrs['aria-selected']; delete attrs['aria-selected'];
attrs['aria-disabled'] = 'true'; attrs['aria-disabled'] = 'true';
} }
@@ -1012,7 +1081,7 @@ S2.define('select2/results',[
this.template(data, option); this.template(data, option);
} }
$.data(option, 'data', data); Utils.StoreData(option, 'data', data);
return option; return option;
}; };
@@ -1053,7 +1122,10 @@ S2.define('select2/results',[
} }
self.setClasses(); self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
}); });
container.on('unselect', function () { container.on('unselect', function () {
@@ -1062,7 +1134,10 @@ S2.define('select2/results',[
} }
self.setClasses(); self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
}); });
container.on('open', function () { container.on('open', function () {
@@ -1098,7 +1173,7 @@ S2.define('select2/results',[
return; return;
} }
var data = $highlighted.data('data'); var data = Utils.GetData($highlighted[0], 'data');
if ($highlighted.attr('aria-selected') == 'true') { if ($highlighted.attr('aria-selected') == 'true') {
self.trigger('close', {}); self.trigger('close', {});
@@ -1116,8 +1191,9 @@ S2.define('select2/results',[
var currentIndex = $options.index($highlighted); var currentIndex = $options.index($highlighted);
// If we are already at te top, don't move further // If we are already at the top, don't move further
if (currentIndex === 0) { // If no options, currentIndex will be -1
if (currentIndex <= 0) {
return; return;
} }
@@ -1210,7 +1286,7 @@ S2.define('select2/results',[
function (evt) { function (evt) {
var $this = $(this); var $this = $(this);
var data = $this.data('data'); var data = Utils.GetData(this, 'data');
if ($this.attr('aria-selected') === 'true') { if ($this.attr('aria-selected') === 'true') {
if (self.options.get('multiple')) { if (self.options.get('multiple')) {
@@ -1233,7 +1309,7 @@ S2.define('select2/results',[
this.$results.on('mouseenter', '.select2-results__option[aria-selected]', this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
function (evt) { function (evt) {
var data = $(this).data('data'); var data = Utils.GetData(this, 'data');
self.getHighlightedResults() self.getHighlightedResults()
.removeClass('select2-results__option--highlighted'); .removeClass('select2-results__option--highlighted');
@@ -1348,14 +1424,15 @@ S2.define('select2/selection/base',[
this._tabindex = 0; this._tabindex = 0;
if (this.$element.data('old-tabindex') != null) { if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
this._tabindex = this.$element.data('old-tabindex'); this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
} else if (this.$element.attr('tabindex') != null) { } else if (this.$element.attr('tabindex') != null) {
this._tabindex = this.$element.attr('tabindex'); this._tabindex = this.$element.attr('tabindex');
} }
$selection.attr('title', this.$element.attr('title')); $selection.attr('title', this.$element.attr('title'));
$selection.attr('tabindex', this._tabindex); $selection.attr('tabindex', this._tabindex);
$selection.attr('aria-disabled', 'false');
this.$selection = $selection; this.$selection = $selection;
@@ -1365,7 +1442,6 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.bind = function (container, $container) { BaseSelection.prototype.bind = function (container, $container) {
var self = this; var self = this;
var id = container.id + '-container';
var resultsId = container.id + '-results'; var resultsId = container.id + '-results';
this.container = container; this.container = container;
@@ -1408,17 +1484,19 @@ S2.define('select2/selection/base',[
self.$selection.removeAttr('aria-activedescendant'); self.$selection.removeAttr('aria-activedescendant');
self.$selection.removeAttr('aria-owns'); self.$selection.removeAttr('aria-owns');
self.$selection.focus(); self.$selection.trigger('focus');
self._detachCloseHandler(container); self._detachCloseHandler(container);
}); });
container.on('enable', function () { container.on('enable', function () {
self.$selection.attr('tabindex', self._tabindex); self.$selection.attr('tabindex', self._tabindex);
self.$selection.attr('aria-disabled', 'false');
}); });
container.on('disable', function () { container.on('disable', function () {
self.$selection.attr('tabindex', '-1'); self.$selection.attr('tabindex', '-1');
self.$selection.attr('aria-disabled', 'true');
}); });
}; };
@@ -1441,7 +1519,6 @@ S2.define('select2/selection/base',[
}; };
BaseSelection.prototype._attachCloseHandler = function (container) { BaseSelection.prototype._attachCloseHandler = function (container) {
var self = this;
$(document.body).on('mousedown.select2.' + container.id, function (e) { $(document.body).on('mousedown.select2.' + container.id, function (e) {
var $target = $(e.target); var $target = $(e.target);
@@ -1451,13 +1528,11 @@ S2.define('select2/selection/base',[
var $all = $('.select2.select2-container--open'); var $all = $('.select2.select2-container--open');
$all.each(function () { $all.each(function () {
var $this = $(this);
if (this == $select[0]) { if (this == $select[0]) {
return; return;
} }
var $element = $this.data('element'); var $element = Utils.GetData(this, 'element');
$element.select2('close'); $element.select2('close');
}); });
@@ -1481,6 +1556,27 @@ S2.define('select2/selection/base',[
throw new Error('The `update` method must be defined in child classes.'); throw new Error('The `update` method must be defined in child classes.');
}; };
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
BaseSelection.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
BaseSelection.prototype.isDisabled = function () {
return this.options.get('disabled');
};
return BaseSelection; return BaseSelection;
}); });
@@ -1518,7 +1614,10 @@ S2.define('select2/selection/single',[
var id = container.id + '-container'; var id = container.id + '-container';
this.$selection.find('.select2-selection__rendered').attr('id', id); this.$selection.find('.select2-selection__rendered')
.attr('id', id)
.attr('role', 'textbox')
.attr('aria-readonly', 'true');
this.$selection.attr('aria-labelledby', id); this.$selection.attr('aria-labelledby', id);
this.$selection.on('mousedown', function (evt) { this.$selection.on('mousedown', function (evt) {
@@ -1542,17 +1641,15 @@ S2.define('select2/selection/single',[
container.on('focus', function (evt) { container.on('focus', function (evt) {
if (!container.isOpen()) { if (!container.isOpen()) {
self.$selection.focus(); self.$selection.trigger('focus');
} }
}); });
container.on('selection:update', function (params) {
self.update(params.data);
});
}; };
SingleSelection.prototype.clear = function () { SingleSelection.prototype.clear = function () {
this.$selection.find('.select2-selection__rendered').empty(); var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title'); // clear tooltip on empty
}; };
SingleSelection.prototype.display = function (data, container) { SingleSelection.prototype.display = function (data, container) {
@@ -1578,7 +1675,14 @@ S2.define('select2/selection/single',[
var formatted = this.display(selection, $rendered); var formatted = this.display(selection, $rendered);
$rendered.empty().append(formatted); $rendered.empty().append(formatted);
$rendered.prop('title', selection.title || selection.text);
var title = selection.title || selection.text;
if (title) {
$rendered.attr('title', title);
} else {
$rendered.removeAttr('title');
}
}; };
return SingleSelection; return SingleSelection;
@@ -1623,14 +1727,14 @@ S2.define('select2/selection/multiple',[
'.select2-selection__choice__remove', '.select2-selection__choice__remove',
function (evt) { function (evt) {
// Ignore the event if it is disabled // Ignore the event if it is disabled
if (self.options.get('disabled')) { if (self.isDisabled()) {
return; return;
} }
var $remove = $(this); var $remove = $(this);
var $selection = $remove.parent(); var $selection = $remove.parent();
var data = $selection.data('data'); var data = Utils.GetData($selection[0], 'data');
self.trigger('unselect', { self.trigger('unselect', {
originalEvent: evt, originalEvent: evt,
@@ -1641,7 +1745,9 @@ S2.define('select2/selection/multiple',[
}; };
MultipleSelection.prototype.clear = function () { MultipleSelection.prototype.clear = function () {
this.$selection.find('.select2-selection__rendered').empty(); var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title');
}; };
MultipleSelection.prototype.display = function (data, container) { MultipleSelection.prototype.display = function (data, container) {
@@ -1679,9 +1785,14 @@ S2.define('select2/selection/multiple',[
var formatted = this.display(selection, $selection); var formatted = this.display(selection, $selection);
$selection.append(formatted); $selection.append(formatted);
$selection.prop('title', selection.title || selection.text);
$selection.data('data', selection); var title = selection.title || selection.text;
if (title) {
$selection.attr('title', title);
}
Utils.StoreData($selection[0], 'data', selection);
$selections.push($selection); $selections.push($selection);
} }
@@ -1746,8 +1857,9 @@ S2.define('select2/selection/placeholder',[
S2.define('select2/selection/allowClear',[ S2.define('select2/selection/allowClear',[
'jquery', 'jquery',
'../keys' '../keys',
], function ($, KEYS) { '../utils'
], function ($, KEYS, Utils) {
function AllowClear () { } function AllowClear () { }
AllowClear.prototype.bind = function (decorated, container, $container) { AllowClear.prototype.bind = function (decorated, container, $container) {
@@ -1776,7 +1888,7 @@ S2.define('select2/selection/allowClear',[
AllowClear.prototype._handleClear = function (_, evt) { AllowClear.prototype._handleClear = function (_, evt) {
// Ignore the event if it is disabled // Ignore the event if it is disabled
if (this.options.get('disabled')) { if (this.isDisabled()) {
return; return;
} }
@@ -1789,10 +1901,22 @@ S2.define('select2/selection/allowClear',[
evt.stopPropagation(); evt.stopPropagation();
var data = $clear.data('data'); var data = Utils.GetData($clear[0], 'data');
var previousVal = this.$element.val();
this.$element.val(this.placeholder.id);
var unselectData = {
data: data
};
this.trigger('clear', unselectData);
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
for (var d = 0; d < data.length; d++) { for (var d = 0; d < data.length; d++) {
var unselectData = { unselectData = {
data: data[d] data: data[d]
}; };
@@ -1802,11 +1926,12 @@ S2.define('select2/selection/allowClear',[
// If the event was prevented, don't clear it out. // If the event was prevented, don't clear it out.
if (unselectData.prevented) { if (unselectData.prevented) {
this.$element.val(previousVal);
return; return;
} }
} }
this.$element.val(this.placeholder.id).trigger('change'); this.$element.trigger('input').trigger('change');
this.trigger('toggle', {}); this.trigger('toggle', {});
}; };
@@ -1829,12 +1954,14 @@ S2.define('select2/selection/allowClear',[
return; return;
} }
var removeAll = this.options.get('translations').get('removeAllItems');
var $remove = $( var $remove = $(
'<span class="select2-selection__clear">' + '<span class="select2-selection__clear" title="' + removeAll() +'">' +
'&times;' + '&times;' +
'</span>' '</span>'
); );
$remove.data('data', data); Utils.StoreData($remove[0], 'data', data);
this.$selection.find('.select2-selection__rendered').prepend($remove); this.$selection.find('.select2-selection__rendered').prepend($remove);
}; };
@@ -1856,7 +1983,7 @@ S2.define('select2/selection/search',[
'<li class="select2-search select2-search--inline">' + '<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' + '<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' + ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' + ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</li>' '</li>'
); );
@@ -1873,14 +2000,18 @@ S2.define('select2/selection/search',[
Search.prototype.bind = function (decorated, container, $container) { Search.prototype.bind = function (decorated, container, $container) {
var self = this; var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container); decorated.call(this, container, $container);
container.on('open', function () { container.on('open', function () {
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus'); self.$search.trigger('focus');
}); });
container.on('close', function () { container.on('close', function () {
self.$search.val(''); self.$search.val('');
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant'); self.$search.removeAttr('aria-activedescendant');
self.$search.trigger('focus'); self.$search.trigger('focus');
}); });
@@ -1900,7 +2031,11 @@ S2.define('select2/selection/search',[
}); });
container.on('results:focus', function (params) { container.on('results:focus', function (params) {
self.$search.attr('aria-activedescendant', params.id); if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
}); });
this.$selection.on('focusin', '.select2-search--inline', function (evt) { this.$selection.on('focusin', '.select2-search--inline', function (evt) {
@@ -1925,7 +2060,7 @@ S2.define('select2/selection/search',[
.prev('.select2-selection__choice'); .prev('.select2-selection__choice');
if ($previousChoice.length > 0) { if ($previousChoice.length > 0) {
var item = $previousChoice.data('data'); var item = Utils.GetData($previousChoice[0], 'data');
self.searchRemoveChoice(item); self.searchRemoveChoice(item);
@@ -1934,6 +2069,12 @@ S2.define('select2/selection/search',[
} }
}); });
this.$selection.on('click', '.select2-search--inline', function (evt) {
if (self.$search.val()) {
evt.stopPropagation();
}
});
// Try to detect the IE version should the `documentMode` property that // Try to detect the IE version should the `documentMode` property that
// is stored on the document. This is only implemented in IE and is // is stored on the document. This is only implemented in IE and is
// slightly cleaner than doing a user agent check. // slightly cleaner than doing a user agent check.
@@ -2019,7 +2160,7 @@ S2.define('select2/selection/search',[
this.resizeSearch(); this.resizeSearch();
if (searchHadFocus) { if (searchHadFocus) {
this.$search.focus(); this.$search.trigger('focus');
} }
}; };
@@ -2052,7 +2193,7 @@ S2.define('select2/selection/search',[
var width = ''; var width = '';
if (this.$search.attr('placeholder') !== '') { if (this.$search.attr('placeholder') !== '') {
width = this.$selection.find('.select2-selection__rendered').innerWidth(); width = this.$selection.find('.select2-selection__rendered').width();
} else { } else {
var minimumWidth = this.$search.val().length + 1; var minimumWidth = this.$search.val().length + 1;
@@ -2076,10 +2217,13 @@ S2.define('select2/selection/eventRelay',[
'open', 'opening', 'open', 'opening',
'close', 'closing', 'close', 'closing',
'select', 'selecting', 'select', 'selecting',
'unselect', 'unselecting' 'unselect', 'unselecting',
'clear', 'clearing'
]; ];
var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting']; var preventableEvents = [
'opening', 'closing', 'selecting', 'unselecting', 'clearing'
];
decorated.call(this, container, $container); decorated.call(this, container, $container);
@@ -2412,6 +2556,7 @@ S2.define('select2/diacritics',[
'\u019F': 'O', '\u019F': 'O',
'\uA74A': 'O', '\uA74A': 'O',
'\uA74C': 'O', '\uA74C': 'O',
'\u0152': 'OE',
'\u01A2': 'OI', '\u01A2': 'OI',
'\uA74E': 'OO', '\uA74E': 'OO',
'\u0222': 'OU', '\u0222': 'OU',
@@ -2821,6 +2966,7 @@ S2.define('select2/diacritics',[
'\uA74B': 'o', '\uA74B': 'o',
'\uA74D': 'o', '\uA74D': 'o',
'\u0275': 'o', '\u0275': 'o',
'\u0153': 'oe',
'\u01A3': 'oi', '\u01A3': 'oi',
'\u0223': 'ou', '\u0223': 'ou',
'\uA74F': 'oo', '\uA74F': 'oo',
@@ -2989,8 +3135,9 @@ S2.define('select2/diacritics',[
'\u03CD': '\u03C5', '\u03CD': '\u03C5',
'\u03CB': '\u03C5', '\u03CB': '\u03C5',
'\u03B0': '\u03C5', '\u03B0': '\u03C5',
'\u03C9': '\u03C9', '\u03CE': '\u03C9',
'\u03C2': '\u03C3' '\u03C2': '\u03C3',
'\u2019': '\''
}; };
return diacritics; return diacritics;
@@ -3075,7 +3222,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) { if ($(data.element).is('option')) {
data.element.selected = true; data.element.selected = true;
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
return; return;
} }
@@ -3096,13 +3243,13 @@ S2.define('select2/data/select',[
} }
self.$element.val(val); self.$element.val(val);
self.$element.trigger('change'); self.$element.trigger('input').trigger('change');
}); });
} else { } else {
var val = data.id; var val = data.id;
this.$element.val(val); this.$element.val(val);
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
} }
}; };
@@ -3118,7 +3265,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) { if ($(data.element).is('option')) {
data.element.selected = false; data.element.selected = false;
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
return; return;
} }
@@ -3136,7 +3283,7 @@ S2.define('select2/data/select',[
self.$element.val(val); self.$element.val(val);
self.$element.trigger('change'); self.$element.trigger('input').trigger('change');
}); });
}; };
@@ -3158,7 +3305,7 @@ S2.define('select2/data/select',[
// Remove anything added to child elements // Remove anything added to child elements
this.$element.find('*').each(function () { this.$element.find('*').each(function () {
// Remove any custom data set by Select2 // Remove any custom data set by Select2
$.removeData(this, 'data'); Utils.RemoveData(this);
}); });
}; };
@@ -3231,7 +3378,7 @@ S2.define('select2/data/select',[
normalizedData.element = option; normalizedData.element = option;
// Override the option's data with the combined data // Override the option's data with the combined data
$.data(option, 'data', normalizedData); Utils.StoreData(option, 'data', normalizedData);
return $option; return $option;
}; };
@@ -3239,7 +3386,7 @@ S2.define('select2/data/select',[
SelectAdapter.prototype.item = function ($option) { SelectAdapter.prototype.item = function ($option) {
var data = {}; var data = {};
data = $.data($option[0], 'data'); data = Utils.GetData($option[0], 'data');
if (data != null) { if (data != null) {
return data; return data;
@@ -3277,13 +3424,13 @@ S2.define('select2/data/select',[
data = this._normalizeItem(data); data = this._normalizeItem(data);
data.element = $option[0]; data.element = $option[0];
$.data($option[0], 'data', data); Utils.StoreData($option[0], 'data', data);
return data; return data;
}; };
SelectAdapter.prototype._normalizeItem = function (item) { SelectAdapter.prototype._normalizeItem = function (item) {
if (!$.isPlainObject(item)) { if (item !== Object(item)) {
item = { item = {
id: item, id: item,
text: item text: item
@@ -3329,15 +3476,19 @@ S2.define('select2/data/array',[
'jquery' 'jquery'
], function (SelectAdapter, Utils, $) { ], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) { function ArrayAdapter ($element, options) {
var data = options.get('data') || []; this._dataToConvert = options.get('data') || [];
ArrayAdapter.__super__.constructor.call(this, $element, options); ArrayAdapter.__super__.constructor.call(this, $element, options);
this.addOptions(this.convertToOptions(data));
} }
Utils.Extend(ArrayAdapter, SelectAdapter); Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.bind = function (container, $container) {
ArrayAdapter.__super__.bind.call(this, container, $container);
this.addOptions(this.convertToOptions(this._dataToConvert));
};
ArrayAdapter.prototype.select = function (data) { ArrayAdapter.prototype.select = function (data) {
var $option = this.$element.find('option').filter(function (i, elm) { var $option = this.$element.find('option').filter(function (i, elm) {
return elm.value == data.id.toString(); return elm.value == data.id.toString();
@@ -3487,7 +3638,8 @@ S2.define('select2/data/ajax',[
}, function () { }, function () {
// Attempt to detect if a request was aborted // Attempt to detect if a request was aborted
// Only works if the transport exposes a status property // Only works if the transport exposes a status property
if ($request.status && $request.status === '0') { if ('status' in $request &&
($request.status === 0 || $request.status === '0')) {
return; return;
} }
@@ -3626,8 +3778,6 @@ S2.define('select2/data/tags',[
}; };
Tags.prototype._removeOldTags = function (_) { Tags.prototype._removeOldTags = function (_) {
var tag = this._lastTag;
var $options = this.$element.find('option[data-select2-tag]'); var $options = this.$element.find('option[data-select2-tag]');
$options.each(function () { $options.each(function () {
@@ -3702,7 +3852,7 @@ S2.define('select2/data/tokenizer',[
// Replace the search term if we have the search box // Replace the search term if we have the search box
if (this.$search.length) { if (this.$search.length) {
this.$search.val(tokenData.term); this.$search.val(tokenData.term);
this.$search.focus(); this.$search.trigger('focus');
} }
params.term = tokenData.term; params.term = tokenData.term;
@@ -3831,10 +3981,30 @@ S2.define('select2/data/maximumSelectionLength',[
decorated.call(this, $e, options); decorated.call(this, $e, options);
} }
MaximumSelectionLength.prototype.bind =
function (decorated, container, $container) {
var self = this;
decorated.call(this, container, $container);
container.on('select', function () {
self._checkIfMaximumSelected();
});
};
MaximumSelectionLength.prototype.query = MaximumSelectionLength.prototype.query =
function (decorated, params, callback) { function (decorated, params, callback) {
var self = this; var self = this;
this._checkIfMaximumSelected(function () {
decorated.call(self, params, callback);
});
};
MaximumSelectionLength.prototype._checkIfMaximumSelected =
function (_, successCallback) {
var self = this;
this.current(function (currentData) { this.current(function (currentData) {
var count = currentData != null ? currentData.length : 0; var count = currentData != null ? currentData.length : 0;
if (self.maximumSelectionLength > 0 && if (self.maximumSelectionLength > 0 &&
@@ -3847,7 +4017,10 @@ S2.define('select2/data/maximumSelectionLength',[
}); });
return; return;
} }
decorated.call(self, params, callback);
if (successCallback) {
successCallback();
}
}); });
}; };
@@ -3886,7 +4059,7 @@ S2.define('select2/dropdown',[
}; };
Dropdown.prototype.position = function ($dropdown, $container) { Dropdown.prototype.position = function ($dropdown, $container) {
// Should be implmented in subclasses // Should be implemented in subclasses
}; };
Dropdown.prototype.destroy = function () { Dropdown.prototype.destroy = function () {
@@ -3910,7 +4083,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' + '<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="search" tabindex="-1"' + '<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' + ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" />' + ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</span>' '</span>'
); );
@@ -3925,6 +4098,8 @@ S2.define('select2/dropdown/search',[
Search.prototype.bind = function (decorated, container, $container) { Search.prototype.bind = function (decorated, container, $container) {
var self = this; var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container); decorated.call(this, container, $container);
this.$search.on('keydown', function (evt) { this.$search.on('keydown', function (evt) {
@@ -3947,23 +4122,27 @@ S2.define('select2/dropdown/search',[
container.on('open', function () { container.on('open', function () {
self.$search.attr('tabindex', 0); self.$search.attr('tabindex', 0);
self.$search.attr('aria-controls', resultsId);
self.$search.focus(); self.$search.trigger('focus');
window.setTimeout(function () { window.setTimeout(function () {
self.$search.focus(); self.$search.trigger('focus');
}, 0); }, 0);
}); });
container.on('close', function () { container.on('close', function () {
self.$search.attr('tabindex', -1); self.$search.attr('tabindex', -1);
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.val(''); self.$search.val('');
self.$search.trigger('blur');
}); });
container.on('focus', function () { container.on('focus', function () {
if (!container.isOpen()) { if (!container.isOpen()) {
self.$search.focus(); self.$search.trigger('focus');
} }
}); });
@@ -3978,6 +4157,14 @@ S2.define('select2/dropdown/search',[
} }
} }
}); });
container.on('results:focus', function (params) {
if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
});
}; };
Search.prototype.handleSearch = function (evt) { Search.prototype.handleSearch = function (evt) {
@@ -4062,6 +4249,7 @@ S2.define('select2/dropdown/infiniteScroll',[
if (this.showLoadingMore(data)) { if (this.showLoadingMore(data)) {
this.$results.append(this.$loadingMore); this.$results.append(this.$loadingMore);
this.loadMoreIfNeeded();
} }
}; };
@@ -4080,25 +4268,27 @@ S2.define('select2/dropdown/infiniteScroll',[
self.loading = true; self.loading = true;
}); });
this.$results.on('scroll', function () { this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
var isLoadMoreVisible = $.contains( };
document.documentElement,
self.$loadingMore[0]
);
if (self.loading || !isLoadMoreVisible) { InfiniteScroll.prototype.loadMoreIfNeeded = function () {
return; var isLoadMoreVisible = $.contains(
} document.documentElement,
this.$loadingMore[0]
);
var currentOffset = self.$results.offset().top + if (this.loading || !isLoadMoreVisible) {
self.$results.outerHeight(false); return;
var loadingMoreOffset = self.$loadingMore.offset().top + }
self.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) { var currentOffset = this.$results.offset().top +
self.loadMore(); this.$results.outerHeight(false);
} var loadingMoreOffset = this.$loadingMore.offset().top +
}); this.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) {
this.loadMore();
}
}; };
InfiniteScroll.prototype.loadMore = function () { InfiniteScroll.prototype.loadMore = function () {
@@ -4119,7 +4309,7 @@ S2.define('select2/dropdown/infiniteScroll',[
var $option = $( var $option = $(
'<li ' + '<li ' +
'class="select2-results__option select2-results__option--load-more"' + 'class="select2-results__option select2-results__option--load-more"' +
'role="treeitem" aria-disabled="true"></li>' 'role="option" aria-disabled="true"></li>'
); );
var message = this.options.get('translations').get('loadingMore'); var message = this.options.get('translations').get('loadingMore');
@@ -4137,7 +4327,7 @@ S2.define('select2/dropdown/attachBody',[
'../utils' '../utils'
], function ($, Utils) { ], function ($, Utils) {
function AttachBody (decorated, $element, options) { function AttachBody (decorated, $element, options) {
this.$dropdownParent = options.get('dropdownParent') || $(document.body); this.$dropdownParent = $(options.get('dropdownParent') || document.body);
decorated.call(this, $element, options); decorated.call(this, $element, options);
} }
@@ -4145,27 +4335,14 @@ S2.define('select2/dropdown/attachBody',[
AttachBody.prototype.bind = function (decorated, container, $container) { AttachBody.prototype.bind = function (decorated, container, $container) {
var self = this; var self = this;
var setupResultsEvents = false;
decorated.call(this, container, $container); decorated.call(this, container, $container);
container.on('open', function () { container.on('open', function () {
self._showDropdown(); self._showDropdown();
self._attachPositioningHandler(container); self._attachPositioningHandler(container);
if (!setupResultsEvents) { // Must bind after the results handlers to ensure correct sizing
setupResultsEvents = true; self._bindContainerResultHandlers(container);
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
}
}); });
container.on('close', function () { container.on('close', function () {
@@ -4214,6 +4391,44 @@ S2.define('select2/dropdown/attachBody',[
this.$dropdownContainer.detach(); this.$dropdownContainer.detach();
}; };
AttachBody.prototype._bindContainerResultHandlers =
function (decorated, container) {
// These should only be bound once
if (this._containerResultsHandlersBound) {
return;
}
var self = this;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:message', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('select', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('unselect', function () {
self._positionDropdown();
self._resizeDropdown();
});
this._containerResultsHandlersBound = true;
};
AttachBody.prototype._attachPositioningHandler = AttachBody.prototype._attachPositioningHandler =
function (decorated, container) { function (decorated, container) {
var self = this; var self = this;
@@ -4224,14 +4439,14 @@ S2.define('select2/dropdown/attachBody',[
var $watchers = this.$container.parents().filter(Utils.hasScroll); var $watchers = this.$container.parents().filter(Utils.hasScroll);
$watchers.each(function () { $watchers.each(function () {
$(this).data('select2-scroll-position', { Utils.StoreData(this, 'select2-scroll-position', {
x: $(this).scrollLeft(), x: $(this).scrollLeft(),
y: $(this).scrollTop() y: $(this).scrollTop()
}); });
}); });
$watchers.on(scrollEvent, function (ev) { $watchers.on(scrollEvent, function (ev) {
var position = $(this).data('select2-scroll-position'); var position = Utils.GetData(this, 'select2-scroll-position');
$(this).scrollTop(position.y); $(this).scrollTop(position.y);
}); });
@@ -4290,16 +4505,26 @@ S2.define('select2/dropdown/attachBody',[
top: container.bottom top: container.bottom
}; };
// Determine what the parent element is to use for calciulating the offset // Determine what the parent element is to use for calculating the offset
var $offsetParent = this.$dropdownParent; var $offsetParent = this.$dropdownParent;
// For statically positoned elements, we need to get the element // For statically positioned elements, we need to get the element
// that is determining the offset // that is determining the offset
if ($offsetParent.css('position') === 'static') { if ($offsetParent.css('position') === 'static') {
$offsetParent = $offsetParent.offsetParent(); $offsetParent = $offsetParent.offsetParent();
} }
var parentOffset = $offsetParent.offset(); var parentOffset = {
top: 0,
left: 0
};
if (
$.contains(document.body, $offsetParent[0]) ||
$offsetParent[0].isConnected
) {
parentOffset = $offsetParent.offset();
}
css.top -= parentOffset.top; css.top -= parentOffset.top;
css.left -= parentOffset.left; css.left -= parentOffset.left;
@@ -4396,8 +4621,8 @@ S2.define('select2/dropdown/minimumResultsForSearch',[
}); });
S2.define('select2/dropdown/selectOnClose',[ S2.define('select2/dropdown/selectOnClose',[
'../utils'
], function () { ], function (Utils) {
function SelectOnClose () { } function SelectOnClose () { }
SelectOnClose.prototype.bind = function (decorated, container, $container) { SelectOnClose.prototype.bind = function (decorated, container, $container) {
@@ -4428,7 +4653,7 @@ S2.define('select2/dropdown/selectOnClose',[
return; return;
} }
var data = $highlightedResults.data('data'); var data = Utils.GetData($highlightedResults[0], 'data');
// Don't re-select already selected resulte // Don't re-select already selected resulte
if ( if (
@@ -4469,7 +4694,7 @@ S2.define('select2/dropdown/closeOnSelect',[
var originalEvent = evt.originalEvent; var originalEvent = evt.originalEvent;
// Don't close if the control key is being held // Don't close if the control key is being held
if (originalEvent && originalEvent.ctrlKey) { if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
return; return;
} }
@@ -4523,6 +4748,9 @@ S2.define('select2/i18n/en',[],function () {
}, },
searching: function () { searching: function () {
return 'Searching…'; return 'Searching…';
},
removeAllItems: function () {
return 'Remove all items';
} }
}; };
}); });
@@ -4761,66 +4989,29 @@ S2.define('select2/defaults',[
); );
} }
if (typeof options.language === 'string') { // If the defaults were not previously applied from an element, it is
// Check if the language is specified with a region // possible for the language option to have not been resolved
if (options.language.indexOf('-') > 0) { options.language = this._resolveLanguage(options.language);
// Extract the region information if it is included
var languageParts = options.language.split('-');
var baseLanguage = languageParts[0];
options.language = [options.language, baseLanguage]; // Always fall back to English since it will always be complete
} else { options.language.push('en');
options.language = [options.language];
var uniqueLanguages = [];
for (var l = 0; l < options.language.length; l++) {
var language = options.language[l];
if (uniqueLanguages.indexOf(language) === -1) {
uniqueLanguages.push(language);
} }
} }
if ($.isArray(options.language)) { options.language = uniqueLanguages;
var languages = new Translation();
options.language.push('en');
var languageNames = options.language; options.translations = this._processTranslations(
options.language,
for (var l = 0; l < languageNames.length; l++) { options.debug
var name = languageNames[l]; );
var language = {};
try {
// Try to load it with the original name
language = Translation.loadPath(name);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
name = this.defaults.amdLanguageBase + name;
language = Translation.loadPath(name);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files.
if (options.debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + name + '" could not be ' +
'automatically loaded. A fallback will be used instead.'
);
}
continue;
}
}
languages.extend(language);
}
options.translations = languages;
} else {
var baseTranslation = Translation.loadPath(
this.defaults.amdLanguageBase + 'en'
);
var customTranslation = new Translation(options.language);
customTranslation.extend(baseTranslation);
options.translations = customTranslation;
}
return options; return options;
}; };
@@ -4887,13 +5078,14 @@ S2.define('select2/defaults',[
debug: false, debug: false,
dropdownAutoWidth: false, dropdownAutoWidth: false,
escapeMarkup: Utils.escapeMarkup, escapeMarkup: Utils.escapeMarkup,
language: EnglishTranslation, language: {},
matcher: matcher, matcher: matcher,
minimumInputLength: 0, minimumInputLength: 0,
maximumInputLength: 0, maximumInputLength: 0,
maximumSelectionLength: 0, maximumSelectionLength: 0,
minimumResultsForSearch: 0, minimumResultsForSearch: 0,
selectOnClose: false, selectOnClose: false,
scrollAfterSelect: false,
sorter: function (data) { sorter: function (data) {
return data; return data;
}, },
@@ -4908,6 +5100,103 @@ S2.define('select2/defaults',[
}; };
}; };
Defaults.prototype.applyFromElement = function (options, $element) {
var optionLanguage = options.language;
var defaultLanguage = this.defaults.language;
var elementLanguage = $element.prop('lang');
var parentLanguage = $element.closest('[lang]').prop('lang');
var languages = Array.prototype.concat.call(
this._resolveLanguage(elementLanguage),
this._resolveLanguage(optionLanguage),
this._resolveLanguage(defaultLanguage),
this._resolveLanguage(parentLanguage)
);
options.language = languages;
return options;
};
Defaults.prototype._resolveLanguage = function (language) {
if (!language) {
return [];
}
if ($.isEmptyObject(language)) {
return [];
}
if ($.isPlainObject(language)) {
return [language];
}
var languages;
if (!$.isArray(language)) {
languages = [language];
} else {
languages = language;
}
var resolvedLanguages = [];
for (var l = 0; l < languages.length; l++) {
resolvedLanguages.push(languages[l]);
if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = languages[l].split('-');
var baseLanguage = languageParts[0];
resolvedLanguages.push(baseLanguage);
}
}
return resolvedLanguages;
};
Defaults.prototype._processTranslations = function (languages, debug) {
var translations = new Translation();
for (var l = 0; l < languages.length; l++) {
var languageData = new Translation();
var language = languages[l];
if (typeof language === 'string') {
try {
// Try to load it with the original name
languageData = Translation.loadPath(language);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
language = this.defaults.amdLanguageBase + language;
languageData = Translation.loadPath(language);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files
if (debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + language + '" could ' +
'not be automatically loaded. A fallback will be used instead.'
);
}
}
}
} else if ($.isPlainObject(language)) {
languageData = new Translation(language);
} else {
languageData = language;
}
translations.extend(languageData);
}
return translations;
};
Defaults.prototype.set = function (key, value) { Defaults.prototype.set = function (key, value) {
var camelKey = $.camelCase(key); var camelKey = $.camelCase(key);
@@ -4916,7 +5205,7 @@ S2.define('select2/defaults',[
var convertedData = Utils._convertData(data); var convertedData = Utils._convertData(data);
$.extend(this.defaults, convertedData); $.extend(true, this.defaults, convertedData);
}; };
var defaults = new Defaults(); var defaults = new Defaults();
@@ -4937,6 +5226,10 @@ S2.define('select2/options',[
this.fromElement($element); this.fromElement($element);
} }
if ($element != null) {
this.options = Defaults.applyFromElement(this.options, $element);
}
this.options = Defaults.apply(this.options); this.options = Defaults.apply(this.options);
if ($element && $element.is('input')) { if ($element && $element.is('input')) {
@@ -4960,14 +5253,6 @@ S2.define('select2/options',[
this.options.disabled = $e.prop('disabled'); this.options.disabled = $e.prop('disabled');
} }
if (this.options.language == null) {
if ($e.prop('lang')) {
this.options.language = $e.prop('lang').toLowerCase();
} else if ($e.closest('[lang]').prop('lang')) {
this.options.language = $e.closest('[lang]').prop('lang');
}
}
if (this.options.dir == null) { if (this.options.dir == null) {
if ($e.prop('dir')) { if ($e.prop('dir')) {
this.options.dir = $e.prop('dir'); this.options.dir = $e.prop('dir');
@@ -4981,7 +5266,7 @@ S2.define('select2/options',[
$e.prop('disabled', this.options.disabled); $e.prop('disabled', this.options.disabled);
$e.prop('multiple', this.options.multiple); $e.prop('multiple', this.options.multiple);
if ($e.data('select2Tags')) { if (Utils.GetData($e[0], 'select2Tags')) {
if (this.options.debug && window.console && console.warn) { if (this.options.debug && window.console && console.warn) {
console.warn( console.warn(
'Select2: The `data-select2-tags` attribute has been changed to ' + 'Select2: The `data-select2-tags` attribute has been changed to ' +
@@ -4990,11 +5275,11 @@ S2.define('select2/options',[
); );
} }
$e.data('data', $e.data('select2Tags')); Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
$e.data('tags', true); Utils.StoreData($e[0], 'tags', true);
} }
if ($e.data('ajaxUrl')) { if (Utils.GetData($e[0], 'ajaxUrl')) {
if (this.options.debug && window.console && console.warn) { if (this.options.debug && window.console && console.warn) {
console.warn( console.warn(
'Select2: The `data-ajax-url` attribute has been changed to ' + 'Select2: The `data-ajax-url` attribute has been changed to ' +
@@ -5003,21 +5288,45 @@ S2.define('select2/options',[
); );
} }
$e.attr('ajax--url', $e.data('ajaxUrl')); $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
$e.data('ajax--url', $e.data('ajaxUrl')); Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
} }
var dataset = {}; var dataset = {};
function upperCaseLetter(_, letter) {
return letter.toUpperCase();
}
// Pre-load all of the attributes which are prefixed with `data-`
for (var attr = 0; attr < $e[0].attributes.length; attr++) {
var attributeName = $e[0].attributes[attr].name;
var prefix = 'data-';
if (attributeName.substr(0, prefix.length) == prefix) {
// Get the contents of the attribute after `data-`
var dataName = attributeName.substring(prefix.length);
// Get the data contents from the consistent source
// This is more than likely the jQuery data helper
var dataValue = Utils.GetData($e[0], dataName);
// camelCase the attribute name to match the spec
var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
// Store the data attribute contents into the dataset since
dataset[camelDataName] = dataValue;
}
}
// Prefer the element's `dataset` attribute if it exists // Prefer the element's `dataset` attribute if it exists
// jQuery 1.x does not correctly handle data attributes with multiple dashes // jQuery 1.x does not correctly handle data attributes with multiple dashes
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
dataset = $.extend(true, {}, $e[0].dataset, $e.data()); dataset = $.extend(true, {}, $e[0].dataset, dataset);
} else {
dataset = $e.data();
} }
var data = $.extend(true, {}, dataset); // Prefer our internal data cache if it exists
var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
data = Utils._convertData(data); data = Utils._convertData(data);
@@ -5054,8 +5363,8 @@ S2.define('select2/core',[
'./keys' './keys'
], function ($, Options, Utils, KEYS) { ], function ($, Options, Utils, KEYS) {
var Select2 = function ($element, options) { var Select2 = function ($element, options) {
if ($element.data('select2') != null) { if (Utils.GetData($element[0], 'select2') != null) {
$element.data('select2').destroy(); Utils.GetData($element[0], 'select2').destroy();
} }
this.$element = $element; this.$element = $element;
@@ -5071,7 +5380,7 @@ S2.define('select2/core',[
// Set up the tabindex // Set up the tabindex
var tabindex = $element.attr('tabindex') || 0; var tabindex = $element.attr('tabindex') || 0;
$element.data('old-tabindex', tabindex); Utils.StoreData($element[0], 'old-tabindex', tabindex);
$element.attr('tabindex', '-1'); $element.attr('tabindex', '-1');
// Set up containers and adapters // Set up containers and adapters
@@ -5132,6 +5441,9 @@ S2.define('select2/core',[
// Synchronize any monitored attributes // Synchronize any monitored attributes
this._syncAttributes(); this._syncAttributes();
Utils.StoreData($element[0], 'select2', this);
// Ensure backwards compatibility with $element.data('select2').
$element.data('select2', this); $element.data('select2', this);
}; };
@@ -5208,6 +5520,12 @@ S2.define('select2/core',[
return null; return null;
} }
if (method == 'computedstyle') {
var computedStyle = window.getComputedStyle($element[0]);
return computedStyle.width;
}
return method; return method;
}; };
@@ -5248,8 +5566,8 @@ S2.define('select2/core',[
if (observer != null) { if (observer != null) {
this._observer = new observer(function (mutations) { this._observer = new observer(function (mutations) {
$.each(mutations, self._syncA); self._syncA();
$.each(mutations, self._syncS); self._syncS(null, mutations);
}); });
this._observer.observe(this.$element[0], { this._observer.observe(this.$element[0], {
attributes: true, attributes: true,
@@ -5371,7 +5689,7 @@ S2.define('select2/core',[
if (self.isOpen()) { if (self.isOpen()) {
if (key === KEYS.ESC || key === KEYS.TAB || if (key === KEYS.ESC || key === KEYS.TAB ||
(key === KEYS.UP && evt.altKey)) { (key === KEYS.UP && evt.altKey)) {
self.close(); self.close(evt);
evt.preventDefault(); evt.preventDefault();
} else if (key === KEYS.ENTER) { } else if (key === KEYS.ENTER) {
@@ -5405,7 +5723,7 @@ S2.define('select2/core',[
Select2.prototype._syncAttributes = function () { Select2.prototype._syncAttributes = function () {
this.options.set('disabled', this.$element.prop('disabled')); this.options.set('disabled', this.$element.prop('disabled'));
if (this.options.get('disabled')) { if (this.isDisabled()) {
if (this.isOpen()) { if (this.isOpen()) {
this.close(); this.close();
} }
@@ -5416,7 +5734,7 @@ S2.define('select2/core',[
} }
}; };
Select2.prototype._syncSubtree = function (evt, mutations) { Select2.prototype._isChangeMutation = function (evt, mutations) {
var changed = false; var changed = false;
var self = this; var self = this;
@@ -5444,7 +5762,22 @@ S2.define('select2/core',[
} }
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) { } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
changed = true; changed = true;
} else if ($.isArray(mutations)) {
$.each(mutations, function(evt, mutation) {
if (self._isChangeMutation(evt, mutation)) {
// We've found a change mutation.
// Let's escape from the loop and continue
changed = true;
return false;
}
});
} }
return changed;
};
Select2.prototype._syncSubtree = function (evt, mutations) {
var changed = this._isChangeMutation(evt, mutations);
var self = this;
// Only re-pull the data if we think there is a change // Only re-pull the data if we think there is a change
if (changed) { if (changed) {
@@ -5466,7 +5799,8 @@ S2.define('select2/core',[
'open': 'opening', 'open': 'opening',
'close': 'closing', 'close': 'closing',
'select': 'selecting', 'select': 'selecting',
'unselect': 'unselecting' 'unselect': 'unselecting',
'clear': 'clearing'
}; };
if (args === undefined) { if (args === undefined) {
@@ -5494,7 +5828,7 @@ S2.define('select2/core',[
}; };
Select2.prototype.toggleDropdown = function () { Select2.prototype.toggleDropdown = function () {
if (this.options.get('disabled')) { if (this.isDisabled()) {
return; return;
} }
@@ -5510,15 +5844,40 @@ S2.define('select2/core',[
return; return;
} }
if (this.isDisabled()) {
return;
}
this.trigger('query', {}); this.trigger('query', {});
}; };
Select2.prototype.close = function () { Select2.prototype.close = function (evt) {
if (!this.isOpen()) { if (!this.isOpen()) {
return; return;
} }
this.trigger('close', {}); this.trigger('close', { originalEvent : evt });
};
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
Select2.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
Select2.prototype.isDisabled = function () {
return this.options.get('disabled');
}; };
Select2.prototype.isOpen = function () { Select2.prototype.isOpen = function () {
@@ -5595,7 +5954,7 @@ S2.define('select2/core',[
}); });
} }
this.$element.val(newVal).trigger('change'); this.$element.val(newVal).trigger('input').trigger('change');
}; };
Select2.prototype.destroy = function () { Select2.prototype.destroy = function () {
@@ -5621,10 +5980,12 @@ S2.define('select2/core',[
this._syncS = null; this._syncS = null;
this.$element.off('.select2'); this.$element.off('.select2');
this.$element.attr('tabindex', this.$element.data('old-tabindex')); this.$element.attr('tabindex',
Utils.GetData(this.$element[0], 'old-tabindex'));
this.$element.removeClass('select2-hidden-accessible'); this.$element.removeClass('select2-hidden-accessible');
this.$element.attr('aria-hidden', 'false'); this.$element.attr('aria-hidden', 'false');
Utils.RemoveData(this.$element[0]);
this.$element.removeData('select2'); this.$element.removeData('select2');
this.dataAdapter.destroy(); this.dataAdapter.destroy();
@@ -5652,7 +6013,7 @@ S2.define('select2/core',[
this.$container.addClass('select2-container--' + this.options.get('theme')); this.$container.addClass('select2-container--' + this.options.get('theme'));
$container.data('element', this.$element); Utils.StoreData($container[0], 'element', this.$element);
return $container; return $container;
}; };
@@ -5862,8 +6223,9 @@ S2.define('select2/compat/initSelection',[
}); });
S2.define('select2/compat/inputData',[ S2.define('select2/compat/inputData',[
'jquery' 'jquery',
], function ($) { '../utils'
], function ($, Utils) {
function InputData (decorated, $element, options) { function InputData (decorated, $element, options) {
this._currentData = []; this._currentData = [];
this._valueSeparator = options.get('valueSeparator') || ','; this._valueSeparator = options.get('valueSeparator') || ',';
@@ -5927,13 +6289,13 @@ S2.define('select2/compat/inputData',[
}); });
this.$element.val(data.id); this.$element.val(data.id);
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
} else { } else {
var value = this.$element.val(); var value = this.$element.val();
value += this._valueSeparator + data.id; value += this._valueSeparator + data.id;
this.$element.val(value); this.$element.val(value);
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
} }
}; };
@@ -5956,7 +6318,7 @@ S2.define('select2/compat/inputData',[
} }
self.$element.val(values.join(self._valueSeparator)); self.$element.val(values.join(self._valueSeparator));
self.$element.trigger('change'); self.$element.trigger('input').trigger('change');
}); });
}; };
@@ -5980,7 +6342,7 @@ S2.define('select2/compat/inputData',[
InputData.prototype.addOptions = function (_, $options) { InputData.prototype.addOptions = function (_, $options) {
var options = $.map($options, function ($option) { var options = $.map($options, function ($option) {
return $.data($option[0], 'data'); return Utils.GetData($option[0], 'data');
}); });
this._currentData.push.apply(this._currentData, options); this._currentData.push.apply(this._currentData, options);
@@ -6383,8 +6745,9 @@ S2.define('jquery.select2',[
'jquery-mousewheel', 'jquery-mousewheel',
'./select2/core', './select2/core',
'./select2/defaults' './select2/defaults',
], function ($, _, Select2, Defaults) { './select2/utils'
], function ($, _, Select2, Defaults, Utils) {
if ($.fn.select2 == null) { if ($.fn.select2 == null) {
// All methods that should return the element // All methods that should return the element
var thisMethods = ['open', 'close', 'destroy']; var thisMethods = ['open', 'close', 'destroy'];
@@ -6405,7 +6768,7 @@ S2.define('jquery.select2',[
var args = Array.prototype.slice.call(arguments, 1); var args = Array.prototype.slice.call(arguments, 1);
this.each(function () { this.each(function () {
var instance = $(this).data('select2'); var instance = Utils.GetData(this, 'select2');
if (instance == null && window.console && console.error) { if (instance == null && window.console && console.error) {
console.error( console.error(
+2 -1
View File
File diff suppressed because one or more lines are too long
+576 -214
View File
@@ -1,11 +1,11 @@
/*! /*!
* Select2 4.0.5 * Select2 4.0.13
* https://select2.github.io * https://select2.github.io
* *
* Released under the MIT license * Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md * https://github.com/select2/select2/blob/master/LICENSE.md
*/ */
(function (factory) { ;(function (factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module. // AMD. Register as an anonymous module.
define(['jquery'], factory); define(['jquery'], factory);
@@ -574,10 +574,10 @@ S2.define('select2/utils',[
DecoratedClass.prototype = new ctr(); DecoratedClass.prototype = new ctr();
for (var m = 0; m < superMethods.length; m++) { for (var m = 0; m < superMethods.length; m++) {
var superMethod = superMethods[m]; var superMethod = superMethods[m];
DecoratedClass.prototype[superMethod] = DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod]; SuperClass.prototype[superMethod];
} }
var calledMethod = function (methodName) { var calledMethod = function (methodName) {
@@ -772,6 +772,70 @@ S2.define('select2/utils',[
$element.append($nodes); $element.append($nodes);
}; };
// Cache objects in Utils.__cache instead of $.data (see #4346)
Utils.__cache = {};
var id = 0;
Utils.GetUniqueElementId = function (element) {
// Get a unique element Id. If element has no id,
// creates a new unique number, stores it in the id
// attribute and returns the new id.
// If an id already exists, it simply returns it.
var select2Id = element.getAttribute('data-select2-id');
if (select2Id == null) {
// If element has id, use it.
if (element.id) {
select2Id = element.id;
element.setAttribute('data-select2-id', select2Id);
} else {
element.setAttribute('data-select2-id', ++id);
select2Id = id.toString();
}
}
return select2Id;
};
Utils.StoreData = function (element, name, value) {
// Stores an item in the cache for a specified element.
// name is the cache key.
var id = Utils.GetUniqueElementId(element);
if (!Utils.__cache[id]) {
Utils.__cache[id] = {};
}
Utils.__cache[id][name] = value;
};
Utils.GetData = function (element, name) {
// Retrieves a value from the cache by its key (name)
// name is optional. If no name specified, return
// all cache items for the specified element.
// and for a specified element.
var id = Utils.GetUniqueElementId(element);
if (name) {
if (Utils.__cache[id]) {
if (Utils.__cache[id][name] != null) {
return Utils.__cache[id][name];
}
return $(element).data(name); // Fallback to HTML5 data attribs.
}
return $(element).data(name); // Fallback to HTML5 data attribs.
} else {
return Utils.__cache[id];
}
};
Utils.RemoveData = function (element) {
// Removes all cached items for a specified element.
var id = Utils.GetUniqueElementId(element);
if (Utils.__cache[id] != null) {
delete Utils.__cache[id];
}
element.removeAttribute('data-select2-id');
};
return Utils; return Utils;
}); });
@@ -791,7 +855,7 @@ S2.define('select2/results',[
Results.prototype.render = function () { Results.prototype.render = function () {
var $results = $( var $results = $(
'<ul class="select2-results__options" role="tree"></ul>' '<ul class="select2-results__options" role="listbox"></ul>'
); );
if (this.options.get('multiple')) { if (this.options.get('multiple')) {
@@ -814,7 +878,7 @@ S2.define('select2/results',[
this.hideLoading(); this.hideLoading();
var $message = $( var $message = $(
'<li role="treeitem" aria-live="assertive"' + '<li role="alert" aria-live="assertive"' +
' class="select2-results__option"></li>' ' class="select2-results__option"></li>'
); );
@@ -907,7 +971,7 @@ S2.define('select2/results',[
$options.each(function () { $options.each(function () {
var $option = $(this); var $option = $(this);
var item = $.data(this, 'data'); var item = Utils.GetData(this, 'data');
// id needs to be converted to a string when comparing // id needs to be converted to a string when comparing
var id = '' + item.id; var id = '' + item.id;
@@ -948,11 +1012,16 @@ S2.define('select2/results',[
option.className = 'select2-results__option'; option.className = 'select2-results__option';
var attrs = { var attrs = {
'role': 'treeitem', 'role': 'option',
'aria-selected': 'false' 'aria-selected': 'false'
}; };
if (data.disabled) { var matches = window.Element.prototype.matches ||
window.Element.prototype.msMatchesSelector ||
window.Element.prototype.webkitMatchesSelector;
if ((data.element != null && matches.call(data.element, ':disabled')) ||
(data.element == null && data.disabled)) {
delete attrs['aria-selected']; delete attrs['aria-selected'];
attrs['aria-disabled'] = 'true'; attrs['aria-disabled'] = 'true';
} }
@@ -1012,7 +1081,7 @@ S2.define('select2/results',[
this.template(data, option); this.template(data, option);
} }
$.data(option, 'data', data); Utils.StoreData(option, 'data', data);
return option; return option;
}; };
@@ -1053,7 +1122,10 @@ S2.define('select2/results',[
} }
self.setClasses(); self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
}); });
container.on('unselect', function () { container.on('unselect', function () {
@@ -1062,7 +1134,10 @@ S2.define('select2/results',[
} }
self.setClasses(); self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
}); });
container.on('open', function () { container.on('open', function () {
@@ -1098,7 +1173,7 @@ S2.define('select2/results',[
return; return;
} }
var data = $highlighted.data('data'); var data = Utils.GetData($highlighted[0], 'data');
if ($highlighted.attr('aria-selected') == 'true') { if ($highlighted.attr('aria-selected') == 'true') {
self.trigger('close', {}); self.trigger('close', {});
@@ -1116,8 +1191,9 @@ S2.define('select2/results',[
var currentIndex = $options.index($highlighted); var currentIndex = $options.index($highlighted);
// If we are already at te top, don't move further // If we are already at the top, don't move further
if (currentIndex === 0) { // If no options, currentIndex will be -1
if (currentIndex <= 0) {
return; return;
} }
@@ -1210,7 +1286,7 @@ S2.define('select2/results',[
function (evt) { function (evt) {
var $this = $(this); var $this = $(this);
var data = $this.data('data'); var data = Utils.GetData(this, 'data');
if ($this.attr('aria-selected') === 'true') { if ($this.attr('aria-selected') === 'true') {
if (self.options.get('multiple')) { if (self.options.get('multiple')) {
@@ -1233,7 +1309,7 @@ S2.define('select2/results',[
this.$results.on('mouseenter', '.select2-results__option[aria-selected]', this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
function (evt) { function (evt) {
var data = $(this).data('data'); var data = Utils.GetData(this, 'data');
self.getHighlightedResults() self.getHighlightedResults()
.removeClass('select2-results__option--highlighted'); .removeClass('select2-results__option--highlighted');
@@ -1348,14 +1424,15 @@ S2.define('select2/selection/base',[
this._tabindex = 0; this._tabindex = 0;
if (this.$element.data('old-tabindex') != null) { if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
this._tabindex = this.$element.data('old-tabindex'); this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
} else if (this.$element.attr('tabindex') != null) { } else if (this.$element.attr('tabindex') != null) {
this._tabindex = this.$element.attr('tabindex'); this._tabindex = this.$element.attr('tabindex');
} }
$selection.attr('title', this.$element.attr('title')); $selection.attr('title', this.$element.attr('title'));
$selection.attr('tabindex', this._tabindex); $selection.attr('tabindex', this._tabindex);
$selection.attr('aria-disabled', 'false');
this.$selection = $selection; this.$selection = $selection;
@@ -1365,7 +1442,6 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.bind = function (container, $container) { BaseSelection.prototype.bind = function (container, $container) {
var self = this; var self = this;
var id = container.id + '-container';
var resultsId = container.id + '-results'; var resultsId = container.id + '-results';
this.container = container; this.container = container;
@@ -1408,17 +1484,19 @@ S2.define('select2/selection/base',[
self.$selection.removeAttr('aria-activedescendant'); self.$selection.removeAttr('aria-activedescendant');
self.$selection.removeAttr('aria-owns'); self.$selection.removeAttr('aria-owns');
self.$selection.focus(); self.$selection.trigger('focus');
self._detachCloseHandler(container); self._detachCloseHandler(container);
}); });
container.on('enable', function () { container.on('enable', function () {
self.$selection.attr('tabindex', self._tabindex); self.$selection.attr('tabindex', self._tabindex);
self.$selection.attr('aria-disabled', 'false');
}); });
container.on('disable', function () { container.on('disable', function () {
self.$selection.attr('tabindex', '-1'); self.$selection.attr('tabindex', '-1');
self.$selection.attr('aria-disabled', 'true');
}); });
}; };
@@ -1441,7 +1519,6 @@ S2.define('select2/selection/base',[
}; };
BaseSelection.prototype._attachCloseHandler = function (container) { BaseSelection.prototype._attachCloseHandler = function (container) {
var self = this;
$(document.body).on('mousedown.select2.' + container.id, function (e) { $(document.body).on('mousedown.select2.' + container.id, function (e) {
var $target = $(e.target); var $target = $(e.target);
@@ -1451,13 +1528,11 @@ S2.define('select2/selection/base',[
var $all = $('.select2.select2-container--open'); var $all = $('.select2.select2-container--open');
$all.each(function () { $all.each(function () {
var $this = $(this);
if (this == $select[0]) { if (this == $select[0]) {
return; return;
} }
var $element = $this.data('element'); var $element = Utils.GetData(this, 'element');
$element.select2('close'); $element.select2('close');
}); });
@@ -1481,6 +1556,27 @@ S2.define('select2/selection/base',[
throw new Error('The `update` method must be defined in child classes.'); throw new Error('The `update` method must be defined in child classes.');
}; };
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
BaseSelection.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
BaseSelection.prototype.isDisabled = function () {
return this.options.get('disabled');
};
return BaseSelection; return BaseSelection;
}); });
@@ -1518,7 +1614,10 @@ S2.define('select2/selection/single',[
var id = container.id + '-container'; var id = container.id + '-container';
this.$selection.find('.select2-selection__rendered').attr('id', id); this.$selection.find('.select2-selection__rendered')
.attr('id', id)
.attr('role', 'textbox')
.attr('aria-readonly', 'true');
this.$selection.attr('aria-labelledby', id); this.$selection.attr('aria-labelledby', id);
this.$selection.on('mousedown', function (evt) { this.$selection.on('mousedown', function (evt) {
@@ -1542,17 +1641,15 @@ S2.define('select2/selection/single',[
container.on('focus', function (evt) { container.on('focus', function (evt) {
if (!container.isOpen()) { if (!container.isOpen()) {
self.$selection.focus(); self.$selection.trigger('focus');
} }
}); });
container.on('selection:update', function (params) {
self.update(params.data);
});
}; };
SingleSelection.prototype.clear = function () { SingleSelection.prototype.clear = function () {
this.$selection.find('.select2-selection__rendered').empty(); var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title'); // clear tooltip on empty
}; };
SingleSelection.prototype.display = function (data, container) { SingleSelection.prototype.display = function (data, container) {
@@ -1578,7 +1675,14 @@ S2.define('select2/selection/single',[
var formatted = this.display(selection, $rendered); var formatted = this.display(selection, $rendered);
$rendered.empty().append(formatted); $rendered.empty().append(formatted);
$rendered.prop('title', selection.title || selection.text);
var title = selection.title || selection.text;
if (title) {
$rendered.attr('title', title);
} else {
$rendered.removeAttr('title');
}
}; };
return SingleSelection; return SingleSelection;
@@ -1623,14 +1727,14 @@ S2.define('select2/selection/multiple',[
'.select2-selection__choice__remove', '.select2-selection__choice__remove',
function (evt) { function (evt) {
// Ignore the event if it is disabled // Ignore the event if it is disabled
if (self.options.get('disabled')) { if (self.isDisabled()) {
return; return;
} }
var $remove = $(this); var $remove = $(this);
var $selection = $remove.parent(); var $selection = $remove.parent();
var data = $selection.data('data'); var data = Utils.GetData($selection[0], 'data');
self.trigger('unselect', { self.trigger('unselect', {
originalEvent: evt, originalEvent: evt,
@@ -1641,7 +1745,9 @@ S2.define('select2/selection/multiple',[
}; };
MultipleSelection.prototype.clear = function () { MultipleSelection.prototype.clear = function () {
this.$selection.find('.select2-selection__rendered').empty(); var $rendered = this.$selection.find('.select2-selection__rendered');
$rendered.empty();
$rendered.removeAttr('title');
}; };
MultipleSelection.prototype.display = function (data, container) { MultipleSelection.prototype.display = function (data, container) {
@@ -1679,9 +1785,14 @@ S2.define('select2/selection/multiple',[
var formatted = this.display(selection, $selection); var formatted = this.display(selection, $selection);
$selection.append(formatted); $selection.append(formatted);
$selection.prop('title', selection.title || selection.text);
$selection.data('data', selection); var title = selection.title || selection.text;
if (title) {
$selection.attr('title', title);
}
Utils.StoreData($selection[0], 'data', selection);
$selections.push($selection); $selections.push($selection);
} }
@@ -1746,8 +1857,9 @@ S2.define('select2/selection/placeholder',[
S2.define('select2/selection/allowClear',[ S2.define('select2/selection/allowClear',[
'jquery', 'jquery',
'../keys' '../keys',
], function ($, KEYS) { '../utils'
], function ($, KEYS, Utils) {
function AllowClear () { } function AllowClear () { }
AllowClear.prototype.bind = function (decorated, container, $container) { AllowClear.prototype.bind = function (decorated, container, $container) {
@@ -1776,7 +1888,7 @@ S2.define('select2/selection/allowClear',[
AllowClear.prototype._handleClear = function (_, evt) { AllowClear.prototype._handleClear = function (_, evt) {
// Ignore the event if it is disabled // Ignore the event if it is disabled
if (this.options.get('disabled')) { if (this.isDisabled()) {
return; return;
} }
@@ -1789,10 +1901,22 @@ S2.define('select2/selection/allowClear',[
evt.stopPropagation(); evt.stopPropagation();
var data = $clear.data('data'); var data = Utils.GetData($clear[0], 'data');
var previousVal = this.$element.val();
this.$element.val(this.placeholder.id);
var unselectData = {
data: data
};
this.trigger('clear', unselectData);
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
for (var d = 0; d < data.length; d++) { for (var d = 0; d < data.length; d++) {
var unselectData = { unselectData = {
data: data[d] data: data[d]
}; };
@@ -1802,11 +1926,12 @@ S2.define('select2/selection/allowClear',[
// If the event was prevented, don't clear it out. // If the event was prevented, don't clear it out.
if (unselectData.prevented) { if (unselectData.prevented) {
this.$element.val(previousVal);
return; return;
} }
} }
this.$element.val(this.placeholder.id).trigger('change'); this.$element.trigger('input').trigger('change');
this.trigger('toggle', {}); this.trigger('toggle', {});
}; };
@@ -1829,12 +1954,14 @@ S2.define('select2/selection/allowClear',[
return; return;
} }
var removeAll = this.options.get('translations').get('removeAllItems');
var $remove = $( var $remove = $(
'<span class="select2-selection__clear">' + '<span class="select2-selection__clear" title="' + removeAll() +'">' +
'&times;' + '&times;' +
'</span>' '</span>'
); );
$remove.data('data', data); Utils.StoreData($remove[0], 'data', data);
this.$selection.find('.select2-selection__rendered').prepend($remove); this.$selection.find('.select2-selection__rendered').prepend($remove);
}; };
@@ -1856,7 +1983,7 @@ S2.define('select2/selection/search',[
'<li class="select2-search select2-search--inline">' + '<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' + '<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' + ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' + ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</li>' '</li>'
); );
@@ -1873,14 +2000,18 @@ S2.define('select2/selection/search',[
Search.prototype.bind = function (decorated, container, $container) { Search.prototype.bind = function (decorated, container, $container) {
var self = this; var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container); decorated.call(this, container, $container);
container.on('open', function () { container.on('open', function () {
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus'); self.$search.trigger('focus');
}); });
container.on('close', function () { container.on('close', function () {
self.$search.val(''); self.$search.val('');
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant'); self.$search.removeAttr('aria-activedescendant');
self.$search.trigger('focus'); self.$search.trigger('focus');
}); });
@@ -1900,7 +2031,11 @@ S2.define('select2/selection/search',[
}); });
container.on('results:focus', function (params) { container.on('results:focus', function (params) {
self.$search.attr('aria-activedescendant', params.id); if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
}); });
this.$selection.on('focusin', '.select2-search--inline', function (evt) { this.$selection.on('focusin', '.select2-search--inline', function (evt) {
@@ -1925,7 +2060,7 @@ S2.define('select2/selection/search',[
.prev('.select2-selection__choice'); .prev('.select2-selection__choice');
if ($previousChoice.length > 0) { if ($previousChoice.length > 0) {
var item = $previousChoice.data('data'); var item = Utils.GetData($previousChoice[0], 'data');
self.searchRemoveChoice(item); self.searchRemoveChoice(item);
@@ -1934,6 +2069,12 @@ S2.define('select2/selection/search',[
} }
}); });
this.$selection.on('click', '.select2-search--inline', function (evt) {
if (self.$search.val()) {
evt.stopPropagation();
}
});
// Try to detect the IE version should the `documentMode` property that // Try to detect the IE version should the `documentMode` property that
// is stored on the document. This is only implemented in IE and is // is stored on the document. This is only implemented in IE and is
// slightly cleaner than doing a user agent check. // slightly cleaner than doing a user agent check.
@@ -2019,7 +2160,7 @@ S2.define('select2/selection/search',[
this.resizeSearch(); this.resizeSearch();
if (searchHadFocus) { if (searchHadFocus) {
this.$search.focus(); this.$search.trigger('focus');
} }
}; };
@@ -2052,7 +2193,7 @@ S2.define('select2/selection/search',[
var width = ''; var width = '';
if (this.$search.attr('placeholder') !== '') { if (this.$search.attr('placeholder') !== '') {
width = this.$selection.find('.select2-selection__rendered').innerWidth(); width = this.$selection.find('.select2-selection__rendered').width();
} else { } else {
var minimumWidth = this.$search.val().length + 1; var minimumWidth = this.$search.val().length + 1;
@@ -2076,10 +2217,13 @@ S2.define('select2/selection/eventRelay',[
'open', 'opening', 'open', 'opening',
'close', 'closing', 'close', 'closing',
'select', 'selecting', 'select', 'selecting',
'unselect', 'unselecting' 'unselect', 'unselecting',
'clear', 'clearing'
]; ];
var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting']; var preventableEvents = [
'opening', 'closing', 'selecting', 'unselecting', 'clearing'
];
decorated.call(this, container, $container); decorated.call(this, container, $container);
@@ -2412,6 +2556,7 @@ S2.define('select2/diacritics',[
'\u019F': 'O', '\u019F': 'O',
'\uA74A': 'O', '\uA74A': 'O',
'\uA74C': 'O', '\uA74C': 'O',
'\u0152': 'OE',
'\u01A2': 'OI', '\u01A2': 'OI',
'\uA74E': 'OO', '\uA74E': 'OO',
'\u0222': 'OU', '\u0222': 'OU',
@@ -2821,6 +2966,7 @@ S2.define('select2/diacritics',[
'\uA74B': 'o', '\uA74B': 'o',
'\uA74D': 'o', '\uA74D': 'o',
'\u0275': 'o', '\u0275': 'o',
'\u0153': 'oe',
'\u01A3': 'oi', '\u01A3': 'oi',
'\u0223': 'ou', '\u0223': 'ou',
'\uA74F': 'oo', '\uA74F': 'oo',
@@ -2989,8 +3135,9 @@ S2.define('select2/diacritics',[
'\u03CD': '\u03C5', '\u03CD': '\u03C5',
'\u03CB': '\u03C5', '\u03CB': '\u03C5',
'\u03B0': '\u03C5', '\u03B0': '\u03C5',
'\u03C9': '\u03C9', '\u03CE': '\u03C9',
'\u03C2': '\u03C3' '\u03C2': '\u03C3',
'\u2019': '\''
}; };
return diacritics; return diacritics;
@@ -3075,7 +3222,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) { if ($(data.element).is('option')) {
data.element.selected = true; data.element.selected = true;
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
return; return;
} }
@@ -3096,13 +3243,13 @@ S2.define('select2/data/select',[
} }
self.$element.val(val); self.$element.val(val);
self.$element.trigger('change'); self.$element.trigger('input').trigger('change');
}); });
} else { } else {
var val = data.id; var val = data.id;
this.$element.val(val); this.$element.val(val);
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
} }
}; };
@@ -3118,7 +3265,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) { if ($(data.element).is('option')) {
data.element.selected = false; data.element.selected = false;
this.$element.trigger('change'); this.$element.trigger('input').trigger('change');
return; return;
} }
@@ -3136,7 +3283,7 @@ S2.define('select2/data/select',[
self.$element.val(val); self.$element.val(val);
self.$element.trigger('change'); self.$element.trigger('input').trigger('change');
}); });
}; };
@@ -3158,7 +3305,7 @@ S2.define('select2/data/select',[
// Remove anything added to child elements // Remove anything added to child elements
this.$element.find('*').each(function () { this.$element.find('*').each(function () {
// Remove any custom data set by Select2 // Remove any custom data set by Select2
$.removeData(this, 'data'); Utils.RemoveData(this);
}); });
}; };
@@ -3231,7 +3378,7 @@ S2.define('select2/data/select',[
normalizedData.element = option; normalizedData.element = option;
// Override the option's data with the combined data // Override the option's data with the combined data
$.data(option, 'data', normalizedData); Utils.StoreData(option, 'data', normalizedData);
return $option; return $option;
}; };
@@ -3239,7 +3386,7 @@ S2.define('select2/data/select',[
SelectAdapter.prototype.item = function ($option) { SelectAdapter.prototype.item = function ($option) {
var data = {}; var data = {};
data = $.data($option[0], 'data'); data = Utils.GetData($option[0], 'data');
if (data != null) { if (data != null) {
return data; return data;
@@ -3277,13 +3424,13 @@ S2.define('select2/data/select',[
data = this._normalizeItem(data); data = this._normalizeItem(data);
data.element = $option[0]; data.element = $option[0];
$.data($option[0], 'data', data); Utils.StoreData($option[0], 'data', data);
return data; return data;
}; };
SelectAdapter.prototype._normalizeItem = function (item) { SelectAdapter.prototype._normalizeItem = function (item) {
if (!$.isPlainObject(item)) { if (item !== Object(item)) {
item = { item = {
id: item, id: item,
text: item text: item
@@ -3329,15 +3476,19 @@ S2.define('select2/data/array',[
'jquery' 'jquery'
], function (SelectAdapter, Utils, $) { ], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) { function ArrayAdapter ($element, options) {
var data = options.get('data') || []; this._dataToConvert = options.get('data') || [];
ArrayAdapter.__super__.constructor.call(this, $element, options); ArrayAdapter.__super__.constructor.call(this, $element, options);
this.addOptions(this.convertToOptions(data));
} }
Utils.Extend(ArrayAdapter, SelectAdapter); Utils.Extend(ArrayAdapter, SelectAdapter);
ArrayAdapter.prototype.bind = function (container, $container) {
ArrayAdapter.__super__.bind.call(this, container, $container);
this.addOptions(this.convertToOptions(this._dataToConvert));
};
ArrayAdapter.prototype.select = function (data) { ArrayAdapter.prototype.select = function (data) {
var $option = this.$element.find('option').filter(function (i, elm) { var $option = this.$element.find('option').filter(function (i, elm) {
return elm.value == data.id.toString(); return elm.value == data.id.toString();
@@ -3487,7 +3638,8 @@ S2.define('select2/data/ajax',[
}, function () { }, function () {
// Attempt to detect if a request was aborted // Attempt to detect if a request was aborted
// Only works if the transport exposes a status property // Only works if the transport exposes a status property
if ($request.status && $request.status === '0') { if ('status' in $request &&
($request.status === 0 || $request.status === '0')) {
return; return;
} }
@@ -3626,8 +3778,6 @@ S2.define('select2/data/tags',[
}; };
Tags.prototype._removeOldTags = function (_) { Tags.prototype._removeOldTags = function (_) {
var tag = this._lastTag;
var $options = this.$element.find('option[data-select2-tag]'); var $options = this.$element.find('option[data-select2-tag]');
$options.each(function () { $options.each(function () {
@@ -3702,7 +3852,7 @@ S2.define('select2/data/tokenizer',[
// Replace the search term if we have the search box // Replace the search term if we have the search box
if (this.$search.length) { if (this.$search.length) {
this.$search.val(tokenData.term); this.$search.val(tokenData.term);
this.$search.focus(); this.$search.trigger('focus');
} }
params.term = tokenData.term; params.term = tokenData.term;
@@ -3831,10 +3981,30 @@ S2.define('select2/data/maximumSelectionLength',[
decorated.call(this, $e, options); decorated.call(this, $e, options);
} }
MaximumSelectionLength.prototype.bind =
function (decorated, container, $container) {
var self = this;
decorated.call(this, container, $container);
container.on('select', function () {
self._checkIfMaximumSelected();
});
};
MaximumSelectionLength.prototype.query = MaximumSelectionLength.prototype.query =
function (decorated, params, callback) { function (decorated, params, callback) {
var self = this; var self = this;
this._checkIfMaximumSelected(function () {
decorated.call(self, params, callback);
});
};
MaximumSelectionLength.prototype._checkIfMaximumSelected =
function (_, successCallback) {
var self = this;
this.current(function (currentData) { this.current(function (currentData) {
var count = currentData != null ? currentData.length : 0; var count = currentData != null ? currentData.length : 0;
if (self.maximumSelectionLength > 0 && if (self.maximumSelectionLength > 0 &&
@@ -3847,7 +4017,10 @@ S2.define('select2/data/maximumSelectionLength',[
}); });
return; return;
} }
decorated.call(self, params, callback);
if (successCallback) {
successCallback();
}
}); });
}; };
@@ -3886,7 +4059,7 @@ S2.define('select2/dropdown',[
}; };
Dropdown.prototype.position = function ($dropdown, $container) { Dropdown.prototype.position = function ($dropdown, $container) {
// Should be implmented in subclasses // Should be implemented in subclasses
}; };
Dropdown.prototype.destroy = function () { Dropdown.prototype.destroy = function () {
@@ -3910,7 +4083,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' + '<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="search" tabindex="-1"' + '<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' + ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" />' + ' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</span>' '</span>'
); );
@@ -3925,6 +4098,8 @@ S2.define('select2/dropdown/search',[
Search.prototype.bind = function (decorated, container, $container) { Search.prototype.bind = function (decorated, container, $container) {
var self = this; var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container); decorated.call(this, container, $container);
this.$search.on('keydown', function (evt) { this.$search.on('keydown', function (evt) {
@@ -3947,23 +4122,27 @@ S2.define('select2/dropdown/search',[
container.on('open', function () { container.on('open', function () {
self.$search.attr('tabindex', 0); self.$search.attr('tabindex', 0);
self.$search.attr('aria-controls', resultsId);
self.$search.focus(); self.$search.trigger('focus');
window.setTimeout(function () { window.setTimeout(function () {
self.$search.focus(); self.$search.trigger('focus');
}, 0); }, 0);
}); });
container.on('close', function () { container.on('close', function () {
self.$search.attr('tabindex', -1); self.$search.attr('tabindex', -1);
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.val(''); self.$search.val('');
self.$search.trigger('blur');
}); });
container.on('focus', function () { container.on('focus', function () {
if (!container.isOpen()) { if (!container.isOpen()) {
self.$search.focus(); self.$search.trigger('focus');
} }
}); });
@@ -3978,6 +4157,14 @@ S2.define('select2/dropdown/search',[
} }
} }
}); });
container.on('results:focus', function (params) {
if (params.data._resultId) {
self.$search.attr('aria-activedescendant', params.data._resultId);
} else {
self.$search.removeAttr('aria-activedescendant');
}
});
}; };
Search.prototype.handleSearch = function (evt) { Search.prototype.handleSearch = function (evt) {
@@ -4062,6 +4249,7 @@ S2.define('select2/dropdown/infiniteScroll',[
if (this.showLoadingMore(data)) { if (this.showLoadingMore(data)) {
this.$results.append(this.$loadingMore); this.$results.append(this.$loadingMore);
this.loadMoreIfNeeded();
} }
}; };
@@ -4080,25 +4268,27 @@ S2.define('select2/dropdown/infiniteScroll',[
self.loading = true; self.loading = true;
}); });
this.$results.on('scroll', function () { this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
var isLoadMoreVisible = $.contains( };
document.documentElement,
self.$loadingMore[0]
);
if (self.loading || !isLoadMoreVisible) { InfiniteScroll.prototype.loadMoreIfNeeded = function () {
return; var isLoadMoreVisible = $.contains(
} document.documentElement,
this.$loadingMore[0]
);
var currentOffset = self.$results.offset().top + if (this.loading || !isLoadMoreVisible) {
self.$results.outerHeight(false); return;
var loadingMoreOffset = self.$loadingMore.offset().top + }
self.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) { var currentOffset = this.$results.offset().top +
self.loadMore(); this.$results.outerHeight(false);
} var loadingMoreOffset = this.$loadingMore.offset().top +
}); this.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) {
this.loadMore();
}
}; };
InfiniteScroll.prototype.loadMore = function () { InfiniteScroll.prototype.loadMore = function () {
@@ -4119,7 +4309,7 @@ S2.define('select2/dropdown/infiniteScroll',[
var $option = $( var $option = $(
'<li ' + '<li ' +
'class="select2-results__option select2-results__option--load-more"' + 'class="select2-results__option select2-results__option--load-more"' +
'role="treeitem" aria-disabled="true"></li>' 'role="option" aria-disabled="true"></li>'
); );
var message = this.options.get('translations').get('loadingMore'); var message = this.options.get('translations').get('loadingMore');
@@ -4137,7 +4327,7 @@ S2.define('select2/dropdown/attachBody',[
'../utils' '../utils'
], function ($, Utils) { ], function ($, Utils) {
function AttachBody (decorated, $element, options) { function AttachBody (decorated, $element, options) {
this.$dropdownParent = options.get('dropdownParent') || $(document.body); this.$dropdownParent = $(options.get('dropdownParent') || document.body);
decorated.call(this, $element, options); decorated.call(this, $element, options);
} }
@@ -4145,27 +4335,14 @@ S2.define('select2/dropdown/attachBody',[
AttachBody.prototype.bind = function (decorated, container, $container) { AttachBody.prototype.bind = function (decorated, container, $container) {
var self = this; var self = this;
var setupResultsEvents = false;
decorated.call(this, container, $container); decorated.call(this, container, $container);
container.on('open', function () { container.on('open', function () {
self._showDropdown(); self._showDropdown();
self._attachPositioningHandler(container); self._attachPositioningHandler(container);
if (!setupResultsEvents) { // Must bind after the results handlers to ensure correct sizing
setupResultsEvents = true; self._bindContainerResultHandlers(container);
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
}
}); });
container.on('close', function () { container.on('close', function () {
@@ -4214,6 +4391,44 @@ S2.define('select2/dropdown/attachBody',[
this.$dropdownContainer.detach(); this.$dropdownContainer.detach();
}; };
AttachBody.prototype._bindContainerResultHandlers =
function (decorated, container) {
// These should only be bound once
if (this._containerResultsHandlersBound) {
return;
}
var self = this;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:message', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('select', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('unselect', function () {
self._positionDropdown();
self._resizeDropdown();
});
this._containerResultsHandlersBound = true;
};
AttachBody.prototype._attachPositioningHandler = AttachBody.prototype._attachPositioningHandler =
function (decorated, container) { function (decorated, container) {
var self = this; var self = this;
@@ -4224,14 +4439,14 @@ S2.define('select2/dropdown/attachBody',[
var $watchers = this.$container.parents().filter(Utils.hasScroll); var $watchers = this.$container.parents().filter(Utils.hasScroll);
$watchers.each(function () { $watchers.each(function () {
$(this).data('select2-scroll-position', { Utils.StoreData(this, 'select2-scroll-position', {
x: $(this).scrollLeft(), x: $(this).scrollLeft(),
y: $(this).scrollTop() y: $(this).scrollTop()
}); });
}); });
$watchers.on(scrollEvent, function (ev) { $watchers.on(scrollEvent, function (ev) {
var position = $(this).data('select2-scroll-position'); var position = Utils.GetData(this, 'select2-scroll-position');
$(this).scrollTop(position.y); $(this).scrollTop(position.y);
}); });
@@ -4290,16 +4505,26 @@ S2.define('select2/dropdown/attachBody',[
top: container.bottom top: container.bottom
}; };
// Determine what the parent element is to use for calciulating the offset // Determine what the parent element is to use for calculating the offset
var $offsetParent = this.$dropdownParent; var $offsetParent = this.$dropdownParent;
// For statically positoned elements, we need to get the element // For statically positioned elements, we need to get the element
// that is determining the offset // that is determining the offset
if ($offsetParent.css('position') === 'static') { if ($offsetParent.css('position') === 'static') {
$offsetParent = $offsetParent.offsetParent(); $offsetParent = $offsetParent.offsetParent();
} }
var parentOffset = $offsetParent.offset(); var parentOffset = {
top: 0,
left: 0
};
if (
$.contains(document.body, $offsetParent[0]) ||
$offsetParent[0].isConnected
) {
parentOffset = $offsetParent.offset();
}
css.top -= parentOffset.top; css.top -= parentOffset.top;
css.left -= parentOffset.left; css.left -= parentOffset.left;
@@ -4396,8 +4621,8 @@ S2.define('select2/dropdown/minimumResultsForSearch',[
}); });
S2.define('select2/dropdown/selectOnClose',[ S2.define('select2/dropdown/selectOnClose',[
'../utils'
], function () { ], function (Utils) {
function SelectOnClose () { } function SelectOnClose () { }
SelectOnClose.prototype.bind = function (decorated, container, $container) { SelectOnClose.prototype.bind = function (decorated, container, $container) {
@@ -4428,7 +4653,7 @@ S2.define('select2/dropdown/selectOnClose',[
return; return;
} }
var data = $highlightedResults.data('data'); var data = Utils.GetData($highlightedResults[0], 'data');
// Don't re-select already selected resulte // Don't re-select already selected resulte
if ( if (
@@ -4469,7 +4694,7 @@ S2.define('select2/dropdown/closeOnSelect',[
var originalEvent = evt.originalEvent; var originalEvent = evt.originalEvent;
// Don't close if the control key is being held // Don't close if the control key is being held
if (originalEvent && originalEvent.ctrlKey) { if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
return; return;
} }
@@ -4523,6 +4748,9 @@ S2.define('select2/i18n/en',[],function () {
}, },
searching: function () { searching: function () {
return 'Searching…'; return 'Searching…';
},
removeAllItems: function () {
return 'Remove all items';
} }
}; };
}); });
@@ -4761,66 +4989,29 @@ S2.define('select2/defaults',[
); );
} }
if (typeof options.language === 'string') { // If the defaults were not previously applied from an element, it is
// Check if the language is specified with a region // possible for the language option to have not been resolved
if (options.language.indexOf('-') > 0) { options.language = this._resolveLanguage(options.language);
// Extract the region information if it is included
var languageParts = options.language.split('-');
var baseLanguage = languageParts[0];
options.language = [options.language, baseLanguage]; // Always fall back to English since it will always be complete
} else { options.language.push('en');
options.language = [options.language];
var uniqueLanguages = [];
for (var l = 0; l < options.language.length; l++) {
var language = options.language[l];
if (uniqueLanguages.indexOf(language) === -1) {
uniqueLanguages.push(language);
} }
} }
if ($.isArray(options.language)) { options.language = uniqueLanguages;
var languages = new Translation();
options.language.push('en');
var languageNames = options.language; options.translations = this._processTranslations(
options.language,
for (var l = 0; l < languageNames.length; l++) { options.debug
var name = languageNames[l]; );
var language = {};
try {
// Try to load it with the original name
language = Translation.loadPath(name);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
name = this.defaults.amdLanguageBase + name;
language = Translation.loadPath(name);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files.
if (options.debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + name + '" could not be ' +
'automatically loaded. A fallback will be used instead.'
);
}
continue;
}
}
languages.extend(language);
}
options.translations = languages;
} else {
var baseTranslation = Translation.loadPath(
this.defaults.amdLanguageBase + 'en'
);
var customTranslation = new Translation(options.language);
customTranslation.extend(baseTranslation);
options.translations = customTranslation;
}
return options; return options;
}; };
@@ -4887,13 +5078,14 @@ S2.define('select2/defaults',[
debug: false, debug: false,
dropdownAutoWidth: false, dropdownAutoWidth: false,
escapeMarkup: Utils.escapeMarkup, escapeMarkup: Utils.escapeMarkup,
language: EnglishTranslation, language: {},
matcher: matcher, matcher: matcher,
minimumInputLength: 0, minimumInputLength: 0,
maximumInputLength: 0, maximumInputLength: 0,
maximumSelectionLength: 0, maximumSelectionLength: 0,
minimumResultsForSearch: 0, minimumResultsForSearch: 0,
selectOnClose: false, selectOnClose: false,
scrollAfterSelect: false,
sorter: function (data) { sorter: function (data) {
return data; return data;
}, },
@@ -4908,6 +5100,103 @@ S2.define('select2/defaults',[
}; };
}; };
Defaults.prototype.applyFromElement = function (options, $element) {
var optionLanguage = options.language;
var defaultLanguage = this.defaults.language;
var elementLanguage = $element.prop('lang');
var parentLanguage = $element.closest('[lang]').prop('lang');
var languages = Array.prototype.concat.call(
this._resolveLanguage(elementLanguage),
this._resolveLanguage(optionLanguage),
this._resolveLanguage(defaultLanguage),
this._resolveLanguage(parentLanguage)
);
options.language = languages;
return options;
};
Defaults.prototype._resolveLanguage = function (language) {
if (!language) {
return [];
}
if ($.isEmptyObject(language)) {
return [];
}
if ($.isPlainObject(language)) {
return [language];
}
var languages;
if (!$.isArray(language)) {
languages = [language];
} else {
languages = language;
}
var resolvedLanguages = [];
for (var l = 0; l < languages.length; l++) {
resolvedLanguages.push(languages[l]);
if (typeof languages[l] === 'string' && languages[l].indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = languages[l].split('-');
var baseLanguage = languageParts[0];
resolvedLanguages.push(baseLanguage);
}
}
return resolvedLanguages;
};
Defaults.prototype._processTranslations = function (languages, debug) {
var translations = new Translation();
for (var l = 0; l < languages.length; l++) {
var languageData = new Translation();
var language = languages[l];
if (typeof language === 'string') {
try {
// Try to load it with the original name
languageData = Translation.loadPath(language);
} catch (e) {
try {
// If we couldn't load it, check if it wasn't the full path
language = this.defaults.amdLanguageBase + language;
languageData = Translation.loadPath(language);
} catch (ex) {
// The translation could not be loaded at all. Sometimes this is
// because of a configuration problem, other times this can be
// because of how Select2 helps load all possible translation files
if (debug && window.console && console.warn) {
console.warn(
'Select2: The language file for "' + language + '" could ' +
'not be automatically loaded. A fallback will be used instead.'
);
}
}
}
} else if ($.isPlainObject(language)) {
languageData = new Translation(language);
} else {
languageData = language;
}
translations.extend(languageData);
}
return translations;
};
Defaults.prototype.set = function (key, value) { Defaults.prototype.set = function (key, value) {
var camelKey = $.camelCase(key); var camelKey = $.camelCase(key);
@@ -4916,7 +5205,7 @@ S2.define('select2/defaults',[
var convertedData = Utils._convertData(data); var convertedData = Utils._convertData(data);
$.extend(this.defaults, convertedData); $.extend(true, this.defaults, convertedData);
}; };
var defaults = new Defaults(); var defaults = new Defaults();
@@ -4937,6 +5226,10 @@ S2.define('select2/options',[
this.fromElement($element); this.fromElement($element);
} }
if ($element != null) {
this.options = Defaults.applyFromElement(this.options, $element);
}
this.options = Defaults.apply(this.options); this.options = Defaults.apply(this.options);
if ($element && $element.is('input')) { if ($element && $element.is('input')) {
@@ -4960,14 +5253,6 @@ S2.define('select2/options',[
this.options.disabled = $e.prop('disabled'); this.options.disabled = $e.prop('disabled');
} }
if (this.options.language == null) {
if ($e.prop('lang')) {
this.options.language = $e.prop('lang').toLowerCase();
} else if ($e.closest('[lang]').prop('lang')) {
this.options.language = $e.closest('[lang]').prop('lang');
}
}
if (this.options.dir == null) { if (this.options.dir == null) {
if ($e.prop('dir')) { if ($e.prop('dir')) {
this.options.dir = $e.prop('dir'); this.options.dir = $e.prop('dir');
@@ -4981,7 +5266,7 @@ S2.define('select2/options',[
$e.prop('disabled', this.options.disabled); $e.prop('disabled', this.options.disabled);
$e.prop('multiple', this.options.multiple); $e.prop('multiple', this.options.multiple);
if ($e.data('select2Tags')) { if (Utils.GetData($e[0], 'select2Tags')) {
if (this.options.debug && window.console && console.warn) { if (this.options.debug && window.console && console.warn) {
console.warn( console.warn(
'Select2: The `data-select2-tags` attribute has been changed to ' + 'Select2: The `data-select2-tags` attribute has been changed to ' +
@@ -4990,11 +5275,11 @@ S2.define('select2/options',[
); );
} }
$e.data('data', $e.data('select2Tags')); Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
$e.data('tags', true); Utils.StoreData($e[0], 'tags', true);
} }
if ($e.data('ajaxUrl')) { if (Utils.GetData($e[0], 'ajaxUrl')) {
if (this.options.debug && window.console && console.warn) { if (this.options.debug && window.console && console.warn) {
console.warn( console.warn(
'Select2: The `data-ajax-url` attribute has been changed to ' + 'Select2: The `data-ajax-url` attribute has been changed to ' +
@@ -5003,21 +5288,45 @@ S2.define('select2/options',[
); );
} }
$e.attr('ajax--url', $e.data('ajaxUrl')); $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
$e.data('ajax--url', $e.data('ajaxUrl')); Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
} }
var dataset = {}; var dataset = {};
function upperCaseLetter(_, letter) {
return letter.toUpperCase();
}
// Pre-load all of the attributes which are prefixed with `data-`
for (var attr = 0; attr < $e[0].attributes.length; attr++) {
var attributeName = $e[0].attributes[attr].name;
var prefix = 'data-';
if (attributeName.substr(0, prefix.length) == prefix) {
// Get the contents of the attribute after `data-`
var dataName = attributeName.substring(prefix.length);
// Get the data contents from the consistent source
// This is more than likely the jQuery data helper
var dataValue = Utils.GetData($e[0], dataName);
// camelCase the attribute name to match the spec
var camelDataName = dataName.replace(/-([a-z])/g, upperCaseLetter);
// Store the data attribute contents into the dataset since
dataset[camelDataName] = dataValue;
}
}
// Prefer the element's `dataset` attribute if it exists // Prefer the element's `dataset` attribute if it exists
// jQuery 1.x does not correctly handle data attributes with multiple dashes // jQuery 1.x does not correctly handle data attributes with multiple dashes
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) { if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
dataset = $.extend(true, {}, $e[0].dataset, $e.data()); dataset = $.extend(true, {}, $e[0].dataset, dataset);
} else {
dataset = $e.data();
} }
var data = $.extend(true, {}, dataset); // Prefer our internal data cache if it exists
var data = $.extend(true, {}, Utils.GetData($e[0]), dataset);
data = Utils._convertData(data); data = Utils._convertData(data);
@@ -5054,8 +5363,8 @@ S2.define('select2/core',[
'./keys' './keys'
], function ($, Options, Utils, KEYS) { ], function ($, Options, Utils, KEYS) {
var Select2 = function ($element, options) { var Select2 = function ($element, options) {
if ($element.data('select2') != null) { if (Utils.GetData($element[0], 'select2') != null) {
$element.data('select2').destroy(); Utils.GetData($element[0], 'select2').destroy();
} }
this.$element = $element; this.$element = $element;
@@ -5071,7 +5380,7 @@ S2.define('select2/core',[
// Set up the tabindex // Set up the tabindex
var tabindex = $element.attr('tabindex') || 0; var tabindex = $element.attr('tabindex') || 0;
$element.data('old-tabindex', tabindex); Utils.StoreData($element[0], 'old-tabindex', tabindex);
$element.attr('tabindex', '-1'); $element.attr('tabindex', '-1');
// Set up containers and adapters // Set up containers and adapters
@@ -5132,6 +5441,9 @@ S2.define('select2/core',[
// Synchronize any monitored attributes // Synchronize any monitored attributes
this._syncAttributes(); this._syncAttributes();
Utils.StoreData($element[0], 'select2', this);
// Ensure backwards compatibility with $element.data('select2').
$element.data('select2', this); $element.data('select2', this);
}; };
@@ -5208,6 +5520,12 @@ S2.define('select2/core',[
return null; return null;
} }
if (method == 'computedstyle') {
var computedStyle = window.getComputedStyle($element[0]);
return computedStyle.width;
}
return method; return method;
}; };
@@ -5248,8 +5566,8 @@ S2.define('select2/core',[
if (observer != null) { if (observer != null) {
this._observer = new observer(function (mutations) { this._observer = new observer(function (mutations) {
$.each(mutations, self._syncA); self._syncA();
$.each(mutations, self._syncS); self._syncS(null, mutations);
}); });
this._observer.observe(this.$element[0], { this._observer.observe(this.$element[0], {
attributes: true, attributes: true,
@@ -5371,7 +5689,7 @@ S2.define('select2/core',[
if (self.isOpen()) { if (self.isOpen()) {
if (key === KEYS.ESC || key === KEYS.TAB || if (key === KEYS.ESC || key === KEYS.TAB ||
(key === KEYS.UP && evt.altKey)) { (key === KEYS.UP && evt.altKey)) {
self.close(); self.close(evt);
evt.preventDefault(); evt.preventDefault();
} else if (key === KEYS.ENTER) { } else if (key === KEYS.ENTER) {
@@ -5405,7 +5723,7 @@ S2.define('select2/core',[
Select2.prototype._syncAttributes = function () { Select2.prototype._syncAttributes = function () {
this.options.set('disabled', this.$element.prop('disabled')); this.options.set('disabled', this.$element.prop('disabled'));
if (this.options.get('disabled')) { if (this.isDisabled()) {
if (this.isOpen()) { if (this.isOpen()) {
this.close(); this.close();
} }
@@ -5416,7 +5734,7 @@ S2.define('select2/core',[
} }
}; };
Select2.prototype._syncSubtree = function (evt, mutations) { Select2.prototype._isChangeMutation = function (evt, mutations) {
var changed = false; var changed = false;
var self = this; var self = this;
@@ -5444,7 +5762,22 @@ S2.define('select2/core',[
} }
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) { } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
changed = true; changed = true;
} else if ($.isArray(mutations)) {
$.each(mutations, function(evt, mutation) {
if (self._isChangeMutation(evt, mutation)) {
// We've found a change mutation.
// Let's escape from the loop and continue
changed = true;
return false;
}
});
} }
return changed;
};
Select2.prototype._syncSubtree = function (evt, mutations) {
var changed = this._isChangeMutation(evt, mutations);
var self = this;
// Only re-pull the data if we think there is a change // Only re-pull the data if we think there is a change
if (changed) { if (changed) {
@@ -5466,7 +5799,8 @@ S2.define('select2/core',[
'open': 'opening', 'open': 'opening',
'close': 'closing', 'close': 'closing',
'select': 'selecting', 'select': 'selecting',
'unselect': 'unselecting' 'unselect': 'unselecting',
'clear': 'clearing'
}; };
if (args === undefined) { if (args === undefined) {
@@ -5494,7 +5828,7 @@ S2.define('select2/core',[
}; };
Select2.prototype.toggleDropdown = function () { Select2.prototype.toggleDropdown = function () {
if (this.options.get('disabled')) { if (this.isDisabled()) {
return; return;
} }
@@ -5510,15 +5844,40 @@ S2.define('select2/core',[
return; return;
} }
if (this.isDisabled()) {
return;
}
this.trigger('query', {}); this.trigger('query', {});
}; };
Select2.prototype.close = function () { Select2.prototype.close = function (evt) {
if (!this.isOpen()) { if (!this.isOpen()) {
return; return;
} }
this.trigger('close', {}); this.trigger('close', { originalEvent : evt });
};
/**
* Helper method to abstract the "enabled" (not "disabled") state of this
* object.
*
* @return {true} if the instance is not disabled.
* @return {false} if the instance is disabled.
*/
Select2.prototype.isEnabled = function () {
return !this.isDisabled();
};
/**
* Helper method to abstract the "disabled" state of this object.
*
* @return {true} if the disabled option is true.
* @return {false} if the disabled option is false.
*/
Select2.prototype.isDisabled = function () {
return this.options.get('disabled');
}; };
Select2.prototype.isOpen = function () { Select2.prototype.isOpen = function () {
@@ -5595,7 +5954,7 @@ S2.define('select2/core',[
}); });
} }
this.$element.val(newVal).trigger('change'); this.$element.val(newVal).trigger('input').trigger('change');
}; };
Select2.prototype.destroy = function () { Select2.prototype.destroy = function () {
@@ -5621,10 +5980,12 @@ S2.define('select2/core',[
this._syncS = null; this._syncS = null;
this.$element.off('.select2'); this.$element.off('.select2');
this.$element.attr('tabindex', this.$element.data('old-tabindex')); this.$element.attr('tabindex',
Utils.GetData(this.$element[0], 'old-tabindex'));
this.$element.removeClass('select2-hidden-accessible'); this.$element.removeClass('select2-hidden-accessible');
this.$element.attr('aria-hidden', 'false'); this.$element.attr('aria-hidden', 'false');
Utils.RemoveData(this.$element[0]);
this.$element.removeData('select2'); this.$element.removeData('select2');
this.dataAdapter.destroy(); this.dataAdapter.destroy();
@@ -5652,7 +6013,7 @@ S2.define('select2/core',[
this.$container.addClass('select2-container--' + this.options.get('theme')); this.$container.addClass('select2-container--' + this.options.get('theme'));
$container.data('element', this.$element); Utils.StoreData($container[0], 'element', this.$element);
return $container; return $container;
}; };
@@ -5672,8 +6033,9 @@ S2.define('jquery.select2',[
'jquery-mousewheel', 'jquery-mousewheel',
'./select2/core', './select2/core',
'./select2/defaults' './select2/defaults',
], function ($, _, Select2, Defaults) { './select2/utils'
], function ($, _, Select2, Defaults, Utils) {
if ($.fn.select2 == null) { if ($.fn.select2 == null) {
// All methods that should return the element // All methods that should return the element
var thisMethods = ['open', 'close', 'destroy']; var thisMethods = ['open', 'close', 'destroy'];
@@ -5694,7 +6056,7 @@ S2.define('jquery.select2',[
var args = Array.prototype.slice.call(arguments, 1); var args = Array.prototype.slice.call(arguments, 1);
this.each(function () { this.each(function () {
var instance = $(this).data('select2'); var instance = Utils.GetData(this, 'select2');
if (instance == null && window.console && console.error) { if (instance == null && window.console && console.error) {
console.error( console.error(
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -1
View File
File diff suppressed because one or more lines are too long
+313 -305
View File
@@ -1,305 +1,313 @@
<?php <?php
namespace sammo; namespace sammo;
require(__DIR__ . '/../vendor/autoload.php'); require(__DIR__ . '/../vendor/autoload.php');
$host = Util::getPost('db_host'); $host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int'); $port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id'); $username = Util::getPost('db_id');
$password = Util::getPost('db_pw'); $password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name'); $dbName = Util::getPost('db_name');
$servHost = Util::getPost('serv_host'); $servHost = Util::getPost('serv_host');
$sharedIconPath = Util::getPost('shared_icon_path'); $sharedIconPath = Util::getPost('shared_icon_path');
$gameImagePath = Util::getPost('game_image_path'); $gameImagePath = Util::getPost('game_image_path');
$imageRequestKey = Util::getPost('image_request_key'); $imageRequestKey = Util::getPost('image_request_key');
$kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', ''); $kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', '');
$kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', ''); $kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', '');
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) { if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '입력 값이 올바르지 않습니다' 'reason' => '입력 값이 올바르지 않습니다'
]); ]);
} }
if (!filter_var($servHost, FILTER_VALIDATE_URL)) { if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '접속 경로가 올바르지 않습니다.' 'reason' => '접속 경로가 올바르지 않습니다.'
]); ]);
} }
if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) { if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_setting/RootDB.php 가 디렉토리입니다' 'reason' => 'd_setting/RootDB.php 가 디렉토리입니다'
]); ]);
} }
if (class_exists('\\sammo\\RootDB')) { if (class_exists('\\sammo\\RootDB')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '이미 RootDB.php 파일이 있습니다' 'reason' => '이미 RootDB.php 파일이 있습니다'
]); ]);
} }
//파일 권한 검사 //파일 권한 검사
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) { if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다' 'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다'
]); ]);
} }
if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) { if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_log 가 디렉토리가 아닙니다' 'reason' => 'd_log 가 디렉토리가 아닙니다'
]); ]);
} }
if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) { if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다' 'reason' => 'd_shared 가 디렉토리가 아닙니다'
]); ]);
} }
if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) { if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다' 'reason' => 'd_shared 가 디렉토리가 아닙니다'
]); ]);
} }
if ( if (
!file_exists(ROOT . '/d_log') !file_exists(ROOT . '/d_log')
|| !file_exists(ROOT . '/d_shared') || !file_exists(ROOT . '/d_shared')
|| !file_exists(ROOT . '/d_setting') || !file_exists(ROOT . '/d_setting')
|| !file_exists(AppConf::getUserIconPathFS()) || !file_exists(AppConf::getUserIconPathFS())
) { ) {
if (!is_writable(ROOT)) { if (!is_writable(ROOT)) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '하위 디렉토리 생성 권한이 없습니다' 'reason' => '하위 디렉토리 생성 권한이 없습니다'
]); ]);
} }
//기본 파일 생성 //기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) { if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS()); mkdir(AppConf::getUserIconPathFS());
} }
if (!file_exists(ROOT . '/d_log')) { if (!file_exists(ROOT . '/d_log')) {
mkdir(ROOT . '/d_log'); mkdir(ROOT . '/d_log');
} }
if (!file_exists(ROOT . '/d_setting')) { if (!file_exists(ROOT . '/d_setting')) {
mkdir(ROOT . '/d_setting'); mkdir(ROOT . '/d_setting');
} }
if (!file_exists(ROOT . '/d_shared')) { if (!file_exists(ROOT . '/d_shared')) {
mkdir(ROOT . '/d_shared'); mkdir(ROOT . '/d_shared');
} }
} }
if (!is_writable(AppConf::getUserIconPathFS())) { if (!is_writable(AppConf::getUserIconPathFS())) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다' 'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다'
]); ]);
} }
if (!is_writable(ROOT . '/d_log')) { if (!is_writable(ROOT . '/d_log')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다' 'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다'
]); ]);
} }
if (!is_writable(ROOT . '/d_shared')) { if (!is_writable(ROOT . '/d_shared')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다' 'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다'
]); ]);
} }
if (!is_writable(ROOT . '/d_setting')) { if (!is_writable(ROOT . '/d_setting')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.' 'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.'
]); ]);
} }
if (!file_exists(ROOT . '/d_log/.htaccess')) { if (!file_exists(ROOT . '/d_log/.htaccess')) {
@file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all'); @file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all');
} }
if (!file_exists(ROOT . '/d_setting/.htaccess')) { if (!file_exists(ROOT . '/d_setting/.htaccess')) {
@file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all'); @file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all');
} }
//DB 접근 권한 검사 //DB 접근 권한 검사
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4'); $rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; $rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->throw_exception_on_nonsql_error = false; $rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) { $rootDB->nonsql_error_handler = function ($params) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'DB 접속에 실패했습니다.' 'reason' => 'DB 접속에 실패했습니다.'
]); ]);
}; };
$rootDB->error_handler = function ($params) { $rootDB->error_handler = function ($params) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.' 'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]); ]);
}; };
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨. $mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) { if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) {
while (true) { while (true) {
if (!$mysqli_obj->more_results()) { if (!$mysqli_obj->more_results()) {
break; break;
} }
if (!$mysqli_obj->next_result()) { if (!$mysqli_obj->next_result()) {
break; break;
} }
} }
} }
$rootDB->insert('system', array( $rootDB->insert('system', array(
'REG' => 'N', 'REG' => 'N',
'LOGIN' => 'N', 'LOGIN' => 'N',
'CRT_DATE' => TimeUtil::now(), 'CRT_DATE' => TimeUtil::now(),
'MDF_DATE' => TimeUtil::now() 'MDF_DATE' => TimeUtil::now()
)); ));
$globalSalt = bin2hex(random_bytes(16)); $globalSalt = bin2hex(random_bytes(16));
'@phan-var-force string $servHost'; '@phan-var-force string $servHost';
'@phan-var-force string $sharedIconPath'; '@phan-var-force string $sharedIconPath';
'@phan-var-force string $gameImagePath'; '@phan-var-force string $gameImagePath';
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost); $sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost); $gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost); $imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost);
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost); $imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost);
$result = Util::generateFileUsingSimpleTemplate( $result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/ServConfig.orig.php', __DIR__ . '/templates/ServConfig.orig.php',
ROOT . '/d_setting/ServConfig.php', ROOT . '/d_setting/ServConfig.php',
[ [
'serverBasePath' => $servHost, 'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath, 'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath, 'gameImagePath' => $gameImagePath,
'imageRequestPath' => $imageRequestPath, 'imageRequestPath' => $imageRequestPath,
'imageRequestKey' => $imageRequestKey 'imageRequestKey' => $imageRequestKey,
], 'serverList' => [
true ['che', '체', 'white'],
); ['kwe', '퀘', 'yellow'],
['pwe', '풰', 'orange'],
if ($imageRequestKey) { ['twe', '퉤', 'magenta'],
@file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey); ['nya', '냐', '#e67e22'],
} ['pya', '퍄', '#9b59b6']
]
if ($result !== true) { ],
Json::die([ true
'result' => false, );
'reason' => $result
]); if ($imageRequestKey) {
} @file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common_path.orig.js', if ($result !== true) {
ROOT . '/d_shared/common_path.js', Json::die([
[ 'result' => false,
'serverBasePath' => $servHost, 'reason' => $result
'sharedIconPath' => $sharedIconPath, ]);
'gameImagePath' => $gameImagePath }
],
true $result = Util::generateFileUsingSimpleTemplate(
); __DIR__ . '/templates/common_path.orig.js',
ROOT . '/d_shared/common_path.js',
$result = Util::generateFileUsingSimpleTemplate( [
__DIR__ . '/templates/menu.orig.json', 'serverBasePath' => $servHost,
ROOT . '/d_shared/menu.json', 'sharedIconPath' => $sharedIconPath,
[], 'gameImagePath' => $gameImagePath
true ],
); true
);
if ($result !== true) {
Json::die([ $result = Util::generateFileUsingSimpleTemplate(
'result' => false, __DIR__ . '/templates/menu.orig.json',
'reason' => $result ROOT . '/d_shared/menu.json',
]); [],
} true
);
$result = Util::generateFileUsingSimpleTemplate( if ($result !== true) {
__DIR__ . '/templates/common.orig.css', Json::die([
ROOT . '/d_shared/common.css', 'result' => false,
[ 'reason' => $result
'serverBasePath' => $servHost, ]);
'sharedIconPath' => $sharedIconPath, }
'gameImagePath' => $gameImagePath
],
true $result = Util::generateFileUsingSimpleTemplate(
); __DIR__ . '/templates/common.orig.css',
ROOT . '/d_shared/common.css',
if ($result !== true) { [
Json::die([ 'serverBasePath' => $servHost,
'result' => false, 'sharedIconPath' => $sharedIconPath,
'reason' => $result 'gameImagePath' => $gameImagePath
]); ],
} true
);
$result = Util::generateFileUsingSimpleTemplate( if ($result !== true) {
__DIR__ . '/templates/RootDB.orig.php', Json::die([
ROOT . '/d_setting/RootDB.php', 'result' => false,
[ 'reason' => $result
'host' => $host, ]);
'user' => $username, }
'password' => $password,
'dbName' => $dbName,
'port' => $port, $result = Util::generateFileUsingSimpleTemplate(
'globalSalt' => $globalSalt, __DIR__ . '/templates/RootDB.orig.php',
] ROOT . '/d_setting/RootDB.php',
); [
'host' => $host,
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/'); 'user' => $username,
'password' => $password,
Util::generateFileUsingSimpleTemplate( 'dbName' => $dbName,
__DIR__ . '/templates/KakaoKey.orig.php', 'port' => $port,
ROOT . '/d_setting/KakaoKey.php', 'globalSalt' => $globalSalt,
[ ]
'REST_API_KEY' => $kakaoRESTKey, );
'ADMIN_KEY' => $kakaoAdminKey,
'REDIRECT_URI' => $kakaoRedirectURI $kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/');
],
true Util::generateFileUsingSimpleTemplate(
); __DIR__ . '/templates/KakaoKey.orig.php',
ROOT . '/d_setting/KakaoKey.php',
if ($result !== true) { [
Json::die([ 'REST_API_KEY' => $kakaoRESTKey,
'result' => false, 'ADMIN_KEY' => $kakaoAdminKey,
'reason' => $result 'REDIRECT_URI' => $kakaoRedirectURI
]); ],
} true
);
Json::die([
'result' => true, if ($result !== true) {
'reason' => 'success', Json::die([
'globalSalt' => $globalSalt 'result' => false,
]); 'reason' => $result
]);
}
Json::die([
'result' => true,
'reason' => 'success',
'globalSalt' => $globalSalt
]);
+74 -55
View File
@@ -1,55 +1,74 @@
<?php <?php
namespace sammo; namespace sammo;
class ServConfig class ServConfig
{ {
private function __construct() private function __construct()
{ {
} }
public static $serverWebPath = '_tK_serverBasePath_'; public static $serverWebPath = '_tK_serverBasePath_';
public static $sharedIconPath = '_tK_sharedIconPath_'; public static $sharedIconPath = '_tK_sharedIconPath_';
public static $gameImagePath = "_tK_gameImagePath_"; public static $gameImagePath = "_tK_gameImagePath_";
public static $imageRequestPath = "_tK_imageRequestPath_"; public static $imageRequestPath = "_tK_imageRequestPath_";
public static $imageRequestKey = '_tK_imageRequestKey_'; public static $imageRequestKey = '_tK_imageRequestKey_';
private static $serverList = null;
public static function getSharedIconPath(string $filepath = ''): string
{ public static function getSharedIconPath(string $filepath = ''): string
if ($filepath) { {
return static::$sharedIconPath . "/{$filepath}"; if ($filepath) {
} return static::$sharedIconPath . "/{$filepath}";
return static::$sharedIconPath; }
} return static::$sharedIconPath;
}
public static function getUserIconPath(string $filepath = ''): string
{ public static function getUserIconPath(string $filepath = ''): string
return AppConf::getUserIconPathWeb($filepath); {
} return AppConf::getUserIconPathWeb($filepath);
}
public static function getGameImagePath(string $filepath = ''): string
{ public static function getGameImagePath(string $filepath = ''): string
if ($filepath) { {
return static::$gameImagePath . "/{$filepath}"; if ($filepath) {
} return static::$gameImagePath . "/{$filepath}";
return static::$gameImagePath; }
} return static::$gameImagePath;
}
public static function getImagePullURI(): string
{ public static function getImagePullURI(): string
$now = time(); {
$req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey); $now = time();
return static::$imageRequestPath . "?req={$req_hash}&time={$now}"; $req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey);
} return static::$imageRequestPath . "?req={$req_hash}&time={$now}";
}
/** /**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함 * 서버 설정 반환
* *
* @return string * @return \sammo\Setting[]
*/ */
public static function getServerBasepath(): string public static function getServerList(): array{
{ $servKeyList = [/*_tK_serverList_*/];
return self::$serverWebPath; $servKeyList[] = ['hwe', '훼', 'red'];
}
} if (self::$serverList === null) {
self::$serverList = [];
foreach($servKeyList as [$servKey, $servNick, $servColor]){
self::$serverList[$servKey] = new Setting(ROOT.'/'.$servKey, $servNick, $servColor);
}
}
return self::$serverList;
}
/**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
*
* @return string
*/
public static function getServerBasepath(): string
{
return self::$serverWebPath;
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ $admin = getAdmin();
</tr> </tr>
<tr> <tr>
<td width=110 align=right>시작시간변경</td> <td width=110 align=right>시작시간변경</td>
<td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=$admin['starttime']?>'><input type=submit name=btn value=변경1></td> <td width=285><input type=text size=20 maxlength=20 style=color:white;background-color:black;text-align:right; name=starttime value='<?=substr($admin['starttime'], 0, 19)?>'><input type=submit name=btn value=변경1></td>
<td width=110 align=right>현재도시훈사</td> <td width=110 align=right>현재도시훈사</td>
<td width=285><?=$admin['city_rate']?></td> <td width=285><?=$admin['city_rate']?></td>
</tr> </tr>
+11
View File
@@ -91,6 +91,7 @@ $types = [
} }
return $v; return $v;
}], }],
["점 령", "int", function($v){$v['value'] = $v['occupied']; return $v; }],
["사 살", "int", function($v){$v['value'] = $v['killcrew']; return $v; }], ["사 살", "int", function($v){$v['value'] = $v['killcrew']; return $v; }],
["살 상 률", "percent", function($v){ ["살 상 률", "percent", function($v){
if($v['warnum'] < 10){ if($v['warnum'] < 10){
@@ -101,6 +102,16 @@ $types = [
} }
return $v; return $v;
}], }],
["대 인 사 살", "int", function($v){$v['value'] = $v['killcrew_person']; return $v; }],
["대 인 살 상 률", "percent", function($v){
if($v['warnum'] < 10){
$v['value'] = 0;
}
else{
$v['value'] = $v['killcrew_person'] / max(1, $v['deathcrew_person']);
}
return $v;
}],
["보 병 숙 련 도", "int", function($v){$v['value'] = $v['dex1']; return $v; }], ["보 병 숙 련 도", "int", function($v){$v['value'] = $v['dex1']; return $v; }],
["궁 병 숙 련 도", "int", function($v){$v['value'] = $v['dex2']; return $v; }], ["궁 병 숙 련 도", "int", function($v){$v['value'] = $v['dex2']; return $v; }],
["기 병 숙 련 도", "int", function($v){$v['value'] = $v['dex3']; return $v; }], ["기 병 숙 련 도", "int", function($v){$v['value'] = $v['dex3']; return $v; }],
+215 -215
View File
@@ -1,215 +1,215 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
$type = Util::getReq('type', 'int', 9); $type = Util::getReq('type', 'int', 9);
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("장수일람", 2); increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID); $me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
$con = checkLimit($me['con']); $con = checkLimit($me['con']);
if ($con >= 2) { if ($con >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
if ($type <= 0 || $type > 15) { if ($type <= 0 || $type > 15) {
$type = 9; $type = 9;
} }
$ownerNameList = []; $ownerNameList = [];
if($gameStor->isunited){ if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){ foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName; $ownerNameList[$ownerID] = $ownerName;
} }
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 장수일람</title> <title><?=UniqueConst::$serverName?>: 장수일람</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?> <?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> <?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?> <?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?> <?=WebUtil::printJS('js/common.js')?>
</head> </head>
<body> <body>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td>장 수 일 람<br><?=closeButton()?></td></tr> <tr><td>장 수 일 람<br><?=closeButton()?></td></tr>
<tr><td><form name=form1 method=post>정렬순서 : <tr><td><form name=form1 method=post>정렬순서 :
<select id='viewType' name='type' size=1> <select id='viewType' name='type' size=1>
<option value=1>국가</option> <option value=1>국가</option>
<option value=2>통솔</option> <option value=2>통솔</option>
<option value=3>무력</option> <option value=3>무력</option>
<option value=4>지력</option> <option value=4>지력</option>
<option value=5>명성</option> <option value=5>명성</option>
<option value=6>계급</option> <option value=6>계급</option>
<option value=7>관직</option> <option value=7>관직</option>
<option value=8>삭턴</option> <option value=8>삭턴</option>
<option value=9>벌점</option> <option value=9>벌점</option>
<option value=10>Lv</option> <option value=10>Lv</option>
<option value=11>성격</option> <option value=11>성격</option>
<option value=12>내특</option> <option value=12>내특</option>
<option value=13>전특</option> <option value=13>전특</option>
<option value=14>연령</option> <option value=14>연령</option>
<option value=15>NPC</option> <option value=15>NPC</option>
</select> </select>
<input type=submit value='정렬하기'></form> <input type=submit value='정렬하기'></form>
</td></tr> </td></tr>
</table> </table>
<?php <?php
$nationname = []; $nationname = [];
$nationlevel = []; $nationlevel = [];
$nationname[0] = "-"; $nationname[0] = "-";
foreach (getAllNationStaticInfo() as $nation) { foreach (getAllNationStaticInfo() as $nation) {
$nationname[$nation['nation']] = $nation['name']; $nationname[$nation['nation']] = $nation['name'];
$nationlevel[$nation['nation']] = $nation['level']; $nationlevel[$nation['nation']] = $nation['level'];
} }
[$orderKey, $orderDesc] = [ [$orderKey, $orderDesc] = [
1=>['nation', false], 1=>['nation', false],
2=>['leadership', true], 2=>['leadership', true],
3=>['strength', true], 3=>['strength', true],
4=>['intel', true], 4=>['intel', true],
5=>['experience', true], 5=>['experience', true],
6=>['dedication', true], 6=>['dedication', true],
7=>['officer_level', true], 7=>['officer_level', true],
8=>['killturn', false], 8=>['killturn', false],
9=>['connect', true], 9=>['connect', true],
10=>['experience', true], 10=>['experience', true],
11=>['personal', true], 11=>['personal', true],
12=>['special', true], 12=>['special', true],
13=>['special2', true], 13=>['special2', true],
14=>['age', true], 14=>['age', true],
15=>['npc', true], 15=>['npc', true],
][$type]; ][$type];
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc?'desc':''); $generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc?'desc':'');
echo" echo"
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr> <tr>
<td width=64 align=center id=bg1>얼 굴</td> <td width=64 align=center id=bg1>얼 굴</td>
<td width=140 align=center id=bg1>이 름</td> <td width=140 align=center id=bg1>이 름</td>
<td width=45 align=center id=bg1>연령</td> <td width=45 align=center id=bg1>연령</td>
<td width=45 align=center id=bg1>성격</td> <td width=45 align=center id=bg1>성격</td>
<td width=80 align=center id=bg1>특기</td> <td width=80 align=center id=bg1>특기</td>
<td width=45 align=center id=bg1>레 벨</td> <td width=45 align=center id=bg1>레 벨</td>
<td width=140 align=center id=bg1>국 가</td> <td width=140 align=center id=bg1>국 가</td>
<td width=55 align=center id=bg1>명 성</td> <td width=55 align=center id=bg1>명 성</td>
<td width=55 align=center id=bg1>계 급</td> <td width=55 align=center id=bg1>계 급</td>
<td width=75 align=center id=bg1>관 직</td> <td width=75 align=center id=bg1>관 직</td>
<td width=45 align=center id=bg1>통솔</td> <td width=45 align=center id=bg1>통솔</td>
<td width=45 align=center id=bg1>무력</td> <td width=45 align=center id=bg1>무력</td>
<td width=45 align=center id=bg1>지력</td> <td width=45 align=center id=bg1>지력</td>
<td width=45 align=center id=bg1>삭턴</td> <td width=45 align=center id=bg1>삭턴</td>
<td width=70 align=center id=bg1>벌점</td> <td width=70 align=center id=bg1>벌점</td>
</tr>"; </tr>";
foreach($generalList as $general){ foreach($generalList as $general){
$nation = $nationname[$general['nation']]; $nation = $nationname[$general['nation']];
$lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0); $lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0);
if ($lbonus > 0) { if ($lbonus > 0) {
$lbonusText = "<font color=cyan>+{$lbonus}</font>"; $lbonusText = "<font color=cyan>+{$lbonus}</font>";
} else { } else {
$lbonusText = ""; $lbonusText = "";
} }
if ($general['injury'] > 0) { if ($general['injury'] > 0) {
$leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100); $leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100);
$strength = intdiv($general['strength'] * (100 - $general['injury']), 100); $strength = intdiv($general['strength'] * (100 - $general['injury']), 100);
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100); $intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
$leadership = "<font color=red>{$leadership}</font>{$lbonusText}"; $leadership = "<font color=red>{$leadership}</font>{$lbonusText}";
$strength = "<font color=red>{$strength}</font>"; $strength = "<font color=red>{$strength}</font>";
$intel = "<font color=red>{$intel}</font>"; $intel = "<font color=red>{$intel}</font>";
} else { } else {
$leadership = "{$general['leadership']}{$lbonusText}"; $leadership = "{$general['leadership']}{$lbonusText}";
$strength = "{$general['strength']}"; $strength = "{$general['strength']}";
$intel = "{$general['intel']}"; $intel = "{$general['intel']}";
} }
if ($general['npc'] >= 2) { if ($general['npc'] >= 2) {
$name = "<font color=cyan>{$general['name']}</font>"; $name = "<font color=cyan>{$general['name']}</font>";
} elseif ($general['npc'] == 1) { } elseif ($general['npc'] == 1) {
$name = "<font color=skyblue>{$general['name']}</font>"; $name = "<font color=skyblue>{$general['name']}</font>";
} else { } else {
$name = "{$general['name']}"; $name = "{$general['name']}";
} }
if(key_exists($general['owner'], $ownerNameList)){ if(key_exists($general['owner'], $ownerNameList)){
$name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>'; $name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>';
} }
$general['connect'] = Util::round($general['connect'], -1); $general['connect'] = Util::round($general['connect'], -1);
$imageTemp = GetImageURL($general['imgsvr']); $imageTemp = GetImageURL($general['imgsvr']);
echo " echo "
<tr data-general-id='{$general['no']}' <tr data-general-id='{$general['no']}'
data-general-wounded='{$general['injury']}' data-general-wounded='{$general['injury']}'
data-general-leadership='{$general['leadership']}' data-general-leadership='{$general['leadership']}'
data-general-leadership-bonus='{$lbonus}' data-general-leadership-bonus='{$lbonus}'
data-general-strength='{$general['strength']}' data-general-strength='{$general['strength']}'
data-general-intel='{$general['intel']}' data-general-intel='{$general['intel']}'
data-is-npc='".($general['npc']>=2?'true':'false')."' data-is-npc='".($general['npc']>=2?'true':'false')."'
> >
<td align=center><img class='generalIcon' width='64' height='64' src='{$imageTemp}/{$general['picture']}'></img></td> <td align=center><img class='generalIcon' width='64' height='64' src='{$imageTemp}/{$general['picture']}'></img></td>
<td align=center>$name</td> <td align=center>$name</td>
<td align=center>{$general['age']}세</td> <td align=center>{$general['age']}세</td>
<td align=center>".displayCharInfo($general['personal'])."</td> <td align=center>".displayCharInfo($general['personal'])."</td>
<td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td> <td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td>
<td align=center>Lv ".getExpLevel($general['experience'])."</td> <td align=center>Lv ".getExpLevel($general['experience'])."</td>
<td align=center>{$nation}</td> <td align=center>{$nation}</td>
<td align=center>".getHonor($general['experience'])."</td> <td align=center>".getHonor($general['experience'])."</td>
<td align=center>".getDed($general['dedication'])."</td> <td align=center>".getDed($general['dedication'])."</td>
<td align=center>"; <td align=center>";
echo getOfficerLevelText($general['officer_level']); echo getOfficerLevelText($general['officer_level']);
echo "</td> echo "</td>
<td align=center>$leadership</td> <td align=center>$leadership</td>
<td align=center>$strength</td> <td align=center>$strength</td>
<td align=center>$intel</td> <td align=center>$intel</td>
<td align=center>{$general['killturn']}</td> <td align=center>{$general['killturn']}</td>
<td align=center>{$general['connect']}"; <td align=center>{$general['connect']}";
echo "<br>【".getConnect($general['connect'])."】</td> echo "<br>【".getConnect($general['connect'])."】</td>
</tr>"; </tr>";
} }
echo " echo "
</table> </table>
"; ";
?> ?>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=closeButton()?></td></tr> <tr><td><?=closeButton()?></td></tr>
<tr><td><?=banner()?></td></tr> <tr><td><?=banner()?></td></tr>
</table> </table>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
$("#viewType").val("<?=$type?>").attr("selected", "selected"); $("#viewType").val("<?=$type?>").attr("selected", "selected");
}); });
</script> </script>
</body> </body>
</html> </html>
+3
View File
@@ -90,8 +90,11 @@ $types = [
'warnum'=>['전 투 횟 수', 'int'], 'warnum'=>['전 투 횟 수', 'int'],
'killnum'=>['승 리', 'int'], 'killnum'=>['승 리', 'int'],
'winrate'=>['승 률', 'percent'], 'winrate'=>['승 률', 'percent'],
'occupied'=>['점 령', 'int'],
'killcrew'=>['사 살', 'int'], 'killcrew'=>['사 살', 'int'],
'killrate'=>['살 상 률', 'percent'], 'killrate'=>['살 상 률', 'percent'],
'killcrew_person'=>['대 인 사 살', 'int'],
'killrate_person'=>['대 인 살 상 률', 'percent'],
'dex1'=>['보 병 숙 련 도', 'int'], 'dex1'=>['보 병 숙 련 도', 'int'],
'dex2'=>['궁 병 숙 련 도', 'int'], 'dex2'=>['궁 병 숙 련 도', 'int'],
'dex3'=>['기 병 숙 련 도', 'int'], 'dex3'=>['기 병 숙 련 도', 'int'],
+1 -1
View File
@@ -72,7 +72,7 @@ var maxChiefTurn = <?=GameConst::$maxChiefTurn?>;
></div ></div
><div ><div
><?=chiefCommandTable($generalObj) ><?=chiefCommandTable($generalObj)
?><input type='button' id='setCommand' style='visibility:hidden;background-color:<?=GameConst::$basecolor2?>;color:white;font-size:13px;' value='실 행' ?><br><input type='button' id='setCommand' style='visibility:hidden;background-color:<?=GameConst::$basecolor2?>;color:white;font-size:13px;' value='실 행'
></div ></div
></div ></div
></div ></div
+1 -1
View File
@@ -93,7 +93,7 @@ switch ($type) {
case 5: $orderSQL = "order by crew desc"; break; case 5: $orderSQL = "order by crew desc"; break;
case 6: $orderSQL = "order by killturn"; break; case 6: $orderSQL = "order by killturn"; break;
case 7: $orderSQL = "order by turntime"; break; case 7: $orderSQL = "order by turntime"; break;
case 8: $orderSQL = "order by troop_leader desc"; break; case 8: $orderSQL = "order by troop desc"; break;
} }
$generals = $db->query( $generals = $db->query(
+527 -527
View File
@@ -1,527 +1,527 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
increaseRefresh("인사부", 1); increaseRefresh("인사부", 1);
//훼섭 추방을 위해 갱신 //훼섭 추방을 위해 갱신
TurnExecutionHelper::executeAllCommand(); TurnExecutionHelper::executeAllCommand();
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID); $me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$nationID = $me['nation']; $nationID = $me['nation'];
$meLevel = $me['officer_level']; $meLevel = $me['officer_level'];
if($meLevel == 0) { if($meLevel == 0) {
echo "재야입니다."; echo "재야입니다.";
exit(); exit();
} }
$nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nation where nation=%i', $nationID); //국가정보 $nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nation where nation=%i', $nationID); //국가정보
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 인사부</title> <title><?=UniqueConst::$serverName?>: 인사부</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> <?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/select2/select2.full.min.js')?> <?=WebUtil::printJS('../e_lib/select2/select2.full.min.js')?>
<?=WebUtil::printJS('js/common.js')?> <?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/bossInfo.js')?> <?=WebUtil::printJS('js/bossInfo.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2.min.css')?> <?=WebUtil::printCSS('../e_lib/select2/select2.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css')?> <?=WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?> <?=WebUtil::printCSS('css/common.css')?>
<script type="text/javascript"> <script type="text/javascript">
var chiefStatMin = <?=GameConst::$chiefStatMin?>; var chiefStatMin = <?=GameConst::$chiefStatMin?>;
var myLevel = <?=$meLevel?>; var myLevel = <?=$meLevel?>;
</script> </script>
<?php <?php
$ambassadors = $db->query('SELECT no, name, officer_level, penalty, permission FROM general WHERE permission = \'ambassador\' AND nation = %i', $nationID); $ambassadors = $db->query('SELECT no, name, officer_level, penalty, permission FROM general WHERE permission = \'ambassador\' AND nation = %i', $nationID);
$auditors = $db->query('SELECT no, name, officer_level, penalty, permission FROM general WHERE permission = \'auditor\' AND nation = %i', $nationID); $auditors = $db->query('SELECT no, name, officer_level, penalty, permission FROM general WHERE permission = \'auditor\' AND nation = %i', $nationID);
$candidateAmbassadors = []; $candidateAmbassadors = [];
$candidateAuditors = []; $candidateAuditors = [];
foreach($ambassadors as $ambassador){ foreach($ambassadors as $ambassador){
$candidateAmbassadors[] = $ambassador; $candidateAmbassadors[] = $ambassador;
} }
foreach($auditors as $auditor){ foreach($auditors as $auditor){
$candidateAuditors[] = $auditor; $candidateAuditors[] = $auditor;
} }
foreach($db->query('SELECT no, name, nation, officer_level, penalty, permission FROM general WHERE nation = %i AND permission = \'normal\' AND officer_level != 12', $nationID) as $candidate){ foreach($db->query('SELECT no, name, nation, officer_level, penalty, permission FROM general WHERE nation = %i AND permission = \'normal\' AND officer_level != 12', $nationID) as $candidate){
$maxPermission = checkSecretMaxPermission($candidate); $maxPermission = checkSecretMaxPermission($candidate);
if($maxPermission == 4){ if($maxPermission == 4){
$candidateAmbassadors[] = $candidate; $candidateAmbassadors[] = $candidate;
} }
if($maxPermission >= 3){ if($maxPermission >= 3){
$candidateAuditors[] = $candidate; $candidateAuditors[] = $candidate;
} }
} }
?> ?>
<script> <script>
var candidateAmbassadors = <?=Json::encode(array_map(function($value){ var candidateAmbassadors = <?=Json::encode(array_map(function($value){
return [ return [
'id'=>$value['no'], 'id'=>$value['no'],
'text'=>$value['name'], 'text'=>$value['name'],
"selected"=>($value['permission']!='normal') "selected"=>($value['permission']!='normal')
]; ];
}, $candidateAmbassadors))?>; }, $candidateAmbassadors))?>;
var candidateAuditors = <?=Json::encode(array_map(function($value){ var candidateAuditors = <?=Json::encode(array_map(function($value){
return [ return [
'id'=>$value['no'], 'id'=>$value['no'],
'text'=>$value['name'], 'text'=>$value['name'],
"selected"=>($value['permission']!='normal') "selected"=>($value['permission']!='normal')
]; ];
}, $candidateAuditors))?>; }, $candidateAuditors))?>;
</script> </script>
</head> </head>
<body> <body>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td>인 사 부<br><?=backButton()?></td></tr> <tr><td>인 사 부<br><?=backButton()?></td></tr>
</table> </table>
<br> <br>
<?php <?php
$lv = getNationChiefLevel($nation['level']); $lv = getNationChiefLevel($nation['level']);
if($meLevel >= 5) { $btn = "button"; } if($meLevel >= 5) { $btn = "button"; }
else { $btn = "hidden"; } else { $btn = "hidden"; }
$level = Util::convertArrayToDict( $level = Util::convertArrayToDict(
$db->query( $db->query(
'SELECT name,officer_level,city,picture,imgsvr,belong from general where nation=%i and officer_level>=%i order by officer_level desc', 'SELECT name,officer_level,city,picture,imgsvr,belong from general where nation=%i and officer_level>=%i order by officer_level desc',
$nationID, $lv $nationID, $lv
), ),
'officer_level' 'officer_level'
); );
$tigers = $db->query('SELECT value, name $tigers = $db->query('SELECT value, name
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
WHERE rank_data.nation_id = %i AND rank_data.type = "warnum" AND value > 0 ORDER BY value DESC LIMIT 5', WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5',
$nationID $nationID
);// 오호장군 );// 오호장군
$tigerstr = join(', ', array_map(function($arr){ $tigerstr = join(', ', array_map(function($arr){
$number = number_format($arr['value']); $number = number_format($arr['value']);
return "{$arr['name']}【{$number}】"; return "{$arr['name']}【{$number}】";
}, $tigers)); }, $tigers));
$eagles = $db->query('SELECT value, name $eagles = $db->query('SELECT value, name
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7', WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7',
$nationID $nationID
);// 건안칠자 );// 건안칠자
$eaglestr = join(', ', array_map(function($arr){ $eaglestr = join(', ', array_map(function($arr){
$number = number_format($arr['value']); $number = number_format($arr['value']);
return "{$arr['name']}【{$number}】"; return "{$arr['name']}【{$number}】";
}, $eagles)); }, $eagles));
?> ?>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr> <tr>
<td align=center style='color:<?=newColor($nation['color'])?>; background-color:<?=$nation['color']?>' colspan=6> <td align=center style='color:<?=newColor($nation['color'])?>; background-color:<?=$nation['color']?>' colspan=6>
<font size=5>【 <?=$nation['name']?> 】</font> <font size=5>【 <?=$nation['name']?> 】</font>
</td> </td>
</tr> </tr>
<?php <?php
for($i=12; $i >= $lv; $i-=2) { for($i=12; $i >= $lv; $i-=2) {
$i1 = $i; $i2 = $i - 1; $i1 = $i; $i2 = $i - 1;
$imageTemp1 = GetImageURL($level[$i1]['imgsvr']??0); $imageTemp1 = GetImageURL($level[$i1]['imgsvr']??0);
$imageTemp2 = GetImageURL($level[$i2]['imgsvr']??0); $imageTemp2 = GetImageURL($level[$i2]['imgsvr']??0);
?> ?>
<tr> <tr>
<td width=98 align=center id=bg1><font size=4><?=getOfficerLevelText($i1, $nation['level'])?></font></td> <td width=98 align=center id=bg1><font size=4><?=getOfficerLevelText($i1, $nation['level'])?></font></td>
<td width=64 class='generalIcon' height=64 style='background:no-repeat center url("<?=$imageTemp1?>/<?=$level[$i1]['picture']??'default.jpg'?>");background-size:64px;'></td> <td width=64 class='generalIcon' height=64 style='background:no-repeat center url("<?=$imageTemp1?>/<?=$level[$i1]['picture']??'default.jpg'?>");background-size:64px;'></td>
<td width=332><font size=4><?=$level[$i1]['name']??'-'?>(<?=$level[$i1]['belong']??'-'?>년)</font></td> <td width=332><font size=4><?=$level[$i1]['name']??'-'?>(<?=$level[$i1]['belong']??'-'?>년)</font></td>
<td width=98 align=center id=bg1><font size=4><?=getOfficerLevelText($i2, $nation['level'])?></font></td> <td width=98 align=center id=bg1><font size=4><?=getOfficerLevelText($i2, $nation['level'])?></font></td>
<td width=64 class='generalIcon' height=64 style='background:no-repeat center url("<?=$imageTemp2?>/<?=$level[$i2]['picture']??'default.jpg'?>");background-size:64px;'></td> <td width=64 class='generalIcon' height=64 style='background:no-repeat center url("<?=$imageTemp2?>/<?=$level[$i2]['picture']??'default.jpg'?>");background-size:64px;'></td>
<td width=332><font size=4><?=$level[$i2]['name']??'-'?>(<?=$level[$i2]['belong']??'-'?>년)</font></td> <td width=332><font size=4><?=$level[$i2]['name']??'-'?>(<?=$level[$i2]['belong']??'-'?>년)</font></td>
</tr> </tr>
<?php <?php
} }
?> ?>
<tr> <tr>
<td width=98 align=center id=bg1>오호장군【승전】</td> <td width=98 align=center id=bg1>오호장군【승전】</td>
<td colspan=5><?=$tigerstr?></td> <td colspan=5><?=$tigerstr?></td>
</tr> </tr>
<tr> <tr>
<td width=98 align=center id=bg1>건안칠자【계략】</td> <td width=98 align=center id=bg1>건안칠자【계략】</td>
<td colspan=5><?=$eaglestr?></td> <td colspan=5><?=$eaglestr?></td>
</tr> </tr>
</table> </table>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=6 height=5></td></tr> <tr><td colspan=6 height=5></td></tr>
<tr><td colspan=2 align=center bgcolor=red>추 방</td></tr> <tr><td colspan=2 align=center bgcolor=red>추 방</td></tr>
<tr> <tr>
<td width=498 align=right id=bg1>대상 장수</td> <td width=498 align=right id=bg1>대상 장수</td>
<td width=498> <td width=498>
<?php <?php
if($meLevel >= 5){ if($meLevel >= 5){
$candidateStrength = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and strength>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin); $candidateStrength = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and strength>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin);
$candidateIntel = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and intel>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin); $candidateIntel = $db->query('SELECT no,name,officer_level,city,npc from general where nation=%i and officer_level!=12 and intel>=%i order by npc,binary(name)', $nationID, GameConst::$chiefStatMin);
$candidateAny = $db->query('SELECT no,name,officer_level,city,npc,leadership,strength,intel,killturn from general where nation=%i and officer_level!=12 order by npc,binary(name)', $nationID); //추방 때문에 조금 더 김 $candidateAny = $db->query('SELECT no,name,officer_level,city,npc,leadership,strength,intel,killturn from general where nation=%i and officer_level!=12 order by npc,binary(name)', $nationID); //추방 때문에 조금 더 김
} }
else{ else{
$candidateStrength = []; $candidateStrength = [];
$candidateIntel = []; $candidateIntel = [];
$candidateAny = []; $candidateAny = [];
} }
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $meLevel)) { if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $meLevel)) {
echo " echo "
<select id='genlist_kick' size=1 style=color:white;background-color:black;>"; <select id='genlist_kick' size=1 style=color:white;background-color:black;>";
foreach($candidateAny as $general) { foreach($candidateAny as $general) {
if($general['no'] === $me['no']){ if($general['no'] === $me['no']){
continue; continue;
} }
echo " echo "
<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} <small>({$general['leadership']}/{$general['strength']}/{$general['intel']}, {$general['killturn']}턴)</small></option>"; <option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} <small>({$general['leadership']}/{$general['strength']}/{$general['intel']}, {$general['killturn']}턴)</small></option>";
} }
echo " echo "
</select> </select>
<input type=$btn id='btn_kick' value=추방>"; <input type=$btn id='btn_kick' value=추방>";
} }
$officerLevelText = getOfficerLevelText(11, $nation['level']); $officerLevelText = getOfficerLevelText(11, $nation['level']);
echo " echo "
</td> </td>
</tr> </tr>
</table> </table>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=4 height=5></td></tr> <tr><td colspan=4 height=5></td></tr>
<tr><td colspan=4 align=center bgcolor=blue>수 뇌 부 임 명</td></tr> <tr><td colspan=4 align=center bgcolor=blue>수 뇌 부 임 명</td></tr>
<tr> <tr>
<td width=98 align=right id=bg1>".getOfficerLevelText(12, $nation['level'])."</td> <td width=98 align=right id=bg1>".getOfficerLevelText(12, $nation['level'])."</td>
<td width=398>{$level[12]['name']} 【".CityConst::byID($level[12]['city'])->name."】</td> <td width=398>{$level[12]['name']} 【".CityConst::byID($level[12]['city'])->name."】</td>
<td width=98 align=right id=bg1>{$officerLevelText}</td> <td width=98 align=right id=bg1>{$officerLevelText}</td>
<td width=398> <td width=398>
"; ";
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], 11)) { if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], 11)) {
echo " echo "
<select id='genlist_11' size=1 maxlength=15 style=color:white;background-color:black;> <select id='genlist_11' size=1 maxlength=15 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>"; <option value=0 data-officer_level='0' data-name=''>____공석____</option>";
foreach($candidateAny as $general) { foreach($candidateAny as $general) {
if($general['officer_level'] == 11) { if($general['officer_level'] == 11) {
echo "<option style=color:red; selected data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:red; selected data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} elseif($general['officer_level'] > 1) { } elseif($general['officer_level'] > 1) {
echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} else { } else {
echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} }
} }
echo " echo "
</select> </select>
<input class='btn_appoint' type=$btn data-officer_level='11' data-officer_level_text='{$officerLevelText}' value=임명>"; <input class='btn_appoint' type=$btn data-officer_level='11' data-officer_level_text='{$officerLevelText}' value=임명>";
} else { } else {
if(key_exists(11, $level)){ if(key_exists(11, $level)){
echo "{$level[11]['name']} 【".CityConst::byID($level[11]['city'])->name."】"; echo "{$level[11]['name']} 【".CityConst::byID($level[11]['city'])->name."】";
} }
} }
echo " echo "
</td> </td>
</tr> </tr>
"; ";
for($i=10; $i >= $lv; $i--) { for($i=10; $i >= $lv; $i--) {
if($i % 2 == 0) { echo "<tr>"; } if($i % 2 == 0) { echo "<tr>"; }
$officerLevelText = getOfficerLevelText($i, $nation['level']); $officerLevelText = getOfficerLevelText($i, $nation['level']);
echo " echo "
<td width=98 align=right id=bg1>{$officerLevelText}</td> <td width=98 align=right id=bg1>{$officerLevelText}</td>
<td width=398> <td width=398>
"; ";
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $i)) { if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $i)) {
echo " echo "
<select id='genlist_{$i}' size=1 style=color:white;background-color:black;> <select id='genlist_{$i}' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>"; <option value=0 data-officer_level='0' data-name=''>____공석____</option>";
foreach(($i%2==0?$candidateStrength:$candidateIntel) as $general) { foreach(($i%2==0?$candidateStrength:$candidateIntel) as $general) {
if($general['officer_level'] == $i) { if($general['officer_level'] == $i) {
echo "<option style=color:red; selected data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:red; selected data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} elseif($general['officer_level'] > 1) { } elseif($general['officer_level'] > 1) {
echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} else { } else {
echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} }
} }
echo " echo "
</select> </select>
<input class='btn_appoint' type=$btn data-officer_level='{$i}' data-officer_level_text='$officerLevelText' value=임명>"; <input class='btn_appoint' type=$btn data-officer_level='{$i}' data-officer_level_text='$officerLevelText' value=임명>";
} else { } else {
$general = $level[$i]??null; $general = $level[$i]??null;
if($general){ if($general){
echo "{$general['name']} 【".CityConst::byID($general['city'])->name."】"; echo "{$general['name']} 【".CityConst::byID($general['city'])->name."】";
} }
} }
echo "</td>"; echo "</td>";
if($i % 2 == 1) { echo "</tr>"; } if($i % 2 == 1) { echo "</tr>"; }
} }
echo " echo "
<tr><td colspan=4>※ <font color=red>빨간색</font>은 현재 임명중인 장수, <font color=orange>노란색</font>은 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr> <tr><td colspan=4>※ <font color=red>빨간색</font>은 현재 임명중인 장수, <font color=orange>노란색</font>은 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr>
</table> </table>
"; ";
if($meLevel == 12): if($meLevel == 12):
?> ?>
<table align='center' width='1000' class='tb_layout bg0'> <table align='center' width='1000' class='tb_layout bg0'>
<tr><td colspan='4' height='5'></td></tr> <tr><td colspan='4' height='5'></td></tr>
<tr><td colspan='4' align='center' bgcolor='purple'>외 교 권 자 임 명</td></tr> <tr><td colspan='4' align='center' bgcolor='purple'>외 교 권 자 임 명</td></tr>
<tr> <tr>
<td width=98 align=right id=bg1>외교권자</td> <td width=98 align=right id=bg1>외교권자</td>
<td width=398> <td width=398>
<select id="selectAmbassador" multiple="multiple"> <select id="selectAmbassador" multiple="multiple">
</select> </select>
<button id='changeAmbassador' type='button'>임명</button> <button id='changeAmbassador' type='button'>임명</button>
</td> </td>
<td width=98 align=right id=bg1>조언자</td> <td width=98 align=right id=bg1>조언자</td>
<td width=398> <td width=398>
<select id="selectAuditor" multiple="multiple"> <select id="selectAuditor" multiple="multiple">
</select> </select>
<button id='changeAuditor' type='button'>임명</button> <button id='changeAuditor' type='button'>임명</button>
</td> </td>
</tr> </tr>
</table> </table>
<?php <?php
endif; endif;
?> ?>
<table align=center width=1000 id='officer_list' class='tb_layout bg0'> <table align=center width=1000 id='officer_list' class='tb_layout bg0'>
<tr><td colspan=5 height=5></td></tr> <tr><td colspan=5 height=5></td></tr>
<?php <?php
if($meLevel >= 5) { if($meLevel >= 5) {
$officerLevelText = getOfficerLevelText(4, $nation['level']); $officerLevelText = getOfficerLevelText(4, $nation['level']);
echo " echo "
<tr><td colspan=5 align=center bgcolor=orange>도 시 관 직 임 명</td></tr> <tr><td colspan=5 align=center bgcolor=orange>도 시 관 직 임 명</td></tr>
<tr> <tr>
<td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td> <td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td>
<td colspan=2> <td colspan=2>
<select id='citylist_4' size=1 style=color:white;background-color:black;> <select id='citylist_4' size=1 style=color:white;background-color:black;>
"; ";
$cityList = $db->query('SELECT city,name,region,officer_set FROM city WHERE nation=%i ORDER BY region,level DESC,binary(name)', $nationID); $cityList = $db->query('SELECT city,name,region,officer_set FROM city WHERE nation=%i ORDER BY region,level DESC,binary(name)', $nationID);
$region = 0; $region = 0;
foreach($cityList as $city){ foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 4)){ if(isOfficerSet($city['officer_set'], 4)){
continue; continue;
} }
if($region != $city['region']) { if($region != $city['region']) {
if($region != 0) { if($region != 0) {
echo "</optgroup>"; echo "</optgroup>";
} }
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>"; echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region']; $region = $city['region'];
} }
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>"; echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
} }
echo "</optgroup>"; echo "</optgroup>";
echo " echo "
</select> </select>
<select id='genlist_4' size=1 style=color:white;background-color:black;> <select id='genlist_4' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option> <option value=0 data-officer_level='0' data-name=''>____공석____</option>
"; ";
foreach($candidateStrength as $general) { foreach($candidateStrength as $general) {
if($general['officer_level'] == 4) { if($general['officer_level'] == 4) {
echo "<option style=color:red; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:red; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} elseif($general['officer_level'] > 1) { } elseif($general['officer_level'] > 1) {
echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} else { } else {
echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} }
} }
echo " echo "
</select> </select>
<input class='btn_appoint' type=$btn data-officer_level='4' data-officer_level_text='{$officerLevelText}' value=임명> <input class='btn_appoint' type=$btn data-officer_level='4' data-officer_level_text='{$officerLevelText}' value=임명>
</td> </td>
</tr>"; </tr>";
$officerLevelText = getOfficerLevelText(3, $nation['level']); $officerLevelText = getOfficerLevelText(3, $nation['level']);
echo "<tr> echo "<tr>
<td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td> <td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td>
<td colspan=2> <td colspan=2>
<select id='citylist_3' size=1 style=color:white;background-color:black;> <select id='citylist_3' size=1 style=color:white;background-color:black;>
"; ";
$region = 0; $region = 0;
foreach($cityList as $city){ foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 3)){ if(isOfficerSet($city['officer_set'], 3)){
continue; continue;
} }
if($region != $city['region']) { if($region != $city['region']) {
if($region != 0) { if($region != 0) {
echo "</optgroup>"; echo "</optgroup>";
} }
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>"; echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region']; $region = $city['region'];
} }
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>"; echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
} }
echo "</optgroup>"; echo "</optgroup>";
echo " echo "
</select> </select>
<select id='genlist_3' size=1 style=color:white;background-color:black;> <select id='genlist_3' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option> <option value=0 data-officer_level='0' data-name=''>____공석____</option>
"; ";
foreach($candidateIntel as $general) { foreach($candidateIntel as $general) {
if($general['officer_level'] == 3) { if($general['officer_level'] == 3) {
echo "<option style=color:red; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:red; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} elseif($general['officer_level'] > 1) { } elseif($general['officer_level'] > 1) {
echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} else { } else {
echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} }
} }
echo " echo "
</select> </select>
<input class='btn_appoint' type=$btn data-officer_level='3' data-officer_level_text='{$officerLevelText}' value=임명> <input class='btn_appoint' type=$btn data-officer_level='3' data-officer_level_text='{$officerLevelText}' value=임명>
</td> </td>
</tr>"; </tr>";
$officerLevelText = getOfficerLevelText(2, $nation['level']); $officerLevelText = getOfficerLevelText(2, $nation['level']);
echo "<tr> echo "<tr>
<td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td> <td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td>
<td colspan=2> <td colspan=2>
<select id='citylist_2' size=1 style=color:white;background-color:black;> <select id='citylist_2' size=1 style=color:white;background-color:black;>
"; ";
$region = 0; $region = 0;
foreach($cityList as $city){ foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 2)){ if(isOfficerSet($city['officer_set'], 2)){
continue; continue;
} }
if($region != $city['region']) { if($region != $city['region']) {
if($region != 0) { if($region != 0) {
echo "</optgroup>"; echo "</optgroup>";
} }
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>"; echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region']; $region = $city['region'];
} }
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>"; echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
} }
echo "</optgroup>"; echo "</optgroup>";
echo " echo "
</select> </select>
<select id='genlist_2' size=1 style=color:white;background-color:black;> <select id='genlist_2' size=1 style=color:white;background-color:black;>
<option value=0>____<span class='name_field'>공석</span>____</option> <option value=0>____<span class='name_field'>공석</span>____</option>
"; ";
foreach ($candidateAny as $general) { foreach ($candidateAny as $general) {
if($general['officer_level'] == 2) { if($general['officer_level'] == 2) {
echo "<option style=color:red; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:red; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} elseif($general['officer_level'] > 1) { } elseif($general['officer_level'] > 1) {
echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option style=color:orange; data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} else { } else {
echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>"; echo "<option data-officer_level='{$general['officer_level']}' data-name='{$general['name']}' value={$general['no']}>{$general['name']} 【".CityConst::byID($general['city'])->name."】</option>";
} }
} }
echo " echo "
</select> </select>
<input class='btn_appoint' type=$btn data-officer_level='2' data-officer_level_text='{$officerLevelText}' value=임명> <input class='btn_appoint' type=$btn data-officer_level='2' data-officer_level_text='{$officerLevelText}' value=임명>
</td> </td>
</tr> </tr>
<tr><td colspan=5>※ <font color=red>빨간색</font>은 현재 임명중인 장수, <font color=orange>노란색</font>은 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr> <tr><td colspan=5>※ <font color=red>빨간색</font>은 현재 임명중인 장수, <font color=orange>노란색</font>은 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr>
"; ";
} }
echo " echo "
<tr> <tr>
<td width=158 align=center id=bg1 colspan=2><font size=4>도 시</font></td> <td width=158 align=center id=bg1 colspan=2><font size=4>도 시</font></td>
<td width=278 align=center id=bg1><font size=4>태 수 (사관) 【현재도시】</font></td> <td width=278 align=center id=bg1><font size=4>태 수 (사관) 【현재도시】</font></td>
<td width=278 align=center id=bg1><font size=4>군 사 (사관) 【현재도시】</font></td> <td width=278 align=center id=bg1><font size=4>군 사 (사관) 【현재도시】</font></td>
<td width=278 align=center id=bg1><font size=4>종 사 (사관) 【현재도시】</font></td> <td width=278 align=center id=bg1><font size=4>종 사 (사관) 【현재도시】</font></td>
</tr> </tr>
"; ";
$citylevel = getCityLevelList(); $citylevel = getCityLevelList();
$officerList = []; $officerList = [];
foreach($db->query('SELECT no,name,npc,city,officer_level,officer_city,belong FROM general WHERE nation = %i AND 2 <= officer_level AND officer_level <= 4', $nationID) as $officer){ foreach($db->query('SELECT no,name,npc,city,officer_level,officer_city,belong FROM general WHERE nation = %i AND 2 <= officer_level AND officer_level <= 4', $nationID) as $officer){
$officerCityID = $officer['officer_city']; $officerCityID = $officer['officer_city'];
if(!key_exists($officerCityID, $officerList)){ if(!key_exists($officerCityID, $officerList)){
$officerList[$officerCityID] = []; $officerList[$officerCityID] = [];
} }
$officerList[$officerCityID][$officer['officer_level']] = $officer; $officerList[$officerCityID][$officer['officer_level']] = $officer;
} }
$region = 0; $region = 0;
$dummyOfficer = [ $dummyOfficer = [
'name'=>'-', 'name'=>'-',
'belong'=>0, 'belong'=>0,
]; ];
$textColor = newColor($nation['color']); $textColor = newColor($nation['color']);
$nationColor = $nation['color']; $nationColor = $nation['color'];
foreach($db->query('SELECT city,name,level,region,officer_set from city where nation=%i order by region,level desc,binary(name)', $nationID) as $city) { foreach($db->query('SELECT city,name,level,region,officer_set from city where nation=%i order by region,level desc,binary(name)', $nationID) as $city) {
$cityID = $city['city']; $cityID = $city['city'];
$cityOfficerList = $officerList[$cityID]??[]; $cityOfficerList = $officerList[$cityID]??[];
?> ?>
<?php if($region != $city['region']): ?> <?php if($region != $city['region']): ?>
<tr><td colspan=5 height=3 id=bg1></td></tr> <tr><td colspan=5 height=3 id=bg1></td></tr>
<tr><td colspan=5 id=bg1><font size=4 color=skyblue> 【 <?=CityConst::$regionMap[$city['region']]?> 】 </font></td></tr> <tr><td colspan=5 id=bg1><font size=4 color=skyblue> 【 <?=CityConst::$regionMap[$city['region']]?> 】 </font></td></tr>
<?php endif; $region = $city['region']; ?> <?php endif; $region = $city['region']; ?>
<tr> <tr>
<td width=78 align=center style='color:<?=$textColor?>;background-color:<?=$nationColor?>;font-size:1.2em;'>【<?=$citylevel[$city['level']]?>】</td> <td width=78 align=center style='color:<?=$textColor?>;background-color:<?=$nationColor?>;font-size:1.2em;'>【<?=$citylevel[$city['level']]?>】</td>
<td width=78 align=right style='color:<?=$textColor?>;background-color:<?=$nationColor?>;font-size:1.2em;'><?=$city['name']?>&nbsp;&nbsp;</td> <td width=78 align=right style='color:<?=$textColor?>;background-color:<?=$nationColor?>;font-size:1.2em;'><?=$city['name']?>&nbsp;&nbsp;</td>
<?php foreach(Util::range(4, 1, -1) as $officerLevel): ?> <?php foreach(Util::range(4, 1, -1) as $officerLevel): ?>
<?php if(key_exists($officerLevel, $cityOfficerList)): <?php if(key_exists($officerLevel, $cityOfficerList)):
$officer = $cityOfficerList[$officerLevel]; $officer = $cityOfficerList[$officerLevel];
?> ?>
<td><?=$officer['name']?>(<?=$officer['belong']?>년) 【<?=CityConst::byID($officer['city'])->name?>】</td> <td style="color:<?=isOfficerSet($city['officer_set'], $officerLevel)?'orange':'white'?>;"><?=$officer['name']?>(<?=$officer['belong']?>년) 【<?=CityConst::byID($officer['city'])->name?>】</td>
<?php else: ?> <?php else: ?>
<td>-</td> <td>-</td>
<?php endif; ?> <?php endif; ?>
<?php endforeach; ?> <?php endforeach; ?>
</tr> </tr>
<?php <?php
} }
?> ?>
<tr><td colspan=5>※ <font color=orange>노란색</font>은 변경 불가능, 하얀색은 변경 가능 관직입니다.</td></tr> <tr><td colspan=5>※ <font color=orange>노란색</font>은 변경 불가능, 하얀색은 변경 가능 관직입니다.</td></tr>
</table> </table>
<br> <br>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr> <tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?></td></tr> <tr><td><?=banner()?></td></tr>
</table> </table>
</body> </body>
</html> </html>
+160 -212
View File
@@ -1,212 +1,160 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
$btn = Util::getPost('btn'); $showDieImmediatelyBtn = false;
$defence_train = Util::getPost('defence_train', 'int', 2); $availableDieImmediately = false;
$tnmt = Util::getPost('tnmt', 'int', 1);
//$detachNPC = Util::getPost('detachNPC', 'bool'); //로그인 검사
$detachNPC = false; $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$showDieImmediatelyBtn = false; $generalID = $session->generalID;
$availableDieImmediately = false;
$db = DB::db();
if ($defence_train <= 60) { $gameStor = KVStorage::getStorage($db, 'game_env');
$defence_train = 60; $gameStor->cacheValues(['turntime', 'opentime', 'autorun_user']);
}
else if($defence_train <= 80){ increaseRefresh("내정보", 1);
$defence_train = 80;
} $me = General::createGeneralObjFromDB($generalID);
else{
$defence_train = 999; $myset = $me->getVar('myset');
} if ($myset > 0) {
$submit = 'button';
if($tnmt < 0 || $tnmt > 1){ } else {
$tnmt = 1; $submit = 'hidden';
} }
//로그인 검사 $targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
$session = Session::requireGameLogin()->setReadOnly(); if($gameStor->turntime <= $gameStor->opentime){
$userID = Session::getUserID(); //서버 가오픈시 할 수 있는 행동
$generalID = $session->generalID; if($me->getNPCType() == 0){
$showDieImmediatelyBtn = true;
$db = DB::db(); if($targetTime <= TimeUtil::now()){
$gameStor = KVStorage::getStorage($db, 'game_env'); $availableDieImmediately = true;
}
increaseRefresh("내정보", 1); }
}
$me = General::createGeneralObjFromDB($generalID);
$use_treatment = $me->getAuxVar('use_treatment')??10;
$myset = $me->getVar('myset'); $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn')??1;
if ($myset > 0) { ?>
$submit = 'submit'; <!DOCTYPE html>
} else { <html>
$submit = 'hidden'; <head>
} <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
if (($btn == "설정저장" || $detachNPC) && $myset > 0) { <meta name="viewport" content="width=1024" />
if ($myset > 1) { <title><?=UniqueConst::$serverName?>: 내정보</title>
$submit = 'submit'; <script>
} else { var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>;
$submit = 'hidden'; </script>
} <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
if($defence_train != $me->getVar('defence_train')){ <?=WebUtil::printJS('js/common.js')?>
if($defence_train == 999){ <?=WebUtil::printJS('js/myPage.js')?>
$me->increaseVar('myset', -1); <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
$me->setVar('defence_train', $defence_train); <?=WebUtil::printCSS('../d_shared/common.css')?>
$me->increaseVar('train', -3); <?=WebUtil::printCSS('css/common.css')?>
$me->increaseVar('atmos', -3); </head>
}
else{ <body>
$me->increaseVar('myset', -1); <table align=center width=1000 class='tb_layout bg0'>
$me->setVar('defence_train', $defence_train); <tr><td>내 정 보<br><?=backButton()?></td></tr>
} </table>
$myset -= 1; <table align=center width=1000 class='tb_layout bg0'>
} <tr>
<td width=50%>
if($me->getVar('tnmt') != $tnmt){ <?php generalInfo($me); ?>
$me->setVar('tnmt', $tnmt); <?php generalInfo2($me); ?>
} </td>
<td width=50% valign=top style="padding-left:4ch;">
if($me->getNPCType() == 1 && $detachNPC){ 토너먼트 【
$turnterm = $gameStor->turnterm; <input type=radio class='tnmt' name=tnmt value=0 <?=$me->getVar('tnmt')==0?"checked":""; ?>>수동참여
<input type=radio class='tnmt' name=tnmt value=1 <?=$me->getVar('tnmt')==1?"checked":""; ?>>자동참여
if($turnterm < 10){ 】<br>
$targetKillTurn = 30 / $turnterm; ∞<span style='color:orange'>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</span><br><br>
}
else{ 환약 사용 【<select id='use_treatment' name='use_treatment'>
$targetKillTurn = 60 / $turnterm; <option value=10 <?=($use_treatment==10)?"selected":""; ?>>경상</option>
} <option value=21 <?=($use_treatment==21)?"selected":""; ?>>중상</option>
$me->setVar('killturn', $targetKillTurn); <option value=41 <?=($use_treatment==41)?"selected":""; ?>>심각</option>
} <option value=61 <?=($use_treatment==61)?"selected":""; ?>>위독</option>
} <option value=100 <?=($use_treatment==100)?"selected":""; ?>>사용안함</option>
$me->applyDB($db); </select>】<br>
∞<span style='color:orange'>부상을 입었을 때 환약을 사용하는 기준입니다.</span><br><br>
if($gameStor->turntime <= $gameStor->opentime){ <?php if(($gameStor->autorun_user['options']['chief'])??false) : ?>
//서버 가오픈시 할 수 있는 행동 자동 사령턴 허용 【<select id='use_auto_nation_turn' name='use_auto_nation_turn'>
<option value=1 <?=$use_auto_nation_turn?"selected":""; ?>>허용</option>
if($me->getNPCType() == 0){ <option value=0 <?=(!$use_auto_nation_turn)?"selected":""; ?>>허용 안함</option>
$showDieImmediatelyBtn = true; </select>】<br>
if(addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2) <= TimeUtil::now()){ ∞<span style='color:orange'>수뇌가 되었을 때 휴식 턴이어도 적당한 턴을 알아서 넣는 것을 허용합니다.</span><br><br>
$availableDieImmediately = true; <?php endif; ?>
} 수비 【<select id='defence_train' name='defence_train'>
} <?php foreach([90, 80, 60, 40] as $targetDefenceTrain): ?>
} <option value='<?=$targetDefenceTrain?>' <?=$me->getVar('defence_train')==$targetDefenceTrain?"selected":""; ?>><?=formatDefenceTrain($targetDefenceTrain)?>(훈사<?=$targetDefenceTrain?>)</option>
<?php endforeach; ?>
?> <option value=999 <?=$me->getVar('defence_train')==999?"selected":""; ?>><?=formatDefenceTrain(999)?>[훈련, 사기 -3]</option>
<!DOCTYPE html> </select>
<html> 】<br><br>
<head> <input type=<?=$submit?> id='set_my_setting' name=btn style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px; value=설정저장><br>
<meta charset="UTF-8"> ∞<span style='color:orange'>설정저장은 이달중 <?=$myset?>회 남았습니다.</span><br><br>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?>
<meta name="viewport" content="width=1024" /> 휴 가 신 청<br>
<title><?=UniqueConst::$serverName?>: 내정보</title> <button type="button" id='vacation' style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button><br><br>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> <?php endif; ?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> <!--빙의 해제용 삭턴 조절<br>
<?=WebUtil::printJS('js/common.js')?> <a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>빙의 해체 요청</button></a>-->
<?=WebUtil::printJS('js/myPage.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> <?php if($showDieImmediatelyBtn): ?>
<?=WebUtil::printCSS('../d_shared/common.css')?> 가오픈 기간 내 장수 삭제 (<?=substr($targetTime, 0, 19)?> 부터)<br>
<?=WebUtil::printCSS('css/common.css')?> <a href="c_die_immediately.php" id='die_immediately'><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>장수 삭제</button></a><br><br>
<script> <?php endif; ?>
var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>;
jQuery(function($){ 개인용 CSS<br>
<textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea>
$('#die_immediately').click(function(){ </td>
if(!availableDieImmediately){ </tr>
alert('삭제를 위해서는 생성 후 2턴 가량의 시간이 필요합니다.'); <tr>
location.reload(); <td align=center id=bg1><font color=skyblue size=3>개인 기록</font></td>
return false; <td align=center id=bg1><font color=orange size=3>전투 기록</font></td>
} </tr>
return confirm('정말로 삭제하시겠습니까?'); <tr>
}); <td valign=top>
<div id='generalActionPlate'>
}); <?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?>
</script> </div>
</head> <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button>
</td>
<body> <td valign=top>
<table align=center width=1000 class='tb_layout bg0'> <div id='battleDetailPlate'>
<tr><td>내 정 보<br><?=backButton()?></td></tr> <?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?>
</table> </div>
<table align=center width=1000 class='tb_layout bg0'> <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button>
<tr> </td>
<td width=50%> </tr>
<?php generalInfo($me); ?> <tr>
<?php generalInfo2($me); ?> <td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td>
</td> <td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
<td width=50% valign=top style="padding-left:4ch;"> </tr>
<form name=form1 action=b_myPage.php method=post> <tr>
토너먼트 【 <td valign=top>
<input type=radio name=tnmt value=0 <?=$me->getVar('tnmt')==0?"checked":""; ?>>수동참여 <?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?>
<input type=radio name=tnmt value=1 <?=$me->getVar('tnmt')==1?"checked":""; ?>>자동참여 </td>
】<br> <td valign=top>
∞<font color=orange>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</font><br><br> <div id='battleResultPlate'>
수비 【 <?=formatHistoryToHTML(getBattleResultRecent($generalID, 24), 'battleResult')?>
<input type=radio name=defence_train value=80 <?=$me->getVar('defence_train')==80?"checked":""; ?>>◎(훈사80) </div>
<input type=radio name=defence_train value=60 <?=$me->getVar('defence_train')==60?"checked":""; ?>>○(훈사60) <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleResult">이전 로그 불러오기</button>
<input type=radio name=defence_train value=999 <?=$me->getVar('defence_train')==999?"checked":""; ?>>× </td>
】<br><br> </tr>
<input type=<?=$submit?> name=btn style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px; value=설정저장><br> </table>
∞<font color=orange>설정저장은 이달중 <?=$myset?>회 남았습니다.</font><br><br> <table align=center width=1000 class='tb_layout bg0'>
</form> <tr><td><?=backButton()?></td></tr>
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?> <tr><td><?=banner()?></td></tr>
휴 가 신 청<br> </table>
<a href="c_vacation.php"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button></a><br><br> </body>
<?php endif; ?> </html>
<!--빙의 해제용 삭턴 조절<br>
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>빙의 해체 요청</button></a>-->
<?php if($showDieImmediatelyBtn): ?>
가오픈 기간 내 장수 삭제<br>
<a href="c_die_immediately.php" id='die_immediately'><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>장수 삭제</button></a><br><br>
<?php endif; ?>
개인용 CSS<br>
<textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea>
</td>
</tr>
<tr>
<td align=center id=bg1><font color=skyblue size=3>개인 기록</font></td>
<td align=center id=bg1><font color=orange size=3>전투 기록</font></td>
</tr>
<tr>
<td valign=top>
<div id='generalActionPlate'>
<?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?>
</div>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button>
</td>
<td valign=top>
<div id='battleDetailPlate'>
<?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?>
</div>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button>
</td>
</tr>
<tr>
<td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td>
<td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
</tr>
<tr>
<td valign=top>
<?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?>
</td>
<td valign=top>
<div id='battleResultPlate'>
<?=formatHistoryToHTML(getBattleResultRecent($generalID, 24), 'battleResult')?>
</div>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleResult">이전 로그 불러오기</button>
</td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?></td></tr>
</table>
</body>
</html>
+6 -5
View File
@@ -64,6 +64,7 @@ if ($currentNationPolicy['reqHumanWarUrgentGold'] ?? 0) {
$autoPolicyVariable['reqHumanWarUrgentGold'] = $currentNationPolicy['reqHumanWarUrgentGold']; $autoPolicyVariable['reqHumanWarUrgentGold'] = $currentNationPolicy['reqHumanWarUrgentGold'];
} }
$autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['options'], ['values' => $autoPolicyVariable], null, $nation, $gameStor->getAll(true)); $autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['options'], ['values' => $autoPolicyVariable], null, $nation, $gameStor->getAll(true));
$zeroPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['options'], null, null, $nation, $gameStor->getAll(true));
?> ?>
@@ -117,7 +118,7 @@ $autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['optio
'긴급내정': '전쟁중에 민심이 70 미만이거나,<br>인구가 제자리 징병이 가능하지 않을 정도로 적을 경우,<br>일정확률로 주민선정과 정착장려를 수행합니다.<br><br>통솔이 높을 수록 수행할 확률이 높습니다.', '긴급내정': '전쟁중에 민심이 70 미만이거나,<br>인구가 제자리 징병이 가능하지 않을 정도로 적을 경우,<br>일정확률로 주민선정과 정착장려를 수행합니다.<br><br>통솔이 높을 수록 수행할 확률이 높습니다.',
'전투준비': '충분한 병력을 가지고 있지만 훈련과 사기가 부족한 경우 훈련과 사기진작을 수행합니다.', '전투준비': '충분한 병력을 가지고 있지만 훈련과 사기가 부족한 경우 훈련과 사기진작을 수행합니다.',
'전방워프': '전투장이 충분한 병력을 가지고 있다면 전방으로 이동합니다.', '전방워프': '전투장이 충분한 병력을 가지고 있다면 전방으로 이동합니다.',
'NPC헌납': '국고가 부족한데 NPC장수가 충분한 금쌀을 가지고 있다면 일부를 헌납합니다. <br>NPC내정장은 국고가 넉넉하더라도 충분한 금쌀을 가지고 있다면 일부를 헌납합니다.', 'NPC헌납': '국고가 부족한데 NPC전쟁장이 충분한 금쌀(권장량 대비 1.5배)을 가지고 있다면 일부를 헌납합니다. <br>NPC내정장은 국고가 넉넉하더라도 충분한 금쌀을 가지고 있다면 권장량만 유지하고 헌납합니다.',
'징병': '전쟁 중 병력을 소진하였다면 재 징병합니다.<br><br>기존에 사용한 병종군 중에서 사용가능한 병종을 랜덤하게 선택합니다.<br>고급 병종을 선택할 확률이 조금 더 높습니다.<br><br>NPC의 경우 도시의 인구가 충분하지 않다면 징병을 할 확률이 감소합니다.<br><br>유저장은 최대한 고급병종을 유지하며,<br>유저장 모병이 허용되는 경우 모병을 3회할 수 있다면 모병합니다.', '징병': '전쟁 중 병력을 소진하였다면 재 징병합니다.<br><br>기존에 사용한 병종군 중에서 사용가능한 병종을 랜덤하게 선택합니다.<br>고급 병종을 선택할 확률이 조금 더 높습니다.<br><br>NPC의 경우 도시의 인구가 충분하지 않다면 징병을 할 확률이 감소합니다.<br><br>유저장은 최대한 고급병종을 유지하며,<br>유저장 모병이 허용되는 경우 모병을 3회할 수 있다면 모병합니다.',
'후방워프': '전쟁 중 병력을 소진하였는데 도시의 인구가 충분하지 않다면,<br>인구가 많은 도시로 이동합니다.', '후방워프': '전쟁 중 병력을 소진하였는데 도시의 인구가 충분하지 않다면,<br>인구가 많은 도시로 이동합니다.',
'전쟁내정': '전쟁 중 수행하는 내정입니다.<br>정착장려, 기술연구의 확률이 좀 더 높고,<br>치안강화, 농지개간, 상업투자의 확률이 낮습니다.<br><br>내정이 가능하다 하더라도 전시임을 고려해,<br>30% 확률로 다른 턴을 수행합니다.', '전쟁내정': '전쟁 중 수행하는 내정입니다.<br>정착장려, 기술연구의 확률이 좀 더 높고,<br>치안강화, 농지개간, 상업투자의 확률이 낮습니다.<br><br>내정이 가능하다 하더라도 전시임을 고려해,<br>30% 확률로 다른 턴을 수행합니다.',
@@ -184,7 +185,7 @@ $autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['optio
</div> </div>
<div style='text-align:right;'><small class="form-text text-muted"> <div style='text-align:right;'><small class="form-text text-muted">
유저장긴급포상시 이보다 금이 적은 장수에게 포상합니다.<br> 유저장긴급포상시 이보다 금이 적은 장수에게 포상합니다.<br>
0이면 보병 6회 징병(<?= number_format(GameConst::$defaultStatMax * 100) ?> * 6) 가능한 금을 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqHumanWarUrgentGold) ?>입니다.</small></div> 0이면 보병 6회 징병(<?= number_format(GameConst::$defaultStatMax * 100) ?> * 6) 가능한 금을 기준으로 하며, 그 수치는 현재 <?= number_format($zeroPolicy->reqHumanWarUrgentGold) ?>입니다.</small></div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="row"> <div class="row">
@@ -193,7 +194,7 @@ $autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['optio
<input type="number" class="form-control" data-type="integer" id="reqHumanWarUrgentRice" min="0" value="0"> <input type="number" class="form-control" data-type="integer" id="reqHumanWarUrgentRice" min="0" value="0">
</div> </div>
</div> </div>
<div style='text-align:right;'><small class="form-text text-muted">유저장긴급포상시 이보다 쌀이 적은 장수에게 포상합니다.<br>0이면 기본 병종으로 <?= number_format(GameConst::$defaultStatMax * 100 * 6) ?>명 사살 가능한 쌀을 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqHumanWarUrgentRice) ?>입니다.</small></div> <div style='text-align:right;'><small class="form-text text-muted">유저장긴급포상시 이보다 쌀이 적은 장수에게 포상합니다.<br>0이면 기본 병종으로 <?= number_format(GameConst::$defaultStatMax * 100 * 6) ?>명 사살 가능한 쌀을 기준으로 하며, 그 수치는 현재 <?= number_format($zeroPolicy->reqHumanWarUrgentRice) ?>입니다.</small></div>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
@@ -205,7 +206,7 @@ $autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['optio
</div> </div>
</div> </div>
<div style='text-align:right;'><small class="form-text text-muted">유저전투장에게 주는 금입니다. 이보다 적으면 포상합니다. <br> <div style='text-align:right;'><small class="form-text text-muted">유저전투장에게 주는 금입니다. 이보다 적으면 포상합니다. <br>
0이면 유저전투장 긴급포상 금의 3배를 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqHumanWarRecommandGold) ?>입니다.</small></div> 0이면 유저전투장 긴급포상 금의 2배를 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqHumanWarRecommandGold) ?>입니다.</small></div>
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="row"> <div class="row">
@@ -215,7 +216,7 @@ $autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['optio
</div> </div>
</div> </div>
<div style='text-align:right;'><small class="form-text text-muted">유저전투장에게 주는 쌀입니다. 이보다 적으면 포상합니다. <br> <div style='text-align:right;'><small class="form-text text-muted">유저전투장에게 주는 쌀입니다. 이보다 적으면 포상합니다. <br>
0이면 유저전투장 긴급포상 쌀의 3배를 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqHumanWarRecommandRice) ?>입니다.</small></div> 0이면 유저전투장 긴급포상 쌀의 2배를 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqHumanWarRecommandRice) ?>입니다.</small></div>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
+131 -127
View File
@@ -1,127 +1,131 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
//로그인 검사 //로그인 검사
$commandType = Util::getReq('command', 'string'); $commandType = Util::getReq('command', 'string');
$turnList = array_map('intval', explode('_', Util::getReq('turnList', 'string', '0'))); $turnList = array_map('intval', explode('_', Util::getReq('turnList', 'string', '0')));
$isChiefTurn = Util::getReq('is_chief', 'bool', false); $isChiefTurn = Util::getReq('is_chief', 'bool', false);
function die_redirect() function die_redirect()
{ {
global $isChiefTurn; global $isChiefTurn;
if(!$isChiefTurn){ if(!$isChiefTurn){
header('location:index.php', true, 303); header('location:index.php', true, 303);
} }
else{ else{
header('location:b_chiefcenter.php', true, 303); header('location:b_chiefcenter.php', true, 303);
} }
die(); die();
} }
if(!$turnList || !$commandType){ if(!$turnList || !$commandType){
die_redirect(); die_redirect();
} }
if(!is_array($turnList)){ if(!is_array($turnList)){
die_redirect(); die_redirect();
} }
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$db = DB::db(); $db = DB::db();
if(!$isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableGeneralCommand))){ if(!$isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableGeneralCommand))){
die_redirect(); die_redirect();
} }
if($isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableChiefCommand))){ if($isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableChiefCommand))){
die_redirect(); die_redirect();
} }
$gameStor = KVStorage::getStorage($db, 'game_env')->turnOnCache(); $gameStor = KVStorage::getStorage($db, 'game_env')->turnOnCache();
$env = $gameStor->getAll(); $env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($session->generalID); $general = General::createGeneralObjFromDB($session->generalID);
if(!$isChiefTurn){ if(!$isChiefTurn){
$commandObj = buildGeneralCommandClass($commandType, $general, $env); $commandObj = buildGeneralCommandClass($commandType, $general, $env);
} }
else{ else{
if($general->getVar('officer_level') < 5){ if($general->getVar('officer_level') < 5){
die_redirect(); die_redirect();
} }
$commandObj = buildNationCommandClass($commandType, $general, $env, new LastTurn()); $commandObj = buildNationCommandClass($commandType, $general, $env, new LastTurn());
} }
if($commandObj->isArgValid()){ if($commandObj->isArgValid()){
//인자가 필요없는 타입의 경우 processing에서 '전혀' 처리하지 않음! //인자가 필요없는 타입의 경우 processing에서 '전혀' 처리하지 않음!
die_redirect(); die_redirect();
} }
if(!$commandObj->hasPermissionToReserve()){ if(!$commandObj->hasPermissionToReserve()){
die_redirect(); die_redirect();
} }
$jsList = $commandObj->getJSFiles(); $jsList = $commandObj->getJSFiles();
$cssList = $commandObj->getCSSFiles(); $cssList = $commandObj->getCSSFiles();
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title><?=$commandObj->getName()?></title> <title><?=$commandObj->getName()?></title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> <?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?> <?=WebUtil::printJS('../e_lib/select2/select2.full.min.js')?>
<?=WebUtil::printJS('js/common.js')?> <?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?> <?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/map.js')?> <?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/processing.js')?> <?=WebUtil::printJS('js/map.js')?>
<script> <?=WebUtil::printJS('js/processing.js')?>
window.serverNick = '<?=DB::prefix()?>'; <script>
window.serverID = '<?=UniqueConst::$serverID?>'; window.serverNick = '<?=DB::prefix()?>';
window.command = '<?=$commandType?>'; window.serverID = '<?=UniqueConst::$serverID?>';
window.turnList = [<?=join(', ',$turnList)?>]; window.command = '<?=$commandType?>';
window.isChiefTurn = <?=$isChiefTurn?'true':'false'?>; window.turnList = [<?=join(', ',$turnList)?>];
</script> window.isChiefTurn = <?=$isChiefTurn?'true':'false'?>;
<?php </script>
foreach($jsList as $js){ <?php
print(WebUtil::printJS($js)); foreach($jsList as $js){
} print(WebUtil::printJS($js));
?> }
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> ?>
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('css/common.css')?> <?=WebUtil::printCSS('../e_lib/select2/select2.min.css')?>
<?=WebUtil::printCSS('css/main.css')?> <?=WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css')?>
<?=WebUtil::printCSS('css/map.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
<?php <?=WebUtil::printCSS('css/common.css')?>
foreach($cssList as $css){ <?=WebUtil::printCSS('css/main.css')?>
print(WebUtil::printCSS($css)); <?=WebUtil::printCSS('css/map.css')?>
} <?=WebUtil::printCSS('css/processing.css')?>
?> <?php
</head> foreach($cssList as $css){
<body class="img_back"> print(WebUtil::printCSS($css));
<table class="tb_layout bg0" style="width:1000px;margin:auto;"> }
<tr><td class="bg1" style='text-align:center;'><?=$commandObj->getName()?></td></tr> ?>
<tr><td> </head>
<input type=button value='돌아가기' onclick="history.back();"><br> <body class="img_back">
</td></tr></table> <table class="tb_layout bg0" style="width:1000px;margin:auto;">
<tr><td class="bg1" style='text-align:center;'><?=$commandObj->getName()?></td></tr>
<div class="tb_layout bg0" style="width:1000px;margin:auto;padding-bottom:2em;border:solid 1px gray;"> <tr><td>
<?=$commandObj->getForm()?> <input type=button value='돌아가기' onclick="history.back();"><br>
</div> </td></tr></table>
<table class="tb_layout bg0" style="width:1000px;margin:auto;"> <div class="tb_layout bg0" style="width:1000px;margin:auto;padding-bottom:2em;border:solid 1px gray;">
<tr><td> <?=$commandObj->getForm()?>
<input type=button value='돌아가기' onclick="history.back();"><br> </div>
<?=banner()?>
</td></tr></table> <table class="tb_layout bg0" style="width:1000px;margin:auto;">
<tr><td>
<input type=button value='돌아가기' onclick="history.back();"><br>
</body> <?=banner()?>
</html> </td></tr></table>
</body>
</html>
+551 -480
View File
@@ -1,481 +1,552 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
$session = Session::requireLogin()->setReadOnly(); $session = Session::requireLogin()->setReadOnly();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->getValue('startyear'); $gameStor->cacheValues(['startyear', 'year']);
$startYear = $gameStor->startyear;
?> $year = $gameStor->year;
<!DOCTYPE html>
<html> $me = $db->queryFirstRow('SELECT no, nation, city FROM general WHERE owner =%i', Session::getUserID());
<head>
<title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title> if($me){
<meta charset="UTF-8"> $generalID = $me['no'];
<meta http-equiv="X-UA-Compatible" content="IE=edge"> $nationID = $me['nation'];
<meta name="viewport" content="width=1100" /> $city = $db->queryFirstRow('SELECT city, level, def, wall FROM city WHERE city = %i', $me['city']);
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> }
<?=WebUtil::printCSS('../d_shared/common.css')?> else{
<?=WebUtil::printCSS('css/common.css')?> $generalID = 0;
<?=WebUtil::printCSS('css/battle_simulator.css')?> $nationID = 0;
<?=WebUtil::printJS('../d_shared/common_path.js')?> $city = [
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> 'city'=>0,
<?=WebUtil::printJS('../e_lib/moment.min.js')?> 'level'=>5,
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> 'def'=>1000,
<?=WebUtil::printJS('../e_lib/download2.js')?> 'wall'=>1000,
<?=WebUtil::printJS('js/common.js')?> ];
<script> }
var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
</script> if($nationID){
<?=WebUtil::printJS('js/battle_simulator.js')?> $nation = $db->queryFirstRow('SELECT level, type, tech, capital FROM nation WHERE nation = %i', $nationID);
</head> }
<body> else{
<div id="container"> $nation = null;
<div class="card mb-3"> }
<div class="card-header">
전역 설정 ?>
</div> <!DOCTYPE html>
<div class="card-body dragpad_battle"> <html>
<div class="row"> <head>
<div class="col-sm-6"> <title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title>
<div class="input-group"> <meta charset="UTF-8">
<input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<div class="input-group-append"> <meta name="viewport" content="width=1100" />
<span class="input-group-text">년 시작</span> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
</div> <?=WebUtil::printCSS('../d_shared/common.css')?>
<input type="number" class="form-control" id="year" value="<?=$startYear+3?>" min="<?=$startYear?>"> <?=WebUtil::printCSS('css/common.css')?>
<div class="input-group-append"> <?=WebUtil::printCSS('css/battle_simulator.css')?>
<span class="input-group-text">년</span> <?=WebUtil::printJS('../d_shared/common_path.js')?>
</div> <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<input type="number" class="form-control" id="month" value="1" min="1" max="12"> <?=WebUtil::printJS('../e_lib/moment.min.js')?>
<div class="input-group-append"> <?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<span class="input-group-text">월</span> <?=WebUtil::printJS('../e_lib/download2.js')?>
</div> <?=WebUtil::printJS('js/common.js')?>
</div> <script>
</div> var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
<div class="col-sm-6"> var city = <?=Json::encode($city)?>;
<div class="btn-toolbar" role="toolbar"> var nation = <?=Json::encode($nation)?>;
<div class="input-group mr-2" role="group"> </script>
<div class="input-group-prepend"> <?=WebUtil::printJS('js/battle_simulator.js')?>
<span class="input-group-text">반복 횟수</span> </head>
</div> <body>
<select class="custom-select" id="repeat_cnt"> <div id="container">
<option value="1">1회 (로그 표기)</option> <div class="card mb-3">
<option value="1000">1000회 (요약 표기)</option> <div class="card-header">
</select> 전역 설정
</div> </div>
<div class="btn-group mr-2" role="group"> <div class="card-body dragpad_battle">
<button type="button" class="btn btn-danger btn-begin_battle">전투</button> <div class="row">
</div> <div class="col-sm-6">
<div class="btn-group mr-2" role="group"> <div class="input-group">
<button type="button" class="btn btn-info btn-battle-save">모두 저장</button> <input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled>
<input type="file" class="form_load_battle_file" accept=".json" style="display: none;" /> <div class="input-group-append">
<button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button> <span class="input-group-text">년 시작</span>
</div> </div>
</div> <input type="number" class="form-control" id="year" value="<?=$year?>" min="<?=$startYear?>">
</div> <div class="input-group-append">
</div> <span class="input-group-text">년</span>
</div> </div>
</div> <input type="number" class="form-control" id="month" value="1" min="1" max="12">
<div class="row"> <div class="input-group-append">
<div class="col-sm"> <span class="input-group-text">월</span>
<div class="card mb-2 attacker_nation"> </div>
<div class="card-header"> </div>
출병국 설정 </div>
</div> <div class="col-sm-6">
<div class="card-body nation_detail dragpad_battle"> <div class="btn-toolbar" role="toolbar">
<div class="input-group mb-1"> <div class="input-group mr-2" role="group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text">국가 성향</span> <span class="input-group-text">반복 횟수</span>
</div> </div>
<select class="custom-select form_nation_type" style="width:25ch;"> <select class="custom-select" id="repeat_cnt">
<?php foreach(GameConst::$availableNationType as $typeID): ?> <option value="1">1회 (로그 표기)</option>
<?php $nationTypeClass = buildNationTypeClass($typeID) ?> <option value="1000">1000회 (요약 표기)</option>
<option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option> </select>
<?php endforeach; ?> </div>
</select> <div class="btn-group mr-2" role="group">
<div class="input-group-prepend"> <button type="button" class="btn btn-danger btn-begin_battle">전투</button>
<span class="input-group-text">기술</span> </div>
</div> <div class="btn-group mr-2" role="group">
<input type="number" class="form-control form_tech" value="1" min="0" max="12"> <button type="button" class="btn btn-info btn-battle-save">모두 저장</button>
<div class="input-group-append"> <input type="file" class="form_load_battle_file" accept=".json" style="display: none;" />
<span class="input-group-text">등급</span> <button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button>
</div> </div>
</div> </div>
<div class="input-group mb-3"> </div>
<div class="input-group-prepend"> </div>
<span class="input-group-text">국가 규모</span> </div>
</div> </div>
<select class="custom-select form_nation_level"> <div class="row">
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?> <div class="col-sm">
<option value="<?=$nationLevel?>"><?=$name?></option> <div class="card mb-2 attacker_nation">
<?php endforeach; ?> <div class="card-header">
</select> 출병국 설정
<div class="input-group-prepend"> </div>
<span class="input-group-text">도시 규모</span> <div class="card-body nation_detail dragpad_battle">
</div> <div class="input-group mb-1">
<select class="custom-select form_city_level"> <div class="input-group-prepend">
<?php foreach(getCityLevelList() as $levelID => $name): ?> <span class="input-group-text">국가 성향</span>
<option value="<?=$levelID?>"><?=$name?></option> </div>
<?php endforeach; ?> <select class="custom-select form_nation_type" style="width:25ch;">
</select> <?php foreach(GameConst::$availableNationType as $typeID): ?>
<div class="input-group-prepend"> <?php $nationTypeClass = buildNationTypeClass($typeID) ?>
<span class="input-group-text">수도</span> <option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option>
</div> <?php endforeach; ?>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons"> </select>
<label class="btn btn-secondary"> <div class="input-group-prepend">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y <span class="input-group-text">기술</span>
</label> </div>
<label class="btn btn-secondary active"> <input type="number" class="form-control form_tech" value="1" min="0" max="12">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="2" autocomplete="off" checked>N <div class="input-group-append">
</label> <span class="input-group-text">등급</span>
</div> </div>
</div>
</div> <div class="input-group mb-3">
<div class="input-group mb-1"> <div class="input-group-prepend">
<span class="input-group-text">국가 규모</span>
</div> </div>
</div> <select class="custom-select form_nation_level">
</div> <?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
<div class="card mb-2 attacker_form general_form" data-general_no='1'> <option value="<?=$nationLevel?>"><?=$name?></option>
<div class="card-header"> <?php endforeach; ?>
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div> </select>
<div class="float-sm-right btn-toolbar" role="toolbar"> <div class="input-group-prepend">
<div class="btn-group btn-group-sm mr-2" role="group"> <span class="input-group-text">도시 규모</span>
<button type="button" class="btn btn-info btn-general-save">저장</button> </div>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" /> <select class="custom-select form_city_level">
<button type="button" class="btn btn-primary btn-general-load">불러오기</button> <?php foreach(getCityLevelList() as $levelID => $name): ?>
</div> <option value="<?=$levelID?>"><?=$name?></option>
</div> <?php endforeach; ?>
</div> </select>
</div> <div class="input-group-prepend">
</div><!-- <div class="col-sm"> --> <span class="input-group-text">수도</span>
<div class="col-sm defender-column"> </div>
<div class="card mb-2 defender_nation"> <div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
<div class="card-header"> <label class="btn btn-secondary">
수비국 설정 <input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y
</div> </label>
<div class="card-body dragpad_battle"> <label class="btn btn-secondary active">
<div class="input-group mb-1"> <input type="radio" name="is_attacker_capital" class="form_is_capital" value="0" autocomplete="off">N
<div class="input-group-prepend"> </label>
<span class="input-group-text">국가 성향</span> </div>
</div>
<select class="custom-select form_nation_type" style="width:25ch;"> </div>
<?php foreach(GameConst::$availableNationType as $typeID): ?> <div class="input-group mb-1">
<?php $nationTypeObj = buildNationTypeClass($typeID) ?>
<option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option> </div>
<?php endforeach; ?> </div>
</select> </div>
<div class="input-group-prepend"> <div class="card mb-2 attacker_form general_form" data-general_no='1'>
<span class="input-group-text">기술</span> <div class="card-header">
</div> <div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
<input type="number" class="form-control form_tech" value="1" min="0" max="12"> <div class="float-sm-right btn-toolbar" role="toolbar">
<div class="input-group-append"> <div class="btn-group btn-group-sm mr-2" role="group">
<span class="input-group-text">등급</span> <button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
</div> </div>
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<div class="input-group mb-3"> <button type="button" class="btn btn-info btn-general-save">저장</button>
<div class="input-group-prepend"> <input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<span class="input-group-text">국가 규모</span> <button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div> </div>
<select class="custom-select form_nation_level"> </div>
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?> </div>
<option value="<?=$nationLevel?>"><?=$name?></option> </div>
<?php endforeach; ?> </div><!-- <div class="col-sm"> -->
</select> <div class="col-sm defender-column">
<div class="input-group-prepend"> <div class="card mb-2 defender_nation">
<span class="input-group-text">도시 규모</span> <div class="card-header">
</div> 수비국 설정
<select class="custom-select form_city_level"> </div>
<?php foreach(getCityLevelList() as $levelID => $name): ?> <div class="card-body dragpad_battle">
<option value="<?=$levelID?>"><?=$name?></option> <div class="input-group mb-1">
<?php endforeach; ?> <div class="input-group-prepend">
</select> <span class="input-group-text">국가 성향</span>
<div class="input-group-prepend"> </div>
<span class="input-group-text">수도</span> <select class="custom-select form_nation_type" style="width:25ch;">
</div> <?php foreach(GameConst::$availableNationType as $typeID): ?>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons"> <?php $nationTypeObj = buildNationTypeClass($typeID) ?>
<label class="btn btn-secondary"> <option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option>
<input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y <?php endforeach; ?>
</label> </select>
<label class="btn btn-secondary active"> <div class="input-group-prepend">
<input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off" checked>N <span class="input-group-text">기술</span>
</label> </div>
</div> <input type="number" class="form-control form_tech" value="1" min="0" max="12">
</div> <div class="input-group-append">
<div class="input-group mb-1"> <span class="input-group-text">등급</span>
<div class="input-group-prepend"> </div>
<span class="input-group-text">수비</span> </div>
</div> <div class="input-group mb-3">
<input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10"> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">국가 규모</span>
<span class="input-group-text">성벽</span> </div>
</div> <select class="custom-select form_nation_level">
<input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10"> <?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
</div> <option value="<?=$nationLevel?>"><?=$name?></option>
</div> <?php endforeach; ?>
</div> </select>
<div class="card mb-2 defender_add_form"> <div class="input-group-prepend">
<div class="card-header"> <span class="input-group-text">도시 규모</span>
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div> </div>
<div class="float-sm-right btn-toolbar" role="toolbar"> <select class="custom-select form_city_level">
<div class="btn-group btn-group-sm mr-2" role="group"> <?php foreach(getCityLevelList() as $levelID => $name): ?>
<button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button> <option value="<?=$levelID?>"><?=$name?></option>
</div> <?php endforeach; ?>
<div class="btn-group btn-group-sm" role="group"> </select>
<button type="button" class="btn btn-success add-defender">추가</button> <div class="input-group-prepend">
</div> <span class="input-group-text">수도</span>
</div> </div>
</div> <div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
</div> <label class="btn btn-secondary">
<div class="card mb-2 form_sample"> <input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y
<div class="card-header"> </label>
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div> <label class="btn btn-secondary active">
<div class="float-sm-right btn-toolbar" role="toolbar"> <input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off">N
<div class="btn-group btn-group-sm mr-2" role="group"> </label>
<button type="button" class="btn btn-info btn-general-save">저장</button> </div>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" /> </div>
<button type="button" class="btn btn-primary btn-general-load">불러오기</button> <div class="input-group mb-1">
</div> <div class="input-group-prepend">
<div class="btn-group btn-group-sm" role="group"> <span class="input-group-text">수비</span>
<button type="button" class="btn btn-warning copy-defender">복제</button> </div>
<button type="button" class="btn btn-danger delete-defender">제거</button> <input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10">
</div> <div class="input-group-prepend">
</div> <span class="input-group-text">성벽</span>
</div> </div>
<div class="card-body general_detail"> <input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10">
<div class="input-group mb-3"> </div>
<div class="input-group-prepend"> </div>
<span class="input-group-text">이름</span> </div>
</div> <div class="card mb-2 defender_add_form">
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;"> <div class="card-header">
<div class="input-group-prepend"> <div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<span class="input-group-text">직위</span> <div class="float-sm-right btn-toolbar" role="toolbar">
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<select class="custom-select form_officer_level" style="width:8ch;"> <button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button>
<option value="1">일반</option> </div>
<option value="4">태수</option> <div class="btn-group btn-group-sm" role="group">
<option value="3">군사</option> <button type="button" class="btn btn-success add-defender">추가</button>
<option value="2">종사</option> </div>
<option value="10">무장 수뇌</option> </div>
<option value="9">지장 수뇌</option> </div>
<option value="11">참모</option> </div>
<option value="12">군주</option> <div class="card mb-2 form_sample">
</select> <div class="card-header">
<div class="input-group-prepend"> <div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<span class="input-group-text">Level</span> <div class="float-sm-right btn-toolbar" role="toolbar">
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1"> <button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
</div>
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<div class="input-group mb-1"> <button type="button" class="btn btn-info btn-general-save">저장</button>
<div class="input-group-prepend"> <input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<span class="input-group-text">통솔</span> <button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div> </div>
<input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1"> <div class="btn-group btn-group-sm" role="group">
<div class="input-group-prepend"> <button type="button" class="btn btn-warning copy-defender">복제</button>
<span class="input-group-text">무력</span> <button type="button" class="btn btn-danger delete-defender">제거</button>
</div> </div>
<input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1"> </div>
<div class="input-group-prepend"> </div>
<span class="input-group-text">지력</span> <div class="card-body general_detail">
</div> <div class="input-group mb-3">
<input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1"> <div class="input-group-prepend">
</div> <span class="input-group-text">이름</span>
<div class="input-group mb-1"> </div>
<div class="input-group-prepend"> <input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
<span class="input-group-text">명마</span> <div class="input-group-prepend">
</div> <span class="input-group-text">직위</span>
<select class="custom-select form_general_horse"> </div>
<option value='None'>-</option> <select class="custom-select form_officer_level" style="width:8ch;">
<?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?> <option value="1">일반</option>
<option value="<?=$horseID?>"><?=getItemName($horseID)?></option> <option value="4">태수</option>
<?php endforeach; ?> <option value="3">군사</option>
</select> <option value="2">종사</option>
<div class="input-group-prepend"> <option value="10">무장 수뇌</option>
<span class="input-group-text">무기</span> <option value="9">지장 수뇌</option>
</div> <option value="11">참모</option>
<select class="custom-select form_general_weap"> <option value="12">군주</option>
<option value='None'>-</option> </select>
<?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?> <div class="input-group-prepend">
<option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option> <span class="input-group-text">Level</span>
<?php endforeach; ?> </div>
</select> <input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
<div class="input-group-prepend">
<span class="input-group-text">서적</span> </div>
</div> <div class="input-group mb-1">
<select class="custom-select form_general_book"> <div class="input-group-prepend">
<option value='None'>-</option> <span class="input-group-text">통솔</span>
<?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?> </div>
<option value="<?=$bookID?>"><?=getItemName($bookID)?></option> <input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1">
<?php endforeach; ?> <div class="input-group-prepend">
</select> <span class="input-group-text">무력</span>
</div> </div>
<div class="input-group mb-3"> <input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text">부상</span> <span class="input-group-text">지력</span>
</div> </div>
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1"> <input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1">
<div class="input-group-append"> </div>
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span> <div class="input-group mb-1">
</div> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">명마</span>
<span class="input-group-text">군량</span> </div>
</div> <select class="custom-select form_general_horse">
<input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50"> <option value='None'>-</option>
<div class="input-group-prepend"> <?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?>
<span class="input-group-text">도구</span> <option value="<?=$horseID?>"><?=getItemName($horseID)?></option>
</div> <?php endforeach; ?>
<select class="custom-select form_general_item"> </select>
<option value='None'>-</option> <div class="input-group-prepend">
<?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?> <span class="input-group-text">무기</span>
<option value="<?=$itemID?>"><?=getItemName($itemID)?></option> </div>
<?php endforeach; ?> <select class="custom-select form_general_weap">
</select> <option value='None'>-</option>
</div> <?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?>
<div class="input-group mb-1"> <option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option>
<div class="input-group-prepend"> <?php endforeach; ?>
<span class="input-group-text">병종</span> </select>
</div> <div class="input-group-prepend">
<select class="custom-select form_crewtype"> <span class="input-group-text">서적</span>
<?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?> </div>
<?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?> <select class="custom-select form_general_book">
<option value="<?=$crewTypeID?>"><?=$crewType->name?></option> <option value='None'>-</option>
<?php endforeach; ?> <?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?>
</select> <option value="<?=$bookID?>"><?=getItemName($bookID)?></option>
<div class="input-group-prepend"> <?php endforeach; ?>
<span class="input-group-text">병사</span> </select>
</div> </div>
<input type="number" class="form-control form_crew" value="7000" min="100" step="100"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text">성격</span> <span class="input-group-text">부상</span>
</div> </div>
<select class="custom-select form_general_character"> <input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
<?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?> <div class="input-group-append">
<option value="<?=$characterID?>"><?=$name?></option> <span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
<?php endforeach; ?> </div>
</select> <div class="input-group-prepend">
</div> <span class="input-group-text">군량</span>
<div class="input-group mb-3"> </div>
<div class="input-group-prepend"> <input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50">
<span class="input-group-text">훈련</span> <div class="input-group-prepend">
</div> <span class="input-group-text">도구</span>
<input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1"> </div>
<div class="input-group-prepend"> <select class="custom-select form_general_item">
<span class="input-group-text">사기</span> <option value='None'>-</option>
</div> <?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?>
<input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1"> <option value="<?=$itemID?>"><?=getItemName($itemID)?></option>
<div class="input-group-prepend"> <?php endforeach; ?>
<span class="input-group-text">전특</span> </select>
</div> </div>
<select class="custom-select form_general_special_war"> <div class="input-group mb-1">
<?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?> <div class="input-group-prepend">
<option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option> <span class="input-group-text">병종</span>
<?php endforeach; ?> </div>
</select> <select class="custom-select form_crewtype">
</div> <?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?>
<div class="input-group mb-1"> <?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?>
<div class="input-group-prepend"> <option value="<?=$crewTypeID?>"><?=$crewType->name?></option>
<span class="input-group-text">보병숙련</span> <?php endforeach; ?>
</div> </select>
<select class="custom-select form_dex1"> <div class="input-group-prepend">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <span class="input-group-text">병사</span>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> </div>
<?php endforeach; ?> <input type="number" class="form-control form_crew" value="7000" min="100" step="100">
</select> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">성격</span>
<span class="input-group-text">궁병숙련</span> </div>
</div> <select class="custom-select form_general_character">
<select class="custom-select form_dex2"> <?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <option value="<?=$characterID?>"><?=$name?></option>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <?php endforeach; ?>
<?php endforeach; ?> </select>
</select> </div>
<div class="input-group-prepend"> <div class="input-group mb-3">
<span class="input-group-text">기병숙련</span> <div class="input-group-prepend">
</div> <span class="input-group-text">훈련</span>
<select class="custom-select form_dex3"> </div>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1">
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <div class="input-group-prepend">
<?php endforeach; ?> <span class="input-group-text">사기</span>
</select> </div>
</div> <input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1">
<div class="input-group mb-1"> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">전특</span>
<span class="input-group-text">귀병숙련</span> </div>
</div> <select class="custom-select form_general_special_war">
<select class="custom-select form_dex4"> <?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <?php endforeach; ?>
<?php endforeach; ?> </select>
</select> </div>
<div class="input-group-prepend"> <div class="input-group mb-1">
<span class="input-group-text">차병숙련</span> <div class="input-group-prepend">
</div> <span class="input-group-text">보병숙련</span>
<select class="custom-select form_dex5"> </div>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <select class="custom-select form_dex1">
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<?php endforeach; ?> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
</select> <?php endforeach; ?>
<div class="input-group-prepend only_defender"> </select>
<span class="input-group-text">수비여부</span> <div class="input-group-prepend">
</div> <span class="input-group-text">궁병숙련</span>
<select class="custom-select form_defence_train only_defender"> </div>
<option value="80">훈사 80</option> <select class="custom-select form_dex2">
<option value="60">훈사 60</option> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="999">안함</option> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
</select> <?php endforeach; ?>
</div> </select>
</div> <div class="input-group-prepend">
</div> <span class="input-group-text">기병숙련</span>
</div>
<select class="custom-select form_dex3">
</div><!-- <div class="col-sm"> --> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
</div> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<div class="card mb-3"> <?php endforeach; ?>
<div class="card-header"> </select>
전투 요약 </div>
</div> <div class="input-group mb-3">
<table class="table"> <div class="input-group-prepend">
<tbody id="battle_result_summary"> <span class="input-group-text">귀병숙련</span>
<tr><th style='width:18ch;'>전투 일시</th><td id='result_datetime'></td></tr> </div>
<tr><th>전투 횟수</th><td id='result_warcnt'></td></tr> <select class="custom-select form_dex4">
<tr><th>전투 페이즈</th><td id='result_phase'></td></tr> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<tr><th>준 피해</th><td><span id='result_killed'>0</span><span id='result_varKilled'> (<span id='result_minKilled'>0</span> ~ <span id='result_maxKilled'>0</span>)</span></td></tr> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<tr><th>받은 피해</th><td><span id='result_dead'>0</span><span id='result_varDead'> (<span id='result_minDead'>0</span> ~ <span id='result_maxDead'>0</span>)</span></td></tr> <?php endforeach; ?>
<tr><th>출병자 군량 소모</th><td id='result_attackerRice'></td></tr> </select>
<tr><th>수비자 군량 소모</th><td id='result_defenderRice'></td></tr> <div class="input-group-prepend">
<tr><th>공격자 스킬</th><td id='result_attackerSkills'></td></tr> <span class="input-group-text">차병숙련</span>
<tr class='result_defenderSkills'><th>수비자1 스킬</th><td></td></tr> </div>
</tbody> <select class="custom-select form_dex5">
</table> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
</div> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<div class="row"> <?php endforeach; ?>
<div class="col-sm"> </select>
<div class="card mb-3"> <div class="input-group-prepend only_defender">
<div class="card-header"> <span class="input-group-text">수비여부</span>
마지막 전투 로그 </div>
</div> <select class="custom-select form_defence_train only_defender">
<div class="card-body" id="generalBattleResultLog"> <option value="90">훈사 90</option>
<option value="80">훈사 80</option>
</div> <option value="60">훈사 60</option>
</div> <option value="40">훈사 40</option>
</div> <option value="999">안함</option>
<div class="col-sm"> </select>
<div class="card mb-3"> </div>
<div class="card-header"> <div class="input-group mb-1">
마지막 전투 상세 로그 <div class="input-group-prepend">
</div> <span class="input-group-text">전투 수</span>
<div class="card-body" id="generalBattleDetailLog"> </div>
<input type="number" class="form-control form_warnum" value="0" step="1">
</div> <div class="input-group-prepend">
</div> <span class="input-group-text">승리 수</span>
</div> </div>
</div> <input type="number" class="form-control form_killnum" value="0" step="1">
</div> <div class="input-group-prepend">
</body> <span class="input-group-text">사살 수</span>
</div>
<input type="number" class="form-control form_killcrew" value="0" step="1">
</div>
</div>
</div>
</div><!-- <div class="col-sm"> -->
</div>
<div class="card mb-3">
<div class="card-header">
전투 요약
</div>
<table class="table">
<tbody id="battle_result_summary">
<tr><th style='width:18ch;'>전투 일시</th><td id='result_datetime'></td></tr>
<tr><th>전투 횟수</th><td id='result_warcnt'></td></tr>
<tr><th>전투 페이즈</th><td id='result_phase'></td></tr>
<tr><th>준 피해</th><td><span id='result_killed'>0</span><span id='result_varKilled'> (<span id='result_minKilled'>0</span> ~ <span id='result_maxKilled'>0</span>)</span></td></tr>
<tr><th>받은 피해</th><td><span id='result_dead'>0</span><span id='result_varDead'> (<span id='result_minDead'>0</span> ~ <span id='result_maxDead'>0</span>)</span></td></tr>
<tr><th>출병자 군량 소모</th><td id='result_attackerRice'></td></tr>
<tr><th>수비자 군량 소모</th><td id='result_defenderRice'></td></tr>
<tr><th>공격자 스킬</th><td id='result_attackerSkills'></td></tr>
<tr class='result_defenderSkills'><th>수비자1 스킬</th><td></td></tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm">
<div class="card mb-3">
<div class="card-header">
마지막 전투 로그
</div>
<div class="card-body" id="generalBattleResultLog">
</div>
</div>
</div>
<div class="col-sm">
<div class="card mb-3">
<div class="card-header">
마지막 전투 상세 로그
</div>
<div class="card-body" id="generalBattleDetailLog">
</div>
</div>
</div>
</div>
</div>
<div id="importModal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">장수 목록</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<select id="modalSelector"></select>
<p>타국 장수를 선택한 경우 숙련과 아이템은 0으로 초기화됩니다.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id='importFromDB'>가져오기</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">닫기</button>
</div>
</div>
</div>
</div>
</body>
</html> </html>
+1 -1
View File
@@ -49,6 +49,7 @@ if($btn == '참가') {
$general['gold'] -= $admin['develcost']; $general['gold'] -= $admin['develcost'];
$freeSlot = [ $freeSlot = [
0=>8,
1=>8, 1=>8,
2=>8, 2=>8,
3=>8, 3=>8,
@@ -56,7 +57,6 @@ if($btn == '참가') {
5=>8, 5=>8,
6=>8, 6=>8,
7=>8, 7=>8,
8=>8,
]; ];
foreach($db->query('SELECT count(*) as cnt, grp FROM tournament WHERE grp < 10 GROUP BY grp') as $grpInfo){ foreach($db->query('SELECT count(*) as cnt, grp FROM tournament WHERE grp < 10 GROUP BY grp') as $grpInfo){
if($grpInfo['cnt'] == 8){ if($grpInfo['cnt'] == 8){
+11
View File
@@ -0,0 +1,11 @@
#amount {
width: 100px;
}
#colorType {
width: 150px;
}
.no-padding .select2-results__option {
padding: 0;
}
+2137 -2105
View File
File diff suppressed because it is too large Load Diff
+447 -447
View File
@@ -1,448 +1,448 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Command\GeneralCommand; use sammo\Command\GeneralCommand;
use sammo\Command\NationCommand; use sammo\Command\NationCommand;
function getGeneralTurnBrief(General $generalObj, array $turnList) { function getGeneralTurnBrief(General $generalObj, array $turnList) {
$result = []; $result = [];
foreach($turnList as $turnIdx => [$action, $arg]){ foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg); $commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg);
$turnText = $commandObj->getBrief(); $turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText; $result[$turnIdx] = $turnText;
} }
return $result; return $result;
} }
function getNationTurnBrief(General $generalObj, array $turnList) { function getNationTurnBrief(General $generalObj, array $turnList) {
$result = []; $result = [];
$tmpTurn = new LastTurn(); $tmpTurn = new LastTurn();
foreach($turnList as $turnIdx => [$action, $arg]){ foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg); $commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg);
$turnText = $commandObj->getBrief(); $turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText; $result[$turnIdx] = $turnText;
} }
return $result; return $result;
} }
function pushGeneralCommand(int $generalID, int $turnCnt=1){ function pushGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pullGeneralCommand($generalID, -$turnCnt); pullGeneralCommand($generalID, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxTurn){ if($turnCnt >= GameConst::$maxTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx DESC', $generalID); ], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn), 'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식' 'brief'=>'휴식'
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn); ], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
} }
function pullGeneralCommand(int $generalID, int $turnCnt=1){ function pullGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pushGeneralCommand($generalID, -$turnCnt); pushGeneralCommand($generalID, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxTurn){ if($turnCnt >= GameConst::$maxTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn), 'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식' 'brief'=>'휴식'
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt); ], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx ASC', $generalID); ], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
} }
function repeatGeneralCommand(int $generalId, int $turnCnt){ function repeatGeneralCommand(int $generalId, int $turnCnt){
if($turnCnt <= 0){ if($turnCnt <= 0){
return; return;
} }
if($turnCnt >= GameConst::$maxTurn){ if($turnCnt >= GameConst::$maxTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$reqTurn = $turnCnt; $reqTurn = $turnCnt;
if($turnCnt * 2 > GameConst::$maxTurn){ if($turnCnt * 2 > GameConst::$maxTurn){
$reqTurn = GameConst::$maxTurn - $turnCnt; $reqTurn = GameConst::$maxTurn - $turnCnt;
} }
$turnList = $db->query('SELECT turn_idx, `action`, arg, brief FROM general_turn WHERE general_id=%i AND turn_idx < %i', $generalId, $reqTurn); $turnList = $db->query('SELECT turn_idx, `action`, arg, brief FROM general_turn WHERE general_id=%i AND turn_idx < %i', $generalId, $reqTurn);
foreach($turnList as $turnItem){ foreach($turnList as $turnItem){
$turnIdx = $turnItem['turn_idx']; $turnIdx = $turnItem['turn_idx'];
$turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt)); $turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt));
$db->update('general_turn', [ $db->update('general_turn', [
'action'=>$turnItem['action'], 'action'=>$turnItem['action'],
'arg'=>$turnItem['arg'], 'arg'=>$turnItem['arg'],
'brief'=>$turnItem['brief'] 'brief'=>$turnItem['brief']
], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget); ], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget);
} }
} }
function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){ function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
if($nationID == 0){ if($nationID == 0){
return; return;
} }
if($officerLevel < 5){ if($officerLevel < 5){
return; return;
} }
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pullNationCommand($nationID, $officerLevel, -$turnCnt); pullNationCommand($nationID, $officerLevel, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxChiefTurn){ if($turnCnt >= GameConst::$maxChiefTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel); ], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn), 'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식' 'brief'=>'휴식'
], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn); ], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn);
} }
function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){ function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
if($nationID == 0){ if($nationID == 0){
return; return;
} }
if($officerLevel < 5){ if($officerLevel < 5){
return; return;
} }
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pushNationCommand($nationID, $officerLevel, -$turnCnt); pushNationCommand($nationID, $officerLevel, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxChiefTurn){ if($turnCnt >= GameConst::$maxChiefTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn), 'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식', 'brief'=>'휴식',
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt); ], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel); ], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
} }
function _setGeneralCommand(GeneralCommand $command, array $turnList):void { function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
if(!$turnList){ if(!$turnList){
return; return;
} }
$db = DB::db(); $db = DB::db();
$generalID = $command->getGeneral()->getID(); $generalID = $command->getGeneral()->getID();
$commandName = $command->getRawClassName(); $commandName = $command->getRawClassName();
$arg = $command->getArg(); $arg = $command->getArg();
$brief = $command->getBrief(); $brief = $command->getBrief();
$db->update('general_turn', [ $db->update('general_turn', [
'action'=>$commandName, 'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT), 'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief 'brief'=>$brief
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList); ], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
} }
function _setNationCommand(NationCommand $command, array $turnList):void { function _setNationCommand(NationCommand $command, array $turnList):void {
if(!$turnList){ if(!$turnList){
return; return;
} }
$db = DB::db(); $db = DB::db();
$nationID = $command->getNationID(); $nationID = $command->getNationID();
$officerLevel = $command->getOfficerLevel(); $officerLevel = $command->getOfficerLevel();
$commandName = $command->getRawClassName(); $commandName = $command->getRawClassName();
$arg = $command->getArg(); $arg = $command->getArg();
$brief = $command->getBrief(); $brief = $command->getBrief();
$db->update('nation_turn', [ $db->update('nation_turn', [
'action'=>$commandName, 'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT), 'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief 'brief'=>$brief
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList); ], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
} }
function sanitizeArg(?array $args):?array{ function sanitizeArg(?array $args):?array{
if($args === null){ if($args === null){
return $args; return $args;
} }
$result = []; $result = [];
foreach($args as $key=>$value){ foreach($args as $key=>$value){
if(is_array($value)){ if(is_array($value)){
$result[$key] = sanitizeArg($value); $result[$key] = sanitizeArg($value);
} }
else if(is_string($value)){ else if(is_string($value)){
$result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value)); $result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value));
} }
else{ else{
$result[$key] = $value; $result[$key] = $value;
} }
} }
return $result; return $result;
} }
function checkCommandArg(?array $arg):?string{ function checkCommandArg(?array $arg):?string{
if($arg === null){ if($arg === null){
return null; return null;
} }
$defaultCheck = [ $defaultCheck = [
/*'string'=>[ /*'string'=>[
'nationName', 'optionText', 'itemType', 'nationType' 'nationName', 'optionText', 'itemType', 'nationType', 'commandType',
],*/ ],*/
'integer'=>[ 'integer'=>[
'crewType', 'destGeneralID', 'destCityID', 'destNationID', 'crewType', 'destGeneralID', 'destCityID', 'destNationID',
'amount', 'colorType', 'amount', 'colorType',
'srcArmType', 'destArmType', //숙련전환 전용 'srcArmType', 'destArmType', //숙련전환 전용
], ],
'boolean'=>[ 'boolean'=>[
'isGold', 'buyRice', 'isGold', 'buyRice',
], ],
'between'=>[ 'between'=>[
['month', [1, 12]] ['month', [1, 12]]
], ],
'min'=>[ 'min'=>[
['year', 0], ['year', 0],
['destGeneralID', 1], ['destGeneralID', 1],
['destCityID', 1], ['destCityID', 1],
['destNationID', 1], ['destNationID', 1],
['amount', 1], ['amount', 1],
['crewType', 0] ['crewType', 0]
], ],
'integerArray'=>[ 'integerArray'=>[
'destNationIDList', 'destGeneralIDList', 'amountList' 'destNationIDList', 'destGeneralIDList', 'amountList'
], ],
'stringWidthBetween'=>[ 'stringWidthBetween'=>[
['nationName', 1, 18] ['nationName', 1, 18]
] ]
]; ];
$v = new Validator($arg); $v = new Validator($arg);
$v->rules($defaultCheck); $v->rules($defaultCheck);
if (!$v->validate()){ if (!$v->validate()){
return $v->errorStr(); return $v->errorStr();
} }
return null; return null;
} }
function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{ function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{
$turnList = []; $turnList = [];
foreach($rawTurnList as $turnIdx){ foreach($rawTurnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){ if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx, 'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx', 'test'=>'turnIdx',
'target'=>$turnIdx, 'target'=>$turnIdx,
]; ];
} }
if($turnIdx >= 0){ if($turnIdx >= 0){
$turnList[$turnIdx] = true; $turnList[$turnIdx] = true;
} }
else if($turnIdx == -1){ else if($turnIdx == -1){
//홀수 //홀수, 0부터 맞다.
foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){ foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true; $turnList[$subIdx] = true;
} }
} }
else if($turnIdx == -2){ else if($turnIdx == -2){
//짝수 //짝수, 1부터 맞다.
foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){ foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true; $turnList[$subIdx] = true;
} }
} }
else if($turnIdx == -3){ else if($turnIdx == -3){
//모두 //모두
foreach(Util::range(GameConst::$maxTurn) as $subIdx){ foreach(Util::range(GameConst::$maxTurn) as $subIdx){
$turnList[$subIdx] = true; $turnList[$subIdx] = true;
} }
} }
} }
$turnList = array_keys($turnList); $turnList = array_keys($turnList);
$arg = sanitizeArg($arg); $arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg); $argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){ if($argBasicTestResult !== null){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.', 'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg', 'test'=>'checkCommandArg',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll(); $env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
try{ try{
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg); $commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
} }
catch (\InvalidArgumentException $e){ catch (\InvalidArgumentException $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getMessage(), 'reason'=>$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
catch (\Exception $e){ catch (\Exception $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getCode().$e->getMessage(), 'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->isArgValid()){ if(!$commandObj->isArgValid()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바르지 않은 argument', 'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid', 'test'=>'isArgValid',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->hasPermissionToReserve()){ if(!$commandObj->hasPermissionToReserve()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(), 'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve', 'test'=>'hasPermissionToReserve',
'target'=>'command' 'target'=>'command'
]; ];
} }
_setGeneralCommand($commandObj, $turnList); _setGeneralCommand($commandObj, $turnList);
return [ return [
'result'=>true, 'result'=>true,
'reason'=>'success' 'reason'=>'success'
]; ];
} }
function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{ function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{
$turnList = array_unique($turnList); $turnList = array_unique($turnList);
foreach($turnList as $turnIdx){ foreach($turnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){ if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx, 'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx', 'test'=>'turnIdx',
'target'=>$turnIdx, 'target'=>$turnIdx,
]; ];
} }
} }
$arg = sanitizeArg($arg); $arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg); $argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){ if($argBasicTestResult !== null){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.', 'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg', 'test'=>'checkCommandArg',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll(); $env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
if($general->getVar('officer_level') < 5){ if($general->getVar('officer_level') < 5){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'수뇌가 아닙니다' 'reason'=>'수뇌가 아닙니다'
]; ];
} }
try{ try{
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg); $commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
} }
catch (\InvalidArgumentException $e){ catch (\InvalidArgumentException $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getMessage(), 'reason'=>$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
catch (\Exception $e){ catch (\Exception $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getCode().$e->getMessage(), 'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->isArgValid()){ if(!$commandObj->isArgValid()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바르지 않은 argument', 'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid', 'test'=>'isArgValid',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->hasPermissionToReserve()){ if(!$commandObj->hasPermissionToReserve()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(), 'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve', 'test'=>'hasPermissionToReserve',
'target'=>'command' 'target'=>'command'
]; ];
} }
_setNationCommand($commandObj, $turnList); _setNationCommand($commandObj, $turnList);
return [ return [
'result'=>true, 'result'=>true,
'arg_test'=>true, 'arg_test'=>true,
'reason'=>'success' 'reason'=>'success'
]; ];
} }
+1139 -1136
View File
@@ -1,1136 +1,1139 @@
<?php <?php
namespace sammo; namespace sammo;
use Monolog\Logger; use Monolog\Logger;
/** /**
* 게임 룰에 해당하는 함수 모음 * 게임 룰에 해당하는 함수 모음
*/ */
function getNationLevelList(): array function getNationLevelList(): array
{ {
$table = [ $table = [
0 => ['방랑군', 2, 0], 0 => ['방랑군', 2, 0],
1 => ['호족', 2, 1], 1 => ['호족', 2, 1],
2 => ['군벌', 4, 2], 2 => ['군벌', 4, 2],
3 => ['주자사', 4, 5], 3 => ['주자사', 4, 5],
4 => ['주목', 6, 8], 4 => ['주목', 6, 8],
5 => ['공', 6, 11], 5 => ['공', 6, 11],
6 => ['왕', 8, 16], 6 => ['왕', 8, 16],
7 => ['황제', 8, 21], 7 => ['황제', 8, 21],
]; ];
return $table; return $table;
} }
function getCityLevelList(): array function getCityLevelList(): array
{ {
return [ return [
1 => '수', 1 => '수',
2 => '진', 2 => '진',
3 => '관', 3 => '관',
4 => '이', 4 => '이',
5 => '소', 5 => '소',
6 => '중', 6 => '중',
7 => '대', 7 => '대',
8 => '특' 8 => '특'
]; ];
} }
//한국가의 전체 전방 설정 //한국가의 전체 전방 설정
function SetNationFront($nationNo) function SetNationFront($nationNo)
{ {
if (!$nationNo) { if (!$nationNo) {
return; return;
} }
// 도시소유 국가와 선포,교전중인 국가 // 도시소유 국가와 선포,교전중인 국가
$adj3 = []; $adj3 = [];
$adj2 = []; $adj2 = [];
$adj1 = []; $adj1 = [];
$db = DB::db(); $db = DB::db();
foreach ($db->queryFirstColumn( foreach ($db->queryFirstColumn(
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i', 'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i',
$nationNo $nationNo
) as $city) { ) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) { foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj3[$adjKey] = $adjVal; $adj3[$adjKey] = $adjVal;
} }
}; };
foreach ($db->queryFirstColumn( foreach ($db->queryFirstColumn(
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 1 AND diplomacy.term <= 5 AND me = %i', 'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 1 AND diplomacy.term <= 5 AND me = %i',
$nationNo $nationNo
) as $city) { ) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) { foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj1[$adjKey] = $adjVal; $adj1[$adjKey] = $adjVal;
} }
} }
if (!$adj3 && !$adj1) { if (!$adj3 && !$adj1) {
//평시이면 공백지 //평시이면 공백지
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다. //NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) { foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) { foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj2[$adjKey] = $adjVal; $adj2[$adjKey] = $adjVal;
} }
} }
} }
$db->update('city', [ $db->update('city', [
'front' => 0 'front' => 0
], 'nation=%i', $nationNo); ], 'nation=%i', $nationNo);
if ($adj1) { if ($adj1) {
$db->update('city', [ $db->update('city', [
'front' => 1, 'front' => 1,
], 'nation=%i and city in %li', $nationNo, array_keys($adj1)); ], 'nation=%i and city in %li', $nationNo, array_keys($adj1));
} }
if ($adj2) { if ($adj2) {
$db->update('city', [ $db->update('city', [
'front' => 2, 'front' => 2,
], 'nation=%i and city in %li', $nationNo, array_keys($adj2)); ], 'nation=%i and city in %li', $nationNo, array_keys($adj2));
} }
if ($adj3) { if ($adj3) {
$db->update('city', [ $db->update('city', [
'front' => 3, 'front' => 3,
], 'nation=%i and city in %li', $nationNo, array_keys($adj3)); ], 'nation=%i and city in %li', $nationNo, array_keys($adj3));
} }
} }
function checkSupply() function checkSupply()
{ {
$db = DB::db(); $db = DB::db();
$cities = []; $cities = [];
foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) { foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) {
$newCity = new \stdClass(); $newCity = new \stdClass();
$newCity->id = Util::toInt($city['city']); $newCity->id = Util::toInt($city['city']);
$newCity->nation = Util::toInt($city['nation']); $newCity->nation = Util::toInt($city['nation']);
$newCity->supply = false; $newCity->supply = false;
$cities[$newCity->id] = $newCity; $cities[$newCity->id] = $newCity;
} }
$queue = new \SplQueue(); $queue = new \SplQueue();
foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) { foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) {
if (!key_exists($capitalID, $cities)) { if (!key_exists($capitalID, $cities)) {
continue; continue;
} }
$city = $cities[$capitalID]; $city = $cities[$capitalID];
if ($nationID != $city->nation) { if ($nationID != $city->nation) {
continue; continue;
} }
$city->supply = true; $city->supply = true;
$queue->enqueue($city); $queue->enqueue($city);
} }
while (!$queue->isEmpty()) { while (!$queue->isEmpty()) {
$cityLink = $queue->dequeue(); $cityLink = $queue->dequeue();
$city = CityConst::byID($cityLink->id); $city = CityConst::byID($cityLink->id);
foreach (array_keys($city->path) as $connCityID) { foreach (array_keys($city->path) as $connCityID) {
if (!key_exists($connCityID, $cities)) { if (!key_exists($connCityID, $cities)) {
continue; continue;
} }
$connCity = $cities[$connCityID]; $connCity = $cities[$connCityID];
if ($connCity->nation != $cityLink->nation) { if ($connCity->nation != $cityLink->nation) {
continue; continue;
} }
if ($connCity->supply) { if ($connCity->supply) {
continue; continue;
} }
$connCity->supply = true; $connCity->supply = true;
$queue->enqueue($connCity); $queue->enqueue($connCity);
} }
} }
$db->update('city', [ $db->update('city', [
'supply' => 1 'supply' => 1
], 'nation=0'); ], 'nation=0');
$db->update('city', [ $db->update('city', [
'supply' => 0 'supply' => 0
], 'nation!=0'); ], 'nation!=0');
$supply = []; $supply = [];
foreach ($cities as $city) { foreach ($cities as $city) {
if ($city->supply) { if ($city->supply) {
$supply[] = $city->id; $supply[] = $city->id;
} }
} }
if ($supply) { if ($supply) {
$db->update('city', [ $db->update('city', [
'supply' => 1 'supply' => 1
], 'city IN %li', $supply); ], 'city IN %li', $supply);
} }
} }
function updateGeneralNumber(){ function updateGeneralNumber(){
$db = DB::db(); $db = DB::db();
foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){ foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){
if($nationID === 0){ if($nationID === 0){
continue; continue;
} }
$db->update('nation', [ $db->update('nation', [
'gennum'=>$gennum 'gennum'=>$gennum
], 'nation=%i', $nationID); ], 'nation=%i', $nationID);
} }
refreshNationStaticInfo(); refreshNationStaticInfo();
} }
function updateYearly() function updateYearly()
{ {
//통계 //통계
checkStatistic(); checkStatistic();
} }
//관직 변경 해제 //관직 변경 해제
function updateQuaterly() function updateQuaterly()
{ {
$db = DB::db(); $db = DB::db();
//천도 제한 해제, 관직 변경 제한 해제 //천도 제한 해제, 관직 변경 제한 해제
$db->update('nation', [ $db->update('nation', [
'chief_set' => 0, 'chief_set' => 0,
], true); ], true);
//관직 변경 제한 해제 //관직 변경 제한 해제
$db->update('city', [ $db->update('city', [
'officer_set' => 0, 'officer_set' => 0,
], true); ], true);
} }
// 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정 // 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
function preUpdateMonthly() function preUpdateMonthly()
{ {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
//연감 월결산 //연감 월결산
$result = LogHistory(); $result = LogHistory();
if ($result == false) { if ($result == false) {
return false; return false;
} }
$admin = $gameStor->getValues(['startyear', 'year', 'month']); $admin = $gameStor->getValues(['startyear', 'year', 'month']);
$logger = new ActionLogger(0, 0, $admin['year'], $admin['month']); $logger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//보급선 체크 //보급선 체크
checkSupply(); checkSupply();
//미보급도시 10% 감소 //미보급도시 10% 감소
$db->update('city', [ $db->update('city', [
'pop' => $db->sqleval('pop * 0.9'), 'pop' => $db->sqleval('pop * 0.9'),
'trust' => $db->sqleval('trust * 0.9'), 'trust' => $db->sqleval('trust * 0.9'),
'agri' => $db->sqleval('agri * 0.9'), 'agri' => $db->sqleval('agri * 0.9'),
'comm' => $db->sqleval('comm * 0.9'), 'comm' => $db->sqleval('comm * 0.9'),
'secu' => $db->sqleval('secu * 0.9'), 'secu' => $db->sqleval('secu * 0.9'),
'def' => $db->sqleval('def * 0.9'), 'def' => $db->sqleval('def * 0.9'),
'wall' => $db->sqleval('wall * 0.9'), 'wall' => $db->sqleval('wall * 0.9'),
], 'supply = 0'); ], 'supply = 0');
//미보급도시 장수 병 훈 사 5%감소 //미보급도시 장수 병 훈 사 5%감소
//NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게. //NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게.
$unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0'); $unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0');
foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) { foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) {
$cityIDList = Util::squeezeFromArray($cityList, 'city'); $cityIDList = Util::squeezeFromArray($cityList, 'city');
$db->update('general', [ $db->update('general', [
'crew' => $db->sqleval('crew*0.95'), 'crew' => $db->sqleval('crew*0.95'),
'atmos' => $db->sqleval('atmos*0.95'), 'atmos' => $db->sqleval('atmos*0.95'),
'train' => $db->sqleval('train*0.95'), 'train' => $db->sqleval('train*0.95'),
], 'city IN %li AND nation = %i', $cityIDList, $nationID); ], 'city IN %li AND nation = %i', $cityIDList, $nationID);
} }
//민심30이하 공백지 처리 //민심30이하 공백지 처리
$lostCities = []; $lostCities = [];
foreach ($unsuppliedCities as $unsuppliedCity) { foreach ($unsuppliedCities as $unsuppliedCity) {
if ($unsuppliedCity['trust'] >= 30) { if ($unsuppliedCity['trust'] >= 30) {
continue; continue;
} }
$lostCities[$unsuppliedCity['city']] = $unsuppliedCity; $lostCities[$unsuppliedCity['city']] = $unsuppliedCity;
} }
if ($lostCities) { if ($lostCities) {
foreach ($lostCities as $lostCity) { foreach ($lostCities as $lostCity) {
$josaYi = JosaUtil::pick($lostCity['name'], '이'); $josaYi = JosaUtil::pick($lostCity['name'], '이');
$logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다."); $logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다.");
} }
$db->update('general', [ $db->update('general', [
'officer_level' => 1, 'officer_level' => 1,
'officer_city' => 0 'officer_city' => 0
], 'officer_city IN %li', array_keys($lostCities)); ], 'officer_city IN %li', array_keys($lostCities));
$db->update('city', [ $db->update('city', [
'nation' => 0, 'nation' => 0,
'officer_set' => 0, 'officer_set' => 0,
'conflict' => '{}', 'conflict' => '{}',
'term' => 0, 'term' => 0,
'front' => 0 'front' => 0
], 'city IN %li', array_keys($lostCities)); ], 'city IN %li', array_keys($lostCities));
} }
//접률감소, 건국제한-1 //접률감소, 건국제한-1
$db->update('general', [ $db->update('general', [
'connect' => $db->sqleval('floor(connect*0.99)'), 'connect' => $db->sqleval('floor(connect*0.99)'),
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'), 'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
], true); ], true);
//전략제한-1, 외교제한-1, 세율동기화 //전략제한-1, 외교제한-1, 세율동기화
$db->update('nation', [ $db->update('nation', [
'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'), 'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'),
'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'), 'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'),
'rate_tmp' => $db->sqleval('rate') 'rate_tmp' => $db->sqleval('rate')
], true); ], true);
//도시훈사 180년 60, 220년 87, 240년 100 //도시훈사 180년 60, 220년 87, 240년 100
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60; $rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
if ($rate > 100) $rate = 100; if ($rate > 100) $rate = 100;
// 20 ~ 140원 // 20 ~ 140원
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2; $develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
$gameStor->city_rate = $rate; $gameStor->city_rate = $rate;
$gameStor->develcost = $develcost; $gameStor->develcost = $develcost;
//매달 사망자 수입 결산 //매달 사망자 수입 결산
processWarIncome(); processWarIncome();
//계략, 전쟁표시 해제 //계략, 전쟁표시 해제
$db->update('city', [ $db->update('city', [
'state' => $db->sqleval(<<<EOD 'state' => $db->sqleval(<<<EOD
(CASE (CASE
WHEN state=31 THEN 0 WHEN state=31 THEN 0
WHEN state=32 THEN 31 WHEN state=32 THEN 31
WHEN state=33 THEN 0 WHEN state=33 THEN 0
WHEN state=34 THEN 33 WHEN state=34 THEN 33
WHEN state=41 THEN 0 WHEN state=41 THEN 0
WHEN state=42 THEN 41 WHEN state=42 THEN 41
WHEN state=43 THEN 42 WHEN state=43 THEN 42
ELSE state END) ELSE state END)
EOD), EOD),
'term' => $db->sqleval('greatest(0, term - 1)'), 'term' => $db->sqleval('greatest(0, term - 1)'),
'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'), 'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'),
], true); ], true);
//첩보-1 //첩보-1
foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) { foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) {
$spyInfo = Json::decode($rawSpy); $spyInfo = Json::decode($rawSpy);
foreach ($spyInfo as $cityNo => $remainMonth) { foreach ($spyInfo as $cityNo => $remainMonth) {
if ($remainMonth <= 1) { if ($remainMonth <= 1) {
unset($spyInfo[$cityNo]); unset($spyInfo[$cityNo]);
} else { } else {
$spyInfo[$cityNo] -= 1; $spyInfo[$cityNo] -= 1;
} }
} }
$db->update('nation', [ $db->update('nation', [
'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT) 'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
], 'nation=%i', $nationNo); ], 'nation=%i', $nationNo);
} }
return true; return true;
} }
// 외교 로그처리, 외교 상태 처리 // 외교 로그처리, 외교 상태 처리
function postUpdateMonthly() function postUpdateMonthly()
{ {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']); $admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']);
$globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']); $globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//도시 수 측정 //도시 수 측정
$cityNations = []; $cityNations = [];
foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) { foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) {
if (!key_exists($cityNation, $cityNations)) { if (!key_exists($cityNation, $cityNations)) {
$cityNations[$cityNation] = []; $cityNations[$cityNation] = [];
} }
$cityNations[$cityNation][] = $cityName; $cityNations[$cityNation][] = $cityName;
} }
//각 국가 전월 장수수 대비 당월 장수수로 단합도 산정 //각 국가 전월 장수수 대비 당월 장수수로 단합도 산정
//각 국가 장수수를 구하고 국력 산정 //각 국가 장수수를 구하고 국력 산정
// $query = "select nation,gennum from nation where level>0"; // $query = "select nation,gennum from nation where level>0";
// 국력= // 국력=
// 자원(국가/장수의 금,쌀) // 자원(국가/장수의 금,쌀)
// 기술력 // 기술력
// 인구수*내정% // 인구수*내정%
// 장수능력 // 장수능력
// 접속률 // 접속률
// 숙련도 // 숙련도
// 명성,공헌 // 명성,공헌
$nations = Util::convertArrayToDict($db->query('SELECT $nations = Util::convertArrayToDict($db->query('SELECT
A.nation, A.nation,
A.gennum, A.gennum,
round(( round((
round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100) round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100)
+A.tech +A.tech
+if(A.level=0,0,( +if(A.level=0,0,(
select round( select round(
sum(pop)*sum(pop+agri+comm+secu+wall+def)/sum(pop_max+agri_max+comm_max+secu_max+wall_max+def_max)/100 sum(pop)*sum(pop+agri+comm+secu+wall+def)/sum(pop_max+agri_max+comm_max+secu_max+wall_max+def_max)/100
) from city where nation=A.nation and supply=1 ) from city where nation=A.nation and supply=1
)) ))
+(select sum(leadership+strength+intel) from general where nation=A.nation) +(select sum(leadership+strength+intel) from general where nation=A.nation)
+(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where nation=A.nation) +(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where nation=A.nation)
+(select round(sum(experience+dedication)/100) from general where nation=A.nation) +(select round(sum(experience+dedication)/100) from general where nation=A.nation)
+(select round(avg(connect)) from general where nation=A.nation) +(select round(avg(connect)) from general where nation=A.nation)
)/10) )/10)
as power, as power,
(select sum(crew) from general where nation=A.nation) as totalCrew (select sum(crew) from general where nation=A.nation) as totalCrew
from nation A from nation A
group by A.nation'), 'nation'); group by A.nation'), 'nation');
$maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power'); $maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power');
foreach ($nations as $nation) { foreach ($nations as $nation) {
$nationID = $nation['nation']; $nationID = $nation['nation'];
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$genNum[$nationID] = $nation['gennum']; $genNum[$nationID] = $nation['gennum'];
$powerValues = $maxPowerValues[$nationID]??[]; $powerValues = $maxPowerValues[$nationID]??[];
//약간의 랜덤치 부여 (95% ~ 105%) //약간의 랜덤치 부여 (95% ~ 105%)
$nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000); $nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000);
$powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']); $powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']);
$powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew'])); $powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew']));
if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) { if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) {
$powerValues['maxCities'] = $cityNations[$nationID]; $powerValues['maxCities'] = $cityNations[$nationID];
} }
$db->update('nation', [ $db->update('nation', [
'power' => $nation['power'] 'power' => $nation['power']
], 'nation=%i', $nationID); ], 'nation=%i', $nationID);
$nationStor->max_power = $powerValues; $nationStor->max_power = $powerValues;
} }
// 전쟁기한 세팅 // 전쟁기한 세팅
foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) { foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) {
$genCount = $genNum[$dip['me']]; $genCount = $genNum[$dip['me']];
// 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산 // 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산
// 4000 / 10 * 0.25 = 100 // 4000 / 10 * 0.25 = 100
$term = floor($dip['dead'] / 100 / $genCount); $term = floor($dip['dead'] / 100 / $genCount);
$dip['dead'] -= $term * 100 * $genCount; $dip['dead'] -= $term * 100 * $genCount;
$term = Util::valueFit($dip['term'] + $term, 0, 13); $term = Util::valueFit($dip['term'] + $term, 0, 13);
$db->update('diplomacy', [ $db->update('diplomacy', [
'term' => $term, 'term' => $term,
'dead' => $dip['dead'], 'dead' => $dip['dead'],
], 'me = %i AND you = %i', $dip['me'], $dip['you']); ], 'me = %i AND you = %i', $dip['me'], $dip['you']);
} }
//개전국 로그 //개전국 로그
foreach($db->query('SELECT me, you FROM diplomacy WHERE state = 1 AND term <= 1 AND me < you') as $dip){ foreach($db->query('SELECT me, you FROM diplomacy WHERE state = 1 AND term <= 1 AND me < you') as $dip){
$nation1 = getNationStaticInfo($dip['me']); $nation1 = getNationStaticInfo($dip['me']);
$name1 = $nation1['name']; $name1 = $nation1['name'];
$nation2 = getNationStaticInfo($dip['you']); $nation2 = getNationStaticInfo($dip['you']);
$name2 = $nation2['name']; $name2 = $nation2['name'];
$josaYi = JosaUtil::pick($name2, '이'); $josaYi = JosaUtil::pick($name2, '이');
$josaWa = JosaUtil::pick($name1, '와'); $josaWa = JosaUtil::pick($name1, '와');
$globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다."); $globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다.");
} }
//휴전국 로그 //휴전국 로그
$stopWarList = []; $stopWarList = [];
foreach($db->queryAllLists('SELECT me,you FROM diplomacy WHERE state=0 AND term <= 1 ORDER BY me desc, you desc') as [$me, $you]){ foreach($db->queryAllLists('SELECT me,you FROM diplomacy WHERE state=0 AND term <= 1 ORDER BY me desc, you desc') as [$me, $you]){
if($me < $you){ if($me < $you){
$key = "{$me}_{$you}"; $key = "{$me}_{$you}";
} }
else{ else{
$key = "{$you}_{$me}"; $key = "{$you}_{$me}";
} }
if(!key_exists($key, $stopWarList)){ if(!key_exists($key, $stopWarList)){
$stopWarList[$key] = true; $stopWarList[$key] = true;
continue; continue;
} }
//양측 기간 모두 0이 되는 상황이면 휴전 //양측 기간 모두 0이 되는 상황이면 휴전
$nation1 = getNationStaticInfo($me); $nation1 = getNationStaticInfo($me);
$name1 = $nation1['name']; $name1 = $nation1['name'];
$nation2 = getNationStaticInfo($you); $nation2 = getNationStaticInfo($you);
$name2 = $nation2['name']; $name2 = $nation2['name'];
$josaWa = JosaUtil::pick($name1, '와'); $josaWa = JosaUtil::pick($name1, '와');
$josaYi = JosaUtil::pick($name2, '이'); $josaYi = JosaUtil::pick($name2, '이');
$globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다."); $globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다.");
$db->update('diplomacy', [ $db->update('diplomacy', [
'state'=>2, 'state'=>2,
'term'=>0, 'term'=>0,
], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you); ], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you);
} }
$globalLogger->flush(); $globalLogger->flush();
//사상자 초기화, 외교 기한-1 //사상자 초기화, 외교 기한-1
$db->update('diplomacy', [ $db->update('diplomacy', [
'dead'=>$db->sqleval('if(state!=0, 0, dead)'), 'dead'=>$db->sqleval('if(state!=0, 0, dead)'),
'term'=>$db->sqleval('greatest(0, term-1)'), 'term'=>$db->sqleval('greatest(0, term-1)'),
], true); ], true);
//불가침 끝나면 통상으로 //불가침 끝나면 통상으로
$db->update('diplomacy', [ $db->update('diplomacy', [
'state'=>2, 'state'=>2,
], 'state = 7 AND term = 0'); ], 'state = 7 AND term = 0');
//선포 끝나면 교전으로 //선포 끝나면 교전으로
$db->update('diplomacy', [ $db->update('diplomacy', [
'state'=>0, 'state'=>0,
'term'=>6, 'term'=>6,
], 'state = 1 AND term = 0'); ], 'state = 1 AND term = 0');
//초반이후 방랑군 자동 해체 //초반이후 방랑군 자동 해체
if ($admin['year'] >= $admin['startyear'] + 2) { if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander(); checkWander();
} }
// 작위 업데이트 // 작위 업데이트
updateNationState(); updateNationState();
updateGeneralNumber(); updateGeneralNumber();
refreshNationStaticInfo(); refreshNationStaticInfo();
// 천통여부 검사 // 천통여부 검사
checkEmperior(); checkEmperior();
//토너먼트 개시 //토너먼트 개시
triggerTournament(); triggerTournament();
// 시스템 거래건 등록 // 시스템 거래건 등록
registerAuction(); registerAuction();
//전방설정 //전방설정
foreach (getAllNationStaticInfo() as $nation) { foreach (getAllNationStaticInfo() as $nation) {
if ($nation['level'] <= 0) { if ($nation['level'] <= 0) {
continue; continue;
} }
SetNationFront($nation['nation']); SetNationFront($nation['nation']);
} }
} }
function checkWander() function checkWander()
{ {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month']); $admin = $gameStor->getValues(['year', 'month']);
$wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12'); $wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12');
foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) { foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) {
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin); $wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
if ($wanderCmd->hasFullConditionMet()) { if ($wanderCmd->hasFullConditionMet()) {
$logger = $wanderer->getLogger(); $logger = $wanderer->getLogger();
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN); $logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
$wanderCmd->run(); $wanderCmd->run();
} $wanderCmd->setNextAvailable();
} }
}
if ($wanderers) {
refreshNationStaticInfo(); if ($wanderers) {
} refreshNationStaticInfo();
} }
}
function updateNationState()
{ function updateNationState()
$db = DB::db(); {
$gameStor = KVStorage::getStorage($db, 'game_env'); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']); $history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']);
$assemblerCnts = [];
foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) { $assemblerCnts = [];
$assemblerCnts[$nationID] = $assemblerCnt; foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) {
}; $assemblerCnts[$nationID] = $assemblerCnt;
};
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음 foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']); //TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
if ($citycount == 0) {
$nationlevel = 0; // 방랑군 if ($citycount == 0) {
} elseif ($citycount == 1) { $nationlevel = 0; // 방랑군
$nationlevel = 1; // 호족 } elseif ($citycount == 1) {
} elseif ($citycount <= 4) { $nationlevel = 1; // 호족
$nationlevel = 2; // 군벌 } elseif ($citycount <= 4) {
} elseif ($citycount <= 7) { $nationlevel = 2; // 군벌
$nationlevel = 3; // 주자사 } elseif ($citycount <= 7) {
} elseif ($citycount <= 10) { $nationlevel = 3; // 주자사
$nationlevel = 4; // 주목 } elseif ($citycount <= 10) {
} elseif ($citycount <= 15) { $nationlevel = 4; // 주목
$nationlevel = 5; // 공 } elseif ($citycount <= 15) {
} elseif ($citycount <= 20) { $nationlevel = 5; // 공
$nationlevel = 6; // 왕 } elseif ($citycount <= 20) {
} else { $nationlevel = 6; // 왕
$nationlevel = 7; // 황제 } else {
} $nationlevel = 7; // 황제
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level']; if ($nationlevel > $nation['level']) {
$oldLevel = $nation['level']; $levelDiff = $nationlevel - $nation['level'];
$nation['level'] = $nationlevel; $oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel $updateVals = [
]; 'level' => $nationlevel,
'gold'=>$db->sqleval('gold + %i', $nationlevel*1000),
switch ($nationlevel) { 'rice'=>$db->sqleval('rice + %i', $nationlevel*1000),
case 7: ];
$josaUl = JosaUtil::pick(getNationLevel($nationlevel), '을');
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다."; switch ($nationlevel) {
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]); case 7:
$auxVal = Json::decode($nation['aux']); $josaUl = JosaUtil::pick(getNationLevel($nationlevel), '을');
$auxVal['can_국기변경'] = 1; $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
$auxVal['can_국호변경'] = 1; pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$updateVals['aux'] = Json::encode($auxVal); $auxVal = Json::decode($nation['aux']);
break; $auxVal['can_국기변경'] = 1;
case 6: $auxVal['can_국호변경'] = 1;
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다."; $updateVals['aux'] = Json::encode($auxVal);
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]); break;
break; case 6:
case 5: $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
case 4: pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
case 3: break;
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다."; case 5:
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]); case 4:
break; case 3:
case 2: $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다."; pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>로 나서다"]); break;
break; case 2:
} $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>로 나서다"]);
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']); break;
}
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) { $db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
$turnRows[] = [ $turnRows = [];
'nation_id' => $nation['nation'], foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
'officer_level' => $chiefLevel, foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
'turn_idx' => $turnIdx, $turnRows[] = [
'action' => '휴식', 'nation_id' => $nation['nation'],
'arg' => null, 'officer_level' => $chiefLevel,
'brief' => '휴식' 'turn_idx' => $turnIdx,
]; 'action' => '휴식',
} 'arg' => null,
} 'brief' => '휴식'
$db->insertIgnore('nation_turn', $turnRows); ];
}
if ($levelDiff) { }
//유니크 아이템 하나 돌리자 $db->insertIgnore('nation_turn', $turnRows);
$targetKillTurn = $admin['killturn'];
$targetKillTurn -= 24 * 60 / $admin['turnterm']; if ($levelDiff) {
$nationGenIDList = $db->queryFirstColumn( //유니크 아이템 하나 돌리자
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2', $targetKillTurn = $admin['killturn'];
$nation['nation'], $targetKillTurn -= 24 * 60 / $admin['turnterm'];
$targetKillTurn $nationGenIDList = $db->queryFirstColumn(
); 'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong'], 2); $nation['nation'],
$targetKillTurn
$uniqueLotteryWeightList = []; );
foreach ($nationGenList as $nationGen) { $nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong'], 2);
$hasUnique = false;
foreach ($nationGen->getItems() as $item) { $uniqueLotteryWeightList = [];
if (!$item->isBuyable()) { foreach ($nationGenList as $nationGen) {
$hasUnique = true; $hasUnique = false;
break; foreach ($nationGen->getItems() as $item) {
} if (!$item->isBuyable()) {
} $hasUnique = true;
if ($hasUnique) { break;
continue; }
} }
if ($hasUnique) {
$score = $nationGen->getVar('belong') + 5; continue;
}
if ($nationGen->getVar('officer_level') == 12) {
$score += 200; //NOTE: 꼬우면 군주하세요. $score = $nationGen->getVar('belong') + 5;
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 70; if ($nationGen->getVar('officer_level') == 12) {
} else if ($nationGen->getVar('officer_level') > 4) { $score += 200; //NOTE: 꼬우면 군주하세요.
$score += 35; } else if ($nationGen->getVar('officer_level') == 11) {
} $score += 70;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score]; } else if ($nationGen->getVar('officer_level') > 4) {
} $score += 35;
}
foreach (Util::range($levelDiff) as $idx) { $uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
if (!$uniqueLotteryWeightList) { }
break;
} foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
/** @var General */ break;
$winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList); }
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
giveRandomUniqueItem($winnerObj, '작위보상'); /** @var General */
$winnerObj->applyDB($db); $winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
} unset($uniqueLotteryWeightList[$winnerObj->getID()]);
} giveRandomUniqueItem($winnerObj, '작위보상');
} $winnerObj->applyDB($db);
}
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0; }
$maxAssemblerCnt = [ }
1 => 0,
2 => 1, $assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0;
3 => 3, $maxAssemblerCnt = [
4 => 4, 1 => 0,
5 => 6, 2 => 1,
6 => 7, 3 => 3,
7 => 9 4 => 4,
][$nationlevel] ?? 0; 5 => 6,
6 => 7,
if ($assemblerCnt < $maxAssemblerCnt) { 7 => 9
$lastAssemblerID = $gameStor->assembler_id ?? 0; ][$nationlevel] ?? 0;
while ($assemblerCnt < $maxAssemblerCnt) { if ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1; $lastAssemblerID = $gameStor->assembler_id ?? 0;
$npcObj = new Scenario\NPC(
999, while ($assemblerCnt < $maxAssemblerCnt) {
sprintf('부대장%4d', $lastAssemblerID), $lastAssemblerID += 1;
null, $npcObj = new Scenario\NPC(
$nation['nation'], 999,
null, sprintf('부대장%4d', $lastAssemblerID),
10, null,
10, $nation['nation'],
10, null,
1, 10,
$admin['year'] - 15, 10,
$admin['year'] + 15, 10,
'은둔', 1,
'척사' $admin['year'] - 15,
); $admin['year'] + 15,
$npcObj->killturn = 70; '은둔',
$npcObj->gold = 0; '척사'
$npcObj->rice = 0; );
$npcObj->npc = 5; $npcObj->killturn = 70;
$npcObj->build($admin); $npcObj->gold = 0;
$npcID = $npcObj->generalID; $npcObj->rice = 0;
$npcObj->npc = 5;
$db->insert('troop', [ $npcObj->build($admin);
'troop_leader' => $npcID, $npcID = $npcObj->generalID;
'name' => $npcObj->realName,
'nation' => $nation['nation'], $db->insert('troop', [
]); 'troop_leader' => $npcID,
$db->update('general', [ 'name' => $npcObj->realName,
'troop' => $npcID 'nation' => $nation['nation'],
], 'no=%i', $npcID); ]);
$db->update('general', [
//TODO: 5턴간 집합턴 입력 'troop' => $npcID
$assemblerCnt += 1; ], 'no=%i', $npcID);
$gameStor->assembler_id = $lastAssemblerID;
} $cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin);
} _setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn)));
} $assemblerCnt += 1;
pushGlobalHistoryLog($history, $admin['year'], $admin['month']); $gameStor->assembler_id = $lastAssemblerID;
} }
}
function checkStatistic() }
{ pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
$db = DB::db(); }
$gameStor = KVStorage::getStorage($db, 'game_env');
function checkStatistic()
$admin = $gameStor->getValues(['year', 'month']); {
$db = DB::db();
$nationHists = []; $gameStor = KVStorage::getStorage($db, 'game_env');
$specialHists = [];
$personalHists = []; $admin = $gameStor->getValues(['year', 'month']);
$specialHists2 = [];
$crewtypeHists = []; $nationHists = [];
$specialHists = [];
$etc = ''; $personalHists = [];
$specialHists2 = [];
$auxData = [ $crewtypeHists = [];
'generals' => [],
'nations' => [], $etc = '';
];
$auxData = [
$avgGeneral = $db->queryFirstRow( 'generals' => [],
'SELECT avg(gold) as avggold, avg(rice) as avgrice, avg(dex1+dex2+dex3+dex4) as avgdex, 'nations' => [],
max(dex1+dex2+dex3+dex4) as maxdex, avg(experience+dedication) as avgexpded, max(experience+dedication) as maxexpded ];
FROM general'
); $avgGeneral = $db->queryFirstRow(
$auxData['generals']['avg'] = $avgGeneral; 'SELECT avg(gold) as avggold, avg(rice) as avgrice, avg(dex1+dex2+dex3+dex4) as avgdex,
max(dex1+dex2+dex3+dex4) as maxdex, avg(experience+dedication) as avgexpded, max(experience+dedication) as maxexpded
$avgGeneral['avggold'] = Util::round($avgGeneral['avggold']); FROM general'
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']); );
$avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']); $auxData['generals']['avg'] = $avgGeneral;
$avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
$etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), "; $avgGeneral['avggold'] = Util::round($avgGeneral['avggold']);
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']);
$avgNation = $db->queryFirstRow( $avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']);
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech, $avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0' $etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), ";
);
$auxData['nations']['avg'] = $avgNation; $avgNation = $db->queryFirstRow(
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech,
$avgNation['mintech'] = floor($avgNation['mintech']); min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0'
$avgNation['maxtech'] = floor($avgNation['maxtech']); );
$avgNation['avgtech'] = Util::round($avgNation['avgtech']); $auxData['nations']['avg'] = $avgNation;
$avgNation['avgpower'] = Util::round($avgNation['avgpower']);
$etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), "; $avgNation['mintech'] = floor($avgNation['mintech']);
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), "; $avgNation['maxtech'] = floor($avgNation['maxtech']);
$avgNation['avgtech'] = Util::round($avgNation['avgtech']);
$nationName = ''; $avgNation['avgpower'] = Util::round($avgNation['avgpower']);
$powerHist = ''; $etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), ";
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), ";
$nations = Util::convertArrayToDict(
$db->query( $nationName = '';
'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc', $powerHist = '';
'nation'
), $nations = Util::convertArrayToDict(
'nation' $db->query(
); 'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc',
$nationCount = count($nations); 'nation'
),
$nationGeneralInfos = Util::convertArrayToDict( 'nation'
$db->query( );
'SELECT nation, sum(leadership+strength+intel) as abil,sum(gold+rice) as goldrice, $nationCount = count($nations);
sum(dex1+dex2+dex3+dex4) as dex,sum(experience+dedication) as expded
from general GROUP BY nation' $nationGeneralInfos = Util::convertArrayToDict(
), $db->query(
'nation' 'SELECT nation, sum(leadership+strength+intel) as abil,sum(gold+rice) as goldrice,
); sum(dex1+dex2+dex3+dex4) as dex,sum(experience+dedication) as expded
from general GROUP BY nation'
$nationCityInfos = Util::convertArrayToDict( ),
$db->query('SELECT nation, count(*) as cnt, sum(pop) as pop,sum(pop_max) as pop_max from city GROUP BY nation'), 'nation'
'nation' );
);
$nationCityInfos = Util::convertArrayToDict(
foreach ($nations as $nationNo => &$nation) { $db->query('SELECT nation, count(*) as cnt, sum(pop) as pop,sum(pop_max) as pop_max from city GROUP BY nation'),
$general = $nationGeneralInfos[$nationNo]; 'nation'
$city = $nationCityInfos[$nationNo]; );
$nation['generalInfo'] = $general; foreach ($nations as $nationNo => &$nation) {
$nation['cityInfo'] = $city; $general = $nationGeneralInfos[$nationNo];
$city = $nationCityInfos[$nationNo];
$nationName .= $nation['name'] . '(' . getNationType($nation['type']) . '), ';
$powerHist .= "{$nation['name']}({$nation['power']}/{$nation['gennum']}/{$city['cnt']}/{$city['pop']}/{$city['pop_max']}/{$nation['goldrice']}/{$general['goldrice']}/{$general['abil']}/{$general['dex']}/{$general['expded']}), "; $nation['generalInfo'] = $general;
$nation['cityInfo'] = $city;
if (!isset($nationHists[$nation['type']])) {
$nationHists[$nation['type']] = 0; $nationName .= $nation['name'] . '(' . getNationType($nation['type']) . '), ';
} $powerHist .= "{$nation['name']}({$nation['power']}/{$nation['gennum']}/{$city['cnt']}/{$city['pop']}/{$city['pop_max']}/{$nation['goldrice']}/{$general['goldrice']}/{$general['abil']}/{$general['dex']}/{$general['expded']}), ";
$nationHists[$nation['type']]++;
} if (!isset($nationHists[$nation['type']])) {
unset($nation); $nationHists[$nation['type']] = 0;
}
$auxData['nations']['all'] = $nations; $nationHists[$nation['type']]++;
}
$nationHist = ''; unset($nation);
foreach (GameConst::$availableNationType as $nationType) {
if (!Util::array_get($nationHists[$nationType])) { $auxData['nations']['all'] = $nations;
$nationHists[$nationType] = '-';
} $nationHist = '';
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), "; foreach (GameConst::$availableNationType as $nationType) {
} if (!Util::array_get($nationHists[$nationType])) {
$nationHists[$nationType] = '-';
$generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general'); }
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
$genCount = 0; }
$npcCount = 0;
$generalCount = count($generals); $generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general');
foreach ($generals as $general) { $genCount = 0;
if (!isset($personalHists[$general['personal']])) { $npcCount = 0;
$personalHists[$general['personal']] = 0; $generalCount = count($generals);
}
foreach ($generals as $general) {
if (!isset($specialHists[$general['special']])) { if (!isset($personalHists[$general['personal']])) {
$specialHists[$general['special']] = 0; $personalHists[$general['personal']] = 0;
} }
if (!isset($specialHists2[$general['special2']])) { if (!isset($specialHists[$general['special']])) {
$specialHists2[$general['special2']] = 0; $specialHists[$general['special']] = 0;
} }
if ($general['npc'] < 2) { if (!isset($specialHists2[$general['special2']])) {
$genCount += 1; $specialHists2[$general['special2']] = 0;
} else { }
$npcCount += 1;
} if ($general['npc'] < 2) {
$genCount += 1;
$personalHists[$general['personal']]++; } else {
$specialHists[$general['special']]++; $npcCount += 1;
$specialHists2[$general['special2']]++; }
}
$personalHists[$general['personal']]++;
foreach ($db->queryAllLists( $specialHists[$general['special']]++;
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype' $specialHists2[$general['special2']]++;
) as [$crewtype, $cnt]) { }
$crewtypeHists[$crewtype] = $cnt;
} foreach ($db->queryAllLists(
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype'
$auxData['generals']['hists'] = [ ) as [$crewtype, $cnt]) {
'personal' => $personalHists, $crewtypeHists[$crewtype] = $cnt;
'special' => $specialHists, }
'special2' => $specialHists2,
'crewtype' => $crewtypeHists, $auxData['generals']['hists'] = [
'userCnt' => $genCount, 'personal' => $personalHists,
'npcCnt' => $npcCount, 'special' => $specialHists,
]; 'special2' => $specialHists2,
'crewtype' => $crewtypeHists,
$generalCountStr = "{$generalCount}({$genCount}+{$npcCount})"; 'userCnt' => $genCount,
'npcCnt' => $npcCount,
$personalHistStr = join(', ', array_map(function ($histPair) { ];
[$histKey, $cnt] = $histPair;
return getGenChar($histKey) . '(' . $cnt . ')'; $generalCountStr = "{$generalCount}({$genCount}+{$npcCount})";
}, Util::convertDictToArray($personalHists)));
$personalHistStr = join(', ', array_map(function ($histPair) {
$specialHistsStr = join(', ', array_map(function ($histPair) { [$histKey, $cnt] = $histPair;
[$histKey, $cnt] = $histPair; return getGenChar($histKey) . '(' . $cnt . ')';
return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')'; }, Util::convertDictToArray($personalHists)));
}, Util::convertDictToArray($specialHists)));
$specialHistsStr = join(', ', array_map(function ($histPair) {
$specialHists2Str = join(', ', array_map(function ($histPair) { [$histKey, $cnt] = $histPair;
[$histKey, $cnt] = $histPair; return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')';
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')'; }, Util::convertDictToArray($specialHists)));
}, Util::convertDictToArray($specialHists2)));
$specialHists2Str = join(', ', array_map(function ($histPair) {
$specialHistsAllStr = "$specialHistsStr // $specialHists2Str"; [$histKey, $cnt] = $histPair;
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')';
$crewtypeHistsStr = join(', ', array_map(function ($histPair) { }, Util::convertDictToArray($specialHists2)));
[$histKey, $cnt] = $histPair;
return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')'; $specialHistsAllStr = "$specialHistsStr // $specialHists2Str";
}, Util::convertDictToArray($crewtypeHists)));
$crewtypeHistsStr = join(', ', array_map(function ($histPair) {
$db->insert('statistic', [ [$histKey, $cnt] = $histPair;
'year' => $admin['year'], return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')';
'month' => $admin['month'], }, Util::convertDictToArray($crewtypeHists)));
'nation_count' => $nationCount,
'nation_name' => $nationName, $db->insert('statistic', [
'nation_hist' => $nationHist, 'year' => $admin['year'],
'gen_count' => $generalCountStr, 'month' => $admin['month'],
'personal_hist' => $personalHistStr, 'nation_count' => $nationCount,
'special_hist' => $specialHistsAllStr, 'nation_name' => $nationName,
'power_hist' => $powerHist, 'nation_hist' => $nationHist,
'crewtype' => $crewtypeHistsStr, 'gen_count' => $generalCountStr,
'etc' => $etc, 'personal_hist' => $personalHistStr,
'aux' => Json::encode($auxData) 'special_hist' => $specialHistsAllStr,
]); 'power_hist' => $powerHist,
} 'crewtype' => $crewtypeHistsStr,
'etc' => $etc,
'aux' => Json::encode($auxData)
function convForOldGeneral(array $general, int $year, int $month) ]);
{ }
$general['history'] = getGeneralHistoryLogAll($general['no']);
return [
'server_id' => UniqueConst::$serverID, function convForOldGeneral(array $general, int $year, int $month)
'general_no' => $general['no'], {
'owner' => $general['owner'], $general['history'] = getGeneralHistoryLogAll($general['no']);
'name' => $general['name'], return [
'last_yearmonth' => $year * 100 + $month, 'server_id' => UniqueConst::$serverID,
'turntime' => $general['turntime'], 'general_no' => $general['no'],
'data' => Json::encode($general) 'owner' => $general['owner'],
]; 'name' => $general['name'],
} 'last_yearmonth' => $year * 100 + $month,
'turntime' => $general['turntime'],
function storeOldGeneral(int $no, int $year, int $month) 'data' => Json::encode($general)
{ ];
$db = DB::db(); }
$general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
if (!$general) { function storeOldGeneral(int $no, int $year, int $month)
return; {
} $db = DB::db();
$data = convForOldGeneral($general, $year, $month); $general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
$db->insertUpdate( if (!$general) {
'ng_old_generals', return;
$data, }
$data $data = convForOldGeneral($general, $year, $month);
); $db->insertUpdate(
} 'ng_old_generals',
$data,
function storeOldGenerals(int $nation, int $year, int $month) $data
{ );
$db = DB::db(); }
foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
$data = convForOldGeneral($general, $year, $month); function storeOldGenerals(int $nation, int $year, int $month)
$db->insertUpdate( {
'ng_old_generals', $db = DB::db();
$data, foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
$data $data = convForOldGeneral($general, $year, $month);
); $db->insertUpdate(
} 'ng_old_generals',
} $data,
$data
function checkEmperior() );
{ }
$db = DB::db(); }
$gameStor = KVStorage::getStorage($db, 'game_env');
function checkEmperior()
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']); {
if ($admin['isunited'] != 0) { $db = DB::db();
return; $gameStor = KVStorage::getStorage($db, 'game_env');
}
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
$remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2'); if ($admin['isunited'] != 0) {
return;
if (!$remainNations || count($remainNations) != 1) { }
return;
} $remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2');
$nationID = $remainNations[0]; if (!$remainNations || count($remainNations) != 1) {
return;
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); }
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID); $nationID = $remainNations[0];
if (!$cityCnt) {
return; $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
}
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID);
if ($cityCnt != count(CityConst::all())) { if (!$cityCnt) {
return; return;
} }
checkStatistic(); if ($cityCnt != count(CityConst::all())) {
return;
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID); }
$nationName = $nation['name'];
checkStatistic();
$josaYi = JosaUtil::pick($nationName, '이');
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID);
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']); $nationName = $nation['name'];
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
$josaYi = JosaUtil::pick($nationName, '이');
$gameStor->isunited = 2;
$gameStor->conlimit = $gameStor->conlimit * 100; $nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
CheckHall($hallGeneralNo); $gameStor->isunited = 2;
} $gameStor->conlimit = $gameStor->conlimit * 100;
[$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city'); foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
$pop = "{$totalPop} / {$totalMaxPop}"; CheckHall($hallGeneralNo);
$poprate = round($totalPop / $totalMaxPop * 100, 2). " %"; }
$chiefs = Util::convertArrayToDict( [$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city');
$db->query( $pop = "{$totalPop} / {$totalMaxPop}";
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5', $poprate = round($totalPop / $totalMaxPop * 100, 2). " %";
$nationID
), $chiefs = Util::convertArrayToDict(
'officer_level' $db->query(
); 'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
$nationID
$nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID); ),
$nation['generals'] = $nationGenerals; 'officer_level'
);
$tigers = $db->query(
'SELECT value, name $nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID);
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no $nation['generals'] = $nationGenerals;
WHERE rank_data.nation_id = %i AND rank_data.type = "warnum" AND value > 0 ORDER BY value DESC LIMIT 5',
$nationID $tigers = $db->query(
); // 오호장군 'SELECT value, name
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
$tigerstr = join(', ', array_map(function ($arr) { WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5',
$number = number_format($arr['value']); $nationID
return "{$arr['name']}{$number}"; ); // 오호장군
}, $tigers));
$tigerstr = join(', ', array_map(function ($arr) {
$eagles = $db->query( $number = number_format($arr['value']);
'SELECT value, name return "{$arr['name']}{$number}";
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no }, $tigers));
WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7',
$nationID $eagles = $db->query(
); // 건안칠자 'SELECT value, name
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
$eaglestr = join(', ', array_map(function ($arr) { WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7',
$number = number_format($arr['value']); $nationID
return "{$arr['name']}{$number}"; ); // 건안칠자
}, $eagles));
$eaglestr = join(', ', array_map(function ($arr) {
$rawGeneralList = $db->query('SELECT no, name, npc, owner FROM general WHERE nation=%i ORDER BY dedication DESC', $nationID); $number = number_format($arr['value']);
foreach ($rawGeneralList as $rawGeneral) { return "{$arr['name']}{$number}";
$generalLogger = new ActionLogger($rawGeneral['no'], $nationID, $admin['year'], $admin['month']); }, $eagles));
$generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH);
$generalLogger->flush(); $rawGeneralList = $db->query('SELECT no, name, npc, owner FROM general WHERE nation=%i ORDER BY dedication DESC', $nationID);
} foreach ($rawGeneralList as $rawGeneral) {
$generalLogger = new ActionLogger($rawGeneral['no'], $nationID, $admin['year'], $admin['month']);
$gen = join(', ', array_column($rawGeneral, 'name')); $generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH);
$nation['type'] = getNationType($nation['type']); $generalLogger->flush();
}
$stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic');
$genCnt = $db->queryFirstField('SELECT count(*) FROM general'); $gen = join(', ', array_column($rawGeneral, 'name'));
$statNC = "1 / {$stat['nc']}"; $stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic');
$statGC = "{$genCnt} / {$stat['gc']}"; $genCnt = $db->queryFirstField('SELECT count(*) FROM general');
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
$statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1'); $statNC = "1 / {$stat['nc']}";
$statGC = "{$genCnt} / {$stat['gc']}";
$nation = $nation; $statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']); $statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1');
$nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->notice; $nation = $nation;
$nation['scout_msg'] = $nationStor->scout_msg; $nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
$nation['aux'] += $nationStor->max_power; $nation['aux'] = Json::decode($nation['aux']);
$nation['history'] = getNationHistoryLogAll($nation['nation']); $nation['msg'] = $nationStor->notice;
$nation['scout_msg'] = $nationStor->scout_msg;
storeOldGenerals(0, $admin['year'], $admin['month']); $nation['aux'] += $nationStor->max_power;
storeOldGenerals($nation['nation'], $admin['year'], $admin['month']); $nation['history'] = getNationHistoryLogAll($nation['nation']);
$db->insert('ng_old_nations', [ storeOldGenerals(0, $admin['year'], $admin['month']);
'server_id' => UniqueConst::$serverID, storeOldGenerals($nation['nation'], $admin['year'], $admin['month']);
'nation' => $nation['nation'],
'data' => Json::encode($nation) $db->insert('ng_old_nations', [
]); 'server_id' => UniqueConst::$serverID,
'nation' => $nation['nation'],
$noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0'); 'data' => Json::encode($nation)
$db->insert('ng_old_nations', [ ]);
'server_id' => UniqueConst::$serverID,
'nation' => 0, $noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0');
'data' => Json::encode([ $db->insert('ng_old_nations', [
'nation' => 0, 'server_id' => UniqueConst::$serverID,
'name' => '재야', 'nation' => 0,
'generals' => $noNationGeneral 'data' => Json::encode([
]) 'nation' => 0,
]); 'name' => '재야',
'generals' => $noNationGeneral
$nationHistory = getNationHistoryLogAll($nation['nation']); ])
]);
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
$serverName = UniqueConst::$serverName; $nationHistory = getNationHistoryLogAll($nation['nation']);
$db->update('ng_games', [ $serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
'winner_nation' => $nation['nation'] $serverName = UniqueConst::$serverName;
], 'server_id=%s', UniqueConst::$serverID);
$db->update('ng_games', [
$db->insert('emperior', [ 'winner_nation' => $nation['nation']
'phase' => $serverName . $serverCnt . '기', ], 'server_id=%s', UniqueConst::$serverID);
'server_id' => UniqueConst::$serverID,
'nation_count' => $statNC, $db->insert('emperior', [
'nation_name' => $statNation['nation_name'], 'phase' => $serverName . $serverCnt . '기',
'nation_hist' => $statNation['nation_hist'], 'server_id' => UniqueConst::$serverID,
'gen_count' => $statGC, 'nation_count' => $statNC,
'personal_hist' => $statGeneral['personal_hist'], 'nation_name' => $statNation['nation_name'],
'special_hist' => $statGeneral['special_hist'], 'nation_hist' => $statNation['nation_hist'],
'name' => $nation['name'], 'gen_count' => $statGC,
'type' => $nation['type'], 'personal_hist' => $statGeneral['personal_hist'],
'color' => $nation['color'], 'special_hist' => $statGeneral['special_hist'],
'year' => $admin['year'], 'name' => $nation['name'],
'month' => $admin['month'], 'type' => $nation['type'],
'power' => $nation['power'], 'color' => $nation['color'],
'gennum' => $nation['gennum'], 'year' => $admin['year'],
'citynum' => $cityCnt, 'month' => $admin['month'],
'pop' => $pop, 'power' => $nation['power'],
'poprate' => $poprate, 'gennum' => $nation['gennum'],
'gold' => $nation['gold'], 'citynum' => $cityCnt,
'rice' => $nation['rice'], 'pop' => $pop,
'l12name' => $chiefs[12]['name'], 'poprate' => $poprate,
'l12pic' => $chiefs[12]['picture'], 'gold' => $nation['gold'],
'l11name' => $chiefs[11]['name'], 'rice' => $nation['rice'],
'l11pic' => $chiefs[11]['picture'], 'l12name' => $chiefs[12]['name'],
'l10name' => $chiefs[10]['name'], 'l12pic' => $chiefs[12]['picture'],
'l10pic' => $chiefs[10]['picture'], 'l11name' => $chiefs[11]['name'],
'l9name' => $chiefs[9]['name'], 'l11pic' => $chiefs[11]['picture'],
'l9pic' => $chiefs[9]['picture'], 'l10name' => $chiefs[10]['name'],
'l8name' => $chiefs[8]['name'], 'l10pic' => $chiefs[10]['picture'],
'l8pic' => $chiefs[8]['picture'], 'l9name' => $chiefs[9]['name'],
'l7name' => $chiefs[7]['name'], 'l9pic' => $chiefs[9]['picture'],
'l7pic' => $chiefs[7]['picture'], 'l8name' => $chiefs[8]['name'],
'l6name' => $chiefs[6]['name'], 'l8pic' => $chiefs[8]['picture'],
'l6pic' => $chiefs[6]['picture'], 'l7name' => $chiefs[7]['name'],
'l5name' => $chiefs[5]['name'], 'l7pic' => $chiefs[7]['picture'],
'l5pic' => $chiefs[5]['picture'], 'l6name' => $chiefs[6]['name'],
'tiger' => $tigerstr, 'l6pic' => $chiefs[6]['picture'],
'eagle' => $eaglestr, 'l5name' => $chiefs[5]['name'],
'gen' => $gen, 'l5pic' => $chiefs[5]['picture'],
'history' => JSON::encode($nationHistory), 'tiger' => $tigerstr,
'aux' => $statGeneral['aux'] 'eagle' => $eaglestr,
]); 'gen' => $gen,
'history' => JSON::encode($nationHistory),
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."]; 'aux' => $statGeneral['aux']
pushGlobalHistoryLog($history, $admin['year'], $admin['month']); ]);
//연감 월결산 $history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
LogHistory(); pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
//연감 월결산
LogHistory();
}
+20 -4
View File
@@ -39,10 +39,26 @@ function bar($per, $h=7) {
} }
function optionsForCities() { function optionsForCities(callable $infoCall=null) {
return join('', array_map(function($city){
return "<option value='{$city->id}'>{$city->name}</option>"; if(!$infoCall){
}, CityConst::all())); return join('', array_map(function($city){
return "<option value='{$city->id}'>{$city->name}</option>";
}, CityConst::all()));
}
$infoList = [];
$noInfoList = [];
foreach(CityConst::all() as $city){
$info = $infoCall($city);
if(!$info){
$noInfoList[] = "<option value='{$city->id}'>{$city->name}</option>";
continue;
}
$infoList[] = "<option value='{$city->id}'>{$city->name} ({$info})</option>";
}
return join('', array_merge($infoList, $noInfoList));
} }
function Submit($url, $msg="", $msg2="") { function Submit($url, $msg="", $msg2="") {
+274 -270
View File
@@ -1,270 +1,274 @@
<?php <?php
namespace sammo; namespace sammo;
/** /**
* 템플릿 생성과 관련된 함수들을 모아두는 파일 * 템플릿 생성과 관련된 함수들을 모아두는 파일
* *
* NOTE: 아직 converter와 명확한 구분이 되어있지 않음. * NOTE: 아직 converter와 명확한 구분이 되어있지 않음.
* TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음 * TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음
* TODO: side effect를 제거 * TODO: side effect를 제거
*/ */
/** /**
* 관리자 권한이 필요함을 출력. * 관리자 권한이 필요함을 출력.
* @return void * @return void
*/ */
function requireAdminPermissionHTML() function requireAdminPermissionHTML()
{ {
ob_start(); ob_start();
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>관리메뉴</title> <title>관리메뉴</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('css/common.css') ?> <?= WebUtil::printCSS('css/common.css') ?>
</head> </head>
<body> <body>
관리자가 아닙니다.<br> 관리자가 아닙니다.<br>
<?= banner() ?> <?= banner() ?>
</body> </body>
</html> </html>
<?php <?php
return ob_get_clean(); return ob_get_clean();
} }
function turnTable() function turnTable()
{ {
$turnList = []; $turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>"; $turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) { foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) {
$turnText = $turnIdx + 1; $turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>"; $turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
} }
$turnText = join("\n", $turnList); $turnText = join("\n", $turnList);
return " return "
<select id='generalTurnSelector' name=turn[] size=11 multiple> <select id='generalTurnSelector' name=turn[] size=11 multiple>
<option value='-3'>전체</option> <option value='-3'>전체</option>
<option value='-1'>홀턴</option> <option value='-1'>홀턴</option>
<option value='-2'>짝턴</option> <option value='-2'>짝턴</option>
{$turnText} {$turnText}
</select> </select>
"; ";
} }
function chiefTurnTable() function chiefTurnTable()
{ {
$turnList = []; $turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>"; $turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) { foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) {
$turnText = $turnIdx + 1; $turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>"; $turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
} }
$turnText = join("\n", $turnList); $turnText = join("\n", $turnList);
return " return "
<select id='chiefTurnSelector' name=turn[] size=6 multiple> <select id='chiefTurnSelector' name=turn[] size=6 multiple>
{$turnText} {$turnText}
</select> </select>
"; ";
} }
function displayiActionObjInfo(?iAction $action) function displayiActionObjInfo(?iAction $action)
{ {
if ($action === null) { if ($action === null) {
$info = ''; $info = '';
$text = '-'; $text = '-';
} else { } else {
$info = $action->getInfo(); $info = $action->getInfo();
$text = $action->getName(); $text = $action->getName();
} }
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $text, 'text' => $text,
'info' => $info, 'info' => $info,
]); ]);
} }
function displayCharInfo(string $type): string function displayCharInfo(string $type): string
{ {
$class = buildPersonalityClass($type); $class = buildPersonalityClass($type);
$info = $class->getInfo(); $info = $class->getInfo();
$text = $class->getName(); $text = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $text, 'text' => $text,
'info' => $info, 'info' => $info,
]); ]);
} }
function displaySpecialWarInfo(?string $type): string function displaySpecialWarInfo(?string $type): string
{ {
$class = buildGeneralSpecialWarClass($type); $class = buildGeneralSpecialWarClass($type);
$info = $class->getInfo(); $info = $class->getInfo();
$name = $class->getName(); $name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $name, 'text' => $name,
'info' => $info, 'info' => $info,
]); ]);
} }
function displaySpecialDomesticInfo(?string $type): string function displaySpecialDomesticInfo(?string $type): string
{ {
$class = buildGeneralSpecialDomesticClass($type); $class = buildGeneralSpecialDomesticClass($type);
$info = $class->getInfo(); $info = $class->getInfo();
$name = $class->getName(); $name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $name, 'text' => $name,
'info' => $info, 'info' => $info,
]); ]);
} }
function allButton(bool $seizeNPCMode) function allButton(bool $seizeNPCMode)
{ {
if ($seizeNPCMode) { if ($seizeNPCMode) {
$site = "a_npcList.php"; $site = "a_npcList.php";
$call = "빙의일람"; $call = "빙의일람";
} else { } else {
$site = "a_vote.php"; $site = "a_vote.php";
$call = "설문조사"; $call = "설문조사";
} }
if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) { if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) {
$templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates');
} else { } else {
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
} }
return $templates->render('allButton', [ return $templates->render('allButton', [
'call' => $call, 'call' => $call,
'site' => $site 'site' => $site
]); ]);
} }
function commandButton() function commandButton()
{ {
$session = Session::getInstance(); $session = Session::getInstance();
$userID = Session::getUserID(); $userID = Session::getUserID();
if (!$session->isGameLoggedIn()) { if (!$session->isGameLoggedIn()) {
return ''; return '';
} }
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow("select no,nation,officer_level,belong,permission,penalty from general where owner=%i", $userID); $me = $db->queryFirstRow("select no,nation,officer_level,belong,permission,penalty from general where owner=%i", $userID);
$nation = $db->queryFirstRow("select nation,level,color,secretlimit from nation where nation=%i", $me['nation']) ?? [ $nation = $db->queryFirstRow("select nation,level,color,secretlimit from nation where nation=%i", $me['nation']) ?? [
'nation' => 0, 'nation' => 0,
'level' => 0, 'level' => 0,
'secretlimit' => 99, 'secretlimit' => 99,
'color' => '#000000' 'color' => '#000000'
]; ];
$bgColor = Util::array_get($nation['color']) ?: '#000000'; $bgColor = Util::array_get($nation['color']) ?: '#000000';
$fgColor = newColor($bgColor); $fgColor = newColor($bgColor);
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
$showSecret = false; $showSecret = false;
$permission = checkSecretPermission($me); $permission = checkSecretPermission($me);
if ($permission >= 1) { if ($permission >= 1) {
$showSecret = true; $showSecret = true;
} else if ($me['officer_level'] == 0) { } else if ($me['officer_level'] == 0) {
$showSecret = false; $showSecret = false;
} }
return $templates->render('commandButton', [ return $templates->render('commandButton', [
'bgColor' => $bgColor, 'bgColor' => $bgColor,
'fgColor' => $fgColor, 'fgColor' => $fgColor,
'meLevel' => $me['officer_level'], 'meLevel' => $me['officer_level'],
'nationLevel' => $nation['level'], 'nationLevel' => $nation['level'],
'showSecret' => $showSecret, 'showSecret' => $showSecret,
'permission' => $permission, 'permission' => $permission,
]); ]);
} }
function formatWounded(int $value, int $wound): string function formatWounded(int $value, int $wound): string
{ {
if ($wound == 0) { if ($wound == 0) {
return "$value"; return "$value";
} }
$woundedValue = intdiv($value * (100 - $wound), 100); $woundedValue = intdiv($value * (100 - $wound), 100);
return "<font color=red>$woundedValue</font>"; return "<font color=red>$woundedValue</font>";
} }
function formatDefenceTrain(int $value): string function formatDefenceTrain(int $value): string
{ {
if ($value === 999) { if ($value === 999) {
return "×"; return "×";
} else if ($value >= 80) { } else if ($value >= 90){
return ""; return "";
} else { } else if ($value >= 80) {
return ""; return "";
} } else if ($value >= 60) {
} return "○";
} else{
function formatLeadershipBonus(int $value): string return "△";
{ }
if ($value == 0) { }
return '';
} function formatLeadershipBonus(int $value): string
return "<font color=cyan>+{$value}</font>"; {
} if ($value == 0) {
return '';
function formatName(string $name, int $npc): string }
{ return "<font color=cyan>+{$value}</font>";
if ($npc == 1) { }
$name = "<font color='skyblue'>$name</font>";
} else if ($npc > 1) { function formatName(string $name, int $npc): string
$name = "<font color='cyan'>$name</font>"; {
} if ($npc == 1) {
return $name; $name = "<font color='skyblue'>$name</font>";
} } else if ($npc > 1) {
$name = "<font color='cyan'>$name</font>";
function getMapHtml(?string $mapTheme = null) }
{ return $name;
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); }
if ($mapTheme === null) { function getMapHtml(?string $mapTheme = null)
$db = DB::db(); {
$gameStor = KVStorage::getStorage($db, 'game_env'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
$mapTheme = $gameStor->map_theme ?? 'che';
} if ($mapTheme === null) {
$db = DB::db();
return $templates->render('map', [ $gameStor = KVStorage::getStorage($db, 'game_env');
'mapTheme' => $mapTheme $mapTheme = $gameStor->map_theme ?? 'che';
]); }
}
return $templates->render('map', [
function getInvitationList(array $nationList) 'mapTheme' => $mapTheme
{ ]);
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); }
foreach ($nationList as &$nation) { function getInvitationList(array $nationList)
$nation['textColor'] = newColor($nation['color']); {
} $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('invitationList', [
'nationList' => $nationList foreach ($nationList as &$nation) {
]); $nation['textColor'] = newColor($nation['color']);
} }
return $templates->render('invitationList', [
'nationList' => $nationList
]);
}
+23 -17
View File
@@ -78,6 +78,7 @@ function processGoldIncome() {
// 실지급률 // 실지급률
$ratio = $realoutcome / $originoutcome; $ratio = $realoutcome / $originoutcome;
} }
$nation['gold'] = Util::valueFit($nation['gold'], GameConst::$basegold);
$adminLog[] = StringUtil::padStringAlignRight((string)$nation['name'],12," ") $adminLog[] = StringUtil::padStringAlignRight((string)$nation['name'],12," ")
." // 세금 : ".StringUtil::padStringAlignRight((string)$income,6," ") ." // 세금 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ") ." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
@@ -87,6 +88,8 @@ function processGoldIncome() {
$incomeText = number_format($income); $incomeText = number_format($income);
$incomeLog = "이번 수입은 금 <C>$incomeText</>입니다."; $incomeLog = "이번 수입은 금 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_gold = $income;
$db->update('nation', [ $db->update('nation', [
'gold'=>$nation['gold'] 'gold'=>$nation['gold']
@@ -353,6 +356,7 @@ function processRiceIncome() {
// 실지급률 // 실지급률
$ratio = $realoutcome / $originoutcome; $ratio = $realoutcome / $originoutcome;
} }
$nation['rice'] = Util::valueFit($nation['rice'], GameConst::$baserice);
$adminLog[] = StringUtil::padStringAlignRight($nation['name'],12," ") $adminLog[] = StringUtil::padStringAlignRight($nation['name'],12," ")
." // 세곡 : ".StringUtil::padStringAlignRight((string)$income,6," ") ." // 세곡 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ") ." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
@@ -362,6 +366,8 @@ function processRiceIncome() {
$incomeText = number_format($income); $incomeText = number_format($income);
$incomeLog = "이번 수입은 쌀 <C>$incomeText</>입니다."; $incomeLog = "이번 수입은 쌀 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_rice = $income;
$db->update('nation', [ $db->update('nation', [
'rice'=>$nation['rice'] 'rice'=>$nation['rice']
@@ -528,36 +534,36 @@ function disaster() {
$targetCityNames = "<G><b>".join(' ', Util::squeezeFromArray($targetCityList, 'name'))."</b></>"; $targetCityNames = "<G><b>".join(' ', Util::squeezeFromArray($targetCityList, 'name'))."</b></>";
$disasterTextList = [ $disasterTextList = [
1 => [ 1 => [
['재난', 4, '역병이 발생하여 도시가 황폐해지고 있습니다.'], ['<M><b>【재난】</b></>', 4, '역병이 발생하여 도시가 황폐해지고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'], ['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 3, '추위가 풀리지 않아 얼어죽는 백성들이 늘어나고 있습니다.'], ['<M><b>【재난】</b></>', 3, '추위가 풀리지 않아 얼어죽는 백성들이 늘어나고 있습니다.'],
['재난', 9, '황건적이 출현해 도시를 습격하고 있습니다.'], ['<M><b>【재난】</b></>', 9, '황건적이 출현해 도시를 습격하고 있습니다.'],
], ],
4 => [ 4 => [
['재난', 7, '홍수로 인해 피해가 급증하고 있습니다.'], ['<M><b>【재난】</b></>', 7, '홍수로 인해 피해가 급증하고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'], ['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 6, '태풍으로 인해 피해가 속출하고 있습니다.'], ['<M><b>【재난】</b></>', 6, '태풍으로 인해 피해가 속출하고 있습니다.'],
], ],
7 => [ 7 => [
['재난', 8, '메뚜기 떼가 발생하여 도시가 황폐해지고 있습니다.'], ['<M><b>【재난】</b></>', 8, '메뚜기 떼가 발생하여 도시가 황폐해지고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'], ['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 8, '흉년이 들어 굶어죽는 백성들이 늘어나고 있습니다.'], ['<M><b>【재난】</b></>', 8, '흉년이 들어 굶어죽는 백성들이 늘어나고 있습니다.'],
], ],
10 => [ 10 => [
['재난', 3, '혹한으로 도시가 황폐해지고 있습니다.'], ['<M><b>【재난】</b></>', 3, '혹한으로 도시가 황폐해지고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'], ['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 3, '눈이 많이 쌓여 도시가 황폐해지고 있습니다.'], ['<M><b>【재난】</b></>', 3, '눈이 많이 쌓여 도시가 황폐해지고 있습니다.'],
['재난', 9, '황건적이 출현해 도시를 습격하고 있습니다.'], ['<M><b>【재난】</b></>', 9, '황건적이 출현해 도시를 습격하고 있습니다.'],
] ]
]; ];
$boomingTextList = [ $boomingTextList = [
1 => null, 1 => null,
4 => [ 4 => [
['호황', 2, '호황으로 도시가 번창하고 있습니다.'], ['<C><b>【호황】</b></>', 2, '호황으로 도시가 번창하고 있습니다.'],
], ],
7 => [ 7 => [
['풍작', 1, '풍작으로 도시가 번창하고 있습니다.'], ['<C><b>【풍작】</b></>', 1, '풍작으로 도시가 번창하고 있습니다.'],
], ],
10 => null 10 => null
]; ];
@@ -566,7 +572,7 @@ function disaster() {
$logger = new ActionLogger(0, 0, $year, $month, false); $logger = new ActionLogger(0, 0, $year, $month, false);
$logger->pushGlobalHistoryLog("<M><b>【{$logTitle}】</b></>{$targetCityNames}{$logBody}"); $logger->pushGlobalHistoryLog("{$logTitle}{$targetCityNames}{$logBody}");
$logger->flush(); $logger->flush();
if (!$isGood) { if (!$isGood) {
+1 -1
View File
@@ -523,7 +523,7 @@ function selection($tnmt_type, $tnmt, $phase) {
if($phase < 31) { if($phase < 31) {
$gameStor->phase+=1; $gameStor->phase+=1;
} else { } else {
$gameStor->tournamemt = 4; $gameStor->tournament = 4;
$gameStor->phase=0; $gameStor->phase=0;
} }
} }
+1 -1
View File
@@ -61,7 +61,7 @@ $scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID(); $nationID = $generalObj->getNationID();
if($nationID){ if($nationID){
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheValues(['notice', 'online_genenerals']); $nationStor->cacheAll();
} }
$valid = 0; $valid = 0;
+100 -100
View File
@@ -1,101 +1,101 @@
<?php <?php
namespace sammo; namespace sammo;
include 'lib.php'; include 'lib.php';
include "func.php"; include "func.php";
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) { if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'affected'=>0, 'affected'=>0,
'status'=>'no_reserved_table' 'status'=>'no_reserved_table'
]); ]);
} }
$reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1'); $reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1');
if(!$reserved){ if(!$reserved){
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'affected'=>0, 'affected'=>0,
'status'=>'no_reserved' 'status'=>'no_reserved'
]); ]);
} }
$reservedDate = new \DateTime($reserved['date']); $reservedDate = new \DateTime($reserved['date']);
$now = new \DateTime(); $now = new \DateTime();
$status = 'not_yet'; $status = 'not_yet';
list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']); list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']);
if($isUnited === null || $lastTurn === null){ if($isUnited === null || $lastTurn === null){
$isUnited = 2; $isUnited = 2;
$lastTurn = '2000-01-01'; $lastTurn = '2000-01-01';
} }
if($lastTurn !== null){ if($lastTurn !== null){
$lastTurn = new \DateTime($lastTurn); $lastTurn = new \DateTime($lastTurn);
} }
if($lastTurn === null){ if($lastTurn === null){
//이미 리셋된 상태임 //이미 리셋된 상태임
} }
else if(file_exists(__DIR__.'/.htaccess')){ else if(file_exists(__DIR__.'/.htaccess')){
//일단 서버는 닫혀 있음 //일단 서버는 닫혀 있음
} }
else if( else if(
$isUnited == 2 && $isUnited == 2 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp() $now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp()
){ ){
//정지 상태 & 중간 넘음 //정지 상태 & 중간 넘음
AppConf::getList()[DB::prefix()]->closeServer(); ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed'; $status = 'closed';
} }
else if( else if(
$isUnited > 0 && $isUnited > 0 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2 $now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2
){ ){
//천통 & 비정지 상태 & 2/3 넘음 //천통 & 비정지 상태 & 2/3 넘음
AppConf::getList()[DB::prefix()]->closeServer(); ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed'; $status = 'closed';
} }
else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){ else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){
//어쨌든 간에 10분 남았다면. //어쨌든 간에 10분 남았다면.
AppConf::getList()[DB::prefix()]->closeServer(); ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed'; $status = 'closed';
} }
if($now < $reservedDate){ if($now < $reservedDate){
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'affected'=>0, 'affected'=>0,
'status'=>$status 'status'=>$status
]); ]);
} }
$options = Json::decode($reserved['options']); $options = Json::decode($reserved['options']);
$result = ResetHelper::buildScenario( $result = ResetHelper::buildScenario(
$options['turnterm'], $options['turnterm'],
$options['sync'], $options['sync'],
$options['scenario'], $options['scenario'],
$options['fiction'], $options['fiction'],
$options['extend'], $options['extend'],
$options['npcmode'], $options['npcmode'],
$options['show_img_level'], $options['show_img_level'],
$options['tournament_trig'], $options['tournament_trig'],
$options['join_mode'], $options['join_mode'],
$options['starttime'], $options['starttime'],
$options['autorun_user']?:null $options['autorun_user']?:null
); );
$result['affected']=1; $result['affected']=1;
$prefix = DB::prefix(); $prefix = DB::prefix();
AppConf::getList()[$prefix]->openServer(); ServConfig::getServerList()[$prefix]->openServer();
Json::die($result); Json::die($result);
@@ -4,6 +4,9 @@ namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX();
$availableDieImmediately = false; $availableDieImmediately = false;
//로그인 검사 //로그인 검사
@@ -16,25 +19,31 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$general = $db->queryFirstRow('SELECT no,name,owner_name,npc,lastrefresh FROM general WHERE owner=%i AND npc = 0', $userID); $general = $db->queryFirstRow('SELECT no,name,owner_name,npc,lastrefresh FROM general WHERE owner=%i AND npc = 0', $userID);
if(!$general){ if(!$general){
header('location:b_myPage.php'); Json::die([
die(); 'result'=>false,
'reason'=>'장수가 없습니다.'
]);
} }
increaseRefresh("장수 삭제", 1); increaseRefresh("장수 삭제", 1);
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']); $gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']);
if($gameStor->turntime <= $gameStor->opentime){ if($gameStor->turntime > $gameStor->opentime){
//서버 가오픈시 할 수 있는 행동 Json::die([
if(addTurn($general['lastrefresh'], $gameStor->turnterm, 2) <= TimeUtil::now()){ 'result'=>false,
$availableDieImmediately = true; 'reason'=>'이미 서버가 시작되었습니다.'
} ]);
} }
if(!$availableDieImmediately){
header('location:b_myPage.php');
die();
}
$targetTime = addTurn($general['lastrefresh'], $gameStor->turnterm, 2);
if($targetTime > TimeUtil::now()){
$targetTimeShort = substr($targetTime, 0, 19);
Json::die([
'result'=>false,
'reason'=>"아직 삭제할 수 없습니다. {$targetTimeShort} 부터 가능합니다."
]);
}
$generalObj = General::createGeneralObjFromDB($general['no']); $generalObj = General::createGeneralObjFromDB($general['no']);
@@ -46,4 +55,7 @@ $josaYi = JosaUtil::pick($generalName, '이');
$generalObj->kill($db, true, "<Y>{$generalName}</>{$josaYi} 이 홀연히 모습을 <R>감추었습니다</>"); $generalObj->kill($db, true, "<Y>{$generalName}</>{$josaYi} 이 홀연히 모습을 <R>감추었습니다</>");
$session->logoutGame(); $session->logoutGame();
header('location:..'); Json::die([
'result'=>true,
'reason'=>'success'
]);
+87
View File
@@ -0,0 +1,87 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$destGeneralID = Util::getPost('destGeneralID', 'int', 0);
if(!$destGeneralID || $destGeneralID <= 0){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 장수 코드입니다'
]);
}
$session = Session::requireGameLogin([])->setReadOnly();
$db = DB::db();
increaseRefresh("시뮬레이터 추출", 1);
$userID = Session::getUserID();
$me = $db->queryFirstRow('SELECT no,nation from general where owner=%i', $userID);
$nationID = $me['nation'];
$reqColumns = [
'nation',
'name', 'officer_level', 'explevel', 'injury',
'leadership', 'horse', 'strength', 'weapon', 'intel', 'book', 'item',
'rice', 'personal', 'special2',
'crew', 'crewtype',
'atmos', 'train', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'defence_train',
];
$reqRankColumns = [
'warnum', 'killnum', 'killcrew'
];
$dummyItems = [
'officer_level'=>1,
'horse'=>'None',
'weapon'=>'None',
'book'=>'None',
'item'=>'None',
'crew'=>0,
'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE,
'rice'=>10000,
'train'=>GameConst::$maxTrainByCommand,
'atmos'=>GameConst::$maxTrainByCommand,
'dex1'=>0,
'dex2'=>0,
'dex3'=>0,
'dex4'=>0,
'dex5'=>0,
'defence_train'=>80,
'warnum'=>0,
'killnum'=>0,
'killcrew'=>0,
];
$rawDestGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no=%i', Util::formatListOfBackticks($reqColumns), $destGeneralID);
if($nationID == 0 || $rawDestGeneral['nation'] != $nationID){
foreach($dummyItems as $key=>$val){
$rawDestGeneral[$key] = $val;
}
}
else{
$rawRankValue = $db->queryAllLists('SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', $destGeneralID, $reqRankColumns);
foreach($rawRankValue as [$rankType, $rankValue]){
$rawDestGeneral[$rankType] = $rankValue;
}
}
foreach(['dex1', 'dex2', 'dex3', 'dex4', 'dex5'] as $dexKey){
$dex = $rawDestGeneral[$dexKey];
$rawDestGeneral[$dexKey] = getDexLevelList()[getDexLevel($dex)][0];
}
Json::die([
'result'=>true,
'reason'=>'success',
'general'=>$rawDestGeneral,
]);
+100 -93
View File
@@ -1,94 +1,101 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("사령부", 1); increaseRefresh("사령부", 1);
$me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow('SELECT no,nation,officer_level,con,turntime,belong,penalty,permission FROM general WHERE owner=%i', $userID);
$nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation = %i', $me['nation']); $nationLevel = $db->queryFirstField('SELECT level FROM nation WHERE nation = %i', $me['nation']);
$nationID = $me['nation']; $nationID = $me['nation'];
$con = checkLimit($me['con']); $con = checkLimit($me['con']);
if($con >= 2) { if($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>"접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : {$me['turntime']})" 'reason'=>"접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : {$me['turntime']})"
]); ]);
} }
$permission = checkSecretPermission($me); $permission = checkSecretPermission($me);
if($permission < 0){ if($permission < 0){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.' 'reason'=>'국가에 소속되어있지 않습니다.'
]); ]);
echo '국가에 소속되어있지 않습니다.'; echo '국가에 소속되어있지 않습니다.';
die(); die();
} }
else if ($permission < 1) { else if ($permission < 1) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'수뇌부가 아니거나 사관년도가 부족합니다.' 'reason'=>'수뇌부가 아니거나 사관년도가 부족합니다.'
]); ]);
die(); die();
} }
$date = TimeUtil::now(); $date = TimeUtil::now();
// 명령 목록 // 명령 목록
[$year, $month, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'turnterm']); [$year, $month, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'turnterm']);
$lv = getNationChiefLevel($nationLevel); $lv = getNationChiefLevel($nationLevel);
$turn = []; $turn = [];
$generals = []; $generals = [];
foreach($db->query('SELECT no,name,turntime,npc,city,nation,officer_level FROM general WHERE nation = %i AND officer_level >= 5',$nationID) as $rawGeneral){ foreach($db->query('SELECT no,name,turntime,npc,city,nation,officer_level FROM general WHERE nation = %i AND officer_level >= 5',$nationID) as $rawGeneral){
$generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, $year, $month, false); $generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, $year, $month, false);
} }
$nationTurnList = []; $nationTurnList = [];
foreach( foreach(
$db->queryAllLists( $db->queryAllLists(
'SELECT officer_level, turn_idx, action, arg, brief FROM nation_turn WHERE nation_id = %i ORDER BY officer_level DESC, turn_idx ASC', 'SELECT officer_level, turn_idx, action, arg, brief FROM nation_turn WHERE nation_id = %i ORDER BY officer_level DESC, turn_idx ASC',
$me['nation'] $me['nation']
) as [$officer_level, $turn_idx, $action, $arg, $brief] ) as [$officer_level, $turn_idx, $action, $arg, $brief]
){ ){
if(!key_exists($officer_level, $nationTurnList)){ if(!key_exists($officer_level, $nationTurnList)){
$nationTurnList[$officer_level] = []; $nationTurnList[$officer_level] = [];
} }
$nationTurnList[$officer_level][$turn_idx] = $brief; $nationTurnList[$officer_level][$turn_idx] = $brief;
} }
$nationTurnBrief = []; $nationTurnBrief = [];
foreach($nationTurnList as $officer_level=>$turnBrief){ foreach($nationTurnList as $officer_level=>$turnBrief){
if(!key_exists($officer_level, $generals)){ if(!key_exists($officer_level, $generals)){
continue; $nationTurnBrief[$officer_level] = [
} 'name'=>null,
$general = $generals[$officer_level]; 'turnTime'=>null,
$nationTurnBrief[$officer_level] = [ 'officerLevelText'=>getOfficerLevelText($officer_level, $nationLevel),
'name'=>$general->getName(), 'npcType'=>null,
'turnTime'=>$general->getTurnTime($general::TURNTIME_FULL), 'turn'=>$turnBrief
'officerLevelText'=>getOfficerLevelText($general->getVar('officer_level'), $nationLevel), ];
'npcType'=>$general->getNPCType(), continue;
'turn'=>$turnBrief }
]; $general = $generals[$officer_level];
} $nationTurnBrief[$officer_level] = [
'name'=>$general->getName(),
$date = substr(TimeUtil::now(), 14); 'turnTime'=>$general->getTurnTime($general::TURNTIME_FULL),
'officerLevelText'=>getOfficerLevelText($general->getVar('officer_level'), $nationLevel),
Json::die([ 'npcType'=>$general->getNPCType(),
'result'=>true, 'turn'=>$turnBrief
'reason'=>'success', ];
'date'=>$date, }
'nationTurnBrief'=>$nationTurnBrief,
'isChief'=>($me['officer_level'] > 4), $date = substr(TimeUtil::now(), 14);
'turnTerm'=>$turnterm
Json::die([
'result'=>true,
'reason'=>'success',
'date'=>$date,
'nationTurnBrief'=>$nationTurnBrief,
'isChief'=>($me['officer_level'] > 4),
'turnTerm'=>$turnterm
]); ]);
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin([]);
$generalID = Session::getGeneralID();
$db = DB::db();
$rawList = Util::convertArrayToDict($db->query('SELECT no, name, npc, nation FROM general'), 'no');
$nationID = $rawList[$generalID]['nation'];
$result = [
'result'=>true,
'reason'=>'success',
'nationID'=>$nationID,
'generalID'=>$generalID,
'column'=>['no', 'name', 'npc']
];
$resultItem = [];
foreach(Util::arrayGroupBy($rawList, 'nation') as $subNationID=>$generals){
$subNation = [];
foreach($generals as $general){
$subNation[] = [$general['no'], $general['name'], $general['npc']];
}
$resultItem[$subNationID] = $subNation;
}
$result['list'] = $resultItem;
$result['nation'] = Util::convertArrayToDict($db->query('SELECT nation, name, color FROM nation'), 'nation');
Json::die($result);
+109 -109
View File
@@ -1,109 +1,109 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireLogin(); $session = Session::requireLogin([]);
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$withToken = Util::getPost('with_token', 'bool', false); $withToken = Util::getPost('with_token', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
if($session->isGameLoggedIn()){ if($session->isGameLoggedIn()){
increaseRefresh("장수일람", 2); increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']); $con = checkLimit($me['con']);
if ($con >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.' 'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]); ]);
} }
} }
else{ else{
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00'; $availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
$now = new \DateTimeImmutable(); $now = new \DateTimeImmutable();
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){ if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall 'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
]); ]);
} }
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s'); $availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
$session->availableNextCallGetGeneralList = $availableNextCall; $session->availableNextCallGetGeneralList = $availableNextCall;
} }
$session->setReadOnly(); $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'); $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 = []; $ownerNameList = [];
if($gameStor->isunited){ if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){ foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName; $ownerNameList[$ownerID] = $ownerName;
} }
} }
$generalList = []; $generalList = [];
foreach($rawGeneralList as $rawGeneral){ 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; [$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)){ if(key_exists($owner, $ownerNameList)){
$ownerName = $ownerNameList[$owner]; $ownerName = $ownerNameList[$owner];
} }
$nationArr = getNationStaticInfo($nation); $nationArr = getNationStaticInfo($nation);
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']); $lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
$generalList[] = [ $generalList[] = [
$no, $no,
$picture, $picture,
$imgsvr, $imgsvr,
$npc, $npc,
$age, $age,
$nationArr['name'], $nationArr['name'],
getGeneralSpecialDomesticName($special), getGeneralSpecialDomesticName($special),
getGeneralSpecialWarName($special2), getGeneralSpecialWarName($special2),
getGenChar($personal), getGenChar($personal),
$name, $name,
$npc==1?$ownerName:null, $npc==1?$ownerName:null,
$injury, $injury,
$leadership, $leadership,
$lbonus, $lbonus,
$strength, $strength,
$intel, $intel,
getExpLevel($experience), getExpLevel($experience),
getHonor($experience), getHonor($experience),
getDed($dedication), getDed($dedication),
getOfficerLevelText($officerLevel, $nationArr['level']), getOfficerLevelText($officerLevel, $nationArr['level']),
$killturn, $killturn,
$connectCnt $connectCnt
]; ];
} }
$result = [ $result = [
'result'=>'true', 'result'=>'true',
'list'=>$generalList, 'list'=>$generalList,
]; ];
if($withToken){ if($withToken){
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s'); $now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
$tokens = []; $tokens = [];
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){ foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
$validUntil = $token['valid_until']; $validUntil = $token['valid_until'];
foreach(Json::decode($token['pick_result']) as $pickResult){ foreach(Json::decode($token['pick_result']) as $pickResult){
$tokens[$pickResult['no']]=$pickResult['keepCnt']; $tokens[$pickResult['no']]=$pickResult['keepCnt'];
} }
} }
$result['token'] = $tokens; $result['token'] = $tokens;
} }
Json::die($result); Json::die($result);
+95 -77
View File
@@ -1,4 +1,5 @@
<?php <?php
namespace sammo; namespace sammo;
//통합 세력장수&암행부 viewer //통합 세력장수&암행부 viewer
@@ -11,145 +12,162 @@ $session = Session::requireGameLogin([])->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$reqType = Util::getPost('req', 'int', 1); $reqType = Util::getReq('req', 'int', 1);
$reqForce = Util::getPost('force', 'bool', false); $reqForce = Util::getReq('force', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("세력장수", 1); increaseRefresh("세력장수", 1);
$me = $db->queryFirstRow('SELECT con, turntime, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow('SELECT con, turntime, belong, nation, officer_level, permission, penalty FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']); $con = checkLimit($me['con']);
if ($con >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.' 'reason' => '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]); ]);
} }
$nationID = $me['nation']; $nationID = $me['nation'];
$permission = checkSecretPermission($me, true); $permission = checkSecretPermission($me, true);
if($reqForce && $reqType > $permission){ if ($reqForce && $reqType > $permission) {
Json::die([ Json::die([
'result'=>false, 'result' => false,
'reason'=>'권한이 부족합니다.' 'reason' => '권한이 부족합니다.'
]); ]);
} }
$permission = min($reqType, $permission); $permission = min($reqType, $permission);
$nationArr = getNationStaticInfo($nationID); $nationArr = getNationStaticInfo($nationID);
$viewColumns = [ $viewColumns = [
'no'=>1, 'no' => 0,
'name'=>1, 'name' => 0,
'owner_name'=>9, 'owner_name' => 9,
'nation'=>1, 'nation' => 0,
'city'=>1, 'city' => 1,
'officer_level'=>9, 'officer_level' => 2,
'npc'=>1, 'officer_city' => 2,
'defence_train'=>2, 'npc' => 0,
'troop'=>2, 'defence_train' => 2,
'injury'=>1, 'troop' => 2,
'leadership'=>1, 'injury' => 0,
'strength'=>1, 'leadership' => 0,
'intel'=>1, 'strength' => 0,
'experience'=>1, 'intel' => 0,
'explevel'=>1, 'experience' => 1,
'dedication'=>1, 'explevel' => 0,
'dedlevel'=>1, 'dedication' => 1,
'gold'=>1, 'dedlevel' => 0,
'rice'=>1, 'gold' => 0,
'crewtype'=>2, 'rice' => 0,
'crew'=>2, 'crewtype' => 2,
'train'=>2, 'crew' => 2,
'atmos'=>2, 'train' => 2,
'killturn'=>1, 'atmos' => 2,
'turntime'=>2, 'killturn' => 0,
'picture'=>1, 'turntime' => 2,
'imgsvr'=>1, 'picture' => 0,
'age'=>1, 'imgsvr' => 0,
'special'=>1, 'age' => 0,
'special2'=>1, 'special' => 0,
'personal'=>1, 'special2' => 0,
'horse'=>3, 'personal' => 0,
'weapon'=>3, 'belong' => 0,
'book'=>3, 'horse' => 2,
'item'=>3, 'weapon' => 2,
'connect'=>1 'book' => 2,
'item' => 2,
'connect' => 0
]; ];
$customViewColumns = [ $customViewColumns = [
'officerLevel'=>1, 'officerLevel' => 0,
'officerLevelText'=>1, 'officerLevelText' => 0,
'lbonus'=>1, 'lbonus' => 0,
'ownerName'=>1, 'ownerName' => 0,
'honorText'=>1, 'honorText' => 0
'expLevelText'=>1,
]; ];
function getOfficerLevel($rawGeneral)
{
global $permission;
$level = $rawGeneral['officer_level'];
if ($level >= 5) {
return $level;
}
if ($permission > 1) {
return $level;
}
return 1;
}
$specialViewFilter = [ $specialViewFilter = [
'officerLevel'=>function($rawGeneral){ 'officerLevel' => function ($rawGeneral){
return $rawGeneral['officer_level']; return getOfficerLevel($rawGeneral);
}, },
'special'=>function($rawGeneral){ 'special' => function ($rawGeneral) {
return getGeneralSpecialDomesticName($rawGeneral['special']); return getGeneralSpecialDomesticName($rawGeneral['special']);
}, },
'special2'=>function($rawGeneral){ 'special2' => function ($rawGeneral) {
return getGeneralSpecialWarName($rawGeneral['special2']); return getGeneralSpecialWarName($rawGeneral['special2']);
}, },
'personal'=>function($rawGeneral){ 'personal' => function ($rawGeneral) {
return getGenChar($rawGeneral['personal']); return getGenChar($rawGeneral['personal']);
}, },
'lbonus'=>function($rawGeneral)use($nationArr){ 'lbonus' => function ($rawGeneral) use ($nationArr) {
return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']); return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']);
}, },
'ownerName'=>function($rawGeneral){ 'ownerName' => function ($rawGeneral) {
if($rawGeneral['npc']!=1){ if ($rawGeneral['npc'] != 1) {
return null; return null;
} }
return $rawGeneral['owner_name']; return $rawGeneral['owner_name'];
}, },
'officerLevelText'=>function($rawGeneral)use($nationArr){ 'officerLevelText' => function ($rawGeneral) use ($nationArr) {
return getOfficerLevelText($rawGeneral['officer_level'], $nationArr['level']); $level = getOfficerLevel($rawGeneral);
return getOfficerLevelText($level, $nationArr['level']);
}, },
'honorText'=>function($rawGeneral){ 'honorText' => function ($rawGeneral) {
return getHonor($rawGeneral['experience']); return getHonor($rawGeneral['experience']);
}, },
'dedLevelText'=>function($rawGeneral){ 'dedLevelText' => function ($rawGeneral) {
return getDedLevelText($rawGeneral['dedLevel']); return getDedLevelText($rawGeneral['dedLevel']);
}, },
'turntime'=>function($rawGeneral){ 'turntime' => function ($rawGeneral) {
//'0000-00-00 11:23'; //'0000-00-00 11:23';
return substr($rawGeneral['turntime'], 11, 5); return substr($rawGeneral['turntime'], 11, 5);
} }
]; ];
$queryColumns = General::mergeQueryColumn(array_keys($viewColumns), 1); [$queryColumns, $rankColumns] = General::mergeQueryColumn(array_keys($viewColumns), 1);
$rawGeneralList = Util::convertArrayToDict($db->queryAllLists('SELECT %lb from general WHERE nation = %i', $queryColumns, $nationID), 'no'); $rawGeneralList = Util::convertArrayToDict($db->query('SELECT %l from general WHERE nation = %i', Util::formatListOfBackticks($queryColumns), $nationID), 'no');
$resultColumns = []; $resultColumns = [];
foreach($viewColumns as $column=>$reqPermission){ foreach ($viewColumns as $column => $reqPermission) {
if($reqPermission > $permission){ if ($reqPermission > $permission) {
continue; continue;
} }
$resultColumns[] = $column; $resultColumns[] = $column;
} }
foreach($customViewColumns as $column=>$reqPermission){ foreach ($customViewColumns as $column => $reqPermission) {
if($reqPermission > $permission){ if ($reqPermission > $permission) {
continue; continue;
} }
$resultColumns[] = $column; $resultColumns[] = $column;
} }
foreach($rawGeneralList as $rawGeneral){ foreach ($rawGeneralList as $rawGeneral) {
//General 생성? //General 생성?
$item = []; $item = [];
foreach($resultColumns as $column){ foreach ($resultColumns as $column) {
$value = $rawGeneral[$column]; if (key_exists($column, $specialViewFilter)) {
if(key_exists($column, $specialViewFilter)){
$value = $specialViewFilter[$column]($rawGeneral); $value = $specialViewFilter[$column]($rawGeneral);
} }
else{
$value = $rawGeneral[$column];
}
$item[] = $value; $item[] = $value;
} }
@@ -157,9 +175,9 @@ foreach($rawGeneralList as $rawGeneral){
} }
$result = [ $result = [
'result'=>true, 'result' => true,
'column'=>$resultColumns, 'column' => $resultColumns,
'list'=>$generalList, 'list' => $generalList,
]; ];
Json::die($result); Json::die($result);
+208 -208
View File
@@ -1,209 +1,209 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
if(!class_exists('\\sammo\\DB')){ if(!class_exists('\\sammo\\DB')){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'DB리셋 필요' 'reason'=>'DB리셋 필요'
]); ]);
} }
$serverName = DB::prefix(); $serverName = DB::prefix();
$serverAcl = $session->acl[$serverName]??[]; $serverAcl = $session->acl[$serverName]??[];
$allowReset = in_array('reset', $serverAcl); $allowReset = in_array('reset', $serverAcl);
$allowFullReset = in_array('fullReset',$serverAcl); $allowFullReset = in_array('fullReset',$serverAcl);
$allowReset |= $allowFullReset; $allowReset |= $allowFullReset;
$reserve_open = Util::getPost('reserve_open'); $reserve_open = Util::getPost('reserve_open');
if($reserve_open && $reserve_open < date('Y-m-d H:i')){ if($reserve_open && $reserve_open < date('Y-m-d H:i')){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.' 'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.'
]); ]);
} }
$pre_reserve_open = Util::getPost('pre_reserve_open'); $pre_reserve_open = Util::getPost('pre_reserve_open');
if($pre_reserve_open && !$reserve_open){ if($pre_reserve_open && !$reserve_open){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.' 'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.'
]); ]);
} }
if($pre_reserve_open && $pre_reserve_open >= $reserve_open){ if($pre_reserve_open && $pre_reserve_open >= $reserve_open){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.' 'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.'
]); ]);
} }
if($session->userGrade < 5 && !$allowReset){ if($session->userGrade < 5 && !$allowReset){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'관리자 아님' 'reason'=>'관리자 아님'
]); ]);
} }
$v = new Validator($_POST); $v = new Validator($_POST);
$v->rule('required', [ $v->rule('required', [
'turnterm', 'turnterm',
'sync', 'sync',
'scenario', 'scenario',
'fiction', 'fiction',
'extend', 'extend',
'join_mode', 'join_mode',
'npcmode', 'npcmode',
'show_img_level', 'show_img_level',
'autorun_user_minutes' 'autorun_user_minutes'
])->rule('integer', [ ])->rule('integer', [
'turnterm', 'turnterm',
'sync', 'sync',
'scenario', 'scenario',
'fiction', 'fiction',
'extend', 'extend',
'npcmode', 'npcmode',
'show_img_level', 'show_img_level',
'tournament_trig', 'tournament_trig',
'autorun_user_minutes' 'autorun_user_minutes'
])->rule('in', 'join_mode', ['onlyRandom', 'full']); ])->rule('in', 'join_mode', ['onlyRandom', 'full']);
if(!$v->validate()){ if(!$v->validate()){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>$v->errorStr() 'reason'=>$v->errorStr()
]); ]);
} }
$allowReset = true; $allowReset = true;
if($session->userGrade < 5 && !$allowFullReset){ if($session->userGrade < 5 && !$allowFullReset){
//리셋 가능한 조건인지 테스트 //리셋 가능한 조건인지 테스트
$allowReset = false; $allowReset = false;
if(file_exists(__DIR__.'/.htaccess')){ if(file_exists(__DIR__.'/.htaccess')){
$allowReset = true; $allowReset = true;
} }
else{ else{
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
if($gameStor->isunited){ if($gameStor->isunited){
$allowReset = true; $allowReset = true;
} }
} }
} }
if(!$allowReset){ if(!$allowReset){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.' 'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.'
]); ]);
} }
$turnterm = (int)$_POST['turnterm']; $turnterm = (int)$_POST['turnterm'];
$sync = (int)$_POST['sync']; $sync = (int)$_POST['sync'];
$scenario = (int)$_POST['scenario']; $scenario = (int)$_POST['scenario'];
$fiction = (int)$_POST['fiction']; $fiction = (int)$_POST['fiction'];
$extend = (int)$_POST['extend']; $extend = (int)$_POST['extend'];
$npcmode = (int)$_POST['npcmode']; $npcmode = (int)$_POST['npcmode'];
$show_img_level = (int)$_POST['show_img_level']; $show_img_level = (int)$_POST['show_img_level'];
$tournament_trig = (int)$_POST['tournament_trig']; $tournament_trig = (int)$_POST['tournament_trig'];
$join_mode = $_POST['join_mode']; $join_mode = $_POST['join_mode'];
$autorun_user_minutes = (int)$_POST['autorun_user_minutes']; $autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
$autorun_user_options = []; $autorun_user_options = [];
foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){ foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){
$autorun_user_options[$autorun_option] = 1; $autorun_user_options[$autorun_option] = 1;
} }
if($autorun_user_minutes > 0 && !$autorun_user_options){ if($autorun_user_minutes > 0 && !$autorun_user_options){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.' 'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
]); ]);
} }
if($autorun_user_minutes < 0){ if($autorun_user_minutes < 0){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.' 'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
]); ]);
} }
$autorun_user = $autorun_user_minutes?[ $autorun_user = $autorun_user_minutes?[
'limit_minutes'=>$autorun_user_minutes, 'limit_minutes'=>$autorun_user_minutes,
'options'=>$autorun_user_options 'options'=>$autorun_user_options
]:null; ]:null;
if($reserve_open){ if($reserve_open){
$reserve_open = new \DateTime($reserve_open); $reserve_open = new \DateTime($reserve_open);
$db = DB::db(); $db = DB::db();
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) { if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
$clearResult = ResetHelper::clearDB(); $clearResult = ResetHelper::clearDB();
if(!$clearResult['result']){ if(!$clearResult['result']){
Json::die($clearResult); Json::die($clearResult);
} }
} }
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) { if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'예약 테이블이 없음!' 'reason'=>'예약 테이블이 없음!'
]); ]);
} }
$scenarioObj = new Scenario($scenario, true); $scenarioObj = new Scenario($scenario, true);
$open_date = $reserve_open->format('Y-m-d H:i:s'); $open_date = $reserve_open->format('Y-m-d H:i:s');
$reserveInfo = [ $reserveInfo = [
'turnterm'=>$turnterm, 'turnterm'=>$turnterm,
'sync'=>$sync, 'sync'=>$sync,
'scenario'=>$scenario, 'scenario'=>$scenario,
'scenarioName'=>$scenarioObj->getTitle(), 'scenarioName'=>$scenarioObj->getTitle(),
'fiction'=>$fiction, 'fiction'=>$fiction,
'extend'=>$extend, 'extend'=>$extend,
'npcmode'=>$npcmode, 'npcmode'=>$npcmode,
'show_img_level'=>$show_img_level, 'show_img_level'=>$show_img_level,
'tournament_trig'=>$tournament_trig, 'tournament_trig'=>$tournament_trig,
'gameConf'=>$scenarioObj->getGameConf(), 'gameConf'=>$scenarioObj->getGameConf(),
'join_mode'=>$join_mode, 'join_mode'=>$join_mode,
'starttime'=>$open_date, 'starttime'=>$open_date,
'autorun_user'=>$autorun_user 'autorun_user'=>$autorun_user
]; ];
if($pre_reserve_open){ if($pre_reserve_open){
$pre_reserve_open = new \DateTime($pre_reserve_open); $pre_reserve_open = new \DateTime($pre_reserve_open);
$open_date = $pre_reserve_open->format('Y-m-d H:i:s'); $open_date = $pre_reserve_open->format('Y-m-d H:i:s');
} }
$db->delete('reserved_open', true); $db->delete('reserved_open', true);
$db->insert('reserved_open', [ $db->insert('reserved_open', [
'options'=>Json::encode($reserveInfo), 'options'=>Json::encode($reserveInfo),
'date'=>$open_date 'date'=>$open_date
]); ]);
AppConf::getList()[DB::prefix()]->closeServer(); ServConfig::getServerList()[DB::prefix()]->closeServer();
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'reason'=>'예약' 'reason'=>'예약'
]); ]);
} }
Json::die(ResetHelper::buildScenario( Json::die(ResetHelper::buildScenario(
$turnterm, $turnterm,
$sync, $sync,
$scenario, $scenario,
$fiction, $fiction,
$extend, $extend,
$npcmode, $npcmode,
$show_img_level, $show_img_level,
$tournament_trig, $tournament_trig,
$join_mode, $join_mode,
TimeUtil::now(), TimeUtil::now(),
$autorun_user $autorun_user
)); ));
+102 -102
View File
@@ -1,103 +1,103 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
if($session->userGrade < 6){ if($session->userGrade < 6){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'관리자 아님' 'reason'=>'관리자 아님'
]); ]);
} }
$fullReset = Util::getPost('full_reset', 'bool', false); $fullReset = Util::getPost('full_reset', 'bool', false);
$host = Util::getPost('db_host'); $host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int'); $port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id'); $username = Util::getPost('db_id');
$password = Util::getPost('db_pw'); $password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name'); $dbName = Util::getPost('db_name');
if(!$host || !$port || !$username || !$password || !$dbName){ if(!$host || !$port || !$username || !$password || !$dbName){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'입력 값이 올바르지 않습니다' 'reason'=>'입력 값이 올바르지 않습니다'
]); ]);
} }
if($fullReset && class_exists('\\sammo\\DB')){ if($fullReset && class_exists('\\sammo\\DB')){
$mysqli_obj = DB::db()->get(); $mysqli_obj = DB::db()->get();
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){ if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){
while(true){ while(true){
if (!$mysqli_obj->more_results()) { if (!$mysqli_obj->more_results()) {
break; break;
} }
if(!$mysqli_obj->next_result()){ if(!$mysqli_obj->next_result()){
break; break;
} }
} }
} }
} }
if($fullReset){ if($fullReset){
FileUtil::delInDir(__DIR__."/logs"); FileUtil::delInDir(__DIR__."/logs");
FileUtil::delInDir(__DIR__."/data"); FileUtil::delInDir(__DIR__."/data");
if(file_exists(__DIR__.'/d_setting/DB.php')){ if(file_exists(__DIR__.'/d_setting/DB.php')){
@unlink(__DIR__.'/d_setting/DB.php'); @unlink(__DIR__.'/d_setting/DB.php');
} }
if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){ if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){
@unlink(__DIR__.'/d_setting/UniqueConst.php'); @unlink(__DIR__.'/d_setting/UniqueConst.php');
} }
} }
function dbConnFail($params){ function dbConnFail($params){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'DB 접속에 실패했습니다.' 'reason'=>'DB 접속에 실패했습니다.'
]); ]);
} }
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4'); $db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4');
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; $db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->throw_exception_on_nonsql_error = false; $db->throw_exception_on_nonsql_error = false;
$db->nonsql_error_handler = 'dbConnFail'; $db->nonsql_error_handler = 'dbConnFail';
$mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨. $mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
$prefix = basename(__DIR__); $prefix = basename(__DIR__);
$result = Util::generateFileUsingSimpleTemplate( $result = Util::generateFileUsingSimpleTemplate(
__DIR__.'/d_setting/DB.orig.php', __DIR__.'/d_setting/DB.orig.php',
__DIR__.'/d_setting/DB.php',[ __DIR__.'/d_setting/DB.php',[
'host'=>$host, 'host'=>$host,
'user'=>$username, 'user'=>$username,
'password'=>$password, 'password'=>$password,
'dbName'=>$dbName, 'dbName'=>$dbName,
'port'=>$port, 'port'=>$port,
'prefix'=>$prefix 'prefix'=>$prefix
], true ], true
); );
if($result !== true){ if($result !== true){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>$result 'reason'=>$result
]); ]);
} }
ResetHelper::clearDB(); ResetHelper::clearDB();
AppConf::getList()[$prefix]->closeServer(); ServConfig::getServerList()[$prefix]->closeServer();
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'reason'=>'success' 'reason'=>'success'
]); ]);
+83
View File
@@ -0,0 +1,83 @@
<?php
namespace sammo;
use Nette\Caching\Cache;
include "lib.php";
include "func.php";
if(!class_exists('\\sammo\\UniqueConst')){
Json::die([
'result'=>false,
'reason'=>'서버 초기화되지 않음'
]);
}
if(!prepareDir('data/file_cache')){
Json::die([
'result'=>false,
'reason'=>'cache 불가'
]);
}
$storage = new \Nette\Caching\Storages\FileStorage('data/file_cache');
$cache = new Cache($storage);
$serverID = UniqueConst::$serverID;
$mapInfo = $cache->load("recent_map");
//로그인 검사
$now = time();
if($mapInfo && ($now - $mapInfo['timestamp'] < 600)){
$mapEtag = $mapInfo['etag'];
$mapModified = $mapInfo['timestamp'];
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mapModified)." GMT");
header("Etag: $mapEtag");
if (
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']??'2000-01-01') === $mapModified ||
trim($_SERVER['HTTP_IF_NONE_MATCH']??'') === $mapEtag
) {
header("HTTP/1.1 304 Not Modified");
die();
}
Json::die($mapInfo['data'], 0);
}
$defaultPost = [
'year' => null,
'month' => null,
'aux' => null,
'neutralView' => true,
'showMe' => false,
];
$history = formatHistoryToHTML(getGlobalHistoryLogRecent(10));
$rawMap = getWorldMap([
'year' => null,
'month' => null,
'aux' => null,
'neutralView' => true,
'showMe' => false,
]);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme ?? 'che';
$rawMap['history'] = $history;
$rawMap['theme'] = $mapTheme;
$etag = hash('sha256', $serverID.$now);
$map = [
'etag'=>$etag,
'timestamp'=>$now,
'data'=>$rawMap,
];
$cache->save("recent_map", $map);
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $now)." GMT");
header("Etag: $etag");
Json::die($map['data'], 0);
+360 -359
View File
@@ -1,360 +1,361 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$action = Util::getPost('action'); $action = Util::getPost('action');
$officerLevel = Util::getPost('officerLevel', 'int'); $officerLevel = Util::getPost('officerLevel', 'int');
$destGeneralID = Util::getPost('destGeneralID', 'int'); $destGeneralID = Util::getPost('destGeneralID', 'int');
$destCityID = Util::getPost('destCityID', 'int'); $destCityID = Util::getPost('destCityID', 'int');
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['startyear','year','month','scenario']); $gameStor->cacheValues(['startyear','year','month','scenario']);
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID); $me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$myOfficerLevel = $me['officer_level']; $myOfficerLevel = $me['officer_level'];
$nationID = $me['nation']; $nationID = $me['nation'];
//수뇌가 아니면 아무것도 할 수 없음 //수뇌가 아니면 아무것도 할 수 없음
if($myOfficerLevel < 5){ if($myOfficerLevel < 5){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'수뇌가 아닙니다.' 'reason'=>'수뇌가 아닙니다.'
]); ]);
} }
if($action === '추방' && $destGeneralID==0){ if($action === '추방' && $destGeneralID==0){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'장수가 지정되지 않았습니다.' 'reason'=>'장수가 지정되지 않았습니다.'
]); ]);
} }
if($destGeneralID==0){ if($destGeneralID==0){
$general = new DummyGeneral(true); $general = new DummyGeneral(true);
} $general->setVar('nation', $nationID);
else{ }
$general = General::createGeneralObjFromDB($destGeneralID, [ else{
'name', 'leadership', 'strength', 'intel', 'gold','rice', $general = General::createGeneralObjFromDB($destGeneralID, [
'troop','officer_level','npc','picture','imgsvr', 'name', 'leadership', 'strength', 'intel', 'gold','rice',
'permission','penalty','belong', 'crewtype', 'troop','officer_level','npc','picture','imgsvr',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'permission','penalty','belong', 'crewtype',
], 1); 'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit',
], 1);
if($general instanceof DummyGeneral){
Json::die([ if($general instanceof DummyGeneral){
'result'=>false, Json::die([
'reason'=>'올바르지 않은 장수입니다.' 'result'=>false,
]); 'reason'=>'올바르지 않은 장수입니다.'
} ]);
}
if($nationID != $general->getNationID()){
Json::die([ if($nationID != $general->getNationID()){
'result'=>false, Json::die([
'reason'=>'아국 장수가 아닙니다' 'result'=>false,
]); 'reason'=>'아국 장수가 아닙니다'
} ]);
} }
}
if($officerLevel == 12){
Json::die([ if($officerLevel == 12){
'result'=>false, Json::die([
'reason'=>'군주를 대상으로 할 수 없습니다.' 'result'=>false,
]); 'reason'=>'군주를 대상으로 할 수 없습니다.'
} ]);
}
function do수뇌임명(General $general, int $targetOfficerLevel):?string{
$generalID = $general->getID(); function do수뇌임명(General $general, int $targetOfficerLevel):?string{
$nationID = $general->getNationID(); $generalID = $general->getID();
$nationID = $general->getNationID();
$db = DB::db();
$db = DB::db();
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
// 임명가능 레벨
$lv = getNationChiefLevel($nationLevel); // 임명가능 레벨
$lv = getNationChiefLevel($nationLevel);
if($targetOfficerLevel < $lv){
return '임명불가능한 관직입니다.'; if($targetOfficerLevel < $lv){
} return '임명불가능한 관직입니다.';
}
if(isOfficerSet($chiefSet, $targetOfficerLevel)){
return '지금은 임명할 수 없습니다.'; if(isOfficerSet($chiefSet, $targetOfficerLevel)){
} return '지금은 임명할 수 없습니다.';
}
//기존 장수 일반으로
$db->update('general', [ //기존 장수 일반으로
'officer_level'=>1, $db->update('general', [
'officer_city'=>0, 'officer_level'=>1,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID); 'officer_city'=>0,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
if($targetOfficerLevel === 11){
if($targetOfficerLevel === 11){
}
else if($targetOfficerLevel % 2 == 0){ }
if($general->getVar('strength') < GameConst::$chiefStatMin){ else if($targetOfficerLevel % 2 == 0){
return '무력이 부족합니다.'; if($general->getVar('strength') < GameConst::$chiefStatMin){
} return '무력이 부족합니다.';
}
}
else{ }
if($general->getVar('intel') < GameConst::$chiefStatMin){ else{
return '지력이 부족합니다.'; if($general->getVar('intel') < GameConst::$chiefStatMin){
} return '지력이 부족합니다.';
} }
}
//신임 장수
$general->setVar('officer_level', $targetOfficerLevel); //신임 장수
$general->setVar('officer_city', 0); $general->setVar('officer_level', $targetOfficerLevel);
$db->update('nation', [ $general->setVar('officer_city', 0);
'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)), $db->update('nation', [
], 'nation=%i', $nationID); 'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
$general->applyDB($db); ], 'nation=%i', $nationID);
$general->applyDB($db);
return null;
} return null;
}
function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
$nationID = $general->getNationID(); function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
$nationID = $general->getNationID();
$db = DB::db();
$db = DB::db();
if(CityConst::byID($cityID) === null){
return '올바르지 않은 도시입니다'; if(CityConst::byID($cityID) === null){
} return '올바르지 않은 도시입니다';
}
$officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
if($officerSet === null){ $officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
return '아국 도시가 아닙니다'; if($officerSet === null){
} return '아국 도시가 아닙니다';
}
if(isOfficerSet($officerSet, $targetOfficerLevel)){
return '이미 다른 장수가 임명되어있습니다'; if(isOfficerSet($officerSet, $targetOfficerLevel)){
} return '이미 다른 장수가 임명되어있습니다';
}
//기존 장수 일반으로
$db->update('general', [ //기존 장수 일반으로
'officer_level'=>1, $db->update('general', [
'officer_city'=>0, 'officer_level'=>1,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID()); 'officer_city'=>0,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
if($general instanceof DummyGeneral){
return null; if($general instanceof DummyGeneral){
} return null;
}
if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
return '무력이 부족합니다.'; if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
} return '무력이 부족합니다.';
}
if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
return '지력이 부족합니다.'; if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
} return '지력이 부족합니다.';
}
//신임 장수
$db->update('city', [ //신임 장수
'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)), $db->update('city', [
], 'city=%i AND nation=%i', $cityID, $nationID); 'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)),
$general->setVar('officer_level', $targetOfficerLevel); ], 'city=%i AND nation=%i', $cityID, $nationID);
$general->setVar('officer_city', $cityID); $general->setVar('officer_level', $targetOfficerLevel);
$general->applyDB($db); $general->setVar('officer_city', $cityID);
$general->applyDB($db);
return null;
} return null;
}
function do추방(General $general, int $myOfficerLevel):?string{
$generalID = $general->getID(); function do추방(General $general, int $myOfficerLevel):?string{
$generalName = $general->getVar('name'); $generalID = $general->getID();
$nationID = $general->getNationID(); $generalName = $general->getVar('name');
$nationID = $general->getNationID();
//추방할사람이 외교권자이면 불가
$permission = checkSecretPermission($general->getRaw()); //추방할사람이 외교권자이면 불가
if($permission == 4){ $permission = checkSecretPermission($general->getRaw());
return '외교권자는 추방할 수 없습니다.'; if($permission == 4){
} return '외교권자는 추방할 수 없습니다.';
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $db = DB::db();
$env = $gameStor->getValues(['startyear','year','month','scenario']); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getValues(['startyear','year','month','scenario']);
$nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name']; $nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name'];
$logger = $general->getLogger();
$logger = $general->getLogger();
//이미 지정했다면 무시
if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) { //이미 지정했다면 무시
return '이미 추방 권한을 사용했습니다.'; if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
} return '이미 추방 권한을 사용했습니다.';
$gold = 0; }
$rice = 0; $gold = 0;
// 금쌀1000이상은 남김 $rice = 0;
if($general->getVar('gold') > GameConst::$defaultGold) { // 금쌀1000이상은 남김
$gold = $general->getVar('gold') - GameConst::$defaultGold; if($general->getVar('gold') > GameConst::$defaultGold) {
$general->setVar('gold', GameConst::$defaultGold); $gold = $general->getVar('gold') - GameConst::$defaultGold;
} $general->setVar('gold', GameConst::$defaultGold);
if($general->getVar('rice') > GameConst::$defaultRice) { }
$rice = $general->getVar('rice') - GameConst::$defaultRice; if($general->getVar('rice') > GameConst::$defaultRice) {
$general->setVar('rice', GameConst::$defaultRice); $rice = $general->getVar('rice') - GameConst::$defaultRice;
} $general->setVar('rice', GameConst::$defaultRice);
}
$general->setVar('nation', 0);
$general->setVar('officer_level', 0); $general->setVar('nation', 0);
$general->setVar('officer_city', 0); $general->setVar('officer_level', 0);
$general->setVar('belong', 0); $general->setVar('officer_city', 0);
$oldMakeLimit = $general->getVar('makelimit'); $general->setVar('belong', 0);
$general->setVar('makelimit', 12); $oldMakeLimit = $general->getVar('makelimit');
$general->setVar('permission', 'normal'); $general->setVar('makelimit', 12);
$general->setVar('permission', 'normal');
$josaYi = JosaUtil::pick($generalName, '이');
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>에서 <R>추방</>당했습니다."); $josaYi = JosaUtil::pick($generalName, '이');
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN); $logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.");
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN);
// 명성/공헌 N*10%감소
if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){ // 명성/공헌 N*10%감소
$general->setVar('makelimit', $oldMakeLimit); if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){
} $general->setVar('makelimit', $oldMakeLimit);
else{ }
$betrayCnt = $general->getVar('betray'); else{
$general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt); $betrayCnt = $general->getVar('betray');
$general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt); $general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt); $general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
} $general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
}
//부대장일 경우
if($general->getVar('troop') == $generalID){ //부대장일 경우
// 모두 탈퇴 if($general->getVar('troop') == $generalID){
$db->update('general', [ // 모두 탈퇴
'troop'=>0, $db->update('general', [
], 'troop = %i', $generalID); 'troop'=>0,
$db->delete('troop', 'troop_leader=%i', $generalID); ], 'troop = %i', $generalID);
} $db->delete('troop', 'troop_leader=%i', $generalID);
$general->setVar('troop', 0); }
$general->setVar('troop', 0);
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
$str = Util::choiceRandom([
'날 버리다니... 곧 전장에서 복수해주겠다...', $str = Util::choiceRandom([
'추방이라... 내가 무얼 잘못했단 말인가...', '날 버리다니... 곧 전장에서 복수해주겠다...',
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...', '추방이라... 내가 무얼 잘못했단 말인가...',
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!', '어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.' '인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
]); '날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
]);
$src = new MessageTarget(
$generalID, $src = new MessageTarget(
$generalName, $generalID,
$nationID, $generalName,
$nation['name'], $nationID,
$nation['color'], $nation['name'],
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture')) $nation['color'],
); GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
$msg = new Message( );
Message::MSGTYPE_PUBLIC, $msg = new Message(
$src, Message::MSGTYPE_PUBLIC,
$src, $src,
$str, $src,
new \DateTime(), $str,
new \DateTime('9999-12-31'), new \DateTime(),
[] new \DateTime('9999-12-31'),
); []
$msg->send(); );
} $msg->send();
}
if($env['year'] < $env['startyear']+3) {
//초반엔 군주 부상 증가(엔장 임관지양) if($env['year'] < $env['startyear']+3) {
$db->update('general', [ //초반엔 군주 부상 증가(엔장 임관지양)
'injury'=>$db->sqleval('least(injury + 1, %i)', 80), $db->update('general', [
], 'nation=%i AND officer_level=12', $nationID); 'injury'=>$db->sqleval('least(injury + 1, %i)', 80),
], 'nation=%i AND officer_level=12', $nationID);
$db->update('nation', [
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0), $db->update('nation', [
'gold'=>$db->sqleval('gold + %i', $gold), 'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'rice'=>$db->sqleval('rice + %i', $rice), 'gold'=>$db->sqleval('gold + %i', $gold),
], 'nation = %i', $nationID); 'rice'=>$db->sqleval('rice + %i', $rice),
} else { ], 'nation = %i', $nationID);
//이번분기는 추방불가(초반 제외) } else {
$db->update('nation', [ //이번분기는 추방불가(초반 제외)
'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)), $db->update('nation', [
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0), 'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
'gold'=>$db->sqleval('gold + %i', $gold), 'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'rice'=>$db->sqleval('rice + %i', $rice), 'gold'=>$db->sqleval('gold + %i', $gold),
], 'nation = %i', $nationID); 'rice'=>$db->sqleval('rice + %i', $rice),
} ], 'nation = %i', $nationID);
}
$logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
$general->applyDB($db); $logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
$general->applyDB($db);
return null;
} return null;
}
if($action == "임명") {
if(2 <= $officerLevel && $officerLevel <= 4){ if($action == "임명") {
if(!$destCityID){ if(2 <= $officerLevel && $officerLevel <= 4){
Json::die([ if(!$destCityID){
'result'=>false, Json::die([
'reason'=>'도시가 지정되지 않았습니다.' 'result'=>false,
]); 'reason'=>'도시가 지정되지 않았습니다.'
} ]);
$result = do도시임명($general, $destCityID, $officerLevel); }
if($result !== null){ $result = do도시임명($general, $destCityID, $officerLevel);
Json::die([ if($result !== null){
'result'=>false, Json::die([
'reason'=>$result 'result'=>false,
]); 'reason'=>$result
} ]);
Json::die([ }
'result'=>true, Json::die([
'reason'=>'success' 'result'=>true,
]); 'reason'=>'success'
} ]);
}
if(5 <= $officerLevel && $officerLevel < 12){
$result = do수뇌임명($general, $officerLevel); if(5 <= $officerLevel && $officerLevel < 12){
if($result !== null){ $result = do수뇌임명($general, $officerLevel);
Json::die([ if($result !== null){
'result'=>false, Json::die([
'reason'=>$result 'result'=>false,
]); 'reason'=>$result
} ]);
Json::die([ }
'result'=>true, Json::die([
'reason'=>'success' 'result'=>true,
]); 'reason'=>'success'
} ]);
}
Json::die([
'result'=>false, Json::die([
'reason'=>'올바르지 않은 지정입니다.' 'result'=>false,
]); 'reason'=>'올바르지 않은 지정입니다.'
} ]);
}
if($action == "추방") {
$result = do추방($general, $myOfficerLevel); if($action == "추방") {
if($result !== null){ $result = do추방($general, $myOfficerLevel);
Json::die([ if($result !== null){
'result'=>false, Json::die([
'reason'=>$result 'result'=>false,
]); 'reason'=>$result
} ]);
Json::die([ }
'result'=>true, Json::die([
'reason'=>'success' 'result'=>true,
]); 'reason'=>'success'
} ]);
}
Json::die([
'result'=>false, Json::die([
'reason'=>'올바르지 않은 명령입니다.' 'result'=>false,
'reason'=>'올바르지 않은 명령입니다.'
]); ]);
+2
View File
@@ -8,6 +8,8 @@ WebUtil::requireAJAX();
$session = Session::requireGameLogin([])->setReadOnly(); $session = Session::requireGameLogin([])->setReadOnly();
increaseRefresh("사령턴 입력", 0);
$generalID = $session->generalID; $generalID = $session->generalID;
+2
View File
@@ -8,6 +8,8 @@ WebUtil::requireAJAX();
$session = Session::requireGameLogin([])->setReadOnly(); $session = Session::requireGameLogin([])->setReadOnly();
increaseRefresh("턴 입력", 0);
$generalID = $session->generalID; $generalID = $session->generalID;
$action = Util::getPost('action', 'string'); $action = Util::getPost('action', 'string');
+82
View File
@@ -0,0 +1,82 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireGameLogin([])->setReadOnly();
$userID = Session::getUserID();
$generalID = $session->generalID;
increaseRefresh("내정보 수정", 0);
$action = Util::getPost('action');
$tnmt = Util::getPost('tnmt', 'int', 1);
$defence_train = Util::getPost('defence_train', 'int', 80);
$use_treatment = Util::getPost('use_treatment', 'int', 10);
$use_auto_nation_turn = Util::getPost('use_auto_nation_turn', 'int', 1);
//$detachNPC = Util::getPost('detachNPC', 'bool');
$detachNPC = false;
if ($defence_train <= 40) {
$defence_train = 40;
}
if($defence_train <= 90){
$defence_train = Util::round($defence_train, -1);
}
else{
$defence_train = 999;
}
if($tnmt < 0 || $tnmt > 1){
$tnmt = 1;
}
$db = DB::db();
$me = General::createGeneralObjFromDB($generalID);
if($defence_train != $me->getVar('defence_train')){
if($defence_train == 999){
$me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train);
$me->increaseVar('train', -3);
$me->increaseVar('atmos', -3);
}
else{
$me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train);
}
}
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
if($use_auto_nation_turn != $me->getAuxVar('use_auto_nation_turn')){
$me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
}
if($me->getVar('tnmt') != $tnmt){
$me->setVar('tnmt', $tnmt);
}
if($me->getNPCType() == 1 && $detachNPC){
$turnterm = $gameStor->turnterm;
if($turnterm < 10){
$targetKillTurn = 30 / $turnterm;
}
else{
$targetKillTurn = 60 / $turnterm;
}
$me->setVar('killturn', $targetKillTurn);
}
$me->applyDB($db);
Json::die([
'result'=>true,
'reason'=>'success'
]);
+2 -6
View File
@@ -10,6 +10,7 @@ $session = Session::requireGameLogin([])->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$generalID = $session->generalID; $generalID = $session->generalID;
increaseRefresh("NPC 정책 수정", 0);
$type = Util::getPost('type', 'string'); $type = Util::getPost('type', 'string');
$data = Util::getPost('data', 'string'); $data = Util::getPost('data', 'string');
@@ -47,12 +48,7 @@ if (!$nationID) {
'reason'=>'국가에 소속되어있지 않습니다.', 'reason'=>'국가에 소속되어있지 않습니다.',
]); ]);
} }
if ($me['officer_level'] < 5) {
Json::die([
'result'=>false,
'reason'=>'수뇌가 아닙니다.',
]);
}
$permission = checkSecretPermission($me); $permission = checkSecretPermission($me);
if ($permission < 3) { if ($permission < 3) {
Json::die([ Json::die([
+465 -449
View File
@@ -1,449 +1,465 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$query = Util::getPost('query'); increaseRefresh("시뮬레이터", 0);
if($query === null){
Json::die([ $query = Util::getPost('query');
'result'=>false, if($query === null){
'reason'=>'입력값이 없습니다.' Json::die([
]); 'result'=>false,
} 'reason'=>'입력값이 없습니다.'
]);
$action = Util::getPost('action'); }
if($action === null || !in_array($action, ['reorder', 'battle'])){
Json::die([ $action = Util::getPost('action');
'result'=>false, if($action === null || !in_array($action, ['reorder', 'battle'])){
'reason'=>'원하는 동작이 지정되지 않았습니다.' Json::die([
]); 'result'=>false,
} 'reason'=>'원하는 동작이 지정되지 않았습니다.'
]);
$query = Json::decode($query); }
if($query === null){
Json::die([ $query = Json::decode($query);
'result'=>false, if($query === null){
'reason'=>'올바르지 않은 JSON입니다.' Json::die([
]); 'result'=>false,
} 'reason'=>'올바르지 않은 JSON입니다.'
]);
$defaultCheck = [ }
'required'=>[
'attackerGeneral', 'attackerCity', 'attackerNation', $defaultCheck = [
'defenderGenerals', 'defenderCity', 'defenderNation', 'required'=>[
'year', 'month', 'repeatCnt' 'attackerGeneral', 'attackerCity', 'attackerNation',
], 'defenderGenerals', 'defenderCity', 'defenderNation',
'integer'=>[ 'year', 'month', 'repeatCnt'
'year','month','repeatCnt' ],
], 'integer'=>[
'between'=>[ 'year','month','repeatCnt'
['month', [1, 12]] ],
], 'between'=>[
'in'=>[ ['month', [1, 12]]
['repeatCnt', [1, 1000]] ],
], 'in'=>[
'min'=>[ ['repeatCnt', [1, 1000]]
['year', 0] ],
], 'min'=>[
'array'=>[ ['year', 0]
'attackerGeneral', 'attackerCity', 'attackerNation', ],
'defenderGenerals', 'defenderCity', 'defenderNation' 'array'=>[
], 'attackerGeneral', 'attackerCity', 'attackerNation',
]; 'defenderGenerals', 'defenderCity', 'defenderNation'
],
$v = new Validator($query); ];
$v->rules($defaultCheck);
if(!$v->validate()){ $v = new Validator($query);
Json::die([ $v->rules($defaultCheck);
'result'=>false, if(!$v->validate()){
'reason'=>$v->errorStr() Json::die([
]); 'result'=>false,
} 'reason'=>$v->errorStr()
]);
$year = $query['year']; }
$month = $query['month'];
$repeatCnt = $query['repeatCnt']; $year = $query['year'];
$month = $query['month'];
$rawAttacker = $query['attackerGeneral']; $repeatCnt = $query['repeatCnt'];
$rawAttacker['turntime'] = TimeUtil::now();
$rawAttackerCity = $query['attackerCity']; $rawAttacker = $query['attackerGeneral'];
$rawAttackerNation = $query['attackerNation']; $rawAttacker['turntime'] = TimeUtil::now();
$rawAttackerCity = $query['attackerCity'];
$rawDefenderList = $query['defenderGenerals']; $rawAttackerNation = $query['attackerNation'];
$rawDefenderCity = $query['defenderCity'];
$rawDefenderNation = $query['defenderNation']; $rawDefenderList = $query['defenderGenerals'];
$rawDefenderCity = $query['defenderCity'];
$rawDefenderNation = $query['defenderNation'];
$generalCheck = [
'required'=>[
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train', $generalCheck = [
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item', 'required'=>[
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'recent_war' 'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
], 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'integer'=>[ 'recent_war', 'warnum', 'killnum', 'killcrew',
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train', ],
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp', 'integer'=>[
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
], 'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
'min'=>[ 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
['no', 1], 'warnum', 'killnum', 'killcrew',
['nation', 1], ],
['crew', 0], 'min'=>[
['intel', 0], ['no', 1],
['strength', 0], ['nation', 1],
['leadership', 0], ['crew', 0],
['experience', 0], ['intel', 0],
['gold', 0], ['strength', 0],
['rice', 0], ['leadership', 0],
['dex1', 0], ['experience', 0],
['dex2', 0], ['gold', 0],
['dex3', 0], ['rice', 0],
['dex4', 0], ['dex1', 0],
['dex5', 0], ['dex2', 0],
], ['dex3', 0],
'between'=>[ ['dex4', 0],
['train', [40, GameConst::$maxTrainByWar]], ['dex5', 0],
['atmos', [40, GameConst::$maxAtmosByWar]], ['warnum', 0],
['explevel', [0, 300]], ['killnum', 0],
['injury', [0, 80]], ['killcrew', 0],
['officer_level', [1, 12]] ],
], 'between'=>[
'in'=>[ ['train', [40, GameConst::$maxTrainByWar]],
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)], ['atmos', [40, GameConst::$maxAtmosByWar]],
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)], ['explevel', [0, 300]],
['crewtype', array_keys(GameUnitConst::all())], ['injury', [0, 80]],
['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])], ['officer_level', [1, 12]]
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])], ],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])], 'in'=>[
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])], ['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
] ['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
]; ['crewtype', array_keys(GameUnitConst::all())],
['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])],
$v = new Validator($rawAttacker); ['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
$v->rules($generalCheck); ['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
if(!$v->validate()){ ['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
Json::die([ ]
'result'=>false, ];
'reason'=>'[출병자]'.$v->errorStr()
]); $v = new Validator($rawAttacker);
} $v->rules($generalCheck);
if(!$v->validate()){
$defenderList = []; Json::die([
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){ 'result'=>false,
$v = new Validator($rawDefenderGeneral); 'reason'=>'[출병자]'.$v->errorStr()
$v->rules($generalCheck); ]);
if(!$v->validate()){ }
$idx+=1;
Json::die([ $defenderList = [];
'result'=>false, foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
'reason'=>"[수비자{$idx}]".$v->errorStr() $v = new Validator($rawDefenderGeneral);
]); $v->rules($generalCheck);
} if(!$v->validate()){
$defenderList[] = new General($rawDefenderGeneral, null, $rawDefenderCity, $rawAttackerNation, $year, $month, true); $idx+=1;
} Json::die([
'result'=>false,
'reason'=>"[수비자{$idx}]".$v->errorStr()
$cityCheck = [ ]);
'required'=>[ }
'city', 'nation', 'supply', 'name',
'pop', 'agri', 'comm', 'secu', 'def', 'wall', $defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
'trust', 'level', }
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'dead', 'state', 'conflict',
], $cityCheck = [
'numeric'=>[ 'required'=>[
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead' 'city', 'nation', 'supply', 'name',
], 'pop', 'agri', 'comm', 'secu', 'def', 'wall',
'integer'=>[ 'trust', 'level',
'city', 'nation', 'supply', 'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max', 'dead', 'state', 'conflict',
'state', ],
], 'numeric'=>[
'min'=>[ 'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
['def', 0], ],
['wall', 0], 'integer'=>[
['trust', 0], 'city', 'nation', 'supply',
['pop', 0], 'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
['comm', 0], 'state',
['secu', 0], ],
['city', 1], 'min'=>[
['nation', 0] ['def', 0],
], ['wall', 0],
'in'=>[ ['trust', 0],
['level', array_keys(getCityLevelList())] ['pop', 0],
] ['comm', 0],
]; ['secu', 0],
['city', 1],
$v = new Validator($rawAttackerCity); ['nation', 0]
$v->rules($cityCheck); ],
if(!$v->validate()){ 'in'=>[
Json::die([ ['level', array_keys(getCityLevelList())]
'result'=>false, ]
'reason'=>'[출병도시]'.$v->errorStr() ];
]);
} $v = new Validator($rawAttackerCity);
$v->rules($cityCheck);
$v = new Validator($rawDefenderCity); if(!$v->validate()){
$v->rules($cityCheck); Json::die([
if(!$v->validate()){ 'result'=>false,
Json::die([ 'reason'=>'[출병도시]'.$v->errorStr()
'result'=>false, ]);
'reason'=>'[수비도시]'.$v->errorStr() }
]);
} $v = new Validator($rawDefenderCity);
$v->rules($cityCheck);
$nationCheck = [ if(!$v->validate()){
'required'=>[ Json::die([
'type', 'tech', 'level', 'capital', 'result'=>false,
'nation', 'name', 'gold', 'rice', 'gennum' 'reason'=>'[수비도시]'.$v->errorStr()
], ]);
'integer'=>[ }
'level', 'capital', 'nation', 'gennum',
], $nationCheck = [
'numeric'=>[ 'required'=>[
'tech', 'gold', 'rice' 'type', 'tech', 'level', 'capital',
], 'nation', 'name', 'gold', 'rice', 'gennum'
'min'=>[ ],
['tech', 0], 'integer'=>[
['gold', 0], 'level', 'capital', 'nation', 'gennum',
['rice', 0], ],
['gennum', 1], 'numeric'=>[
], 'tech', 'gold', 'rice'
'in'=>[ ],
['type', GameConst::$availableNationType], 'min'=>[
['level', array_keys(getNationLevelList())] ['tech', 0],
] ['gold', 0],
]; ['rice', 0],
['gennum', 1],
$v = new Validator($rawAttackerNation); ],
$v->rules($nationCheck); 'in'=>[
if(!$v->validate()){ ['type', GameConst::$availableNationType],
Json::die([ ['level', array_keys(getNationLevelList())]
'result'=>false, ]
'reason'=>'[출병국]'.$v->errorStr() ];
]);
} $v = new Validator($rawAttackerNation);
$v->rules($nationCheck);
$v = new Validator($rawDefenderNation); if(!$v->validate()){
$v->rules($nationCheck); Json::die([
if(!$v->validate()){ 'result'=>false,
Json::die([ 'reason'=>'[출병국]'.$v->errorStr()
'result'=>false, ]);
'reason'=>'[수비국]'.$v->errorStr() }
]);
} $v = new Validator($rawDefenderNation);
$v->rules($nationCheck);
if($action == 'reorder'){ if(!$v->validate()){
usort($defenderList, function(General $lhs, General $rhs){ Json::die([
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); 'result'=>false,
}); 'reason'=>'[수비국]'.$v->errorStr()
]);
$order = []; }
foreach($defenderList as $defenderGeneral){
$order[] = $defenderGeneral->getID(); if($action == 'reorder'){
} usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
Json::die([ });
'result'=>true,
'reason'=>'success', $order = [];
'order'=>$order foreach($defenderList as $defenderGeneral){
]); $order[] = $defenderGeneral->getID();
} }
usort($defenderList, function(General $lhs, General $rhs){ Json::die([
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); 'result'=>true,
}); 'reason'=>'success',
'order'=>$order
$rawDefenderList = array_map(function(General $general){ ]);
return $general->getRaw(); }
}, $defenderList);
unset($defenderList); usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
$db = DB::db(); });
$gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->startyear; $rawDefenderList = array_map(function(General $general){
$cityRate = Util::round(($year - $startYear) / 1.5) + 60; return $general->getRaw();
}, $defenderList);
unset($defenderList);
function simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation, $db = DB::db();
$rawDefenderList, $rawDefenderCity, $rawDefenderNation, $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear, $year, $month, $cityRate $startYear = $gameStor->startyear;
){ $cityRate = Util::round(($year - $startYear) / 1.5) + 60;
$attacker = new WarUnitGeneral(
new General($rawAttacker, null, $rawAttackerCity, $rawAttackerNation, $year, $month), function extractRankVar(array $rawVal):array{
$rawAttackerNation, $rankVars = [];
true foreach($rawVal as $rawKey=>$rawVal){
); if(key_exists($rawKey, General::RANK_COLUMN)){
$city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate); $rankVars[$rawKey] = $rawVal;
}
$iterDefender = new \ArrayIterator($rawDefenderList); }
$iterDefender->rewind(); return $rankVars;
}
$battleResult = [];
function simulateBattle(
$attackerRice = $rawAttacker['rice']; $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$defenderRice = 0; $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) ){
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) { $attacker = new WarUnitGeneral(
if($prevDefender !== null){ new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
$prevDefender->getLogger()->rollback(); $rawAttackerNation,
$battleResult[] = $prevDefender; true
if($prevDefender instanceof WarUnitGeneral){ );
$defenderRice -= $prevDefender->getVar('rice'); $city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
}
} $iterDefender = new \ArrayIterator($rawDefenderList);
$iterDefender->rewind();
if(!$reqNext){
return null; $battleResult = [];
}
$attackerRice = $rawAttacker['rice'];
if(!$iterDefender->valid()){ $defenderRice = 0;
return null;
} $getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
$defenderObj = new General($iterDefender->current(), null, $rawDefenderCity, $rawDefenderNation, $year, $month); if($prevDefender !== null){
if(extractBattleOrder($defenderObj) <= 0){ $prevDefender->getLogger()->rollback();
return null; $battleResult[] = $prevDefender;
} if($prevDefender instanceof WarUnitGeneral){
$defenderRice -= $prevDefender->getVar('rice');
$defenderRice += $defenderObj->getVar('rice'); }
}
$retVal = new WarUnitGeneral(
$defenderObj, if(!$reqNext){
$rawDefenderNation, return null;
false }
);
$iterDefender->next(); if(!$iterDefender->valid()){
return $retVal; return null;
}; }
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear); $defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
if(extractBattleOrder($defenderObj) <= 0){
$rawDefenderCity = $city->getRaw(); return null;
$updateAttackerNation = []; }
$updateDefenderNation = [];
$defenderRice += $defenderObj->getVar('rice');
$attackerRice -= $attacker->getVar('rice');
$retVal = new WarUnitGeneral(
if($city->getPhase() > 0){ $defenderObj,
$rice = $city->getKilled() / 100 * 0.8; $rawDefenderNation,
$rice *= $city->getCrewType()->rice; false
$rice *= getTechCost($rawDefenderNation['tech']); );
$rice *= $cityRate / 100 - 0.2; $iterDefender->next();
Util::setRound($rice); return $retVal;
};
$defenderRice += $rice;
} $conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
$totalDead = $attacker->getKilled() + $attacker->getDead(); $rawDefenderCity = $city->getRaw();
$attackerCityDead = $totalDead * 0.4; $updateAttackerNation = [];
$defenderCityDead = $totalDead * 0.6; $updateDefenderNation = [];
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice]; $attackerRice -= $attacker->getVar('rice');
}
if($city->getPhase() > 0){
$lastWarLog = []; $rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice;
$attackerKilled = 0; $rice *= getTechCost($rawDefenderNation['tech']);
$attackerDead = 0; $rice *= $cityRate / 100 - 0.2;
Util::setRound($rice);
$attackerMaxKilled = 0;
$attackerMinKilled = PHP_INT_MAX; $defenderRice += $rice;
}
$attackerMaxDead = 0;
$attackerMinDead = PHP_INT_MAX; $totalDead = $attacker->getKilled() + $attacker->getDead();
$attackerCityDead = $totalDead * 0.4;
$defenderCityDead = $totalDead * 0.6;
$attackerAvgRice = 0;
$defenderAvgRice = 0; return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
}
$avgPhase = 0;
$avgWar = 0; $lastWarLog = [];
$attackerActivatedSkills = []; $attackerKilled = 0;
$defendersActivatedSkills = []; $attackerDead = 0;
foreach(Util::range($repeatCnt) as $repeatIdx){ $attackerMaxKilled = 0;
/** @var WarUnit $attacker */ $attackerMinKilled = PHP_INT_MAX;
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation, $attackerMaxDead = 0;
$rawDefenderList, $rawDefenderCity, $rawDefenderNation, $attackerMinDead = PHP_INT_MAX;
$startYear, $year, $month, $cityRate
);
$lastWarLog = Util::mapWithKey(function($key, $values){ $attackerAvgRice = 0;
return ConvertLog(join('<br>', $values)); $defenderAvgRice = 0;
}, $attacker->getLogger()->rollback());
$avgPhase = 0;
$avgPhase += $attacker->getPhase() / $repeatCnt; $avgWar = 0;
$killed = $attacker->getKilled(); $attackerActivatedSkills = [];
$dead = $attacker->getDead(); $defendersActivatedSkills = [];
$attackerKilled += $killed / $repeatCnt; foreach(Util::range($repeatCnt) as $repeatIdx){
$attackerDead += $dead / $repeatCnt; /** @var WarUnit $attacker */
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$attackerMaxKilled = max($attackerMaxKilled, $killed); $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$attackerMinKilled = min($attackerMinKilled, $killed); $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
$attackerMaxDead = max($attackerMaxDead, $dead); );
$attackerMinDead = min($attackerMinDead, $dead); $lastWarLog = Util::mapWithKey(function($key, $values){
return ConvertLog(join('<br>', $values));
$attackerAvgRice += $attackerRice / $repeatCnt; }, $attacker->getLogger()->rollback());
$defenderAvgRice += $defenderRice / $repeatCnt;
$avgPhase += $attacker->getPhase() / $repeatCnt;
$avgWar += count($battleResult) / $repeatCnt;
$killed = $attacker->getKilled();
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){ $dead = $attacker->getDead();
if(!key_exists($skillName, $attackerActivatedSkills)){
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt; $attackerKilled += $killed / $repeatCnt;
} $attackerDead += $dead / $repeatCnt;
else{
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt; $attackerMaxKilled = max($attackerMaxKilled, $killed);
} $attackerMinKilled = min($attackerMinKilled, $killed);
}
$attackerMaxDead = max($attackerMaxDead, $dead);
foreach($battleResult as $idx=>$defender){ $attackerMinDead = min($attackerMinDead, $dead);
while($idx >= count($defendersActivatedSkills)){
$defendersActivatedSkills[] = []; $attackerAvgRice += $attackerRice / $repeatCnt;
} $defenderAvgRice += $defenderRice / $repeatCnt;
$activatedSkills = &$defendersActivatedSkills[$idx]; $avgWar += count($battleResult) / $repeatCnt;
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
if(!key_exists($skillName, $activatedSkills)){ foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
$activatedSkills[$skillName] = $skillCnt / $repeatCnt; if(!key_exists($skillName, $attackerActivatedSkills)){
} $attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
else{ }
$activatedSkills[$skillName] += $skillCnt / $repeatCnt; else{
} $attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
}
}
} foreach($battleResult as $idx=>$defender){
while($idx >= count($defendersActivatedSkills)){
Json::die([ $defendersActivatedSkills[] = [];
'result'=>true, }
'datetime'=>$rawAttacker['turntime'],
'reason'=>'success', $activatedSkills = &$defendersActivatedSkills[$idx];
'lastWarLog'=>$lastWarLog, foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
'avgWar'=>$avgWar, if(!key_exists($skillName, $activatedSkills)){
'phase'=>$avgPhase, $activatedSkills[$skillName] = $skillCnt / $repeatCnt;
'killed'=>$attackerKilled, }
'maxKilled'=>$attackerMaxKilled, else{
'minKilled'=>$attackerMinKilled, $activatedSkills[$skillName] += $skillCnt / $repeatCnt;
'dead'=>$attackerDead, }
'maxDead'=>$attackerMaxDead, }
'minDead'=>$attackerMinDead,
'attackerRice'=>$attackerAvgRice, }
'defenderRice'=>$defenderAvgRice, }
'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills'=>$defendersActivatedSkills, Json::die([
]); 'result'=>true,
'datetime'=>$rawAttacker['turntime'],
'reason'=>'success',
'lastWarLog'=>$lastWarLog,
'avgWar'=>$avgWar,
'phase'=>$avgPhase,
'killed'=>$attackerKilled,
'maxKilled'=>$attackerMaxKilled,
'minKilled'=>$attackerMinKilled,
'dead'=>$attackerDead,
'maxDead'=>$attackerMaxDead,
'minDead'=>$attackerMinDead,
'attackerRice'=>$attackerAvgRice,
'defenderRice'=>$defenderAvgRice,
'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills'=>$defendersActivatedSkills,
]);
+2
View File
@@ -15,6 +15,8 @@ $troop = Util::getPost('troop', 'int');
$session = Session::requireGameLogin([])->setReadOnly(); $session = Session::requireGameLogin([])->setReadOnly();
$userID = $session::getUserID(); $userID = $session::getUserID();
increaseRefresh("부대명령", 0);
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow('SELECT `no`, name, nation, troop FROM general WHERE `owner`=%i', $userID); $me = $db->queryFirstRow('SELECT `no`, name, nation, troop FROM general WHERE `owner`=%i', $userID);
+8 -2
View File
@@ -13,7 +13,10 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
$autorun_user = $gameStor->autorun_user; $autorun_user = $gameStor->autorun_user;
if($autorun_user['limit_minutes']??false){ if($autorun_user['limit_minutes']??false){
//자동 턴인 경우에는 휴가 불가 //자동 턴인 경우에는 휴가 불가
header('location:b_myPage.php', true, 303); Json::die([
'result'=>false,
'reason'=>'자동 턴인 경우에는 휴가 명령이 불가능합니다.'
]);
} }
$killturn = $gameStor->killturn; $killturn = $gameStor->killturn;
@@ -23,5 +26,8 @@ $db->update('general', [
], 'owner=%i', $userID); ], 'owner=%i', $userID);
header('location:b_myPage.php', true, 303); Json::die([
'result'=>true,
'reason'=>'success'
]);
+1 -1
View File
@@ -169,7 +169,7 @@ if ($genius) {
'dex5'=>0 'dex5'=>0
]); ]);
} else { } else {
$specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age)/4 - $relYear / 2), 3) + $age; $specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age)/6 - $relYear / 2), 3) + $age;
$special2 = GameConst::$defaultSpecialWar; $special2 = GameConst::$defaultSpecialWar;
} }
//내특 //내특
+931 -799
View File
@@ -1,800 +1,932 @@
jQuery(function($){ jQuery(function($) {
var $generalForm = $('.form_sample .general_detail'); var $generalForm = $('.form_sample .general_detail');
var $defenderHeaderForm = $('.form_sample .card-header'); var $defenderHeaderForm = $('.form_sample .card-header');
var $defenderColumn = $('.defender-column'); var $defenderColumn = $('.defender-column');
var defenderNoList = {}; var defenderNoList = {};
var $attackerCard = $('.attacker_form'); var $attackerCard = $('.attacker_form');
var initBasicEvent = function(){ var initBasicEvent = function() {
$('.form_injury').change(function(){ if (window.nation) {
var $this = $(this); $('.form_city_level').val(window.city.level);
var $general = getGeneralDetail($this); $('.form_def').val(parseInt(window.city.def));
var $helptext = $general.find('.injury_helptext'); $('.form_wall').val(parseInt(window.city.wall));
$('.form_nation_type').val(window.nation.type);
var injury = parseInt($this.val()); $('.form_nation_level').val(window.nation.level);
//FIXME: PHP 코드와 항상 일치하도록 변경 $('.form_tech').val(parseInt(window.nation.tech / 1000));
var text = '건강'; if (window.nation.capital == window.city.city) {
var color = 'white'; $('.attacker_nation .form_is_capital:first').click();
if(injury > 60){ $('.defender_nation .form_is_capital:first').click();
text = '위독'; } else {
color = 'red'; $('.attacker_nation .form_is_capital:last').click();
} $('.defender_nation .form_is_capital:last').click();
else if(injury > 40){ }
text = '심각'; } else {
color = 'magenta'; $('.attacker_nation .form_is_capital:last').click();
} $('.defender_nation .form_is_capital:last').click();
else if(injury > 20){ }
text = '중상';
color = 'orange'; $('.form_injury').change(function() {
} var $this = $(this);
else if(injury > 0){ var $general = getGeneralDetail($this);
text = '경상'; var $helptext = $general.find('.injury_helptext');
color = 'yellow';
} var injury = parseInt($this.val());
$helptext.html(text).css('color', color); //FIXME: PHP 코드와 항상 일치하도록 변경
}); var text = '건강';
var color = 'white';
$('.export_general').click(function(){ if (injury > 60) {
var $btn = $(this); text = '위독';
var $general = getGeneralDetail($btn); color = 'red';
} else if (injury > 40) {
var values = exportGeneralInfo($general); text = '심각';
console.log(values); color = 'magenta';
}); } else if (injury > 20) {
$('.delete-defender').click(function(){ text = '중상';
var $card = getGeneralFrame($(this)); color = 'orange';
deleteDefender($card); } else if (injury > 0) {
}); text = '경상';
$('.copy-defender').click(function(){ color = 'yellow';
var $card = getGeneralFrame($(this)); }
copyDefender($card); $helptext.html(text).css('color', color);
}); });
$('.add-defender').click(function(){ $('.export_general').click(function() {
addDefender(); var $btn = $(this);
}); var $general = getGeneralDetail($btn);
$('.btn-general-load').click(function(){ var values = exportGeneralInfo($general);
var $file = $(this).prev(); console.log(values);
$file[0].click(); });
}) $('.delete-defender').click(function() {
var $card = getGeneralFrame($(this));
$('.form_load_general_file').on('change', function(e){ deleteDefender($card);
e.preventDefault(); });
var $this = $(this); $('.copy-defender').click(function() {
var $card = getGeneralFrame($this); var $card = getGeneralFrame($(this));
copyDefender($card);
var files = e.target.files; });
importGeneralInfoByFile(files, $card); $('.add-defender').click(function() {
return false; addDefender();
}); });
$('.btn-general-save').click(function(){ $('.btn-general-load').click(function() {
var $this = $(this); var $file = $(this).prev();
var $general = getGeneralDetail($this); $file[0].click();
var generalData = exportGeneralInfo($general); })
var filename = "general_{0}.json".format(generalData.name); $('.form_load_general_file').on('change', function(e) {
var saveData = JSON.stringify({ e.preventDefault();
objType:'general', var $this = $(this);
data:generalData var $card = getGeneralFrame($this);
}, null, 4);
var files = e.target.files;
download(saveData, filename, 'application/json');
}); importGeneralInfoByFile(files, $card);
return false;
$('.btn-battle-load').click(function(){ });
var $file = $(this).prev();
$file[0].click(); $('.btn-general-import-server').click(function() {
}) var $this = $(this);
var $card = getGeneralFrame($this);
$('.form_load_battle_file').on('change', function(e){
e.preventDefault(); var $modal = $('#importModal');
var $this = $(this); $modal.data('target', $card);
var files = e.target.files; $modal.modal('show');
});
importBattleInfoByFile(files);
return false; $('.btn-general-save').click(function() {
}); var $this = $(this);
var $general = getGeneralDetail($this);
$('.btn-battle-save').click(function(){ var generalData = exportGeneralInfo($general);
var battleData = exportAllData();
var filename = "battle_{0}.json".format(moment().format('YYYYMMDD_hhmmss')); var filename = "general_{0}.json".format(generalData.name);
var saveData = JSON.stringify({ var saveData = JSON.stringify({
objType:'battle', objType: 'general',
data:battleData data: generalData
}, null, 4); }, null, 4);
download(saveData, filename, 'application/json'); download(saveData, filename, 'application/json');
}) });
var $generals = $('.general_detail'); $('.btn-battle-load').click(function() {
$generals.bind('dragover dragleave', function(e) { var $file = $(this).prev();
e.stopPropagation() $file[0].click();
e.preventDefault() })
})
$generals.bind('drop', function(e){ $('.form_load_battle_file').on('change', function(e) {
e.preventDefault(); e.preventDefault();
var $this = $(this); var $this = $(this);
var $card = getGeneralFrame($this); var files = e.target.files;
var files = e.originalEvent.dataTransfer.files; importBattleInfoByFile(files);
return false;
importGeneralInfoByFile(files, $card); });
return false;
}); $('.btn-battle-save').click(function() {
var battleData = exportAllData();
var $battlePad = $('.dragpad_battle'); var filename = "battle_{0}.json".format(moment().format('YYYYMMDD_hhmmss'));
$battlePad.bind('dragover dragleave', function(e) { var saveData = JSON.stringify({
e.stopPropagation() objType: 'battle',
e.preventDefault() data: battleData
}) }, null, 4);
$battlePad.bind('drop', function(e){
e.preventDefault(); download(saveData, filename, 'application/json');
})
var files = e.originalEvent.dataTransfer.files;
var $generals = $('.general_detail');
importBattleInfoByFile(files); $generals.bind('dragover dragleave', function(e) {
return false; e.stopPropagation()
}); e.preventDefault()
} })
$generals.bind('drop', function(e) {
var importGeneralInfo = function($general, data){ e.preventDefault();
var setVal = function(query, val){ var $this = $(this);
$general.find(query).val(val).change(); var $card = getGeneralFrame($this);
}
var files = e.originalEvent.dataTransfer.files;
setVal('.form_general_name', data.name);
importGeneralInfoByFile(files, $card);
setVal('.form_officer_level', data.officer_level); return false;
setVal('.form_exp_level', data.explevel); });
setVal('.form_injury', data.injury);
var $battlePad = $('.dragpad_battle');
setVal('.form_leadership', data.leadership); $battlePad.bind('dragover dragleave', function(e) {
setVal('.form_general_horse', data.horse); e.stopPropagation()
setVal('.form_strength', data.strength); e.preventDefault()
setVal('.form_general_weap', data.weapon); })
setVal('.form_intel', data.intel); $battlePad.bind('drop', function(e) {
setVal('.form_general_book', data.book); e.preventDefault();
setVal('.form_general_item', data.item);
var files = e.originalEvent.dataTransfer.files;
setVal('.form_injury', data.injury);
importBattleInfoByFile(files);
setVal('.form_rice', data.rice); return false;
});
setVal('.form_general_character', data.personal); }
setVal('.form_general_special_war', data.special2);
var importGeneralInfo = function($general, data) {
setVal('.form_crew', data.crew); var setVal = function(query, val) {
setVal('.form_crewtype', data.crewtype); $general.find(query).val(val).change();
setVal('.form_atmos', data.atmos); }
setVal('.form_train', data.train);
setVal('.form_general_name', data.name);
setVal('.form_dex1', data.dex1);
setVal('.form_dex2', data.dex2); setVal('.form_officer_level', data.officer_level);
setVal('.form_dex3', data.dex3); setVal('.form_exp_level', data.explevel);
setVal('.form_dex4', data.dex4);
setVal('.form_dex5', data.dex5); setVal('.form_leadership', data.leadership);
setVal('.form_defence_train', data.defence_train); setVal('.form_general_horse', data.horse);
setVal('.form_strength', data.strength);
if(!setGeneralNo($general, data.no)){ setVal('.form_general_weap', data.weapon);
setGeneralNo($general, generateNewGeneralNo()); setVal('.form_intel', data.intel);
} setVal('.form_general_book', data.book);
} setVal('.form_general_item', data.item);
var exportGeneralInfo = function($general){ setVal('.form_injury', data.injury);
var getInt = function(query){
return parseInt($general.find(query).val()); setVal('.form_rice', data.rice);
}
setVal('.form_general_character', data.personal);
var getVal = function(query){ setVal('.form_general_special_war', data.special2);
return $general.find(query).val();
} setVal('.form_crew', data.crew);
setVal('.form_crewtype', data.crewtype);
return { setVal('.form_atmos', data.atmos);
no:getGeneralNo($general), setVal('.form_train', data.train);
name:getVal('.form_general_name'),
officer_level:getInt('.form_officer_level'), setVal('.form_dex1', data.dex1);
explevel:getInt('.form_exp_level'), setVal('.form_dex2', data.dex2);
setVal('.form_dex3', data.dex3);
leadership:getInt('.form_leadership'), setVal('.form_dex4', data.dex4);
horse:getVal('.form_general_horse'), setVal('.form_dex5', data.dex5);
strength:getInt('.form_strength'), setVal('.form_defence_train', data.defence_train);
weapon:getVal('.form_general_weap'),
intel:getInt('.form_intel'), setVal('.form_warnum', data.warnum);
book:getVal('.form_general_book'), setVal('.form_killnum', data.killnum);
item:getVal('.form_general_item'), setVal('.form_killcrew', data.killcrew);
injury:getInt('.form_injury'), if (!setGeneralNo($general, data.no)) {
setGeneralNo($general, generateNewGeneralNo());
rice:getInt('.form_rice'), }
}
personal:getVal('.form_general_character'),
special2:getVal('.form_general_special_war'), var exportGeneralInfo = function($general) {
var getInt = function(query) {
crew:getInt('.form_crew'), return parseInt($general.find(query).val());
crewtype:getInt('.form_crewtype'), }
atmos:getInt('.form_atmos'),
train:getInt('.form_train'), var getVal = function(query) {
return $general.find(query).val();
dex1:getInt('.form_dex1'), }
dex2:getInt('.form_dex2'),
dex3:getInt('.form_dex3'), return {
dex4:getInt('.form_dex4'), no: getGeneralNo($general),
dex5:getInt('.form_dex5'), name: getVal('.form_general_name'),
defence_train:getInt('.form_defence_train'), officer_level: getInt('.form_officer_level'),
}; explevel: getInt('.form_exp_level'),
}
leadership: getInt('.form_leadership'),
var importBattleInfoByFile = function(files){ horse: getVal('.form_general_horse'),
if(files === null){ strength: getInt('.form_strength'),
alert('파일 에러!'); weapon: getVal('.form_general_weap'),
return false; intel: getInt('.form_intel'),
} book: getVal('.form_general_book'),
item: getVal('.form_general_item'),
if(files.length < 1){
alert("파일 에러!"); injury: getInt('.form_injury'),
return false;
} rice: getInt('.form_rice'),
personal: getVal('.form_general_character'),
var file = files[0]; special2: getVal('.form_general_special_war'),
if(file.size > 1024*1024){
alert('파일이 너무 큽니다!'); crew: getInt('.form_crew'),
return false; crewtype: getInt('.form_crewtype'),
} atmos: getInt('.form_atmos'),
if(file.type === ''){ train: getInt('.form_train'),
alert('폴더를 업로드할 수 없습니다!');
return false; dex1: getInt('.form_dex1'),
} dex2: getInt('.form_dex2'),
dex3: getInt('.form_dex3'),
var reader = new FileReader(); dex4: getInt('.form_dex4'),
reader.onload = function(){ dex5: getInt('.form_dex5'),
var battleData = {};
try { defence_train: getInt('.form_defence_train'),
battleData = JSON.parse(reader.result);
} catch(e) { warnum: getInt('.form_warnum'),
alert('올바르지 않은 파일 형식입니다'); killnum: getInt('.form_killnum'),
return false; killcrew: getInt('.form_killcrew'),
}
};
if(!('objType' in battleData)){ }
alert('파일 형식을 확인할 수 없습니다');
return false; var importBattleInfoByFile = function(files) {
} if (files === null) {
alert('파일 에러!');
if(battleData.objType != 'battle'){ return false;
alert('전투 데이터가 아닙니다'); }
return false;
} if (files.length < 1) {
alert("파일 에러!");
importBattleInfo(battleData.data); return false;
return true; }
};
try { var file = files[0];
if (file.size > 1024 * 1024) {
reader.readAsText(file); alert('파일이 너무 큽니다!');
} return false;
catch(e) { }
alert('파일을 읽는데 실패했습니다.'); if (file.type === '') {
return false; alert('폴더를 업로드할 수 없습니다!');
} return false;
}
return true;
} var reader = new FileReader();
reader.onload = function() {
var importGeneralInfoByFile = function(files, $card){ var battleData = {};
if($card === undefined){ try {
$card = addDefender(); battleData = JSON.parse(reader.result);
} } catch (e) {
alert('올바르지 않은 파일 형식입니다');
if(files === null){ return false;
alert('파일 에러!'); }
return false;
} if (!('objType' in battleData)) {
alert('파일 형식을 확인할 수 없습니다');
if(files.length < 1){ return false;
alert("파일 에러!"); }
return false;
} if (battleData.objType != 'battle') {
alert('전투 데이터가 아닙니다');
return false;
var file = files[0]; }
if(file.size > 1024*1024){
alert('파일이 너무 큽니다!'); importBattleInfo(battleData.data);
return false; return true;
} };
if(file.type === ''){
alert('폴더를 업로드할 수 없습니다!'); try {
return false;
} reader.readAsText(file);
} catch (e) {
var reader = new FileReader(); alert('파일을 읽는데 실패했습니다.');
reader.onload = function(){ return false;
var generalData = {}; }
try {
generalData = JSON.parse(reader.result); return true;
} catch(e) { }
alert('올바르지 않은 파일 형식입니다');
return false; var importGeneralInfoByFile = function(files, $card) {
} if ($card === undefined) {
$card = addDefender();
if(!('objType' in generalData)){ }
alert('파일 형식을 확인할 수 없습니다');
return false; if (files === null) {
} alert('파일 에러!');
return false;
if(generalData.objType == 'battle'){ }
importBattleInfo(generalData.data);
return true; if (files.length < 1) {
} alert("파일 에러!");
if(generalData.objType != 'general'){ return false;
alert('장수 데이터가 아닙니다'); }
return false;
}
var file = files[0];
$card.find('.form_load_general_file').val(''); if (file.size > 1024 * 1024) {
alert('파일이 너무 큽니다!');
importGeneralInfo($card, generalData.data); return false;
return true; }
}; if (file.type === '') {
alert('폴더를 업로드할 수 없습니다!');
try { return false;
}
reader.readAsText(file);
} var reader = new FileReader();
catch(e) { reader.onload = function() {
alert('파일을 읽는데 실패했습니다.'); var generalData = {};
return false; try {
} generalData = JSON.parse(reader.result);
} catch (e) {
return true; alert('올바르지 않은 파일 형식입니다');
} return false;
}
var extendGeneralInfoForDB = function(generalData){
if (!('objType' in generalData)) {
var dbVal = { alert('파일 형식을 확인할 수 없습니다');
nation: (generalData.no)<=1 ? 1 : 2, return false;
city: (generalData.no)<=1 ? 1 : 3, }
turntime:'2018-08-26 12:00',
special:defaultSpecialDomestic, if (generalData.objType == 'battle') {
leadership_exp:0, importBattleInfo(generalData.data);
strength_exp:0, return true;
intel_exp:0, }
if (generalData.objType != 'general') {
gold:10000, alert('장수 데이터가 아닙니다');
return false;
dedication:0, }
recent_war:'2018-08-26 12:00', $card.find('.form_load_general_file').val('');
experience:Math.pow(generalData.explevel, 2),
}; importGeneralInfo($card, generalData.data);
return true;
return $.extend({}, generalData, dbVal); };
}
try {
var getGeneralFrame = function($btn){
var $card = $btn.closest('.general_form'); reader.readAsText(file);
return $card; } catch (e) {
} alert('파일을 읽는데 실패했습니다.');
return false;
var getGeneralDetail = function($btn){ }
var $card = getGeneralFrame($btn);
var $general = $card.find('.general_detail'); return true;
return $general; }
}
var extendGeneralInfoForDB = function(generalData) {
var getGeneralNo = function($btn){
return parseInt(getGeneralFrame($btn).data('general_no')); var dbVal = {
} nation: (generalData.no) <= 1 ? 1 : 2,
city: (generalData.no) <= 1 ? 1 : 3,
var setGeneralNo = function($btn, value){ turntime: '2018-08-26 12:00',
if(value == 1){ special: defaultSpecialDomestic,
//1번은 무조건 공격자임 leadership_exp: 0,
return false; strength_exp: 0,
} intel_exp: 0,
if(value in defenderNoList){
return false; gold: 10000,
}
var $card = getGeneralFrame($btn); dedication: 0,
$card.data('general_no', value);
defenderNoList[value] = $card; recent_war: '2018-08-26 12:00',
return true; experience: Math.pow(generalData.explevel, 2),
} };
var generateNewGeneralNo = function(){ return $.extend({}, generalData, dbVal);
while(true){ }
var newGeneralNo = parseInt(Math.random()*(1<<24))+2;
if(newGeneralNo in defenderNoList){ var getGeneralFrame = function($btn) {
continue; var $card = $btn.closest('.general_form');
} return $card;
return newGeneralNo; }
}
} var getGeneralDetail = function($btn) {
var $card = getGeneralFrame($btn);
var deleteGeneralNo = function($btn){ var $general = $card.find('.general_detail');
var $card = getGeneralFrame($btn); return $general;
$card.removeData('general_no'); }
var generalNo = getGeneralNo($card);
delete defenderNoList[generalNo]; var getGeneralNo = function($btn) {
} return parseInt(getGeneralFrame($btn).data('general_no'));
}
var addDefender = function($cardAfter){
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>'); var setGeneralNo = function($btn, value) {
if (value == 1) {
if($cardAfter === undefined){ //1번은 무조건 공격자임
$defenderColumn.append($newCard); return false;
} }
else{ if (value in defenderNoList) {
$cardAfter.after($newCard); return false;
} }
var $card = getGeneralFrame($btn);
$newCard.append($defenderHeaderForm.clone(true,true)); $card.data('general_no', value);
$newCard.append($generalForm.clone(true,true)); defenderNoList[value] = $card;
return true;
$newGeneral = getGeneralDetail($newCard); }
setGeneralNo($newCard, generateNewGeneralNo());
var generateNewGeneralNo = function() {
return $newCard; while (true) {
} var newGeneralNo = parseInt(Math.random() * (1 << 24)) + 2;
if (newGeneralNo in defenderNoList) {
var deleteDefender = function($card){ continue;
deleteGeneralNo($card); }
$card.detach(); return newGeneralNo;
} }
}
var copyDefender = function($card){
var $general = getGeneralDetail($card); var deleteGeneralNo = function($btn) {
var $card = getGeneralFrame($btn);
var generalData = exportGeneralInfo($general); $card.removeData('general_no');
var $newObj = addDefender($card); var generalNo = getGeneralNo($card);
importGeneralInfo(getGeneralDetail($newObj), generalData); delete defenderNoList[generalNo];
} }
var importBattleInfo = function(battleData){ var addDefender = function($cardAfter) {
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>');
$('.form_load_battle_file').val('');
console.log(battleData); if ($cardAfter === undefined) {
$defenderColumn.append($newCard);
var $attackerNation = $('.attacker_nation'); } else {
var $defenderNation = $('.defender_nation'); $cardAfter.after($newCard);
}
var attackerGeneral = battleData.attackerGeneral;
var attackerCity = battleData.attackerCity; $newCard.append($defenderHeaderForm.clone(true, true));
var attackerNation = battleData.attackerNation; $newCard.append($generalForm.clone(true, true));
var defenderGenerals = battleData.defenderGenerals; $newGeneral = getGeneralDetail($newCard);
var defenderCity = battleData.defenderCity; setGeneralNo($newCard, generateNewGeneralNo());
var defenderNation = battleData.defenderNation;
return $newCard;
$('#year').val(battleData.year); }
$('#month').val(battleData.month);
$('#repeat_cnt').val(battleData.repeatCnt); var deleteDefender = function($card) {
deleteGeneralNo($card);
$('.delete-defender').click(); $card.detach();
}
$attackerNation.find('.form_nation_type').val(attackerNation.type);
$attackerNation.find('.form_tech').val(Math.floor(attackerNation.tech/1000)); var copyDefender = function($card) {
$attackerNation.find('.form_nation_level').val(attackerNation.level); var $general = getGeneralDetail($card);
if(attackerNation.capital == 1){
$attackerNation.find('.form_is_capital:first').click(); var generalData = exportGeneralInfo($general);
} var $newObj = addDefender($card);
else{ importGeneralInfo(getGeneralDetail($newObj), generalData);
$attackerNation.find('.form_is_capital:last').click(); }
}
$attackerNation.find('.form_city_level').val(attackerCity.level); var importBattleInfo = function(battleData) {
importGeneralInfo($('.attacker_form'), attackerGeneral); $('.form_load_battle_file').val('');
console.log(battleData);
$defenderNation.find('.form_nation_type').val(defenderNation.type);
$defenderNation.find('.form_tech').val(Math.floor(defenderNation.tech/1000)); var $attackerNation = $('.attacker_nation');
$defenderNation.find('.form_nation_level').val(defenderNation.level); var $defenderNation = $('.defender_nation');
if(defenderNation.capital == 1){
$defenderNation.find('.form_is_capital:first').click(); var attackerGeneral = battleData.attackerGeneral;
} var attackerCity = battleData.attackerCity;
else{ var attackerNation = battleData.attackerNation;
$defenderNation.find('.form_is_capital:last').click();
} var defenderGenerals = battleData.defenderGenerals;
$defenderNation.find('.form_city_level').val(defenderCity.level); var defenderCity = battleData.defenderCity;
$('#city_def').val(defenderCity.def); var defenderNation = battleData.defenderNation;
$('#city_wall').val(defenderCity.wall);
$('#year').val(battleData.year);
$.each(defenderGenerals, function(idx, defenderGeneral){ $('#month').val(battleData.month);
var $card = addDefender(); $('#repeat_cnt').val(battleData.repeatCnt);
importGeneralInfo($card, defenderGeneral);
}); $('.delete-defender').click();
}
$attackerNation.find('.form_nation_type').val(attackerNation.type);
var exportAllData = function(){ $attackerNation.find('.form_tech').val(Math.floor(attackerNation.tech / 1000));
var $attackerNation = $('.attacker_nation'); $attackerNation.find('.form_nation_level').val(attackerNation.level);
var $defenderNation = $('.defender_nation'); if (attackerNation.capital == 1) {
$attackerNation.find('.form_is_capital:first').click();
var attackerGeneral = exportGeneralInfo($('.attacker_form')); } else {
$attackerNation.find('.form_is_capital:last').click();
var attackerCity = { }
level:parseInt($attackerNation.find('.form_city_level').val()), $attackerNation.find('.form_city_level').val(attackerCity.level);
};
importGeneralInfo($('.attacker_form'), attackerGeneral);
var attackerNation = {
type:$attackerNation.find('.form_nation_type').val(), $defenderNation.find('.form_nation_type').val(defenderNation.type);
tech:parseInt($attackerNation.find('.form_tech').val()) * 1000, $defenderNation.find('.form_tech').val(Math.floor(defenderNation.tech / 1000));
level:parseInt($attackerNation.find('.form_nation_level').val()), $defenderNation.find('.form_nation_level').val(defenderNation.level);
capital:$attackerNation.find('.form_is_capital:checked').val()=='1'?1:2, if (defenderNation.capital == 1) {
} $defenderNation.find('.form_is_capital:first').click();
} else {
var defenderGenerals = $('.defender_form').map(function(){ $defenderNation.find('.form_is_capital:last').click();
return exportGeneralInfo($(this)); }
}).toArray(); $defenderNation.find('.form_city_level').val(defenderCity.level);
$('#city_def').val(defenderCity.def);
var defenderCity = { $('#city_wall').val(defenderCity.wall);
def: parseInt($('#city_def').val()),
wall: parseInt($('#city_wall').val()), $.each(defenderGenerals, function(idx, defenderGeneral) {
level:parseInt($defenderNation.find('.form_city_level').val()), var $card = addDefender();
}; importGeneralInfo($card, defenderGeneral);
});
var defenderNation = { }
type:$defenderNation.find('.form_nation_type').val(),
tech:parseInt($defenderNation.find('.form_tech').val()) * 1000, var exportAllData = function() {
level:parseInt($defenderNation.find('.form_nation_level').val()), var $attackerNation = $('.attacker_nation');
capital:$defenderNation.find('.form_is_capital:checked').val()=='1'?3:4, var $defenderNation = $('.defender_nation');
}
var attackerGeneral = exportGeneralInfo($('.attacker_form'));
var year = parseInt($('#year').val());
var month = parseInt($('#month').val()); var attackerCity = {
var repeatCnt = parseInt($('#repeat_cnt').val()); level: parseInt($attackerNation.find('.form_city_level').val()),
};
return {
attackerGeneral:attackerGeneral, var attackerNation = {
attackerCity:attackerCity, type: $attackerNation.find('.form_nation_type').val(),
attackerNation:attackerNation, tech: parseInt($attackerNation.find('.form_tech').val()) * 1000,
level: parseInt($attackerNation.find('.form_nation_level').val()),
defenderGenerals:defenderGenerals, capital: $attackerNation.find('.form_is_capital:checked').val() == '1' ? 1 : 2,
defenderCity:defenderCity, }
defenderNation:defenderNation,
var defenderGenerals = $('.defender_form').map(function() {
year:year, return exportGeneralInfo($(this));
month:month, }).toArray();
repeatCnt:repeatCnt,
}; var defenderCity = {
} def: parseInt($('#city_def').val()),
wall: parseInt($('#city_wall').val()),
var extendAllDataForDB = function(allData){ level: parseInt($defenderNation.find('.form_city_level').val()),
var defaultNation = { };
nation:0,
name:'재야', var defenderNation = {
capital:0, type: $defenderNation.find('.form_nation_type').val(),
level:0, tech: parseInt($defenderNation.find('.form_tech').val()) * 1000,
gold:0, level: parseInt($defenderNation.find('.form_nation_level').val()),
rice:2000, capital: $defenderNation.find('.form_is_capital:checked').val() == '1' ? 3 : 4,
type:'None', }
tech:0,
gennum:200, var year = parseInt($('#year').val());
}; var month = parseInt($('#month').val());
var repeatCnt = parseInt($('#repeat_cnt').val());
var defaultCity = {
nation:0, return {
supply:1, attackerGeneral: attackerGeneral,
name:'도시', attackerCity: attackerCity,
attackerNation: attackerNation,
pop:500000,
agri:10000, defenderGenerals: defenderGenerals,
comm:10000, defenderCity: defenderCity,
secu:10000, defenderNation: defenderNation,
def:1000,
wall:1000, year: year,
month: month,
trust:100, repeatCnt: repeatCnt,
};
pop_max:600000, }
agri_max:12000,
comm_max:12000, var extendAllDataForDB = function(allData) {
secu_max:10000, var defaultNation = {
def_max:12000, nation: 0,
wall_max:12000, name: '재야',
capital: 0,
dead:0, level: 0,
gold: 0,
state:0, rice: 2000,
type: 'None',
conflict:'{}', tech: 0,
}; gennum: 200,
};
var attackerNation = $.extend({}, defaultNation, allData.attackerNation);
attackerNation.nation = 1; var defaultCity = {
attackerNation.name = '출병국'; nation: 0,
supply: 1,
var attackerCity = $.extend({}, defaultCity, allData.attackerCity); name: '도시',
attackerCity.nation = 1;
attackerCity.city = 1; pop: 500000,
agri: 10000,
var attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral); comm: 10000,
if(2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4){ secu: 10000,
attackerGeneral.officer_city = 1; def: 1000,
} wall: 1000,
else{
attackerGeneral.officer_city = 0; trust: 100,
}
pop_max: 600000,
var defenderNation = $.extend({}, defaultNation, allData.defenderNation); agri_max: 12000,
defenderNation.nation = 2; comm_max: 12000,
defenderNation.name = '수비국'; secu_max: 10000,
def_max: 12000,
var defenderCity = $.extend({}, defaultCity, allData.defenderCity); wall_max: 12000,
defenderCity.nation = 2;
defenderCity.city = 3; dead: 0,
defenderCity.wall_max = defenderCity.wall/5*6;
defenderCity.def_max = defenderCity.def/5*6; state: 0,
var defenderGenerals = []; conflict: '{}',
$.each(allData.defenderGenerals, function(){ };
var defenderGeneral = extendGeneralInfoForDB(this);
if(2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4){ var attackerNation = $.extend({}, defaultNation, allData.attackerNation);
defenderGeneral.officer_city = 3; attackerNation.nation = 1;
} attackerNation.name = '출병국';
else{
defenderGeneral.officer_city = 0; var attackerCity = $.extend({}, defaultCity, allData.attackerCity);
} attackerCity.nation = 1;
attackerCity.city = 1;
defenderGenerals.push(defenderGeneral);
}); var attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral);
if (2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4) {
attackerGeneral.officer_city = 1;
return $.extend({}, allData, { } else {
attackerGeneral:attackerGeneral, attackerGeneral.officer_city = 0;
attackerCity:attackerCity, }
attackerNation:attackerNation,
var defenderNation = $.extend({}, defaultNation, allData.defenderNation);
defenderGenerals:defenderGenerals, defenderNation.nation = 2;
defenderCity:defenderCity, defenderNation.name = '수비국';
defenderNation:defenderNation,
}); var defenderCity = $.extend({}, defaultCity, allData.defenderCity);
} defenderCity.nation = 2;
defenderCity.city = 3;
var parseSkillCount = function(skills){ defenderCity.wall_max = parseInt(defenderCity.wall / 5 * 6);
var result = []; defenderCity.def_max = parseInt(defenderCity.def / 5 * 6);
$.each(skills, function(key, value){
result.push("{0}({1}회)".format(key, toPretty(value))); var defenderGenerals = [];
}) $.each(allData.defenderGenerals, function() {
var defenderGeneral = extendGeneralInfoForDB(this);
if(result.length == 0){ if (2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4) {
return '-'; defenderGeneral.officer_city = 3;
} } else {
return result.join(', '); defenderGeneral.officer_city = 0;
} }
var toPretty = function(number){ defenderGenerals.push(defenderGeneral);
if(isInt(number)){ });
number = parseInt(number);
}
else{ return $.extend({}, allData, {
number = parseFloat(number).toFixed(2); attackerGeneral: attackerGeneral,
} attackerCity: attackerCity,
return numberWithCommas(number); attackerNation: attackerNation,
}
defenderGenerals: defenderGenerals,
var showBattleResult = function(result){ defenderCity: defenderCity,
$('#result_datetime').html(result.datetime); defenderNation: defenderNation,
$('#result_warcnt').html(toPretty(result.avgWar)); });
$('#result_phase').html(toPretty(result.phase)); }
$('#result_killed').html(toPretty(result.killed));
if(result.minKilled != result.maxKilled){ var parseSkillCount = function(skills) {
$('#result_maxKilled').html(toPretty(result.maxKilled)); var result = [];
$('#result_minKilled').html(toPretty(result.minKilled)); $.each(skills, function(key, value) {
$('#result_varKilled').show(); result.push("{0}({1}회)".format(key, toPretty(value)));
} })
else{
$('#result_varKilled').hide(); if (result.length == 0) {
} return '-';
$('#result_dead').html(toPretty(result.dead)); }
if(result.minDead != result.maxDead){ return result.join(', ');
$('#result_maxDead').html(toPretty(result.maxDead)); }
$('#result_minDead').html(toPretty(result.minDead));
$('#result_varDead').show(); var toPretty = function(number) {
} if (isInt(number)) {
else{ number = parseInt(number);
$('#result_varDead').hide(); } else {
} number = parseFloat(number).toFixed(2);
}
$('#result_attackerRice').html(toPretty(result.attackerRice)); return numberWithCommas(number);
$('#result_defenderRice').html(toPretty(result.defenderRice)); }
$('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
var showBattleResult = function(result) {
$('.result_defenderSkills').detach(); $('#result_datetime').html(result.datetime);
$('#result_warcnt').html(toPretty(result.avgWar));
var $summary = $('#battle_result_summary'); $('#result_phase').html(toPretty(result.phase));
$('#result_killed').html(toPretty(result.killed));
$.each(result.defendersSkills, function(idx, defenderSkills){ if (result.minKilled != result.maxKilled) {
console.log(defenderSkills); $('#result_maxKilled').html(toPretty(result.maxKilled));
var $result = $("<tr class='result_defenderSkills'><th>수비자{0} 스킬</th><td></td></tr>".format(idx + 1)); $('#result_minKilled').html(toPretty(result.minKilled));
$result.find('td').html(parseSkillCount(defenderSkills)); $('#result_varKilled').show();
$summary.append($result); } else {
}); $('#result_varKilled').hide();
}
$('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog); $('#result_dead').html(toPretty(result.dead));
$('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog); if (result.minDead != result.maxDead) {
$('#result_maxDead').html(toPretty(result.maxDead));
} $('#result_minDead').html(toPretty(result.minDead));
$('#result_varDead').show();
var beginBattle = function(){ } else {
var data = extendAllDataForDB(exportAllData()); $('#result_varDead').hide();
console.log(data); }
$.ajax({
type:'post', $('#result_attackerRice').html(toPretty(result.attackerRice));
url:'j_simulate_battle.php', $('#result_defenderRice').html(toPretty(result.defenderRice));
dataType:'json', $('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
data:{
action:'battle', $('.result_defenderSkills').detach();
query:JSON.stringify(data),
} var $summary = $('#battle_result_summary');
}).then(function(result){
console.log(result); $.each(result.defendersSkills, function(idx, defenderSkills) {
if(!result.result){ console.log(defenderSkills);
alert(result.reason); var $result = $("<tr class='result_defenderSkills'><th>수비자{0} 스킬</th><td></td></tr>".format(idx + 1));
return; $result.find('td').html(parseSkillCount(defenderSkills));
} $summary.append($result);
showBattleResult(result); });
}, function(result){ $('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog);
alert('전투 개시 실패!'); $('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog);
});
} }
var beginBattle = function() {
var reorderDefender = function(defenderOrder){ var data = extendAllDataForDB(exportAllData());
$.each(defenderOrder, function(idx, generalNo){ console.log(data);
$.ajax({
if(!(generalNo in defenderNoList)){ type: 'post',
//음..? url: 'j_simulate_battle.php',
alert("{0}이 수비자 리스트에 없습니다. 버그인 듯 합니다.".format(generalNo)); dataType: 'json',
return true; data: {
} action: 'battle',
query: JSON.stringify(data),
var $defenderObj = defenderNoList[generalNo]; }
$defenderObj.detach(); }).then(function(result) {
$defenderColumn.append($defenderObj); console.log(result);
}) if (!result.result) {
} alert(result.reason);
return;
var requestReorderDefender = function(){ }
var data = extendAllDataForDB(exportAllData()); showBattleResult(result);
console.log(data);
$.ajax({ }, function(result) {
type:'post', alert('전투 개시 실패!');
url:'j_simulate_battle.php', });
dataType:'json', }
data:{
action:'reorder',
query:JSON.stringify(data), var reorderDefender = function(defenderOrder) {
} $.each(defenderOrder, function(idx, generalNo) {
}).then(function(result){
console.log(result); if (!(generalNo in defenderNoList)) {
if(!result.result){ //음..?
alert(result.reason); alert("{0}이 수비자 리스트에 없습니다. 버그인 듯 합니다.".format(generalNo));
return; return true;
} }
reorderDefender(result.order);
var $defenderObj = defenderNoList[generalNo];
}, function(result){ $defenderObj.detach();
alert('재정렬 실패!'); $defenderColumn.append($defenderObj);
}); })
} }
initBasicEvent(); var requestReorderDefender = function() {
$attackerCard.append($generalForm.clone(true,true)); var data = extendAllDataForDB(exportAllData());
addDefender(); console.log(data);
$.ajax({
$('.btn-begin_battle').click(function(){ type: 'post',
beginBattle(); url: 'j_simulate_battle.php',
}); dataType: 'json',
data: {
$('.btn-reorder_defender').click(function(){ action: 'reorder',
requestReorderDefender(); query: JSON.stringify(data),
}) }
}).then(function(result) {
console.log(result);
if (!result.result) {
alert(result.reason);
return;
}
reorderDefender(result.order);
}, function(result) {
alert('재정렬 실패!');
});
}
var initGeneralList = false;
$('#importFromDB').click(function() {
var generalID = $('#modalSelector').val();
console.log(generalID);
$.post({
url: 'j_export_simulator_object.php',
dataType: 'json',
data: {
destGeneralID: generalID
}
}).then(function(data) {
if (!data.result) {
alert(data.reason);
return false;
}
var $modal = $('#importModal');
var $card = $modal.data('target');
importGeneralInfo($card, data.general);
$modal.modal('hide');
}, errUnknown);
});
$('#importModal').on('show.bs.modal', function(e) {
if (!initGeneralList) {
var $list = $('#modalSelector');
var addNation = function(generalList, nationName, color) {
generalList.sort(function(lhs, rhs) {
if (lhs.npc != rhs.npc) {
return lhs.npc - rhs.npc;
}
if (lhs.name < rhs.name) {
return -1;
}
if (lhs.name > rhs.name) {
return 1;
}
return 0;
})
var $optGroup = $('<optgroup label="{0}"></optgroup>'.format(nationName));
$optGroup.css('background-color', color);
$optGroup.css('color', isBrightColor(color) ? 'black' : 'white');
$.each(generalList, function(idx, general) {
$item = $('<option value="{0}">{1}</option>'.format(general.no, general.name));
if (general.npc) {
$item.css('color', getNpcColor(general.npc));
} else {
$item.css('color', 'white');
}
$item.css('background-color', 'black');
$optGroup.append($item);
});
$list.append($optGroup);
}
$.post({
url: 'j_get_basic_general_list.php',
dataType: 'json',
data: {
req: 2,
}
}).then(function(data) {
if (!data.result) {
alert(data.reason);
$('#importModal').modal('hide');
return false;
}
var nations = data.nation;
var myNationID = data.nationID;
$list.empty();
//자국 먼저
if (0 in data.list) {
nations[0] = {
nation: 0,
name: '재야',
color: '#000000'
};
}
addNation(combineArray(data.list[myNationID], data.column), nations[myNationID].name, nations[myNationID].color);
for (var nationID in data.list) {
if (nationID == myNationID) {
continue;
}
addNation(combineArray(data.list[nationID], data.column), nations[nationID].name, nations[nationID].color);
}
initGeneralList = true;
}, errUnknown);
}
});
initBasicEvent();
$attackerCard.append($generalForm.clone(true, true));
addDefender();
$('.btn-begin_battle').click(function() {
beginBattle();
});
$('.btn-reorder_defender').click(function() {
requestReorderDefender();
})
}); });
+194 -200
View File
@@ -1,201 +1,195 @@
function changePermission(isAmbassador, rawGeneralList){ function changePermission(isAmbassador, rawGeneralList) {
console.log(isAmbassador); console.log(isAmbassador);
console.log(rawGeneralList); console.log(rawGeneralList);
var generalList = []; var generalList = [];
$.each(rawGeneralList, function(idx, value){ $.each(rawGeneralList, function(idx, value) {
generalList.push(parseInt(value.id)); generalList.push(parseInt(value.id));
}) })
$.post({ $.post({
url:'j_general_set_permission.php', url: 'j_general_set_permission.php',
dataType:'json', dataType: 'json',
data:{ data: {
isAmbassador:isAmbassador, isAmbassador: isAmbassador,
genlist:generalList genlist: generalList
}, },
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
alert('변경하지 못했습니다.'); alert('변경하지 못했습니다.');
return false; return false;
} }
if(!data.result){ if (!data.result) {
alert('변경하지 못했습니다. : '+data.reason); alert('변경하지 못했습니다. : ' + data.reason);
return false; return false;
} }
alert('변경했습니다.'); alert('변경했습니다.');
location.reload(); location.reload();
}, errUnknown); }, errUnknown);
} }
$(function(){ $(function() {
$('#selectAmbassador').select2({ $('#selectAmbassador').select2({
theme: 'bootstrap4', theme: 'bootstrap4',
placeholder: "", placeholder: "",
allowClear: true, allowClear: true,
language: "ko", language: "ko",
width:300, width: 300,
maximumSelectionLength: 2, maximumSelectionLength: 2,
containerCss: { containerCss: {
display: "inline-block !important;", display: "inline-block !important;",
color: 'white !important' color: 'white !important'
}, },
data:candidateAmbassadors, data: candidateAmbassadors,
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary', //containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary', dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
}); });
$('#selectAuditor').select2({ $('#selectAuditor').select2({
theme: 'bootstrap4', theme: 'bootstrap4',
placeholder: "", placeholder: "",
allowClear: true, allowClear: true,
language: "ko", language: "ko",
width:300, width: 300,
maximumSelectionLength: 2, maximumSelectionLength: 2,
containerCss: { containerCss: {
display: "inline-block !important;", display: "inline-block !important;",
color: 'white !important' color: 'white !important'
}, },
data:candidateAuditors, data: candidateAuditors,
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary', //containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary', dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
}); });
$('#changeAmbassador').click(function(){ $('#changeAmbassador').click(function() {
if(!confirm('외교권자를 변경할까요?')){ if (!confirm('외교권자를 변경할까요?')) {
return false; return false;
} }
changePermission(true, $('#selectAmbassador').select2('data')); changePermission(true, $('#selectAmbassador').select2('data'));
return false; return false;
}); });
$('#changeAuditor').click(function(){ $('#changeAuditor').click(function() {
if(!confirm('조언자를 변경할까요?')){ if (!confirm('조언자를 변경할까요?')) {
return false; return false;
} }
changePermission(false, $('#selectAuditor').select2('data')); changePermission(false, $('#selectAuditor').select2('data'));
return false; return false;
}); });
$('#btn_kick').click(function(){ $('#btn_kick').click(function() {
var $kickSelect = $('#genlist_kick option:selected'); var $kickSelect = $('#genlist_kick option:selected');
var generalID = $kickSelect.val(); var generalID = $kickSelect.val();
if(!generalID){ if (!generalID) {
alert('장수를 선택해주세요'); alert('장수를 선택해주세요');
return false; return false;
} }
var generalName = $kickSelect.data('name'); var generalName = $kickSelect.data('name');
if(!confirm('{0}를 추방하시겠습니까?'.format(generalName))){ if (!confirm('{0}를 추방하시겠습니까?'.format(generalName))) {
return false; return false;
} }
$.post({ $.post({
url:'j_myBossInfo.php', url: 'j_myBossInfo.php',
dataType:'json', dataType: 'json',
data:{ data: {
action:'추방', action: '추방',
destGeneralID:generalID destGeneralID: generalID
}, },
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
alert('추방하지 못했습니다.'); alert('추방하지 못했습니다.');
return false; return false;
} }
if(!data.result){ if (!data.result) {
alert('추방하지 못했습니다. : '+data.reason); alert('추방하지 못했습니다. : ' + data.reason);
return false; return false;
} }
alert('{0}를 추방했습니다.'.format(generalName)); alert('{0}를 추방했습니다.'.format(generalName));
location.reload(); location.reload();
}, errUnknown); }, errUnknown);
return false; return false;
}); });
$('.btn_appoint').click(function(){ $('.btn_appoint').click(function() {
var $btn = $(this); var $btn = $(this);
var officerLevel = $btn.data('officer_level'); var officerLevel = $btn.data('officer_level');
var officerLevelText = $btn.data('officer_level_text'); var officerLevelText = $btn.data('officer_level_text');
var cityID = 0; var cityID = 0;
var cityName = '_'; var cityName = '_';
var $generalSelect = $('#genlist_{0} option:selected'.format(officerLevel)); var $generalSelect = $('#genlist_{0} option:selected'.format(officerLevel));
var $citySelect = $('#citylist_{0} option:selected'.format(officerLevel)); var $citySelect = $('#citylist_{0} option:selected'.format(officerLevel));
var generalID = $generalSelect.val(); var generalID = parseInt($generalSelect.val());
var generalName = $generalSelect.data('name'); var generalName = $generalSelect.data('name');
var generalOfficerLevel = $generalSelect.data('officer_level'); var generalOfficerLevel = $generalSelect.data('officer_level');
if(officerLevel >= 5){ if (officerLevel >= 5) {
if(generalID == 0){ if (generalID == 0) {
if(!confirm('{0}직을 비우시겠습니까?'.format(officerLevelText))){ if (!confirm('{0}직을 비우시겠습니까?'.format(officerLevelText))) {
return false; return false;
} }
} } else if (generalOfficerLevel >= 5) {
else if(generalOfficerLevel >= 5){ if (!confirm('이미 수뇌인 {0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))) {
if(!confirm('이미 수뇌인 {0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))){ return false;
return false; }
} } else {
} if (!confirm('{0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))) {
else{ return false;
if(!confirm('{0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))){ }
return false; }
} } else {
} cityID = $citySelect.val();
} if (!cityID) {
else{ alert('도시를 선택해주세요');
cityID = $citySelect.val(); return false;
if(!cityID){ }
alert('도시를 선택해주세요'); cityName = $citySelect.find('option:selected .name_field').text();
return false;
} if (generalID == 0) {
cityName = $citySelect.find('option:selected .name_field').text(); if (!confirm('{0} {1}직을 비우시겠습니까?'.format(cityName, officerLevelText))) {
return false;
if(generalID == 0){ }
if(!confirm('{0} {1}직을 비우시겠습니까?'.format(cityName, officerLevelText))){ } else if (generalOfficerLevel >= 5) {
return false; if (!confirm('수뇌인 {0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))) {
} return false;
} }
else if(generalOfficerLevel >= 5){ } else {
if(!confirm('수뇌인 {0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))){ if (!confirm('{0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))) {
return false; return false;
} }
} }
else{ }
if(!confirm('{0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))){
return false; $.post({
} url: 'j_myBossInfo.php',
} dataType: 'json',
} data: {
action: '임명',
$.post({ destGeneralID: generalID,
url:'j_myBossInfo.php', destCityID: cityID,
dataType:'json', officerLevel: officerLevel
data:{ },
action:'임명', }).then(function(data) {
destGeneralID:generalID, if (!data) {
destCityID:cityID, alert('임명하지 못했습니다.');
officerLevel:officerLevel return false;
}, }
}).then(function(data){ if (!data.result) {
if(!data){ alert('임명하지 못했습니다. : ' + data.reason);
alert('임명하지 못했습니다.'); return false;
return false; }
}
if(!data.result){ if (generalID) {
alert('임명하지 못했습니다. : '+data.reason); alert('{0}을(를) 임명했습니다.'.format(generalName));
return false; } else {
} alert('관직을 비웠습니다.');
}
if(generalID){
alert('{0}을(를) 임명했습니다.'.format(generalName)); location.reload();
} }, errUnknown);
else{
alert('관직을 비웠습니다.'); })
}
location.reload();
}, errUnknown);
})
}) })
+184 -164
View File
@@ -1,165 +1,185 @@
var filledChiefList = {}; var filledChiefList = {};
var chiefTableObj = {}; var chiefTableObj = {};
function clearTable(){ function clearTable(){
$('.chiefLevelText').html('-'); $('.chiefLevelText').html('-');
$('.chiefTurnTime, .chiefTurnText, .chiefName').html('&nbsp;'); $('.chiefTurnTime, .chiefTurnText, .chiefName').html('&nbsp;');
} }
function genChiefTableObj(){ function genChiefTableObj(){
var objTable = { var objTable = {
btns: $('#turnPush,#turnPull,#setCommand') btns: $('#turnPush,#turnPull,#setCommand')
}; };
for(var chiefIdx = 5; chiefIdx <= 12; chiefIdx++){ for(var chiefIdx = 5; chiefIdx <= 12; chiefIdx++){
var $plate = $('#chief_{0}'.format(chiefIdx)); var $plate = $('#chief_{0}'.format(chiefIdx));
var $officerLevelText = $plate.find('.chiefLevelText'); var $officerLevelText = $plate.find('.chiefLevelText');
var $name = $plate.find('.chiefName'); var $name = $plate.find('.chiefName');
var turn = []; var turn = [];
for(var turnIdx=0;turnIdx<maxChiefTurn;turnIdx++){ for(var turnIdx=0;turnIdx<maxChiefTurn;turnIdx++){
var $turn = $plate.find('.turn{0}'.format(turnIdx)); var $turn = $plate.find('.turn{0}'.format(turnIdx));
var $turnTime = $turn.find('.chiefTurnTime'); var $turnTime = $turn.find('.chiefTurnTime');
var $turnPad = $turn.find('.chiefTurnPad'); var $turnPad = $turn.find('.chiefTurnPad');
var $turnText = $turn.find('.chiefTurnText'); var $turnText = $turn.find('.chiefTurnText');
turn.push({turnTime:$turnTime,turnPad:$turnPad,turnText:$turnText}); turn.push({turnTime:$turnTime,turnPad:$turnPad,turnText:$turnText});
} }
objTable[chiefIdx] = { objTable[chiefIdx] = {
officerLevelText: $officerLevelText, officerLevelText: $officerLevelText,
name: $name, name: $name,
turn: turn turn: turn
}; };
} }
return objTable; return objTable;
} }
function clearChief(chiefIdx){ function clearChief(chiefIdx){
var $plate = $('#chief_{0}'.format(chiefIdx)); var $plate = $('#chief_{0}'.format(chiefIdx));
$plate.find('.chiefLevelText').html('-'); $plate.find('.chiefLevelText').html('-');
$plate.find('.chiefTurnTime, .chiefTurnText, .chiefName').html('&nbsp;'); $plate.find('.chiefTurnTime, .chiefTurnText, .chiefName').html('&nbsp;');
} }
function reloadTable(){ function reloadTable(){
$.post({ $.post({
url:'j_getChiefTurn.php', url:'j_getChiefTurn.php',
dataType:'json', dataType:'json',
}).then(function(data){ }).then(function(data){
if(!data.result){ if(!data.result){
alert(data.reason); alert(data.reason);
return; return;
} }
var turnTerm = data.turnTerm; var turnTerm = data.turnTerm;
var tmpFilledChiefList = {}; var tmpFilledChiefList = {};
if(data.isChief){ if(data.isChief){
chiefTableObj.btns.css('visibility', 'visible'); chiefTableObj.btns.css('visibility', 'visible');
} }
else{ else{
chiefTableObj.btns.css('visibility', 'hidden'); chiefTableObj.btns.css('visibility', 'hidden');
} }
$.each(data.nationTurnBrief, function(chiefIdx, chiefInfo){ $.each(data.nationTurnBrief, function(chiefIdx, chiefInfo){
tmpFilledChiefList[chiefIdx] = true; tmpFilledChiefList[chiefIdx] = true;
filledChiefList[chiefIdx] = true; filledChiefList[chiefIdx] = true;
var plateObj = chiefTableObj[chiefIdx]; var plateObj = chiefTableObj[chiefIdx];
var $name = $('<span>{0}</span>'.format(chiefInfo.name)); if(chiefInfo.name){
var nameColor = getNpcColor(chiefInfo.npcType); var $name = $('<span>{0}</span>'.format(chiefInfo.name));
if(nameColor){ var nameColor = getNpcColor(chiefInfo.npcType);
$name.css('color',nameColor); if(nameColor){
} $name.css('color',nameColor);
plateObj.officerLevelText.text(chiefInfo.officerLevelText); }
plateObj.name.html($name); plateObj.name.html($name);
}
var turnTimeObj = moment(chiefInfo.turnTime); else{
var turnList = plateObj.turn; plateObj.name.html('');
$.each(chiefInfo.turn, function(turnIdx, turnText){ }
turnList[turnIdx].turnTime.text(turnTimeObj.format('hh:mm'));
turnList[turnIdx].turnText.html(turnText).css('font-size', '13px'); plateObj.officerLevelText.text(chiefInfo.officerLevelText);
var oWidth = turnList[turnIdx].turnPad.innerWidth();
var iWidth = turnList[turnIdx].turnText.outerWidth(); if(chiefInfo.turnTime){
if(iWidth > oWidth * 0.95){ var turnTimeObj = moment(chiefInfo.turnTime);
var newFontSize = 13 * oWidth / iWidth * 0.9; }
turnList[turnIdx].turnText.css('font-size', '{0}px'.format(newFontSize)); else{
} var turnTimeObj = null;
turnTimeObj = turnTimeObj.add(turnTerm, 'minute'); }
}); var turnList = plateObj.turn;
}); $.each(chiefInfo.turn, function(turnIdx, turnText){
if(turnTimeObj){
for(var idx=5;idx<=12;idx++){ turnList[turnIdx].turnTime.text(turnTimeObj.format('HH:mm'));
if(idx in tmpFilledChiefList){ }
continue; else{
} turnList[turnIdx].turnTime.text('');
if(idx in filledChiefList){ }
clearChief(chiefIdx);
} turnList[turnIdx].turnText.html(turnText).css('font-size', '13px');
} var oWidth = turnList[turnIdx].turnPad.innerWidth();
filledChiefList = tmpFilledChiefList; var iWidth = turnList[turnIdx].turnText.outerWidth();
}, errUnknown); if(iWidth > oWidth * 0.95){
} var newFontSize = 13 * oWidth / iWidth * 0.9;
turnList[turnIdx].turnText.css('font-size', '{0}px'.format(newFontSize));
function reserveTurn(turnList, command){ }
console.log(turnList, command); if(turnTimeObj){
$.post({ turnTimeObj = turnTimeObj.add(turnTerm, 'minute');
url:'j_set_chief_command.php', }
dataType:'json',
data:{ });
action:command, });
turnList:turnList
} for(var idx=5;idx<=12;idx++){
}).then(function(data){ if(idx in tmpFilledChiefList){
if(!data.result){ continue;
alert(data.reason); }
} if(idx in filledChiefList){
reloadTable(); clearChief(chiefIdx);
}, errUnknown); }
} }
filledChiefList = tmpFilledChiefList;
function pushTurn(turnCnt){ }, errUnknown);
$.post({ }
url:'j_chief_turn.php',
dataType:'json', function reserveTurn(turnList, command){
data:{ console.log(turnList, command);
amount:turnCnt $.post({
} url:'j_set_chief_command.php',
}).then(function(data){ dataType:'json',
if(!data.result){ data:{
alert(data.reason); action:command,
} turnList:turnList
reloadTable(); }
}, errUnknown); }).then(function(data){
} if(!data.result){
alert(data.reason);
jQuery(function($){ }
reloadTable();
chiefTableObj= genChiefTableObj(); }, errUnknown);
reloadTable(); }
$('#reloadTable').click(reloadTable);
$('#setCommand').click(function(){ function pushTurn(turnCnt){
var turnList = $('#chiefTurnSelector').val().map(function(v){return parseInt(v);}); $.post({
var $command = $('#chiefCommandList option:selected'); url:'j_chief_turn.php',
if($command.data('reqarg')){ dataType:'json',
$.redirect( data:{
"b_processing.php", { amount:turnCnt
command: $command.val(), }
turnList: turnList.join('_'), }).then(function(data){
is_chief: true if(!data.result){
}, "GET"); alert(data.reason);
} }
else{ reloadTable();
reserveTurn(turnList, $command.val()); }, errUnknown);
} }
return false;
}); jQuery(function($){
$('#turnPush').click(function(){ chiefTableObj= genChiefTableObj();
pushTurn(1); reloadTable();
}); $('#reloadTable').click(reloadTable);
$('#setCommand').click(function(){
$('#turnPull').click(function(){ var turnList = $('#chiefTurnSelector').val().map(function(v){return parseInt(v);});
pushTurn(-1); var $command = $('#chiefCommandList option:selected');
}); if($command.data('reqarg')){
$.redirect(
"b_processing.php", {
command: $command.val(),
turnList: turnList.join('_'),
is_chief: true
}, "GET");
}
else{
reserveTurn(turnList, $command.val());
}
return false;
});
$('#turnPush').click(function(){
pushTurn(1);
});
$('#turnPull').click(function(){
pushTurn(-1);
});
}) })
+129 -103
View File
@@ -3,8 +3,8 @@
* @see https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery * @see https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
* @param {string} string escape하고자 하는 문자열 * @param {string} string escape하고자 하는 문자열
* @returns {string} * @returns {string}
*/ */
var escapeHtml = (function (string) { var escapeHtml = (function(string) {
var entityMap = { var entityMap = {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
@@ -32,58 +32,70 @@ function isInt(n) {
return +n === n && !(n % 1); return +n === n && !(n % 1);
} }
;(function(ns){ ;
(function(ns) {
//https://gist.github.com/demouth/3217440 //https://gist.github.com/demouth/3217440
/** /**
* mb_strwidth * mb_strwidth
* @param String * @param String
* @return int * @return int
* @see http://php.net/manual/ja/function.mb-strwidth.php * @see http://php.net/manual/ja/function.mb-strwidth.php
*/ */
var mb_strwidth = function(str){ var mb_strwidth = function(str) {
var i=0,l=str.length,c='',length=0; var i = 0,
for(;i<l;i++){ l = str.length,
c=str.charCodeAt(i); c = '',
if(0x0000<=c&&c<=0x0019){ length = 0;
length += 0; for (; i < l; i++) {
}else if(0x0020<=c&&c<=0x1FFF){ c = str.charCodeAt(i);
length += 1; if (0x0000 <= c && c <= 0x0019) {
}else if(0x2000<=c&&c<=0xFF60){ length += 0;
length += 2; } else if (0x0020 <= c && c <= 0x1FFF) {
}else if(0xFF61<=c&&c<=0xFF9F){ length += 1;
length += 1; } else if (0x2000 <= c && c <= 0xFF60) {
}else if(0xFFA0<=c){ length += 2;
length += 2; } else if (0xFF61 <= c && c <= 0xFF9F) {
} length += 1;
} } else if (0xFFA0 <= c) {
return length; length += 2;
}; }
}
/** return length;
* mb_strimwidth };
* @param String
* @param int /**
* @param int * mb_strimwidth
* @param String * @param String
* @return String * @param int
* @see http://www.php.net/manual/ja/function.mb-strimwidth.php * @param int
*/ * @param String
var mb_strimwidth = function(str,start,width,trimmarker){ * @return String
if(typeof trimmarker === 'undefined') trimmarker=''; * @see http://www.php.net/manual/ja/function.mb-strimwidth.php
var trimmakerWidth = mb_strwidth(trimmarker),i=start,l=str.length,trimmedLength=0,trimmedStr=''; */
for(;i<l;i++){ var mb_strimwidth = function(str, start, width, trimmarker) {
var charCode=str.charCodeAt(i),c=str.charAt(i),charWidth=mb_strwidth(c),next=str.charAt(i+1),nextWidth=mb_strwidth(next); if (typeof trimmarker === 'undefined') trimmarker = '';
trimmedLength += charWidth; var trimmakerWidth = mb_strwidth(trimmarker),
trimmedStr += c; i = start,
if(trimmedLength+trimmakerWidth+nextWidth>width){ l = str.length,
trimmedStr += trimmarker; trimmedLength = 0,
break; trimmedStr = '';
} for (; i < l; i++) {
} var charCode = str.charCodeAt(i),
return trimmedStr; c = str.charAt(i),
}; charWidth = mb_strwidth(c),
ns.mb_strwidth = mb_strwidth; next = str.charAt(i + 1),
ns.mb_strimwidth = mb_strimwidth; nextWidth = mb_strwidth(next);
trimmedLength += charWidth;
trimmedStr += c;
if (trimmedLength + trimmakerWidth + nextWidth > width) {
trimmedStr += trimmarker;
break;
}
}
return trimmedStr;
};
ns.mb_strwidth = mb_strwidth;
ns.mb_strimwidth = mb_strimwidth;
})(window); })(window);
/** /**
@@ -93,7 +105,7 @@ function isInt(n) {
*/ */
function convertDictById(arr) { function convertDictById(arr) {
var result = {}; var result = {};
arr.forEach(function (v, i) { arr.forEach(function(v, i) {
result[v.id] = v; result[v.id] = v;
}); });
return result; return result;
@@ -106,7 +118,7 @@ function convertDictById(arr) {
*/ */
function convertSet(arr) { function convertSet(arr) {
var result = {}; var result = {};
arr.forEach(function (v) { arr.forEach(function(v) {
result[v] = true; result[v] = true;
}); });
return result; return result;
@@ -115,10 +127,10 @@ function convertSet(arr) {
/** /**
* {0}, {1}, {2}형태로 포맷해주는 함수 * {0}, {1}, {2}형태로 포맷해주는 함수
*/ */
String.prototype.format = function() { String.prototype.format = function() {
var args = arguments; var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) { return this.replace(/{(\d+)}/g, function(match, number) {
return (typeof args[number] != 'undefined') ? args[number] : match; return (typeof args[number] != 'undefined') ? args[number] : match;
}); });
}; };
@@ -134,12 +146,11 @@ function hexToRgb(hex) {
} }
function isBrightColor(color){ function isBrightColor(color) {
color = hexToRgb(color); color = hexToRgb(color);
if ((color.r*0.299 + color.g*0.587 + color.b*0.114) > 140){ if ((color.r * 0.299 + color.g * 0.587 + color.b * 0.114) > 140) {
return true; return true;
} } else {
else{
return false; return false;
} }
} }
@@ -177,7 +188,7 @@ function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} }
function linkifyStrWithOpt(text){ function linkifyStrWithOpt(text) {
return linkifyStr(text, {}); return linkifyStr(text, {});
} }
@@ -188,14 +199,14 @@ function linkifyStrWithOpt(text){
* @param {object} options * @param {object} options
* @returns {string} * @returns {string}
*/ */
var TemplateEngine = function (html, options) { var TemplateEngine = function(html, options) {
var re = /<%(.+?)%>/g, var re = /<%(.+?)%>/g,
reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g, reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g,
code = 'with(obj) { var r=[];\n', code = 'with(obj) { var r=[];\n',
cursor = 0, cursor = 0,
result, result,
match; match;
var add = function (line, js) { var add = function(line, js) {
js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') : js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : ''); (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
return add; return add;
@@ -208,82 +219,97 @@ var TemplateEngine = function (html, options) {
} }
add(html.substr(cursor, html.length - cursor)); add(html.substr(cursor, html.length - cursor));
code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, ' '); code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, ' ');
try { result = new Function('obj', code).apply(options, [options]); } try { result = new Function('obj', code).apply(options, [options]); } catch (err) { console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n"); }
catch (err) { console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n"); }
return result; return result;
} }
function getIconPath(imgsvr, picture){ function getIconPath(imgsvr, picture) {
// ../d_shared/common_path.js 필요 // ../d_shared/common_path.js 필요
if(!imgsvr){ if (!imgsvr) {
return pathConfig.sharedIcon+'/'+picture; return pathConfig.sharedIcon + '/' + picture;
} } else {
else{ return pathConfig.root + '/d_pic/' + picture;
return pathConfig.root+'/d_pic/'+picture;
} }
} }
function activeFlip($obj){ function activeFlip($obj) {
var $result; var $result;
if($obj === undefined){ if ($obj === undefined) {
$result = $('img[data-flip]'); $result = $('img[data-flip]');
} } else {
else{
$result = $obj.find('img[data-flip]'); $result = $obj.find('img[data-flip]');
} }
$result.each(function(){ $result.each(function() {
activeFlipItem($(this)); activeFlipItem($(this));
}); });
} }
function activeFlipItem($img){ function combineObject(item, columnList) {
var newItem = {};
for (var columnIdx in columnList) {
var columnName = columnList[columnIdx];
newItem[columnName] = item[columnIdx];
}
return newItem;
}
function combineArray(array, columnList) {
var result = [];
for (var key in array) {
var item = array[key];
result[key] = combineObject(item, columnList);
}
return result;
}
function activeFlipItem($img) {
var imageList = []; var imageList = [];
imageList.push($img.attr('src')); imageList.push($img.attr('src'));
$.each($img.data('flip').split(','), function(idx, value){ $.each($img.data('flip').split(','), function(idx, value) {
var value = $.trim(value); var value = $.trim(value);
if(!value){ if (!value) {
return true; return true;
} }
imageList.push(value); imageList.push(value);
}); });
if(imageList.length <= 1){ if (imageList.length <= 1) {
return; return;
} }
$img.data('computed_flip_array', imageList); $img.data('computed_flip_array', imageList);
$img.data('computed_flip_idx', 0); $img.data('computed_flip_idx', 0);
$img.click(function(){ $img.click(function() {
var arr = $img.data('computed_flip_array'); var arr = $img.data('computed_flip_array');
var idx = $img.data('computed_flip_idx'); var idx = $img.data('computed_flip_idx');
idx = (idx + 1)%(arr.length); idx = (idx + 1) % (arr.length);
$img.attr('src', arr[idx]); $img.attr('src', arr[idx]);
$img.data('computed_flip_idx', idx); $img.data('computed_flip_idx', idx);
}); });
$img.css('cursor','pointer'); $img.css('cursor', 'pointer');
} }
jQuery(function($){ jQuery(function($) {
$('.obj_tooltip').mouseover(function(){ $('.obj_tooltip').mouseover(function() {
var $objTooltip = $(this); var $objTooltip = $(this);
if($objTooltip.data('setObjTooltip')){ if ($objTooltip.data('setObjTooltip')) {
return true; return true;
} }
var tooltipClassText = $objTooltip.data('tooltip-class'); var tooltipClassText = $objTooltip.data('tooltip-class');
if(!tooltipClassText){ if (!tooltipClassText) {
tooltipClassText = ''; tooltipClassText = '';
} }
var template = '<div class="tooltip {0}" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>' var template = '<div class="tooltip {0}" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'
.format(tooltipClassText); .format(tooltipClassText);
$objTooltip.tooltip({ $objTooltip.tooltip({
title:function(){ title: function() {
return $.trim($(this).find('.tooltiptext').html()); return $.trim($(this).find('.tooltiptext').html());
}, },
template:template, template: template,
html:true html: true
}).tooltip('show'); }).tooltip('show');
$objTooltip.data('setObjTooltip', true); $objTooltip.data('setObjTooltip', true);
@@ -297,21 +323,21 @@ jQuery(function($){
activeFlip(); activeFlip();
var customCSS = localStorage.getItem('sam_customCSS'); var customCSS = localStorage.getItem('sam_customCSS');
if(customCSS){ if (customCSS) {
var $style = $('<style type="text/css"></style>'); var $style = $('<style type="text/css"></style>');
$style.text(customCSS); $style.text(customCSS);
$style.appendTo($('head')); $style.appendTo($('head'));
} }
}); });
function errUnknown(){ function errUnknown() {
alert('작업을 실패했습니다.'); alert('작업을 실패했습니다.');
} }
function errUnknownToast(){ function errUnknownToast() {
$.toast({ $.toast({
title: '에러!', title: '에러!',
content: '작업을 실패했습니다.', content: '작업을 실패했습니다.',
@@ -320,8 +346,8 @@ function errUnknownToast(){
}); });
} }
function quickReject(errMsg){ function quickReject(errMsg) {
if(errMsg === undefined){ if (errMsg === undefined) {
errMsg = '작업을 실패했습니다.'; errMsg = '작업을 실패했습니다.';
} }
var deferred = $.Deferred(); var deferred = $.Deferred();
@@ -329,8 +355,8 @@ function quickReject(errMsg){
return deferred.promise(); return deferred.promise();
} }
function nl2br(text){ function nl2br(text) {
return text.replace(/\n/g,"<br>"); return text.replace(/\n/g, "<br>");
} }
/* /*
function br2nl (text) { function br2nl (text) {
@@ -338,11 +364,11 @@ function br2nl (text) {
} }
*/ */
function getNpcColor(npcType){ function getNpcColor(npcType) {
if(npcType >= 2){ if (npcType >= 2) {
return 'cyan'; return 'cyan';
} }
if(npcType == 1){ if (npcType == 1) {
return 'skyblue'; return 'skyblue';
} }
return null; return null;
+16 -16
View File
@@ -1,17 +1,17 @@
$(function(){ $(function() {
var $target = $("#destCityID"); var $target = $("#destCityID");
reloadWorldMap({ reloadWorldMap({
isDetailMap:false, isDetailMap: false,
clickableAll:true, clickableAll: true,
neutralView:true, neutralView: true,
useCachedMap:true, useCachedMap: true,
selectCallback:function(city){ selectCallback: function(city) {
var currVal = $target.val(); var currVal = $target.val();
$target.val(city.id); $target.val(city.id).trigger("change");
if($target.val() === null){ if ($target.val() === null) {
$target.val(currVal); $target.val(currVal).trigger("change");
} }
return false; return false;
} }
}); });
}); });
+16 -16
View File
@@ -1,17 +1,17 @@
$(function(){ $(function() {
var $target = $("#destNationID"); var $target = $("#destNationID");
reloadWorldMap({ reloadWorldMap({
isDetailMap:false, isDetailMap: false,
clickableAll:true, clickableAll: true,
neutralView:true, neutralView: true,
useCachedMap:true, useCachedMap: true,
selectCallback:function(city){ selectCallback: function(city) {
var currVal = $target.val(); var currVal = $target.val();
$target.val(city.nationId); $target.val(city.nationId).trigger("change");
if($target.val() === null){ if ($target.val() === null) {
$target.val(currVal); $target.val(currVal).trigger("change");
} }
return false; return false;
} }
}); });
}); });
+898 -898
View File
@@ -1,899 +1,899 @@
$(function() { $(function() {
var cityList = {}; var cityList = {};
var userList = {}; var userList = {};
var cityGroupOrder = ['하북','중원','서북','서촉','남중','초','오월','동이']; var cityGroupOrder = ['하북','중원','서북','서촉','남중','초','오월','동이'];
var city규모 = {:1,:2,:3,:4,:5,:6,:7,:8}; var city규모 = {:1,:2,:3,:4,:5,:6,:7,:8};
window.cityList = cityList; window.cityList = cityList;
window.userList = userList; window.userList = userList;
var basicPath = document.location.pathname; var basicPath = document.location.pathname;
basicPath = basicPath.substring(0, basicPath.lastIndexOf('/'))+'/'; basicPath = basicPath.substring(0, basicPath.lastIndexOf('/'))+'/';
var mergeSort = function(arr,cmpFunc){ var mergeSort = function(arr,cmpFunc){
if(typeof cmpFunc == "undefined"){ if(typeof cmpFunc == "undefined"){
cmpFunc = function(a,b){ cmpFunc = function(a,b){
if(a<b) return -1; if(a<b) return -1;
if(a>b) return 1; if(a>b) return 1;
return 0; return 0;
} }
} }
var merge = function(left,right){ var merge = function(left,right){
var retVal=[]; var retVal=[];
var leftIdx=0; var leftIdx=0;
var rightIdx=0; var rightIdx=0;
while(leftIdx<left.length && rightIdx<right.length){ while(leftIdx<left.length && rightIdx<right.length){
var cmpVal = cmpFunc(left[leftIdx],right[rightIdx]); var cmpVal = cmpFunc(left[leftIdx],right[rightIdx]);
if(cmpVal<=0){ if(cmpVal<=0){
retVal.push(left[leftIdx]); retVal.push(left[leftIdx]);
leftIdx++; leftIdx++;
} }
else{ else{
retVal.push(right[rightIdx]); retVal.push(right[rightIdx]);
rightIdx++; rightIdx++;
} }
} }
retVal = retVal.concat(left.slice(leftIdx)).concat(right.slice(rightIdx)) retVal = retVal.concat(left.slice(leftIdx)).concat(right.slice(rightIdx))
return retVal; return retVal;
}; };
var _mergeSort = function(arr){ var _mergeSort = function(arr){
if(arr.length<2){ if(arr.length<2){
return arr; return arr;
} }
var middle = Math.floor(arr.length/2); var middle = Math.floor(arr.length/2);
var left = arr.slice(0,middle); var left = arr.slice(0,middle);
var right = arr.slice(middle); var right = arr.slice(middle);
return merge(_mergeSort(left),_mergeSort(right)); return merge(_mergeSort(left),_mergeSort(right));
}; };
return _mergeSort(arr); return _mergeSort(arr);
}; };
window.mergeSort = mergeSort; window.mergeSort = mergeSort;
var extDutyWindow = function(userInfo){ var extDutyWindow = function(userInfo){
window.currUser = userInfo; window.currUser = userInfo;
//도시 순서 재구성 //도시 순서 재구성
var subCityGroupList = {}; var subCityGroupList = {};
var subCityList = {}; var subCityList = {};
var tmpOldVal = 0; var tmpOldVal = 0;
//var callCity = function(num){console.log('city no.'+num+' is clicked!')}; //var callCity = function(num){console.log('city no.'+num+' is clicked!')};
if($('#ext_win').length==0){ if($('#ext_win').length==0){
var $win = $('<div id="ext_win" style="padding:0;" title="관직 임명"><table style="padding:0;margin:0;" cellspacing="0" cellpadding="0" border="0"><tr><td width="700px" style="padding:0;"><iframe id="in_frame" src="map.php?type=1&amp;graphic=1" width="700" height="520" frameborder="0" marginwidth="0" marginheight="0" topmargin="0" scrolling="no"></iframe></td>'+ var $win = $('<div id="ext_win" style="padding:0;" title="관직 임명"><table style="padding:0;margin:0;" cellspacing="0" cellpadding="0" border="0"><tr><td width="700px" style="padding:0;"><iframe id="in_frame" src="map.php?type=1&amp;graphic=1" width="700" height="520" frameborder="0" marginwidth="0" marginheight="0" topmargin="0" scrolling="no"></iframe></td>'+
'<td width="305px" style="padding:0;vertical-align:top;height:520px;"><div style="height:520px;width:305px;overflow-y:scroll;overflow-x:hidden;">'+ '<td width="305px" style="padding:0;vertical-align:top;height:520px;"><div style="height:520px;width:305px;overflow-y:scroll;overflow-x:hidden;">'+
'<table id="inner_table"><thead><tr><th width="35">도시</th><th width="85">태수</th><th width="85">군사</th><th width="85">종사</th></tr></thead><tbody class="content">'+ '<table id="inner_table"><thead><tr><th width="35">도시</th><th width="85">태수</th><th width="85">군사</th><th width="85">종사</th></tr></thead><tbody class="content">'+
'</tbody></table></div></td></tr></table>'+ '</tbody></table></div></td></tr></table>'+
'<form name="form1" id="fake_form"><span id="user_name"></span> : <select name="double" id="city_select"></select>'+ '<form name="form1" id="fake_form"><span id="user_name"></span> : <select name="double" id="city_select"></select>'+
'<div id="duty_radio" style="display:inline;">'+ '<div id="duty_radio" style="display:inline;">'+
'<input type="radio" id="duty_type1" value="4" name="duty_radio"><label for="duty_type1">태수</label>'+ '<input type="radio" id="duty_type1" value="4" name="duty_radio"><label for="duty_type1">태수</label>'+
'<input type="radio" id="duty_type2" value="3" name="duty_radio"><label for="duty_type2">군사</label>'+ '<input type="radio" id="duty_type2" value="3" name="duty_radio"><label for="duty_type2">군사</label>'+
'<input type="radio" id="duty_type3" value="2" name="duty_radio"><label for="duty_type3">종사</label>'+ '<input type="radio" id="duty_type3" value="2" name="duty_radio"><label for="duty_type3">종사</label>'+
'</div></form></div>'); '</div></form></div>');
$win.hide(); $win.hide();
$win.css('font-size','9pt'); $win.css('font-size','9pt');
$('#fake_form').css('display','inline'); $('#fake_form').css('display','inline');
$('body').append($win); $('body').append($win);
$('#inner_table').attr('border','1').attr('cellspacing',"0").attr('cellpadding',"0") $('#inner_table').attr('border','1').attr('cellspacing',"0").attr('cellpadding',"0")
.attr('bordercolordark',"gray").attr('bordercolorlight',"black").attr('align','center') .attr('bordercolordark',"gray").attr('bordercolorlight',"black").attr('align','center')
.css('font-size','13px').css('width','290px'); .css('font-size','13px').css('width','290px');
$('#inner_table thead tr'); $('#inner_table thead tr');
$('#fake_form').submit(function(){ $('#fake_form').submit(function(){
return false; return false;
}); });
$('#in_frame').load(function(){ $('#in_frame').load(function(){
$('#in_frame').contents().find('div').click(function(){$('#city_select').change();}); $('#in_frame').contents().find('div').click(function(){$('#city_select').change();});
}); });
$("#duty_radio").buttonset(); $("#duty_radio").buttonset();
var $city_select = $('#city_select'); var $city_select = $('#city_select');
$city_select.css('color','white').css('background-color','black'); $city_select.css('color','white').css('background-color','black');
$city_select.change(function(event){ $city_select.change(function(event){
if($city_select.val()==null){ if($city_select.val()==null){
$city_select.val(tmpOldVal); $city_select.val(tmpOldVal);
return false; return false;
} }
if($city_select.val() == tmpOldVal){ if($city_select.val() == tmpOldVal){
return false; return false;
} }
tmpOldVal = $city_select.val(); tmpOldVal = $city_select.val();
//console.log(tmpOldVal); //console.log(tmpOldVal);
var newInfo = subCityList[tmpOldVal]; var newInfo = subCityList[tmpOldVal];
var cityInfo = newInfo.city; var cityInfo = newInfo.city;
var p태수 = cityInfo.p태수 && currUser.p태수; var p태수 = cityInfo.p태수 && currUser.p태수;
var p군사 = cityInfo.p군사 && currUser.p군사; var p군사 = cityInfo.p군사 && currUser.p군사;
var p종사 = cityInfo.p종사 && currUser.p종사; var p종사 = cityInfo.p종사 && currUser.p종사;
//console.log(p태수,p군사,p종사); //console.log(p태수,p군사,p종사);
$('#duty_type1').button({disabled:!p태수}); $('#duty_type1').button({disabled:!p태수});
$('#duty_type2').button({disabled:!p군사}); $('#duty_type2').button({disabled:!p군사});
$('#duty_type3').button({disabled:!p종사}); $('#duty_type3').button({disabled:!p종사});
var $태수 = cityInfo.$태수; var $태수 = cityInfo.$태수;
var $군사 = cityInfo.$군사; var $군사 = cityInfo.$군사;
var $종사 = cityInfo.$종사; var $종사 = cityInfo.$종사;
return true; return true;
}); });
$win.dialog({ $win.dialog({
autoOpen:false, autoOpen:false,
width:1005, width:1005,
height:680, height:680,
buttons:{ buttons:{
"임명":function(){ "임명":function(){
//console.log("임명!"); //console.log("임명!");
var $checked = $('#duty_radio :radio:checked'); var $checked = $('#duty_radio :radio:checked');
if($checked.length==0 || $checked.attr('disabled')=='disabled'){ if($checked.length==0 || $checked.attr('disabled')=='disabled'){
alert('직책을 선택해주세요!'); alert('직책을 선택해주세요!');
return false; return false;
} }
var type = $checked.attr('value'); var type = $checked.attr('value');
var text = $checked.next().text(); var text = $checked.next().text();
var userVal = currUser.val; var userVal = currUser.val;
var userName = currUser.name; var userName = currUser.name;
var cityVal = $city_select.val(); var cityVal = $city_select.val();
var cityInfo = subCityList[cityVal].city; var cityInfo = subCityList[cityVal].city;
$.post(basicPath+'j_myBossInfo.php',{ $.post(basicPath+'j_myBossInfo.php',{
destCityID:cityVal, destCityID:cityVal,
destGeneralID:userVal, destGeneralID:userVal,
officerLevel:type, officerLevel:type,
action:'임명' action:'임명'
},function(rawData){ },function(rawData){
cityInfo['p'+text]=false; cityInfo['p'+text]=false;
var $target = cityInfo.users.find('.mode_'+type); var $target = cityInfo.users.find('.mode_'+type);
$target.prop('disabled',true); $target.prop('disabled',true);
$target.css('background','transparent'); $target.css('background','transparent');
$target.css('border','0'); $target.css('border','0');
$target.css('color',''); $target.css('color','');
cityInfo['$'+text].html(userName); cityInfo['$'+text].html(userName);
$win.dialog("close"); $win.dialog("close");
}); });
}, },
"닫기":function(){ "닫기":function(){
$win.dialog("close"); $win.dialog("close");
} }
} }
}); });
//console.log($win.parent()); //console.log($win.parent());
$win.parent().css('font-size','10pt'); $win.parent().css('font-size','10pt');
} }
$('#ext_win').dialog("close").dialog( "option", "position", { my: "center top", at: "center bottom", of: userInfo.$user} ); $('#ext_win').dialog("close").dialog( "option", "position", { my: "center top", at: "center bottom", of: userInfo.$user} );
var $innerContent = $('#inner_table .content'); var $innerContent = $('#inner_table .content');
$innerContent.html(''); $innerContent.html('');
$("#user_name").html(userInfo.name+'['+userInfo.city+']'); $("#user_name").html(userInfo.name+'['+userInfo.city+']');
$('#city_select').html(''); $('#city_select').html('');
$.each(cityList,function(idx,cityInfo){ $.each(cityList,function(idx,cityInfo){
var 지역 = cityInfo.지역; var 지역 = cityInfo.지역;
var p태수 = cityInfo.p태수 && currUser.p태수; var p태수 = cityInfo.p태수 && currUser.p태수;
var p군사 = cityInfo.p군사 && currUser.p군사; var p군사 = cityInfo.p군사 && currUser.p군사;
var p종사 = cityInfo.p종사 && currUser.p종사; var p종사 = cityInfo.p종사 && currUser.p종사;
var newInfo = { var newInfo = {
지역 : 지역, 지역 : 지역,
규모 : cityInfo.규모, 규모 : cityInfo.규모,
이름 : cityInfo.이름, 이름 : cityInfo.이름,
val : cityInfo.val, val : cityInfo.val,
city : cityInfo, city : cityInfo,
p태수 : p태수, p태수 : p태수,
p군사 : p군사, p군사 : p군사,
p종사 : p종사 p종사 : p종사
}; };
//console.log(newInfo); //console.log(newInfo);
if(p태수 || p군사 || p종사){ if(p태수 || p군사 || p종사){
if(typeof subCityGroupList[지역] == 'undefined'){ if(typeof subCityGroupList[지역] == 'undefined'){
subCityGroupList[지역] = []; subCityGroupList[지역] = [];
} }
subCityGroupList[지역].push(newInfo); subCityGroupList[지역].push(newInfo);
subCityList[cityInfo.val] = newInfo; subCityList[cityInfo.val] = newInfo;
} }
}); });
$.each(cityGroupOrder,function(idx,groupName){ $.each(cityGroupOrder,function(idx,groupName){
if(typeof subCityGroupList[groupName] == 'undefined'){ if(typeof subCityGroupList[groupName] == 'undefined'){
return true; return true;
} }
var subList = subCityGroupList[groupName]; var subList = subCityGroupList[groupName];
var $group = $('<tr><td colspan="4" style="color:skyblue;">【 '+groupName+' 】</td></tr>'); var $group = $('<tr><td colspan="4" style="color:skyblue;">【 '+groupName+' 】</td></tr>');
$innerContent.append($group); $innerContent.append($group);
subList.sort(function(a,b){ subList.sort(function(a,b){
var cmp규모 = city규모[a.규모] - city규모[b.규모]; var cmp규모 = city규모[a.규모] - city규모[b.규모];
if(cmp규모 != 0) return cmp규모; if(cmp규모 != 0) return cmp규모;
return a.이름.localeCompare(b.이름); return a.이름.localeCompare(b.이름);
}); });
var $optgroup = $('<optgroup label=" 【 '+groupName+' 】 " style="color:skyblue;"></optgroup>'); var $optgroup = $('<optgroup label=" 【 '+groupName+' 】 " style="color:skyblue;"></optgroup>');
$.each(subList,function(idx,newInfo){ $.each(subList,function(idx,newInfo){
$optgroup.append('<option value="'+newInfo.val+'" style="color:white;">'+newInfo.이름+'</option>'); $optgroup.append('<option value="'+newInfo.val+'" style="color:white;">'+newInfo.이름+'</option>');
var cityInfo = newInfo.city; var cityInfo = newInfo.city;
var $city = $('<tr><td>'+newInfo.이름+'</td></tr>'); var $city = $('<tr><td>'+newInfo.이름+'</td></tr>');
var $태수 = cityInfo.$태수.clone(); var $태수 = cityInfo.$태수.clone();
$city.append($태수); $city.append($태수);
if(!newInfo.p태수){ if(!newInfo.p태수){
$태수.css('color','red'); $태수.css('color','red');
} }
else{ else{
$태수.click(function(){ $태수.click(function(){
$('#duty_radio :radio:eq(0)').attr('checked','checked'); $('#duty_radio :radio:eq(0)').attr('checked','checked');
$('#duty_radio :radio').button('refresh'); $('#duty_radio :radio').button('refresh');
}).css('cursor','pointer'); }).css('cursor','pointer');
} }
var $군사 = cityInfo.$군사.clone(); var $군사 = cityInfo.$군사.clone();
$city.append($군사); $city.append($군사);
if(!newInfo.p군사)$군사.css('color','red'); if(!newInfo.p군사)$군사.css('color','red');
else{ else{
$군사.click(function(){ $군사.click(function(){
$('#duty_radio :radio:eq(1)').attr('checked','checked'); $('#duty_radio :radio:eq(1)').attr('checked','checked');
$('#duty_radio :radio').button('refresh'); $('#duty_radio :radio').button('refresh');
}).css('cursor','pointer'); }).css('cursor','pointer');
} }
var $종사 = cityInfo.$종사.clone(); var $종사 = cityInfo.$종사.clone();
$city.append($종사); $city.append($종사);
if(!newInfo.p종사)$종사.css('color','red'); if(!newInfo.p종사)$종사.css('color','red');
else{ else{
$종사.click(function(){ $종사.click(function(){
$('#duty_radio :radio:eq(2)').attr('checked','checked'); $('#duty_radio :radio:eq(2)').attr('checked','checked');
$('#duty_radio :radio').button('refresh'); $('#duty_radio :radio').button('refresh');
}).css('cursor','pointer'); }).css('cursor','pointer');
} }
$innerContent.append($city); $innerContent.append($city);
$city.click(function(){ $city.click(function(){
$('#city_select').val(newInfo.val).change(); $('#city_select').val(newInfo.val).change();
}); });
}); });
$('#city_select').append($optgroup); $('#city_select').append($optgroup);
}); });
tmpOldVal = $('#city_select').val(); tmpOldVal = $('#city_select').val();
$('#city_select').change(); $('#city_select').change();
$('#ext_win').dialog("open"); $('#ext_win').dialog("open");
}; };
var loadDuty = function(){ var loadDuty = function(){
try{ try{
$('.for_duty').remove(); $('.for_duty').remove();
$.get(basicPath+'b_myBossInfo.php',function(rawData){ $.get(basicPath+'b_myBossInfo.php',function(rawData){
$html = $(rawData); $html = $(rawData);
//window.$html = $html; //window.$html = $html;
var cnt =0; var cnt =0;
var $tmpTable = $html.filter('#officer_list').eq(0); var $tmpTable = $html.filter('#officer_list').eq(0);
$selects = $tmpTable.find("select"); $selects = $tmpTable.find("select");
if($selects.length == 0){ if($selects.length == 0){
alert("수뇌가 아닙니다!"); alert("수뇌가 아닙니다!");
return false; return false;
} }
var setUserAvailable = function($userList,typeName){ var setUserAvailable = function($userList,typeName){
$userList.each(function(idx){ $userList.each(function(idx){
var $this = $(this); var $this = $(this);
var val = $this.val(); var val = $this.val();
var name = $.trim($this.text()); var name = $.trim($this.text());
for(var i=name.length-1;i>0;i--){ for(var i=name.length-1;i>0;i--){
if(name[i]=='【'){ if(name[i]=='【'){
name = $.trim(name.substr(0,i)); name = $.trim(name.substr(0,i));
break; break;
} }
} }
if(val == '0'){ if(val == '0'){
return true; return true;
} }
if(typeof userList[name] != 'undefined'){ if(typeof userList[name] != 'undefined'){
userList[name].val = val; userList[name].val = val;
userList[name][typeName] = true; userList[name][typeName] = true;
} }
}); });
}; };
var setCityAvailiable = function($cityList,typeName){ var setCityAvailiable = function($cityList,typeName){
$cityList.each(function(idx){ $cityList.each(function(idx){
var $this = $(this); var $this = $(this);
var val = $.trim($this.val()); var val = $.trim($this.val());
var name = $.trim($this.text()); var name = $.trim($this.text());
cityList[name].val = val; cityList[name].val = val;
cityList[name][typeName] = true; cityList[name][typeName] = true;
}); });
} }
$.each(cityList,function(idx,cityInfo){ $.each(cityList,function(idx,cityInfo){
cityInfo.p태수=false; cityInfo.p태수=false;
cityInfo.p군사=false; cityInfo.p군사=false;
cityInfo.p종사=false; cityInfo.p종사=false;
}); });
$.each(userList,function(idx,userInfo){ $.each(userList,function(idx,userInfo){
userInfo.p태수=false; userInfo.p태수=false;
userInfo.p군사=false; userInfo.p군사=false;
userInfo.p종사=false; userInfo.p종사=false;
}); });
setUserAvailable($selects.eq(1).find("option"),"p태수"); setUserAvailable($selects.eq(1).find("option"),"p태수");
setUserAvailable($selects.eq(3).find("option"),"p군사"); setUserAvailable($selects.eq(3).find("option"),"p군사");
setUserAvailable($selects.eq(5).find("option"),"p종사"); setUserAvailable($selects.eq(5).find("option"),"p종사");
setCityAvailiable($selects.eq(0).find("option"),"p태수"); setCityAvailiable($selects.eq(0).find("option"),"p태수");
setCityAvailiable($selects.eq(2).find("option"),"p군사"); setCityAvailiable($selects.eq(2).find("option"),"p군사");
setCityAvailiable($selects.eq(4).find("option"),"p종사"); setCityAvailiable($selects.eq(4).find("option"),"p종사");
$.each(cityList,function(idx,cityInfo){ $.each(cityList,function(idx,cityInfo){
//console.log(cityInfo.users.children()); //console.log(cityInfo.users.children());
cityInfo.users.children().each(function(idx){ cityInfo.users.children().each(function(idx){
//console.log(this); //console.log(this);
var $this = $(this); var $this = $(this);
var username = $this.data('username'); var username = $this.data('username');
var userInfo = userList[username]; var userInfo = userList[username];
if(!userInfo){ if(!userInfo){
return true; return true;
} }
if(userInfo.val == '-1'){ if(userInfo.val == '-1'){
return true; return true;
} }
$name = $this.find('.nameplate'); $name = $this.find('.nameplate');
$name.append('<br class="for_duty">'); $name.append('<br class="for_duty">');
var addBtn=function($name,cityInfo,userInfo,type,text,warn){ var addBtn=function($name,cityInfo,userInfo,type,text,warn){
var enabled = cityInfo['p'+text]&&userInfo['p'+text]; var enabled = cityInfo['p'+text]&&userInfo['p'+text];
var cityVal = cityInfo.val; var cityVal = cityInfo.val;
var $btn = $('<button type="button">'+text.substr(0,1)+'</button>'); var $btn = $('<button type="button">'+text.substr(0,1)+'</button>');
$btn.addClass('mode_'+type); $btn.addClass('mode_'+type);
$btn.addClass('for_duty'); $btn.addClass('for_duty');
if(!enabled){ if(!enabled){
$btn.prop('disabled',true); $btn.prop('disabled',true);
$btn.css('background','transparent'); $btn.css('background','transparent');
$btn.css('border','0'); $btn.css('border','0');
} }
else{ else{
if(userInfo.is수뇌){ if(userInfo.is수뇌){
$btn.css('color','red'); $btn.css('color','red');
} }
} }
$btn.css('padding','1px 4px'); $btn.css('padding','1px 4px');
$btn.css('margin','0'); $btn.css('margin','0');
$btn.click(function(){ $btn.click(function(){
if(userInfo.is수뇌){ if(userInfo.is수뇌){
if(!confirm('수뇌입니다. 임명할까요?')){ if(!confirm('수뇌입니다. 임명할까요?')){
return false; return false;
} }
} }
$.post(basicPath+'j_myBossInfo.php',{ $.post(basicPath+'j_myBossInfo.php',{
destCityID:cityVal, destCityID:cityVal,
destGeneralID:userInfo.val, destGeneralID:userInfo.val,
officerLevel:type, officerLevel:type,
action:'임명' action:'임명'
},function(rawData){ },function(rawData){
cityInfo['p'+text]=false; cityInfo['p'+text]=false;
var $target = cityInfo.users.find('.mode_'+type); var $target = cityInfo.users.find('.mode_'+type);
$target.prop('disabled',true); $target.prop('disabled',true);
$target.css('background','transparent'); $target.css('background','transparent');
$target.css('border','0'); $target.css('border','0');
$target.css('color',''); $target.css('color','');
cityInfo['$'+text].html(userInfo.name); cityInfo['$'+text].html(userInfo.name);
}); });
}); });
//console.log($btn); //console.log($btn);
$name.append($btn); $name.append($btn);
}; };
addBtn($name,cityInfo,userInfo,4,'태수'); addBtn($name,cityInfo,userInfo,4,'태수');
addBtn($name,cityInfo,userInfo,3,'군사'); addBtn($name,cityInfo,userInfo,3,'군사');
addBtn($name,cityInfo,userInfo,2,'종사'); addBtn($name,cityInfo,userInfo,2,'종사');
//특수 버튼! //특수 버튼!
if(userInfo.p태수||userInfo.p군사||userInfo.p종사){ if(userInfo.p태수||userInfo.p군사||userInfo.p종사){
var $btn = $('<button type="button">...</button>'); var $btn = $('<button type="button">...</button>');
$btn.addClass('for_duty'); $btn.addClass('for_duty');
if(userInfo.is수뇌){ if(userInfo.is수뇌){
$btn.css('color','red'); $btn.css('color','red');
} }
$btn.css('padding','1px 4px'); $btn.css('padding','1px 4px');
$btn.css('margin','0'); $btn.css('margin','0');
$btn.click(function(){ $btn.click(function(){
if(userInfo.is수뇌){ if(userInfo.is수뇌){
if(!confirm('수뇌입니다. 임명할까요?')){ if(!confirm('수뇌입니다. 임명할까요?')){
return false; return false;
} }
} }
extDutyWindow(userInfo); extDutyWindow(userInfo);
}); });
$btn.css('border','solid 1px Chocolate').css('background-color','#400000').css('margin-left','4px'); $btn.css('border','solid 1px Chocolate').css('background-color','#400000').css('margin-left','4px');
$btn.css('line-hight','20px').css('color','GhostWhite').css('padding','2px 2px').css('height','18px').css('line-height','8px'); $btn.css('line-hight','20px').css('color','GhostWhite').css('padding','2px 2px').css('height','18px').css('line-height','8px');
//$name.append($btn); //$name.append($btn);
} }
}); });
}); });
}); });
} }
catch(a){ catch(a){
console.log(a); console.log(a);
} }
return false; return false;
}; };
var loadUser = function(){ var loadUser = function(){
$.each(cityList,function(idx,val){ $.each(cityList,function(idx,val){
if(typeof val.users == "undefined"){ if(typeof val.users == "undefined"){
val.obj.append('<tr><td colspan="12"><table align="center" class="tb_layout cityUser bg0">'+ val.obj.append('<tr><td colspan="12"><table align="center" class="tb_layout cityUser bg0">'+
'<thead><tr>'+ '<thead><tr>'+
'<td width="100" align="center" class="bg1">이 름</td><td width="100" align="center" class="bg1">통무지</td><td width="100" align="center" class="bg1">부 대</td><td width="60" align="center" class="bg1">자 금</td>'+ '<td width="100" align="center" class="bg1">이 름</td><td width="100" align="center" class="bg1">통무지</td><td width="100" align="center" class="bg1">부 대</td><td width="60" align="center" class="bg1">자 금</td>'+
'<td width="60" align="center" class="bg1">군 량</td><td width="30" align="center" class="bg1">守</td><td width="60" align="center" class="bg1">병 종</td>'+ '<td width="60" align="center" class="bg1">군 량</td><td width="30" align="center" class="bg1">守</td><td width="60" align="center" class="bg1">병 종</td>'+
'<td width="60" align="center" class="bg1">병 사</td><td width="50" align="center" class="bg1">훈련</td><td width="50" align="center" class="bg1">사기</td><td width="150" align="center" class="bg1">명 령</td>'+ '<td width="60" align="center" class="bg1">병 사</td><td width="50" align="center" class="bg1">훈련</td><td width="50" align="center" class="bg1">사기</td><td width="150" align="center" class="bg1">명 령</td>'+
'<td width="60" align="center" class="bg1">삭턴</td><td width="60" align="center" class="bg1">턴</td>'+ '<td width="60" align="center" class="bg1">삭턴</td><td width="60" align="center" class="bg1">턴</td>'+
'</tr></thead>'+ '</tr></thead>'+
'<tbody class="cityUserBody"></tbody></table></td></tr>'); '<tbody class="cityUserBody"></tbody></table></td></tr>');
val.users = val.obj.find(".cityUserBody"); val.users = val.obj.find(".cityUserBody");
} }
else{ else{
val.users.html(""); val.users.html("");
} }
}); });
$.get(basicPath+'b_genList.php',function(rawData){ $.get(basicPath+'b_genList.php',function(rawData){
var cnt =0; var cnt =0;
var $helper = $('#helper_genlist'); var $helper = $('#helper_genlist');
$helper.html('').append($.parseHTML(rawData)); $helper.html('').append($.parseHTML(rawData));
var tmpUsers = $('#general_list tbody tr'); var tmpUsers = $('#general_list tbody tr');
tmpUsers.each(function(idx){ tmpUsers.each(function(idx){
var $this = $(this); var $this = $(this);
var $city = $this.children('.i_city'); var $city = $this.children('.i_city');
$city.remove(); $city.remove();
var cityName = $.trim($city.text()); var cityName = $.trim($city.text());
var $name = $this.children('.i_name'); var $name = $this.children('.i_name');
$name.addClass('nameplate'); $name.addClass('nameplate');
var name = $name.find('.t_name').text(); var name = $name.find('.t_name').text();
var $work = $this.children('.i_action'); var $work = $this.children('.i_action');
var cityInfo = cityList[cityName]; var cityInfo = cityList[cityName];
if(typeof cityInfo == 'undefined'){ if(typeof cityInfo == 'undefined'){
return true; return true;
} }
if(cityInfo.warn주민)$work.html($work.html().split('정착 장려').join('<span style="color:yellow;">정착 장려</span>')); if(cityInfo.warn주민)$work.html($work.html().split('정착 장려').join('<span style="color:yellow;">정착 장려</span>'));
if(cityInfo.warn농업)$work.html($work.html().split('농지 개간').join('<span style="color:yellow;">농지 개간</span>')); if(cityInfo.warn농업)$work.html($work.html().split('농지 개간').join('<span style="color:yellow;">농지 개간</span>'));
if(cityInfo.warn상업)$work.html($work.html().split('상업 투자').join('<span style="color:yellow;">상업 투자</span>')); if(cityInfo.warn상업)$work.html($work.html().split('상업 투자').join('<span style="color:yellow;">상업 투자</span>'));
if(cityInfo.warn치안)$work.html($work.html().split('치안 강화').join('<span style="color:yellow;">치안 강화</span>')); if(cityInfo.warn치안)$work.html($work.html().split('치안 강화').join('<span style="color:yellow;">치안 강화</span>'));
if(cityInfo.warn수비)$work.html($work.html().split('수비 강화').join('<span style="color:yellow;">수비 강화</span>')); if(cityInfo.warn수비)$work.html($work.html().split('수비 강화').join('<span style="color:yellow;">수비 강화</span>'));
if(cityInfo.warn성벽)$work.html($work.html().split('성벽 보수').join('<span style="color:yellow;">성벽 보수</span>')); if(cityInfo.warn성벽)$work.html($work.html().split('성벽 보수').join('<span style="color:yellow;">성벽 보수</span>'));
var $stat = $this.children('.i_stat'); var $stat = $this.children('.i_stat');
var stat = $stat.text(); var stat = $stat.text();
var is수뇌 = stat.indexOf('+')>=0; var is수뇌 = stat.indexOf('+')>=0;
$this.data('username',name); $this.data('username',name);
if(cityList[cityName].$태수.text() == name){ if(cityList[cityName].$태수.text() == name){
cityList[cityName].$태수.css('color','lightgreen'); cityList[cityName].$태수.html('<span style="color:lightgreen">{0}</span>'.format(name));
} }
if(cityList[cityName].$군사.text() == name){ if(cityList[cityName].$군사.text() == name){
cityList[cityName].$군사.css('color','lightgreen'); cityList[cityName].$군사.html('<span style="color:lightgreen">{0}</span>'.format(name));
} }
if(cityList[cityName].$종사.text() == name){ if(cityList[cityName].$종사.text() == name){
cityList[cityName].$종사.css('color','lightgreen'); cityList[cityName].$종사.html('<span style="color:lightgreen">{0}</span>'.format(name));
} }
userList[name]={ userList[name]={
$city:cityInfo, $city:cityInfo,
city:cityName, city:cityName,
$user:$this, $user:$this,
name:name, name:name,
val:'-1', val:'-1',
p태수:false, p태수:false,
p군사:false, p군사:false,
p종사:false, p종사:false,
is수뇌:is수뇌 is수뇌:is수뇌
}; };
if(cityList[cityName]){ if(cityList[cityName]){
cityList[cityName].users.append($this); cityList[cityName].users.append($this);
} }
}); });
}); });
if($("#loadDutyBtn").length == 0){ if($("#loadDutyBtn").length == 0){
var $onBossList = $('<button id="loadDutyBtn">인사부 연동</button>'); var $onBossList = $('<button id="loadDutyBtn">인사부 연동</button>');
$onBossList.click(function(){ $onBossList.click(function(){
loadDuty(); loadDuty();
return false; return false;
}); });
$('form').append($onBossList); $('form').append($onBossList);
} }
$('#by_users').show(); $('#by_users').show();
}; };
var mainFunc = function(){ var mainFunc = function(){
//대상 추출 //대상 추출
window.cityList = {}; window.cityList = {};
window.userList = {}; window.userList = {};
$("form").each(function(){ $("form").each(function(){
var $this = $(this); var $this = $(this);
$this.attr('name','p'+$this.attr('name')); $this.attr('name','p'+$this.attr('name'));
}); });
$("table").each(function(idx,val){ $("table").each(function(idx,val){
$this = $(this); $this = $(this);
if($this.attr('class')=='tb_layout bg2'){ if($this.attr('class')=='tb_layout bg2'){
$this.addClass('cityInfo'); $this.addClass('cityInfo');
} }
else{ else{
return true; return true;
} }
window.$tmpTable = $this; window.$tmpTable = $this;
var cityInfo = {}; var cityInfo = {};
//이름 추출 //이름 추출
{ {
var titleText = $this.find('tr:eq(0)>td:eq(0)').text(); var titleText = $this.find('tr:eq(0)>td:eq(0)').text();
var loc0 = titleText.indexOf("【"); var loc0 = titleText.indexOf("【");
var loc1 = titleText.indexOf("|"); var loc1 = titleText.indexOf("|");
var loc2 = titleText.indexOf("】"); var loc2 = titleText.indexOf("】");
var cityLoc = $.trim(titleText.substring(loc0+1,loc1)); var cityLoc = $.trim(titleText.substring(loc0+1,loc1));
var citySize = $.trim(titleText.substring(loc1+1,loc2)); var citySize = $.trim(titleText.substring(loc1+1,loc2));
var cityName = $.trim(titleText.substring(loc2+1)); var cityName = $.trim(titleText.substring(loc2+1));
cityName = cityName.replace("[",""); cityName = cityName.replace("[","");
cityName = cityName.replace("]",""); cityName = cityName.replace("]","");
$this.data('cityname',cityName); $this.data('cityname',cityName);
cityInfo.지역 = cityLoc; cityInfo.지역 = cityLoc;
cityInfo.규모 = citySize; cityInfo.규모 = citySize;
cityInfo.이름 = cityName; cityInfo.이름 = cityName;
cityInfo.val = '-1'; cityInfo.val = '-1';
cityInfo.p태수 = false; cityInfo.p태수 = false;
cityInfo.p군사 = false; cityInfo.p군사 = false;
cityInfo.p종사 = false; cityInfo.p종사 = false;
} }
//주민, 농상치성수 //주민, 농상치성수
{ {
var $baseTr = $this.find('tr:eq(1)'); var $baseTr = $this.find('tr:eq(1)');
cityInfo.$주민 = $baseTr.find('td:eq(1)'); cityInfo.$주민 = $baseTr.find('td:eq(1)');
cityInfo.$농업 = $baseTr.find('td:eq(3)'); cityInfo.$농업 = $baseTr.find('td:eq(3)');
cityInfo.$상업 = $baseTr.find('td:eq(5)'); cityInfo.$상업 = $baseTr.find('td:eq(5)');
cityInfo.$치안 = $baseTr.find('td:eq(7)'); cityInfo.$치안 = $baseTr.find('td:eq(7)');
cityInfo.$수비 = $baseTr.find('td:eq(9)'); cityInfo.$수비 = $baseTr.find('td:eq(9)');
cityInfo.$성벽 = $baseTr.find('td:eq(11)'); cityInfo.$성벽 = $baseTr.find('td:eq(11)');
var tmpVal; var tmpVal;
tmpVal = cityInfo.$주민.text().split('/'); tmpVal = cityInfo.$주민.text().split('/');
cityInfo.주민 = parseInt(tmpVal[0]); cityInfo.주민 = parseInt(tmpVal[0]);
cityInfo.max주민 = parseInt(tmpVal[1]); cityInfo.max주민 = parseInt(tmpVal[1]);
tmpVal = cityInfo.$농업.text().split('/'); tmpVal = cityInfo.$농업.text().split('/');
cityInfo.농업 = parseInt(tmpVal[0]); cityInfo.농업 = parseInt(tmpVal[0]);
cityInfo.max농업 = parseInt(tmpVal[1]); cityInfo.max농업 = parseInt(tmpVal[1]);
tmpVal = cityInfo.$상업.text().split('/'); tmpVal = cityInfo.$상업.text().split('/');
cityInfo.상업 = parseInt(tmpVal[0]); cityInfo.상업 = parseInt(tmpVal[0]);
cityInfo.max상업 = parseInt(tmpVal[1]); cityInfo.max상업 = parseInt(tmpVal[1]);
tmpVal = cityInfo.$치안.text().split('/'); tmpVal = cityInfo.$치안.text().split('/');
cityInfo.치안 = parseInt(tmpVal[0]); cityInfo.치안 = parseInt(tmpVal[0]);
cityInfo.max치안 = parseInt(tmpVal[1]); cityInfo.max치안 = parseInt(tmpVal[1]);
tmpVal = cityInfo.$수비.text().split('/'); tmpVal = cityInfo.$수비.text().split('/');
cityInfo.수비 = parseInt(tmpVal[0]); cityInfo.수비 = parseInt(tmpVal[0]);
cityInfo.max수비 = parseInt(tmpVal[1]); cityInfo.max수비 = parseInt(tmpVal[1]);
tmpVal = cityInfo.$성벽.text().split('/'); tmpVal = cityInfo.$성벽.text().split('/');
cityInfo.성벽 = parseInt(tmpVal[0]); cityInfo.성벽 = parseInt(tmpVal[0]);
cityInfo.max성벽 = parseInt(tmpVal[1]); cityInfo.max성벽 = parseInt(tmpVal[1]);
if (cityInfo.주민>cityInfo.max주민*0.9){ cityInfo.$주민.css('color','lightgreen');} if (cityInfo.주민>cityInfo.max주민*0.9){ cityInfo.$주민.css('color','lightgreen');}
else if (cityInfo.주민>cityInfo.max주민*0.7){ cityInfo.$주민.css('color','yellow');} else if (cityInfo.주민>cityInfo.max주민*0.7){ cityInfo.$주민.css('color','yellow');}
else { cityInfo.$주민.css('color','orangered');} else { cityInfo.$주민.css('color','orangered');}
if (cityInfo.농업>cityInfo.max농업*0.8){ cityInfo.$농업.css('color','lightgreen');} if (cityInfo.농업>cityInfo.max농업*0.8){ cityInfo.$농업.css('color','lightgreen');}
else if (cityInfo.농업>cityInfo.max농업*0.4){ cityInfo.$농업.css('color','yellow');} else if (cityInfo.농업>cityInfo.max농업*0.4){ cityInfo.$농업.css('color','yellow');}
else { cityInfo.$농업.css('color','orangered');} else { cityInfo.$농업.css('color','orangered');}
if (cityInfo.상업>cityInfo.max상업*0.8){ cityInfo.$상업.css('color','lightgreen');} if (cityInfo.상업>cityInfo.max상업*0.8){ cityInfo.$상업.css('color','lightgreen');}
else if (cityInfo.상업>cityInfo.max상업*0.4){ cityInfo.$상업.css('color','yellow');} else if (cityInfo.상업>cityInfo.max상업*0.4){ cityInfo.$상업.css('color','yellow');}
else { cityInfo.$상업.css('color','orangered');} else { cityInfo.$상업.css('color','orangered');}
if (cityInfo.치안>cityInfo.max치안*0.8){ cityInfo.$치안.css('color','lightgreen');} if (cityInfo.치안>cityInfo.max치안*0.8){ cityInfo.$치안.css('color','lightgreen');}
else if (cityInfo.치안>cityInfo.max치안*0.4){ cityInfo.$치안.css('color','yellow');} else if (cityInfo.치안>cityInfo.max치안*0.4){ cityInfo.$치안.css('color','yellow');}
else { cityInfo.$치안.css('color','orangered');} else { cityInfo.$치안.css('color','orangered');}
if (cityInfo.수비>cityInfo.max수비*0.6){ cityInfo.$수비.css('color','lightgreen');} if (cityInfo.수비>cityInfo.max수비*0.6){ cityInfo.$수비.css('color','lightgreen');}
else if (cityInfo.수비>cityInfo.max수비*0.3){ cityInfo.$수비.css('color','yellow');} else if (cityInfo.수비>cityInfo.max수비*0.3){ cityInfo.$수비.css('color','yellow');}
else { cityInfo.$수비.css('color','orangered');} else { cityInfo.$수비.css('color','orangered');}
if (cityInfo.성벽>cityInfo.max성벽*0.6){ cityInfo.$성벽.css('color','lightgreen');} if (cityInfo.성벽>cityInfo.max성벽*0.6){ cityInfo.$성벽.css('color','lightgreen');}
else if (cityInfo.성벽>cityInfo.max성벽*0.3){ cityInfo.$성벽.css('color','yellow');} else if (cityInfo.성벽>cityInfo.max성벽*0.3){ cityInfo.$성벽.css('color','yellow');}
else { cityInfo.$성벽.css('color','orangered');} else { cityInfo.$성벽.css('color','orangered');}
cityInfo.remain주민 = cityInfo.주민-cityInfo.max주민; cityInfo.remain주민 = cityInfo.주민-cityInfo.max주민;
cityInfo.remain농업 = cityInfo.농업-cityInfo.max농업; cityInfo.remain농업 = cityInfo.농업-cityInfo.max농업;
cityInfo.remain상업 = cityInfo.상업-cityInfo.max상업; cityInfo.remain상업 = cityInfo.상업-cityInfo.max상업;
cityInfo.remain치안 = cityInfo.치안-cityInfo.max치안; cityInfo.remain치안 = cityInfo.치안-cityInfo.max치안;
cityInfo.remain수비 = cityInfo.수비-cityInfo.max수비; cityInfo.remain수비 = cityInfo.수비-cityInfo.max수비;
cityInfo.remain성벽 = cityInfo.성벽-cityInfo.max성벽; cityInfo.remain성벽 = cityInfo.성벽-cityInfo.max성벽;
cityInfo.warn주민 = false; cityInfo.warn주민 = false;
cityInfo.warn농업 = false; cityInfo.warn농업 = false;
cityInfo.warn상업 = false; cityInfo.warn상업 = false;
cityInfo.warn치안 = false; cityInfo.warn치안 = false;
cityInfo.warn수비 = false; cityInfo.warn수비 = false;
cityInfo.warn성벽 = false; cityInfo.warn성벽 = false;
if(cityInfo.remain주민 > -10*2000) cityInfo.warn주민 = true; if(cityInfo.remain주민 > -10*2000) cityInfo.warn주민 = true;
if(cityInfo.주민 > 0.92*cityInfo.max주민) cityInfo.warn주민 = true; if(cityInfo.주민 > 0.92*cityInfo.max주민) cityInfo.warn주민 = true;
if(cityInfo.remain농업 > -10*100) cityInfo.warn농업 = true; if(cityInfo.remain농업 > -10*100) cityInfo.warn농업 = true;
if(cityInfo.remain상업 > -10*100) cityInfo.warn상업 = true; if(cityInfo.remain상업 > -10*100) cityInfo.warn상업 = true;
if(cityInfo.remain치안 > -10*100) cityInfo.warn치안 = true; if(cityInfo.remain치안 > -10*100) cityInfo.warn치안 = true;
if(cityInfo.remain수비 > -10*70) cityInfo.warn수비 = true; if(cityInfo.remain수비 > -10*70) cityInfo.warn수비 = true;
if(cityInfo.remain성벽 > -10*70) cityInfo.warn성벽 = true; if(cityInfo.remain성벽 > -10*70) cityInfo.warn성벽 = true;
if(cityInfo.warn농업) cityInfo.$농업.append('<span class="remain" style="color:yellow;">['+cityInfo.remain농업+']</span>'); if(cityInfo.warn농업) cityInfo.$농업.append('<span class="remain" style="color:yellow;">['+cityInfo.remain농업+']</span>');
if(cityInfo.warn상업) cityInfo.$상업.append('<span class="remain" style="color:yellow;">['+cityInfo.remain상업+']</span>'); if(cityInfo.warn상업) cityInfo.$상업.append('<span class="remain" style="color:yellow;">['+cityInfo.remain상업+']</span>');
if(cityInfo.warn치안) cityInfo.$치안.append('<span class="remain" style="color:yellow;">['+cityInfo.remain치안+']</span>'); if(cityInfo.warn치안) cityInfo.$치안.append('<span class="remain" style="color:yellow;">['+cityInfo.remain치안+']</span>');
if(cityInfo.warn수비) cityInfo.$수비.append('<span class="remain" style="color:yellow;">['+cityInfo.remain수비+']</span>'); if(cityInfo.warn수비) cityInfo.$수비.append('<span class="remain" style="color:yellow;">['+cityInfo.remain수비+']</span>');
if(cityInfo.warn성벽) cityInfo.$성벽.append('<span class="remain" style="color:yellow;">['+cityInfo.remain성벽+']</span>'); if(cityInfo.warn성벽) cityInfo.$성벽.append('<span class="remain" style="color:yellow;">['+cityInfo.remain성벽+']</span>');
} }
//태수,군사,종사 //태수,군사,종사
{ {
var $baseTr = $this.find('tr:eq(2)'); var $baseTr = $this.find('tr:eq(2)');
cityInfo.$태수 = $baseTr.find('td:eq(7)'); cityInfo.$태수 = $baseTr.find('td:eq(7)');
cityInfo.$군사 = $baseTr.find('td:eq(9)'); cityInfo.$군사 = $baseTr.find('td:eq(9)');
cityInfo.$종사 = $baseTr.find('td:eq(11)'); cityInfo.$종사 = $baseTr.find('td:eq(11)');
} }
//기타 //기타
{ {
cityInfo.userCnt = $this.find('tr:eq(3) td:eq(1)').text().split(',').length -1; cityInfo.userCnt = $this.find('tr:eq(3) td:eq(1)').text().split(',').length -1;
} }
cityInfo.obj = $this; cityInfo.obj = $this;
cityList[cityInfo.이름] = cityInfo; cityList[cityInfo.이름] = cityInfo;
}); });
var $onGenList = $('<button type="button">암행부 연동</button>'); var $onGenList = $('<button type="button">암행부 연동</button>');
$onGenList.click(function(){ $onGenList.click(function(){
loadUser(); loadUser();
return false; return false;
}); });
$('form').append($onGenList); $('form').append($onGenList);
$('table:eq(0) tr:last').after('<tr><td id="sort_more"></td></tr>'); $('table:eq(0) tr:last').after('<tr><td id="sort_more"></td></tr>');
$sort_more = $('#sort_more'); $sort_more = $('#sort_more');
$sort_more.html('재 정렬 순서 :'); $sort_more.html('재 정렬 순서 :');
var sortIt = function(callback){ var sortIt = function(callback){
var arCity = []; var arCity = [];
$('.cityInfo').each(function(){ $('.cityInfo').each(function(){
var $this = $(this); var $this = $(this);
var cityName = $this.data('cityname'); var cityName = $this.data('cityname');
var cityInfo = cityList[cityName]; var cityInfo = cityList[cityName];
arCity.push(cityInfo); arCity.push(cityInfo);
}); });
arCity = mergeSort(arCity,callback); arCity = mergeSort(arCity,callback);
//console.log(arCity); //console.log(arCity);
var $anchor = $('.anchor'); var $anchor = $('.anchor');
//console.log($anchor); //console.log($anchor);
$('body > br').remove(); $('body > br').remove();
$('.cityInfo').detach(); $('.cityInfo').detach();
$.each(arCity,function(idx,val){ $.each(arCity,function(idx,val){
$anchor.before('<br>'); $anchor.before('<br>');
$anchor.before(val.obj); $anchor.before(val.obj);
}); });
$anchor.before('<br>'); $anchor.before('<br>');
}; };
var $btn; var $btn;
$btn = $('<button type="button">도시명</button>').click(function(){ $btn = $('<button type="button">도시명</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return a.이름.localeCompare(b.이름); return a.이름.localeCompare(b.이름);
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">인구율</button>').click(function(){ $btn = $('<button type="button">인구율</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return 1.0*a.주민/a.max주민 - 1.0*b.주민/b.max주민; return 1.0*a.주민/a.max주민 - 1.0*b.주민/b.max주민;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">남은 주민</button>').click(function(){ $btn = $('<button type="button">남은 주민</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return a.remain주민 - b.remain주민; return a.remain주민 - b.remain주민;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">남은 농업</button>').click(function(){ $btn = $('<button type="button">남은 농업</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return a.remain농업 - b.remain농업; return a.remain농업 - b.remain농업;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">남은 상업</button>').click(function(){ $btn = $('<button type="button">남은 상업</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return a.remain상업 - b.remain상업; return a.remain상업 - b.remain상업;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">남은 치안</button>').click(function(){ $btn = $('<button type="button">남은 치안</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return a.remain치안 - b.remain치안; return a.remain치안 - b.remain치안;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">남은 수비</button>').click(function(){ $btn = $('<button type="button">남은 수비</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return a.remain수비 - b.remain수비; return a.remain수비 - b.remain수비;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">남은 성벽</button>').click(function(){ $btn = $('<button type="button">남은 성벽</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return a.remain성벽 - b.remain성벽; return a.remain성벽 - b.remain성벽;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
$btn = $('<button type="button">배치 장수 수</button>').click(function(){ $btn = $('<button type="button">배치 장수 수</button>').click(function(){
sortIt(function(a,b){ sortIt(function(a,b){
return b.userCnt - a.userCnt; return b.userCnt - a.userCnt;
}); });
}); });
$sort_more.append($btn); $sort_more.append($btn);
}; };
mainFunc(); mainFunc();
}); });
+685 -653
View File
@@ -1,654 +1,686 @@
function is_touch_device() {
function is_touch_device() { var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' '); var mq = function(query) {
var mq = function(query) { return window.matchMedia(query).matches;
return window.matchMedia(query).matches; }
}
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) { return true;
return true; }
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// include the 'heartz' as a way to have a non matching MQ to help terminate the join // https://git.io/vznFH
// https://git.io/vznFH var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''); return mq(query);
return mq(query); }
}
function reloadWorldMap(option, drawTarget) {
function reloadWorldMap(option){ if (drawTarget === undefined || drawTarget === null) {
var $world_map = $('.world_map'); drawTarget = '.world_map'
}
if($world_map.length == 0){ var $world_map = $(drawTarget);
return;
} if ($world_map.length == 0) {
return;
var defaultOption = { }
isDetailMap:true, //복잡 지도, 단순 지도
clickableAll:false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도. var defaultOption = {
selectCallback:null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행. isDetailMap: true, //복잡 지도, 단순 지도
hrefTemplate:'#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨 clickableAll: false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
useCachedMap:false, //맵 캐시를 사용 selectCallback: null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
hrefTemplate: '#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨
//아래부터는 post query에 들어갈 녀석 useCachedMap: false, //맵 캐시를 사용
year:null, //year값, 연감등에 사용
month:null, //month값, 연감등에 사용 //아래부터는 post query에 들어갈 녀석
aux:null, //기타 넣고 싶은 값을 입력 year: null, //year값, 연감등에 사용
neutralView:false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정 month: null, //month값, 연감등에 사용
showMe:true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개 aux: null, //기타 넣고 싶은 값을 입력
targetJson:'j_map.php', neutralView: false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정
showMe: true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개
//기타 보조 값
startYear:null, targetJson: 'j_map.php',
}; reqType: 'post',
dynamicMapTheme: false,
option = $.extend(defaultOption, option); callback: null,
var useCachedMap = option.useCachedMap; //기타 보조 값
var isDetailMap = option.isDetailMap; startYear: null,
var clickableAll = option.clickableAll; };
var selectCallback = option.selectCallback;
var hrefTemplate = option.hrefTemplate; option = $.extend(defaultOption, option);
var cityPosition = getCityPosition(); var useCachedMap = option.useCachedMap;
var isDetailMap = option.isDetailMap;
var storedOldMapKey = 'sam.{0}.map'.format(serverNick); var clickableAll = option.clickableAll;
var storedStartYear = 'sam.{0}.startYear'.format(serverNick); var selectCallback = option.selectCallback;
//OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity var hrefTemplate = option.hrefTemplate;
function checkReturnObject(obj){ var cityPosition = getCityPosition();
if(!obj.result){
var obj = $.Deferred(); var storedOldMapKey = 'sam.{0}.map'.format(serverNick);
obj.reject('fail'); var storedStartYear = 'sam.{0}.startYear'.format(serverNick);
return obj.promise(); //OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity
}
function checkReturnObject(obj) {
if(!$.isNumeric(obj.startYear) if (!obj.result) {
||!$.isNumeric(obj.year) var obj = $.Deferred();
||!$.isNumeric(obj.month) obj.reject('fail');
){ return obj.promise();
var obj = $.Deferred(); }
obj.reject('fail');
return obj.promise(); if (!$.isNumeric(obj.startYear) ||
} !$.isNumeric(obj.year) ||
!$.isNumeric(obj.month)
if(useCachedMap){ ) {
localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj])); var obj = $.Deferred();
localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear)); obj.reject('fail');
} return obj.promise();
}
$world_map.removeClass('draw_required');
if (useCachedMap) {
return obj; localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj]));
} localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear));
}
function setMapBackground(obj){
var startYear = obj.startYear; $world_map.removeClass('draw_required');
var year = obj.year;
var month = obj.month; return obj;
}
if(isDetailMap){
$world_map.addClass('map_detail').removeClass('map_basic');
}
else{ function setMapBackground(obj) {
$world_map.addClass('map_basic').removeClass('map_detail'); function setTheme() {
} var oldTheme = $world_map.data('currentTheme');
var newTheme = obj.theme;
var $map_title = $('.map_title_text'); if (oldTheme === newTheme) {
if(year < startYear + 1){ return;
$map_title.css('color', 'magenta'); }
} if (oldTheme) {
else if(year < startYear + 2){ $world_map.removeClass('map_theme_' + oldTheme);
$map_title.css('color', 'orange'); }
} $world_map.addClass('map_theme_' + newTheme);
else if(year < startYear + 3){ $world_map.data('currentTheme', newTheme);
$map_title.css('color', 'yellow'); }
} if (option.dynamicMapTheme) {
setTheme();
$map_title_tooltip = $('.map_title .tooltiptext'); }
$map_title_tooltip.empty(); var startYear = obj.startYear;
var year = obj.year;
var tooltipTexts = []; var month = obj.month;
if(year < startYear + 3){
var startYearText = []; if (isDetailMap) {
var remainYear = startYear + 3 - year; $world_map.addClass('map_detail').removeClass('map_basic');
var remainMonth = 12 - month + 1; } else {
if(remainMonth > 0){ $world_map.addClass('map_basic').removeClass('map_detail');
remainYear -= 1; }
}
if(remainYear){ var $map_title = $('.map_title_text');
startYearText.push('{0}년'.format(remainYear)); if (year < startYear + 1) {
} $map_title.css('color', 'magenta');
if(remainMonth){ } else if (year < startYear + 2) {
startYearText.push('{0}개월'.format(remainMonth)); $map_title.css('color', 'orange');
} } else if (year < startYear + 3) {
$map_title.css('color', 'yellow');
tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3)); }
}
$map_title_tooltip = $('.map_title .tooltiptext');
var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1; $map_title_tooltip.empty();
var nextTechLimitYear = currentTechLimit * 5 + startYear;
var tooltipTexts = [];
tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit+1)); if (year < startYear + 3) {
$map_title_tooltip.html(tooltipTexts.join('<br>')); var startYearText = [];
var remainYear = startYear + 3 - year;
$world_map.removeClass('map_string map_summer map_fall map_winter'); var remainMonth = 12 - month + 1;
if(month <= 3){ if (remainMonth > 0) {
$world_map.addClass('map_spring'); remainYear -= 1;
} }
else if(month <= 6){ if (remainYear) {
$world_map.addClass('map_summer'); startYearText.push('{0}년'.format(remainYear));
} }
else if(month <= 9){ if (remainMonth) {
$world_map.addClass('map_fall'); startYearText.push('{0}개월'.format(remainMonth));
} }
else{
$world_map.addClass('map_winter'); tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3));
} }
$map_title.html('{0}年 {1}月'.format(year, month)); var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1;
var nextTechLimitYear = currentTechLimit * 5 + startYear;
return obj;
} tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit + 1));
$map_title_tooltip.html(tooltipTexts.join('<br>'));
function convertCityObjs(obj){
//원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다. $world_map.removeClass('map_string map_summer map_fall map_winter');
if (month <= 3) {
function toCityObj(arr){ $world_map.addClass('map_spring');
return { } else if (month <= 6) {
id:arr[0], $world_map.addClass('map_summer');
level:arr[1], } else if (month <= 9) {
state:arr[2], $world_map.addClass('map_fall');
nationId:(arr[3]>0)?arr[3]:null, } else {
region:arr[4], $world_map.addClass('map_winter');
supply:(arr[5]!=0) }
};
} $map_title.html('{0}年 {1}月'.format(year, month));
function toNationObj(arr){ return obj;
return { }
id:arr[0],
name:arr[1], function convertCityObjs(obj) {
color:arr[2], //원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다.
capital:arr[3]
}; function toCityObj(arr) {
} return {
id: arr[0],
var cityList = obj.cityList.map(toCityObj); level: arr[1],
var nationList = obj.nationList.map(toNationObj); state: arr[2],
nationList = convertDictById(nationList); //array of object -> dict nationId: (arr[3] > 0) ? arr[3] : null,
region: arr[4],
var spyList = obj.spyList; supply: (arr[5] != 0)
var shownByGeneralList = convertSet(obj.shownByGeneralList);//Array -> Set };
}
var myCity = obj.myCity;
var myNation = obj.myNation; function toNationObj(arr) {
return {
id: arr[0],
function mergePositionInfo(city){ name: arr[1],
var id = city.id; color: arr[2],
if(!(id in cityPosition)){ capital: arr[3]
return city; };
} }
var xy_val = cityPosition[id];
city.name = xy_val[0]; var cityList = obj.cityList.map(toCityObj);
city.x = xy_val[1]; var nationList = obj.nationList.map(toNationObj);
city.y = xy_val[2]; nationList = convertDictById(nationList); //array of object -> dict
return city;
} var spyList = obj.spyList;
var shownByGeneralList = convertSet(obj.shownByGeneralList); //Array -> Set
function mergeNationInfo(city){
//nationId 값으로 isCapital, color, nation을 통합 var myCity = obj.myCity;
var myNation = obj.myNation;
var nationId = city.nationId;
if(nationId === null || !(nationId in nationList)){
city.nationId = null; function mergePositionInfo(city) {
city.nation = null; var id = city.id;
city.color = null; if (!(id in cityPosition)) {
city.isCapital = false; return city;
return city; }
} var xy_val = cityPosition[id];
city.name = xy_val[0];
var nationObj = nationList[nationId]; city.x = xy_val[1];
city.nation = nationObj.name; city.y = xy_val[2];
city.color = nationObj.color; return city;
city.isCapital = (nationObj.capital == city.id); }
return city; function mergeNationInfo(city) {
} //nationId 값으로 isCapital, color, nation을 통합
function mergeClickable(city){ var nationId = city.nationId;
//clickable = (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll if (nationId === null || !(nationId in nationList)) {
var id = city.id; city.nationId = null;
var nationId = city.nationId; city.nation = null;
var clickable = 0; city.color = null;
if(id in spyList){ city.isCapital = false;
clickable |= spyList[id] << 3; return city;
} }
if(myNation !== null && nationId == myNation){
clickable |= 4; var nationObj = nationList[nationId];
} city.nation = nationObj.name;
if(shownByGeneralList.hasOwnProperty(id)){ city.color = nationObj.color;
clickable |= 2; city.isCapital = (nationObj.capital == city.id);
}
if(myCity !== null && id == myCity){ return city;
clickable |= 2; }
}
if(clickableAll){ function mergeClickable(city) {
clickable |= 1; //clickable = (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
} var id = city.id;
var nationId = city.nationId;
var clickable = 0;
city.clickable = clickable; if (id in spyList) {
return city; clickable |= spyList[id] << 3;
} }
if (myNation !== null && nationId == myNation) {
cityList = cityList clickable |= 4;
.map(mergePositionInfo) }
.map(mergeNationInfo) if (shownByGeneralList.hasOwnProperty(id)) {
.map(mergeClickable) clickable |= 2;
.map(formatCityInfo); }
if (myCity !== null && id == myCity) {
return { clickable |= 2;
'cityList' : cityList, }
'myCity' : myCity if (clickableAll) {
}; clickable |= 1;
} }
function drawDetailWorldMap(obj){
city.clickable = clickable;
var $map_body = $('.world_map .map_body'); return city;
}
var cityList = obj.cityList;
var myCity = obj.myCity; cityList = cityList
.map(mergePositionInfo)
cityList.forEach(function(city){ .map(mergeNationInfo)
var id = city.id; .map(mergeClickable)
$('.city_base_{0}'.format(id)).detach(); .map(formatCityInfo);
//이전 도시는 지운다.
return {
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id)); 'cityList': cityList,
$cityObj.addClass('city_level_{0}'.format(city.level)); 'myCity': myCity
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15}); };
}
if('color' in city && city.color !== null){
var $bgObj = $('<div class="city_bg"></div>'); function drawDetailWorldMap(obj) {
$cityObj.append($bgObj);
$bgObj.css({'background-image':'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color))}); var $map_body = $(drawTarget + ' .map_body');
}
var cityList = obj.cityList;
var $linkObj = $('<a class="city_link"></a>'); var myCity = obj.myCity;
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id});
$cityObj.append($linkObj); cityList.forEach(function(city) {
var id = city.id;
var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level)); $('.city_base_{0}'.format(id)).detach();
$linkObj.append($imgObj); //이전 도시는 지운다.
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
$cityObj.addClass('city_level_{0}'.format(city.level));
if(city.state > 0){ $cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
$linkObj.append($stateObj); if ('color' in city && city.color !== null) {
} var $bgObj = $('<div class="city_bg"></div>');
$cityObj.append($bgObj);
if(city.nationId && city.nationId > 0){ $bgObj.css({ 'background-image': 'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color)) });
var flagType = city.supply?'f':'d'; }
var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
if(city.isCapital){ var $linkObj = $('<a class="city_link"></a>');
var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage)); $linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
$flagObj.append($capitalObj); $cityObj.append($linkObj);
}
$imgObj.append($flagObj); var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level));
} $linkObj.append($imgObj);
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
$imgObj.append($nameObj);
if (city.state > 0) {
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
$map_body.append($cityObj); $linkObj.append($stateObj);
}
}); if (city.nationId && city.nationId > 0) {
var flagType = city.supply ? 'f' : 'd';
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city'); var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
if (city.isCapital) {
return obj; var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage));
} $flagObj.append($capitalObj);
}
function drawBasicWorldMap(obj){ $imgObj.append($flagObj);
}
var $map_body = $('.world_map .map_body');
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
var cityList = obj.cityList; $imgObj.append($nameObj);
var myCity = obj.myCity;
cityList.forEach(function(city){ $map_body.append($cityObj);
var id = city.id;
$('.city_base_{0}'.format(id)).detach();
//이전 도시는 지운다. });
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id)); $world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
$cityObj.addClass('city_level_{0}'.format(city.level));
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15}); return obj;
}
var $linkObj = $('<a class="city_link"></a>');
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id}); function drawBasicWorldMap(obj) {
$cityObj.append($linkObj);
var $map_body = $(drawTarget + ' .map_body');
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
if('color' in city && city.color !== null){ var cityList = obj.cityList;
$imgObj.css({'background-color':city.color}); var myCity = obj.myCity;
}
$linkObj.append($imgObj); cityList.forEach(function(city) {
var id = city.id;
if(city.state > 0){ $('.city_base_{0}'.format(id)).detach();
var state_text = 'wrong'; //이전 도시는 지운다.
if(city.state < 10){
state_text = 'good'; var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
} $cityObj.addClass('city_level_{0}'.format(city.level));
else if(city.state < 40){ $cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
state_text = 'bad';
} var $linkObj = $('<a class="city_link"></a>');
else if(city.state < 50){ $linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
state_text = 'war'; $cityObj.append($linkObj);
}
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text)); if ('color' in city && city.color !== null) {
$imgObj.append($stateObj); $imgObj.css({ 'background-color': city.color });
} }
$linkObj.append($imgObj);
//단순 표기에서는 깃발 여부가 없음
if(city.isCapital){ if (city.state > 0) {
var $capitalObj = $('<div class="city_capital"></div>'); var state_text = 'wrong';
$imgObj.append($capitalObj); if (city.state < 10) {
} state_text = 'good';
} else if (city.state < 40) {
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name)); state_text = 'bad';
$imgObj.append($nameObj); } else if (city.state < 50) {
state_text = 'war';
$map_body.append($cityObj); }
});
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text));
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city'); $imgObj.append($stateObj);
}
return obj;
} //단순 표기에서는 깃발 여부가 없음
if (city.isCapital) {
function setMouseWork(obj){ var $capitalObj = $('<div class="city_capital"></div>');
var $tooltip = $('.world_map .city_tooltip'); $imgObj.append($capitalObj);
var $tooltip_city = $tooltip.find('.city_name'); }
var $tooltip_nation = $tooltip.find('.nation_name');
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
var $objs = $('.world_map .city_link'); $imgObj.append($nameObj);
var $map_body = $('.world_map .map_body'); $map_body.append($cityObj);
});
//터치스크린 탭
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
if(!option.neutralView && is_touch_device()){
$objs.on('touchstart', function(e){ return obj;
if(window.sam_toggleSingleTap){ }
return true;
} function setMouseWork(obj) {
var $this = $(this); var $tooltip = $(drawTarget + ' .city_tooltip');
var $tooltip_city = $tooltip.find('.city_name');
var touchMode = $this.data('touchMode'); var $tooltip_nation = $tooltip.find('.nation_name');
if($tooltip_city.data('target') != $this.data('id')){
$this.data('touchMode', 1); var $objs = $(drawTarget + ' .city_link');
}
else if(touchMode === undefined){ var $map_body = $(drawTarget + ' .map_body');
$this.data('touchMode', 1);
} //터치스크린 탭
else{
$this.data('touchMode', touchMode + 1); if (!option.neutralView && is_touch_device()) {
} $objs.on('touchstart', function(e) {
$map_body.data('touchMode', 1); if (window.sam_toggleSingleTap) {
return true;
$tooltip_city.data('target', $this.data('id')); }
var $this = $(this);
}); var touchMode = $this.data('touchMode');
if ($tooltip_city.data('target') != $this.data('id')) {
$objs.on('touchend', function(e){ $this.data('touchMode', 1);
if(window.sam_toggleSingleTap){ } else if (touchMode === undefined) {
return true; $this.data('touchMode', 1);
} } else {
var $this = $(this); $this.data('touchMode', touchMode + 1);
var position = $this.parent().position(); }
$tooltip_city.html($this.data('text')); $map_body.data('touchMode', 1);
var nation_text = $this.data('nation'); $tooltip_city.data('target', $this.data('id'));
if(nation_text){
$tooltip_nation.html(nation_text).show();
} });
else{
$tooltip_nation.html('').hide(); $objs.on('touchend', function(e) {
} if (window.sam_toggleSingleTap) {
return true;
$tooltip.css({'top': position.top + 25, 'left': position.left + 35}).show(); }
var $this = $(this);
var touchMode = $this.data('touchMode'); var position = $this.parent().position();
if(touchMode <= 1){ $tooltip_city.html($this.data('text'));
return false;
} var nation_text = $this.data('nation');
if (nation_text) {
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다. $tooltip_nation.html(nation_text).show();
$this.data('touchMode', 0); } else {
}); $tooltip_nation.html('').hide();
}
$map_body.on('touchend',function(e){
if(window.sam_toggleSingleTap){ var left = position.left;
return true; var top = position.top;
}
//위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치 var scale = $map_body.data('scale');
$tooltip.hide(); if (scale) {
}); left /= scale;
top /= scale;
} }
//Mouse over 모드 작동 $tooltip.css({ 'top': top + 25, 'left': left + 35 }).show();
$map_body.on('mousemove', function(e){ var touchMode = $this.data('touchMode');
if($(this).data('touchMode')){ if (touchMode <= 1) {
return true; return false;
} }
var parentOffset = $map_body.offset(); //xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
var relX = e.pageX - parentOffset.left; $this.data('touchMode', 0);
var relY = e.pageY - parentOffset.top; });
$tooltip.css({'top': relY + 10, 'left': relX + 10}); $map_body.on('touchend', function(e) {
}); if (window.sam_toggleSingleTap) {
return true;
$objs.on('mouseenter', function(e){ }
if($map_body.data('touchMode')){ //위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치
return true; $tooltip.hide();
} });
var $this = $(this); }
$tooltip_city.data('target', $this.data('id')); //Mouse over 모드 작동
$tooltip_city.html($this.data('text'));
var nation_text = $this.data('nation'); $map_body.on('mousemove', function(e) {
if(nation_text){ if ($(this).data('touchMode')) {
$tooltip_nation.html(nation_text).show(); return true;
} }
else{
$tooltip_nation.html('').hide(); var rect = this.getBoundingClientRect();
} var left = (e.clientX - rect.left - this.clientLeft + this.scrollLeft);
var top = (e.clientY - rect.top - this.clientTop + this.scrollTop);
$tooltip.show();
}); var scale = $map_body.data('scale');
if (scale) {
$objs.on('mouseleave', function(event){ left /= scale;
$tooltip.hide(); top /= scale;
}); }
$objs.on('click', function(e){ $tooltip.css({ 'top': top + 10, 'left': left + 10 });
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다. });
var touchMode = $(this).data('touchMode');
if(touchMode === undefined){ $objs.on('mouseenter', function(e) {
return; if ($map_body.data('touchMode')) {
} return true;
}
if(touchMode === 1){
return false; var $this = $(this);
}
}); $tooltip_city.data('target', $this.data('id'));
$tooltip_city.html($this.data('text'));
var nation_text = $this.data('nation');
return obj; if (nation_text) {
} $tooltip_nation.html(nation_text).show();
} else {
function setCityClickable(obj){ $tooltip_nation.html('').hide();
}
obj.cityList.forEach(function(city){
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id)); $tooltip.show();
});
if('clickable' in city && city.clickable > 0){
$cityLink.attr('href',hrefTemplate.format(city.id)); $objs.on('mouseleave', function(event) {
} $tooltip.hide();
});
if(selectCallback){
$cityLink.click(function(){ $objs.on('click', function(e) {
return selectCallback(city); //xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
}); var touchMode = $(this).data('touchMode');
} if (touchMode === undefined) {
}); return;
}
return obj;
} if (touchMode === 1) {
return false;
function saveCityInfo(obj){ }
$world_map.data('cityInfo', obj); });
return obj;
}
return obj;
var $hideCityNameBtn = $world_map.find('.map_toggle_cityname'); }
if(localStorage.getItem('sam.hideMapCityName') == 'yes'){
$world_map.addClass('hide_cityname'); function setCityClickable(obj) {
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
} obj.cityList.forEach(function(city) {
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id));
$hideCityNameBtn.click(function(){
//이전 상태 확인 if ('clickable' in city && city.clickable > 0) {
var state = !$hideCityNameBtn.hasClass('active'); $cityLink.attr('href', hrefTemplate.format(city.id));
if(state){ }
$world_map.addClass('hide_cityname');
localStorage.setItem('sam.hideMapCityName', 'yes'); if (selectCallback) {
} $cityLink.click(function() {
else{ return selectCallback(city);
$world_map.removeClass('hide_cityname'); });
localStorage.setItem('sam.hideMapCityName', 'no'); }
} });
});
return obj;
var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap'); }
if(localStorage.getItem('sam.toggleSingleTap') == 'yes'){
window.sam_toggleSingleTap = true; function saveCityInfo(obj) {
$toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true'); $world_map.data('cityInfo', obj);
} return obj;
else{ }
window.sam_toggleSingleTap = false;
} var $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
if (localStorage.getItem('sam.hideMapCityName') == 'yes') {
var $map_body = $('.world_map .map_body'); $world_map.addClass('hide_cityname');
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
$toggleSingleTapBtn.click(function(){ }
//이전 상태 확인
var state = !$toggleSingleTapBtn.hasClass('active'); $hideCityNameBtn.click(function() {
if(state){ //이전 상태 확인
$map_body.removeData('touchMode'); var state = !$hideCityNameBtn.hasClass('active');
localStorage.setItem('sam.toggleSingleTap', 'yes'); if (state) {
window.sam_toggleSingleTap = true; $world_map.addClass('hide_cityname');
} localStorage.setItem('sam.hideMapCityName', 'yes');
else{ } else {
localStorage.setItem('sam.toggleSingleTap', 'no'); $world_map.removeClass('hide_cityname');
window.sam_toggleSingleTap = false; localStorage.setItem('sam.hideMapCityName', 'no');
} }
}); });
if(isDetailMap){ var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap');
$world_map.addClass('map_detail'); if (localStorage.getItem('sam.toggleSingleTap') == 'yes') {
} window.sam_toggleSingleTap = true;
else{ $toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true');
$world_map.removeClass('map_datail'); } else {
} window.sam_toggleSingleTap = false;
}
//deferred mode of jQuery. != promise-then.
var deferred = $.ajax({ var $map_body = $(drawTarget + ' .map_body');
url: option.targetJson,
type: 'post', $toggleSingleTapBtn.click(function() {
dataType:'json', //이전 상태 확인
data: { var state = !$toggleSingleTapBtn.hasClass('active');
data: JSON.stringify({ if (state) {
neutralView:option.neutralView, $map_body.removeData('touchMode');
year:option.year, localStorage.setItem('sam.toggleSingleTap', 'yes');
month:option.month, window.sam_toggleSingleTap = true;
showMe:option.showMe, } else {
aux:option.aux localStorage.setItem('sam.toggleSingleTap', 'no');
}) window.sam_toggleSingleTap = false;
} }
}); });
deferred if (isDetailMap) {
.then(checkReturnObject) $world_map.addClass('map_detail');
.then(setMapBackground) } else {
.then(convertCityObjs) $world_map.removeClass('map_datail');
.then(isDetailMap?drawDetailWorldMap:drawBasicWorldMap) }
.then(setMouseWork)
.then(setCityClickable) //deferred mode of jQuery. != promise-then.
.then(saveCityInfo); var deferred = $.ajax({
url: option.targetJson,
if($world_map.hasClass('draw_required')){ type: option.reqType,
if(useCachedMap){ dataType: 'json',
//일단 불러옴 ifModified: true,
do{ data: {
var storedMap = localStorage.getItem(storedOldMapKey); data: JSON.stringify({
if(!storedMap){ neutralView: option.neutralView,
break; year: option.year,
} month: option.month,
storedMap = JSON.parse(storedMap); showMe: option.showMe,
var storedServerID = storedMap[0]; aux: option.aux
if(storedServerID != serverID){ })
break; }
} });
storedMap = storedMap[1]; var rawObject = null;
storedMap = setMapBackground(storedMap);
storedMap = convertCityObjs(storedMap); deferred
if(isDetailMap){ .then(function(data) {
storedMap = drawDetailWorldMap(storedMap); rawObject = data;
} return data;
else{ })
storedMap = drawBasicWorldMap(storedMap); .then(checkReturnObject)
} .then(setMapBackground)
storedMap = setMouseWork(storedMap); .then(convertCityObjs)
storedMap = setCityClickable(storedMap); .then(isDetailMap ? drawDetailWorldMap : drawBasicWorldMap)
storedMap = saveCityInfo(storedMap); .then(setMouseWork)
}while(false); .then(setCityClickable)
} .then(saveCityInfo)
else if(option.year && option.month){ .then(function(data) {
var startYear = localStorage.getItem(storedStartYear); if (option.callback) {
if(startYear){ option.callback(data, rawObject);
startYear = JSON.parse(startYear); }
}
else{ });
startYear = option.year;
} if ($world_map.hasClass('draw_required')) {
var tmp = { if (useCachedMap) {
year : option.year, //일단 불러옴
month : option.month, do {
startYear : startYear var storedMap = localStorage.getItem(storedOldMapKey);
}; if (!storedMap) {
setMapBackground(tmp); break;
} }
storedMap = JSON.parse(storedMap);
var storedServerID = storedMap[0];
} if (storedServerID != serverID) {
} break;
$(function(){ }
if(is_touch_device()){
$('.map_body .map_toggle_single_tap').show(); storedMap = storedMap[1];
} storedMap = setMapBackground(storedMap);
storedMap = convertCityObjs(storedMap);
if (isDetailMap) {
storedMap = drawDetailWorldMap(storedMap);
} else {
storedMap = drawBasicWorldMap(storedMap);
}
storedMap = setMouseWork(storedMap);
storedMap = setCityClickable(storedMap);
storedMap = saveCityInfo(storedMap);
} while (false);
} else if (option.year && option.month) {
var startYear = localStorage.getItem(storedStartYear);
if (startYear) {
startYear = JSON.parse(startYear);
} else {
startYear = option.year;
}
var tmp = {
year: option.year,
month: option.month,
startYear: startYear
};
setMapBackground(tmp);
}
}
}
$(function() {
if (is_touch_device()) {
$('.map_body .map_toggle_single_tap').show();
}
}) })
+166 -84
View File
@@ -1,85 +1,167 @@
jQuery(function($){ jQuery(function($) {
var initCustomCSSForm = function(){ var initCustomCSSForm = function() {
var lastTimeOut = null; var lastTimeOut = null;
var $obj = $('#custom_css'); var $obj = $('#custom_css');
var key = 'sam_customCSS'; var key = 'sam_customCSS';
var text = localStorage.getItem(key); var text = localStorage.getItem(key);
if(text){ if (text) {
$obj.val(text); $obj.val(text);
console.log(text); console.log(text);
} }
if($obj.on('change keyup paste', function(){ if ($obj.on('change keyup paste', function() {
var newText = $obj.val(); var newText = $obj.val();
if(text == newText){ if (text == newText) {
return; return;
} }
if(lastTimeOut){ if (lastTimeOut) {
clearTimeout(lastTimeOut); clearTimeout(lastTimeOut);
} }
$obj.css('background-color', '#222222'); $obj.css('background-color', '#222222');
lastTimeOut = setTimeout(function(){ lastTimeOut = setTimeout(function() {
text = $obj.val(); text = $obj.val();
localStorage.setItem(key, text); localStorage.setItem(key, text);
$obj.css('background-color', 'black'); $obj.css('background-color', 'black');
}, 500); }, 500);
})); }));
} }
$('.load_old_log').click(function(){ $('.load_old_log').click(function() {
var $thisBtn = $(this); var $thisBtn = $(this);
var logType = $thisBtn.data('log_type'); var logType = $thisBtn.data('log_type');
var $last = $('.log_{0}:last'.format(logType)); var $last = $('.log_{0}:last'.format(logType));
var reqTo = null; var reqTo = null;
if($last.length){ if ($last.length) {
reqTo = $last.data('seq'); reqTo = $last.data('seq');
} }
$.post({ $.post({
url:'j_general_log_old.php', url: 'j_general_log_old.php',
dataType:'json', dataType: 'json',
data:{ data: {
to:reqTo, to: reqTo,
type:logType type: logType
} }
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
return quickReject('로그를 받아오지 못했습니다.'); return quickReject('로그를 받아오지 못했습니다.');
} }
if(!data.result){ if (!data.result) {
return quickReject('로그를 받아오지 못했습니다. : '+data.reason); return quickReject('로그를 받아오지 못했습니다. : ' + data.reason);
} }
var keys = Object.keys(data.log); var keys = Object.keys(data.log);
if(keys.length > 1 && keys[0] < keys[1]){ if (keys.length > 1 && keys[0] < keys[1]) {
keys.reverse(); keys.reverse();
} }
if(keys == 0){ if (keys == 0) {
$thisBtn.hide(); $thisBtn.hide();
return; return;
} }
var html = []; var html = [];
$.each(keys, function(_, key){ $.each(keys, function(_, key) {
if($('#log_{0}_{1}'.format(logType, key)).length){ if ($('#log_{0}_{1}'.format(logType, key)).length) {
return true; return true;
} }
var item = data.log[key]; var item = data.log[key];
html.push("<div class='log_{0}' id='log_{0}_{1}' data-seq='{1}'>{2}</div>".format(logType, key, item)); html.push("<div class='log_{0}' id='log_{0}_{1}' data-seq='{1}'>{2}</div>".format(logType, key, item));
}); });
$('#{0}Plate'.format(logType)).append(html); $('#{0}Plate'.format(logType)).append(html);
}, errUnknown) }, errUnknown)
.fail(function(reason){ .fail(function(reason) {
alert(reason); alert(reason);
location.reload(); location.reload();
}); });
}) })
initCustomCSSForm(); initCustomCSSForm();
$('#die_immediately').click(function() {
if (!confirm('정말로 삭제하시겠습니까?')) {
return false;
}
$.post({
url: 'j_die_immediately.php',
dataType: 'json',
}).then(function(data) {
if (!data) {
return quickReject('실패했습니다.');
}
if (!data.result) {
return quickReject(data.reason);
}
location.replace('..');
}, errUnknown)
.fail(function(reason) {
alert(reason);
location.reload();
});
return false;
return false;
});
$('#vacation').click(function() {
if (!confirm('휴가 기능을 신청할까요?')) {
return false;
}
$.post({
url: 'j_vacation.php',
dataType: 'json',
}).then(function(data) {
if (!data) {
return quickReject('실패했습니다.');
}
if (!data.result) {
return quickReject(data.reason);
}
location.reload();
}, errUnknown)
.fail(function(reason) {
alert(reason);
location.reload();
});
return false;
return false;
});
$('#set_my_setting').click(function() {
$.post({
url: 'j_set_my_setting.php',
dataType: 'json',
data: {
tnmt: $('.tnmt:checked').val(),
defence_train: $('#defence_train').val(),
use_treatment: $('#use_treatment').val(),
use_auto_nation_turn: $('#use_auto_nation_turn').val(),
}
}).then(function(data) {
if (!data) {
return quickReject('실패했습니다.');
}
if (!data.result) {
return quickReject(data.reason);
}
location.reload();
}, errUnknown)
.fail(function(reason) {
alert(reason);
location.reload();
});
return false;
return false;
});
}); });
+40 -3
View File
@@ -33,6 +33,35 @@ jQuery(function ($) {
var $disabled = $(itemFrameDisabled.format('&lt;비활성화 항목들&gt;')).addClass('filtered'); var $disabled = $(itemFrameDisabled.format('&lt;비활성화 항목들&gt;')).addClass('filtered');
$disabledList.append($disabled); $disabledList.append($disabled);
var lastInfoObj = null;
var lastInfoData = null;
var onChoose = function(evt){
//$(evt.item).find('.help-message').popopver('disable');
if(lastInfoObj){
lastInfoObj.popover('hide');
}
}
var onUnchoose = function(evt){
var $item = $(evt.item);//.find('.help-message').popopver('enable');
var $helpMessage = $item.find('.help-message');
if(!$helpMessage.length){
return;
}
if(lastInfoData != $item.data('value')){
$helpMessage.popover('show')
lastInfoData = $item.data('value');
lastInfoObj = $helpMessage;
}
else{
$helpMessage.popover('hide');
lastInfoData = null;
lastInfoObj = null;
}
}
$.each(availablePriority, function (key, val) { $.each(availablePriority, function (key, val) {
if (val in usedKey) { if (val in usedKey) {
return true; return true;
@@ -45,12 +74,16 @@ jQuery(function ($) {
$disabledList.sortable({ $disabledList.sortable({
group: priorityKey, group: priorityKey,
filter: '.filtered', filter: '.filtered',
onChoose,onChoose,
onUnchoose:onUnchoose,
animation: 150 animation: 150
}); });
$enabledList.sortable({ $enabledList.sortable({
group: priorityKey, group: priorityKey,
filter: '.filtered', filter: '.filtered',
onChoose,onChoose,
onUnchoose:onUnchoose,
animation: 150 animation: 150
}); });
@@ -59,14 +92,18 @@ jQuery(function ($) {
if(!(itemValue in btnHelpMessage)){ if(!(itemValue in btnHelpMessage)){
return true; return true;
} }
var helpText = btnHelpMessage[itemValue]; var helpText = btnHelpMessage[itemValue];
$item.find('.help-message').popover({ var $helpMessage = $item.find('.help-message');
$helpMessage.popover({
content:helpText, content:helpText,
placement:'right', placement:'top',
html:true, html:true,
trigger:'hover' trigger:'hover'
}); });
$item.mouseleave(function(){
$helpMessage.popover('hide');
});
}); });
} }
+244 -101
View File
@@ -1,102 +1,245 @@
function reserveTurn(turnList, command, arg){ function reserveTurn(turnList, command, arg) {
var target; var target;
if(isChiefTurn){ if (isChiefTurn) {
target = 'j_set_chief_command.php'; target = 'j_set_chief_command.php';
} } else {
else{ target = 'j_set_general_command.php';
target = 'j_set_general_command.php'; }
} $.post({
$.post({ url: target,
url:target, dataType: 'json',
dataType:'json', data: {
data:{ action: command,
action:command, turnList: turnList,
turnList:turnList, arg: JSON.stringify(arg)
arg:JSON.stringify(arg) }
} }).then(function(data) {
}).then(function(data){ if (!data.result) {
if(!data.result){ alert(data.reason);
alert(data.reason); return;
return; }
}
if (!isChiefTurn) {
if(!isChiefTurn){ window.location.href = './';
window.location.href = './'; } else {
} window.location.href = 'b_chiefcenter.php';
else{ }
window.location.href = 'b_chiefcenter.php';
} }, errUnknown);
}
}, errUnknown);
} jQuery(function($) {
jQuery(function($){ window.submitAction = function() {
window.submitAction = function(){ //checkCommandArg 참고
var availableArgumentList = {
//checkCommandArg 참고 'string': [
var availableArgumentList = { 'nationName', 'optionText', 'itemType', 'nationType', 'itemCode', 'commandType',
'string':[ ],
'nationName', 'optionText', 'itemType', 'nationType', 'itemCode', 'int': [
], 'crewType', 'destGeneralID', 'destCityID', 'destNationID',
'int':[ 'amount', 'colorType',
'crewType', 'destGeneralID', 'destCityID', 'destNationID', 'year', 'month',
'amount', 'colorType', 'srcArmType', 'destArmType', //숙련전환 전용
'year', 'month', ],
'srcArmType', 'destArmType', //숙련전환 전용 'boolean': [
], 'isGold', 'buyRice',
'boolean':[ ],
'isGold', 'buyRice', 'integerArray': [
], 'destNationIDList', 'destGeneralIDList', 'amountList'
'integerArray':[ ]
'destNationIDList', 'destGeneralIDList', 'amountList' }
]
} var handlerList = {
'string': function($obj) {
var handlerList = { return $.trim($obj.eq(0).val());
'string':function($obj){ },
return $.trim($obj.eq(0).val()); 'int': function($obj) {
}, return parseInt($obj.eq(0).val());
'int':function($obj){ },
return parseInt($obj.eq(0).val()); 'boolean': function($obj) {
}, switch ($obj.eq(0).val().toLowerCase()) {
'boolean':function($obj){ case "true":
switch ($obj.eq(0).val().toLowerCase()) { case "yes":
case "true": case "yes": case "1": case "1":
return true; return true;
case "false": case "no": case "0": case "false":
return false; case "no":
default: case "0":
throw new Error ("Boolean.parse: Cannot convert string to boolean."); return false;
} default:
}, throw new Error("Boolean.parse: Cannot convert string to boolean.");
'integerArray':function($obj){ }
return $obj.map(function(){ },
return parseInt($(this).val()); 'integerArray': function($obj) {
}); var result = [];
} $obj.each(function() {
} result.push(parseInt($(this).val()));
});
var argument = {}; return result;
for (var typeName in availableArgumentList) { }
availableArgumentList[typeName].forEach(function(argName){ }
var $obj = $('#'+argName);
if($obj.length == 0){ var argument = {};
$obj = $('.'+argName); for (var typeName in availableArgumentList) {
if($obj.length == 0){ availableArgumentList[typeName].forEach(function(argName) {
return; var $obj = $('#' + argName);
} if ($obj.length == 0) {
} $obj = $('.' + argName);
if ($obj.length == 0) {
argument[argName] = handlerList[typeName]($obj); return;
}); }
} }
console.log(argument); argument[argName] = handlerList[typeName]($obj);
reserveTurn(turnList, command, argument); });
}; }
$('#commonSubmit').click(submitAction); console.log(argument);
reserveTurn(turnList, command, argument);
};
$('#commonSubmit').click(submitAction);
var $colorType = $('#colorType');
if ($colorType.length) {
$colorType.select2({
theme: 'bootstrap4',
placeholder: "색상을 선택해 주세요.",
language: "ko",
containerCss: {
display: "inline-block !important",
color: 'white !important',
},
templateSelection: function(item) {
if (item.disabled) {
return item.text;
}
var bgcolor = item.element.dataset.color;
var fgcolor = item.element.dataset.fontColor;
return $("<span><span style='background-color:{0};color:{1};'> </span>&nbsp;{2}</span>".format(
bgcolor, fgcolor, item.text
));
},
templateResult: function(item) {
if (item.disabled) {
return item.text;
}
var bgcolor = item.element.dataset.color;
var fgcolor = item.element.dataset.fontColor;
return $("<div style='padding: 0.75rem 0.375rem; background-color:{0};color:{1};'>{2}</div>".format(
bgcolor, fgcolor, item.text
));
},
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'no-padding simple-select2-align-center bg-secondary text-secondary',
});
}
var $nationType = $('#nationType');
if ($nationType.length) {
$nationType.select2({
theme: 'bootstrap4',
language: "ko",
containerCss: {
display: "inline-block !important",
color: 'white !important',
},
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
});
}
var $destCityID = $('#destCityID');
if ($destCityID.length) {
$destCityID.select2({
theme: 'bootstrap4',
placeholder: "도시를 선택해 주세요.",
language: "ko",
containerCss: {
display: "inline-block !important",
color: 'white !important',
},
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
});
}
var $destNationID = $('#destNationID');
if ($destNationID.length) {
$destNationID.select2({
theme: 'bootstrap4',
placeholder: "국가를 선택해 주세요.",
language: "ko",
containerCss: {
display: "inline-block !important",
color: 'white !important',
},
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
});
}
var $destGeneralID = $('#destGeneralID');
if ($destGeneralID.length) {
$destGeneralID.select2({
theme: 'bootstrap4',
placeholder: "장수를 선택해 주세요.",
language: "ko",
containerCss: {
display: "inline-block !important",
color: 'white !important',
},
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
});
}
var $isGold = $('#isGold');
if ($isGold.length) {
$isGold.select2({
theme: 'bootstrap4',
placeholder: "분량을 지정해 주세요.",
language: "ko",
containerCss: {
display: "inline-block !important",
color: 'white !important',
},
minimumResultsForSearch: -1,
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
});
}
var $amount = $('#amount:not([type=hidden])');
if ($amount.length) {
$amount.select2({
theme: 'bootstrap4',
placeholder: "분량을 지정해 주세요.",
allowClear: false,
language: "ko",
containerCss: {
display: "inline-block !important",
color: 'white !important',
},
tags: true,
sorter: function(items) {
items.sort(function(lhs, rhs) {
return parseInt(lhs.id) - parseInt(rhs.id);
})
return items;
},
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'select2-only-number simple-select2-align-center bg-secondary text-secondary',
})
}
$(document).on('keypress', '.select2-only-number .select2-search__field', function() {
$(this).val($(this).val().replace(/[^\d].+/, ""));
if ((event.which < 48 || event.which > 57)) {
event.preventDefault();
}
});
}); });
+1 -1
View File
@@ -23,7 +23,7 @@ $(function(){
var crewtype = parseInt($parent.data('crewtype')); var crewtype = parseInt($parent.data('crewtype'));
calc(crewtype); calc(crewtype);
$formCrewtype.val(crewtype); $formCrewtype.val(crewtype);
$formAmount.val($this.val()); $formAmount.val($this.val()*100);
if(e.which === 13){ if(e.which === 13){
submitAction(); submitAction();
+352 -359
View File
@@ -1,360 +1,353 @@
var templateGeneralCard = var templateGeneralCard =
'<div class="general_card">\ '<div class="general_card">\
<h4 class="bg1 with_border"><%name%></h4>\ <h4 class="bg1 with_border"><%name%></h4>\
<h4><img src="<%iconPath%>" height=64 width=64></h4>\ <h4><img src="<%iconPath%>" height=64 width=64></h4>\
<p><%leadership%> / <%strength%> / <%intel%><br>\ <p><%leadership%> / <%strength%> / <%intel%><br>\
<%nation%><br>\ <%nation%><br>\
<%personalText%><br>\ <%personalText%><br>\
<%specialText%> / <%special2Text%></p>\ <%specialText%> / <%special2Text%></p>\
<button type="subject" class="with_skin with_border select_btn" data-name="<%name%>" value="<%no%>" name="pick">빙의하기</button>\ <button type="subject" class="with_skin with_border select_btn" data-name="<%name%>" value="<%no%>" name="pick">빙의하기</button>\
<label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>)</label>\ <label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>)</label>\
</div>'; </div>';
var templateSpecial = var templateSpecial =
'<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\ '<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\
<span class="tooltiptext">\ <span class="tooltiptext">\
<%info%>\ <%info%>\
</span>\ </span>\
</span>\ </span>\
'; ';
var templateGeneralRow = var templateGeneralRow =
'<tr>\ '<tr>\
<td><img class="generalIcon" width="64" height="64" src="<%iconPath%>"></td>\ <td><img class="generalIcon" width="64" height="64" src="<%iconPath%>"></td>\
<td style="<%userCSS%>"><%name%><%nameAux%></td>\ <td style="<%userCSS%>"><%name%><%nameAux%></td>\
<td><%age%></td>\ <td><%age%></td>\
<td><%personalWithTooltip%></td>\ <td><%personalWithTooltip%></td>\
<td><%specialDomesticWithTooltip%> / <%speicalWarWithTooltip%></td>\ <td><%specialDomesticWithTooltip%> / <%speicalWarWithTooltip%></td>\
<td>Lv <%explevel%></td>\ <td>Lv <%explevel%></td>\
<td><%nation%></td>\ <td><%nation%></td>\
<td><%experience%></td>\ <td><%experience%></td>\
<td><%dedication%></td>\ <td><%dedication%></td>\
<td><%officerLevel%></td>\ <td><%officerLevel%></td>\
<td><%total%></td>\ <td><%total%></td>\
<td><%leadership%></td>\ <td><%leadership%></td>\
<td><%strength%></td>\ <td><%strength%></td>\
<td><%intel%></td>\ <td><%intel%></td>\
<td><%killturn%></td>\ <td><%killturn%></td>\
</tr>'; </tr>';
function pickGeneral(){ function pickGeneral() {
$btn = $(this); $btn = $(this);
if (!confirm('빙의할까요? : {0}'.format($btn.data('name')))) { if (!confirm('빙의할까요? : {0}'.format($btn.data('name')))) {
return false; return false;
} }
$.post({ $.post({
url:'j_select_npc.php', url: 'j_select_npc.php',
dataType:'json', dataType: 'json',
data:{ data: {
pick:$btn.val() pick: $btn.val()
} }
}).then(function(result){ }).then(function(result) {
if(!result.result){ if (!result.result) {
alert(result.reason); alert(result.reason);
location.refresh(); location.refresh();
} }
alert('빙의에 성공했습니다.'); alert('빙의에 성공했습니다.');
location.href = './'; location.href = './';
}); });
return false; return false;
} }
function updateOutdateTimer(){ function updateOutdateTimer() {
var $validUntilText = $('#valid_until_text'); var $validUntilText = $('#valid_until_text');
var now = Date.now(); var now = Date.now();
var validUntil = $validUntilText.data('until'); var validUntil = $validUntilText.data('until');
if(validUntil <= 0){ if (validUntil <= 0) {
return; return;
} } else if (validUntil < now) {
else if(validUntil < now){ $validUntilText.data('until', 0);
$validUntilText.data('until',0); $('#valid_until').hide();
$('#valid_until').hide(); $('#outdate_token').show();
$('#outdate_token').show(); return;
return; } else if (validUntil - now <= 30000) {
} $validUntilText.css('color', "rgb(255, {0}, {0})".format(255 * (validUntil - now) / 30000));
else if(validUntil - now <= 30000){ }
$validUntilText.css('color', "rgb(255, {0}, {0})".format(255*(validUntil - now)/30000));
} setTimeout(updateOutdateTimer, 1000);
}
setTimeout(updateOutdateTimer, 1000);
} function updatePickMoreTimer() {
var $btn = $('#btn_pick_more');
function updatePickMoreTimer(){
var $btn = $('#btn_pick_more'); var now = Date.now();
var remain = ($btn.data('available') - now) / 1000;
var now = Date.now(); if (remain <= 0) {
var remain = ($btn.data('available') - now) / 1000; $btn.prop('disabled', false)
if(remain <= 0){ $btn.html('다른 장수 보기');
$btn.prop('disabled', false) return;
$btn.html('다른 장수 보기'); }
return;
} $btn.html('다른 장수 보기({0}초)'.format(Math.ceil(remain)));
$btn.html('다른 장수 보기({0}초)'.format(Math.ceil(remain))); setTimeout(updatePickMoreTimer, 250);
}
setTimeout(updatePickMoreTimer, 250);
} function printGenerals(value) {
$('.card_holder').empty();
function printGenerals(value){ $('#valid_until').show();
$('.card_holder').empty(); $('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white');
$('#valid_until').show(); $('#outdate_token').hide();
$('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color','white'); var time = Date.now() + value.pickMoreSeconds * 1000;
$('#outdate_token').hide(); $('#btn_pick_more').data('available', time).prop('disabled', true);
var time = Date.now() + value.pickMoreSeconds*1000;
$('#btn_pick_more').data('available', time).prop('disabled',true); var pick = $.map(value.pick, function(value, key) {
return value;
var pick = $.map(value.pick, function(value, key) { });
return value;
}); pick.sort(function(lhs, rhs) {
var lsum = lhs.leadership + lhs.strength + lhs.intel;
pick.sort(function(lhs, rhs){ var rsum = rhs.leadership + rhs.strength + rhs.intel;
var lsum = lhs.leadership+lhs.strength+lhs.intel; return lsum - rsum;
var rsum = rhs.leadership+rhs.strength+rhs.intel; });
return lsum - rsum;
}); $.each(pick, function(idx, cardData) {
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
$.each(pick, function(idx, cardData){ if (cardData.special in specialInfo) {
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture); cardData.specialText = TemplateEngine(templateSpecial, {
if(cardData.special in specialInfo){ text: cardData.special,
cardData.specialText = TemplateEngine(templateSpecial, { info: specialInfo[cardData.special]
text:cardData.special, });
info:specialInfo[cardData.special] } else {
}); cardData.specialText = cardData.special;
} }
else{
cardData.specialText = cardData.special; if (cardData.special2 in specialInfo) {
} cardData.special2Text = TemplateEngine(templateSpecial, {
text: cardData.special2,
if(cardData.special2 in specialInfo){ info: specialInfo[cardData.special2]
cardData.special2Text = TemplateEngine(templateSpecial, { });
text:cardData.special2, } else {
info:specialInfo[cardData.special2] cardData.special2Text = cardData.special2;
}); }
}
else{ if (cardData.personal in characterInfo) {
cardData.special2Text = cardData.special2; cardData.personalText = TemplateEngine(templateSpecial, {
} text: cardData.personal,
info: characterInfo[cardData.personal]
if(cardData.personal in characterInfo){ });
cardData.personalText = TemplateEngine(templateSpecial, { } else {
text:cardData.personal, cardData.personalText = cardData.personal;
info:characterInfo[cardData.personal] }
});
}
else{ var $card = $(TemplateEngine(templateGeneralCard, cardData));
cardData.personalText = cardData.personal;
} $('.card_holder').append($card);
$card.find('.select_btn').click(pickGeneral);
$card.find('.obj_tooltip').tooltip({
var $card = $(TemplateEngine(templateGeneralCard, cardData)); title: function() {
return $.trim($(this).find('.tooltiptext').html());
$('.card_holder').append($card); },
$card.find('.select_btn').click(pickGeneral); html: true
$card.find('.obj_tooltip').tooltip({ });
title:function(){ });
return $.trim($(this).find('.tooltiptext').html());
}, updatePickMoreTimer();
html:true updateOutdateTimer();
}); }
});
function printGeneralList(value) {
updatePickMoreTimer(); var tokenList = value.token;
updateOutdateTimer(); var generalList = $.map(value.list, function(general) {
} general = {
no: general[0],
function printGeneralList(value){ picture: general[1],
var tokenList = value.token; imgsvr: general[2],
var generalList = $.map(value.list, function(general){ npc: general[3],
general = { age: general[4],
no:general[0], nation: general[5],
picture:general[1], special: general[6],
imgsvr:general[2], special2: general[7],
npc:general[3], personal: general[8],
age:general[4], name: general[9],
nation:general[5], ownerName: general[10],
special:general[6], injury: general[11],
special2:general[7], leadership: general[12],
personal:general[8], lbonus: general[13],
name:general[9], strength: general[14],
ownerName:general[10], intel: general[15],
injury:general[11], explevel: general[16],
leadership:general[12], experience: general[17],
lbonus:general[13], dedication: general[18],
strength:general[14], officerLevel: general[19],
intel:general[15], killturn: general[20],
explevel:general[16], connect: general[21],
experience:general[17], reserved: 0
dedication:general[18], };
officerLevel:general[19], if (general.npc < 2) {
killturn:general[20], general.reserved = 2;
connect:general[21], }
reserved:0 if (general.no in tokenList) {
}; general.reserved = 1;
if(general.npc < 2){ }
general.reserved = 2;
} general.userCSS = "";
if(general.no in tokenList){ general.nameAux = "";
general.reserved = 1;
} if (general.reserved == 1) {
general.userCSS = 'color:violet';
general.userCSS = ""; } else if (general.npc >= 2) {
general.nameAux = ""; general.userCSS = 'color:cyan';
} else if (general.npc == 1) {
if(general.reserved == 1){ general.userCSS = 'color:skyblue';
general.userCSS = 'color:violet'; }
}
else if(general.npc >= 2){ if (general.ownerName) {
general.userCSS = 'color:cyan'; general.nameAux += '<br><small>({0})</small>'.format(general.ownerName);
} }
else if(general.npc == 1){
general.userCSS = 'color:skyblue'; if (general.reserved == 1) {
} general.nameAux += '<br><small>({0}회)</small>'.format(tokenList[general.no]);
}
if(general.ownerName){
general.nameAux += '<br><small>({0})</small>'.format(general.ownerName);
} general.total = general.leadership + general.strength + general.intel;
general.iconPath = getIconPath(general.imgsvr, general.picture);
if(general.reserved == 1){
general.nameAux += '<br><small>({0}회)</small>'.format(tokenList[general.no]); general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, {
} text: general.special,
info: specialInfo[general.special]
});
general.total = general.leadership + general.strength + general.intel;
general.iconPath = getIconPath(general.imgsvr, general.picture); general.speicalWarWithTooltip = TemplateEngine(templateSpecial, {
text: general.special2,
general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, { info: specialInfo[general.special2]
text:general.special, });
info:specialInfo[general.special]
}); general.personalWithTooltip = TemplateEngine(templateSpecial, {
text: general.personal,
general.speicalWarWithTooltip = TemplateEngine(templateSpecial, { info: characterInfo[general.personal]
text:general.special2, });
info:specialInfo[general.special2]
}); return general;
});
general.personalWithTooltip = TemplateEngine(templateSpecial, {
text:general.personal, generalList.sort(function(lhs, rhs) {
info:characterInfo[general.personal] if (lhs.reserved > rhs.reserved) {
}); return -1;
}
return general; if (lhs.reserved < rhs.reserved) {
}); return 1;
}
generalList.sort(function(lhs, rhs){ if (lhs.total != rhs.total) {
if(lhs.reserved > rhs.reserved){ return rhs.total - lhs.total;
return -1; }
} if (lhs.leadership != rhs.leadership) {
if(lhs.reserved < rhs.reserved){ return rhs.leadership - lhs.total;
return 1; }
}
if(lhs.total != rhs.total){ if (lhs.name < rhs.name) {
return rhs.total - lhs.total; return -1;
} }
if(lhs.leadership != rhs.leadership){ if (lhs.name > rhs.name) {
return rhs.leadership - lhs.total; return 1;
} }
return 0;
if(lhs.name < rhs.name){ });
return -1;
} window.generalList = generalList;
if(lhs.name > rhs.name){ _printGeneralList(true);
return 1; }
}
return 0; function _printGeneralList(clear) {
}); var $generalTable = $('#general_list');
if (clear) {
window.generalList = generalList; $generalTable.empty();
_printGeneralList(true); $generalTable.data('lastIdx', 0);
} $('#row_print_more').show();
}
function _printGeneralList(clear){
var $generalTable = $('#general_list'); generalList = window.generalList;
if(clear){
$generalTable.empty(); var idxFrom = $generalTable.data('lastIdx');
$generalTable.data('lastIdx', 0); var idxTo = Math.min(idxFrom + 50, generalList.length);
$('#row_print_more').show(); $generalTable.data('lastIdx', idxTo);
}
for (var idx = idxFrom; idx < idxFrom + 50; idx++) {
generalList = window.generalList; var general = generalList[idx];
$generalTable.append(TemplateEngine(templateGeneralRow, general));
var idxFrom = $generalTable.data('lastIdx'); }
var idxTo = Math.min(idxFrom + 50, generalList.length);
$generalTable.data('lastIdx', idxTo); if (idxTo == generalList.length) {
$('#row_print_more').hide();
for(var idx = idxFrom; idx < idxFrom + 50; idx++){ }
var general = generalList[idx];
$generalTable.append(TemplateEngine(templateGeneralRow, general)); $generalTable.find('.obj_tooltip').tooltip({
} title: function() {
return $.trim($(this).find('.tooltiptext').html());
if(idxTo == generalList.length){ },
$('#row_print_more').hide(); html: true
} });
$('#tb_general_list').show();
$generalTable.find('.obj_tooltip').tooltip({ }
title:function(){
return $.trim($(this).find('.tooltiptext').html()); $(function($) {
}, window.generalList = [];
html:true
}); $.post('j_get_select_npc_token.php').then(function(value) {
$('#tb_general_list').show(); if (!value.result) {
} alert(value.reason);
return;
$(function($){ }
window.generalList = [];
console.log(value);
$.post('j_get_select_npc_token.php').then(function(value){ printGenerals(value);
if(!value.result){ });
alert(value.reason);
return; $('#btn_pick_more').click(function() {
} var generals = $.map($('.keep_select:checked'), function(value) {
return $(value).val();
console.log(value); });
printGenerals(value); console.log(generals);
}); $.post({
url: 'j_get_select_npc_token.php',
$('#btn_pick_more').click(function(){ dataType: 'json',
var generals = $.map($('.keep_select:checked'), function(value){ data: {
return $(value).val(); refresh: true,
}); keep: generals
console.log(generals); }
$.post({ }).then(function(result) {
url:'j_get_select_npc_token.php', if (!result.result) {
dataType:'json', alert(result.reason);
data:{ location.refresh();
refresh:true, }
keep:generals console.log(result);
} printGenerals(result);
}).then(function(result){ });
if(!result.result){ });
alert(result.reason);
location.refresh(); $('#btn_load_general_list').click(function() {
} $.post({
console.log(result); url: 'j_get_general_list.php',
printGenerals(result); dataType: 'json',
}); data: {
}); with_token: true
}
$('#btn_load_general_list').click(function(){ }).then(function(result) {
$.post({ if (!result.result) {
url:'j_get_general_list.php', alert(result.reason);
dataType:'json', return false;
data:{ }
with_token:true printGeneralList(result);
} });
}).then(function(result){ });
if(!result.result){
alert(result.reason); $('#btn_print_more').click(function() {
return false; _printGeneralList();
} })
printGeneralList(result);
});
});
$('#btn_print_more').click(function(){
_printGeneralList();
})
}); });
+74 -57
View File
@@ -1,57 +1,74 @@
<?php <?php
namespace sammo; namespace sammo;
/** @var \Composer\Autoload\ClassLoader $loader */ /** @var \Composer\Autoload\ClassLoader $loader */
$loader = require __DIR__.'/../vendor/autoload.php'; $loader = require __DIR__.'/../vendor/autoload.php';
$loader->addPsr4('sammo\\', __DIR__.'/sammo', true); $loader->addPsr4('sammo\\', __DIR__.'/sammo', true);
$loader->addClassMap((function () { $loader->addClassMap((function () {
$d_settingMap = []; $d_settingMap = [];
foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) { foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) {
$filepath = str_replace('.orig.php', '.php', $filepath); $filepath = str_replace('.orig.php', '.php', $filepath);
$filename = basename($filepath); $filename = basename($filepath);
$classname = explode('.', $filename)[0]; $classname = explode('.', $filename)[0];
$d_settingMap['sammo\\'.$classname] = $filepath; $d_settingMap['sammo\\'.$classname] = $filepath;
}; };
return $d_settingMap; return $d_settingMap;
})()); })());
//디버그용 매크로 //디버그용 매크로
ini_set("session.cache_expire", 10080); // minutes ini_set("session.cache_expire", 10080); // minutes
// 각종 변수 // 각종 변수
define('STEP_LOG', true); define('STEP_LOG', true);
define('PROCESS_LOG', true); define('PROCESS_LOG', true);
ob_start(); ob_start();
// 에러 메세지 출력 // 에러 메세지 출력
function Error($message='', $url="") function Error($message='', $url="")
{ {
if (!$url) { if (!$url) {
$url = $_SERVER['REQUEST_URI']; $url = $_SERVER['REQUEST_URI'];
} }
$e = new \Exception(); $e = new \Exception();
logError("aux_err", $message, '', getExceptionTraceAsString($e)); logError("aux_err", $message, '', getExceptionTraceAsString($e));
$templates = new \League\Plates\Engine(__DIR__.'/templates'); $templates = new \League\Plates\Engine(__DIR__.'/templates');
ob_get_flush(); ob_get_flush();
WebUtil::setHeaderNoCache(); WebUtil::setHeaderNoCache();
die($templates->render('error', [ die($templates->render('error', [
'message' => $message 'message' => $message
])); ]));
} }
function MessageBox($str) function MessageBox($str)
{ {
echo "<script>alert('$str');</script>"; echo "<script>alert('$str');</script>";
} }
function LogText($prefix, $variable) function LogText($prefix, $variable)
{ {
$text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable)); $text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable));
file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND); file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND);
} }
function prepareDir(string $dirPath, bool $forceCreate=true):bool{
if(file_exists($dirPath)){
if(is_dir($dirPath)){
return true;
}
if(!$forceCreate){
throw new \RuntimeException('이미 파일이 있습니다');
}
if(!unlink($dirPath)){
return false;
}
return mkdir($dirPath);
}
return mkdir($dirPath, 0777, true);
}
+7 -3
View File
@@ -558,13 +558,17 @@ function ConquerCity(array $admin, General $general, array $city) {
} }
} }
//NPC인 경우 10% 확률로 임관(엔장, 인재, 의병) //NPC인 경우 일정 확률로 임관(엔장, 인재, 의병)
$npcType = $oldGeneral->getNPCType(); $npcType = $oldGeneral->getNPCType();
if($admin['join_mode'] != 'onlyRandom' && 2 <= $npcType && $npcType <= 8 && $npcType != 5 && Util::randBool(0.1)) { if($admin['join_mode'] != 'onlyRandom' && 2 <= $npcType && $npcType <= 8 && $npcType != 5 && Util::randBool(GameConst::$joinRuinedNPCProp)) {
$cmd = buildGeneralCommandClass('che_임관', $oldGeneral, $admin, [ $cmd = buildGeneralCommandClass('che_임관', $oldGeneral, $admin, [
'destNationID'=>$attackerNationID 'destNationID'=>$attackerNationID
]); ]);
_setGeneralCommand($cmd, [0]); $joinTurn = Util::randRangeInt(0, 12);
if($joinTurn){
_setGeneralCommand(buildGeneralCommandClass('che_견문', $oldGeneral, $admin), iterator_to_array(Util::range($joinTurn)));
}
_setGeneralCommand($cmd, [$joinTurn]);
} }
} }
+4
View File
@@ -0,0 +1,4 @@
<?php
require('../vendor/autoload.php');
//ParsedownExtra;
+31 -21
View File
@@ -1,22 +1,32 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_삼략 extends \sammo\BaseItem{ class che_계략_삼략 extends \sammo\BaseItem{
protected $id = 22; protected $id = 22;
protected $rawName = '삼략'; protected $rawName = '삼략';
protected $name = '삼략(계략)'; protected $name = '삼략(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.2; if($varType == 'success') return $value + 0.2;
} }
return $value; return $value;
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.1;
}
if($statName === 'warMagicSuccessProb'){
return $value + 0.1;
}
return $value;
}
} }
+31 -21
View File
@@ -1,22 +1,32 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_육도 extends \sammo\BaseItem{ class che_계략_육도 extends \sammo\BaseItem{
protected $id = 21; protected $id = 21;
protected $rawName = '육도'; protected $rawName = '육도';
protected $name = '육도(계략)'; protected $name = '육도(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.2; if($varType == 'success') return $value + 0.2;
} }
return $value; return $value;
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.1;
}
if($statName === 'warMagicSuccessProb'){
return $value + 0.1;
}
return $value;
}
} }
+30 -30
View File
@@ -1,31 +1,31 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_이추 extends \sammo\BaseItem{ class che_계략_이추 extends \sammo\BaseItem{
protected $id = 5; protected $id = 5;
protected $rawName = '이추'; protected $rawName = '이추';
protected $name = '이추(계략)'; protected $name = '이추(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +10%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p';
protected $cost = 1000; protected $cost = 1000;
protected $consumable = true; protected $consumable = true;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 1000; protected $reqSecu = 1000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.1; if($varType == 'success') return $value + 0.2;
} }
return $value; return $value;
} }
function isConsumableNow(string $actionType, string $command):bool{ function isConsumableNow(string $actionType, string $command):bool{
if($actionType == 'GeneralCommand' && $command == '계략'){ if($actionType == 'GeneralCommand' && $command == '계략'){
return true; return true;
} }
return false; return false;
} }
} }
+30 -30
View File
@@ -1,31 +1,31 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_향낭 extends \sammo\BaseItem{ class che_계략_향낭 extends \sammo\BaseItem{
protected $id = 5; protected $id = 5;
protected $rawName = '항냥'; protected $rawName = '항냥';
protected $name = '항냥(계략)'; protected $name = '항냥(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +50%p';
protected $cost = 3000; protected $cost = 3000;
protected $consumable = true; protected $consumable = true;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 2000; protected $reqSecu = 2000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.2; if($varType == 'success') return $value + 0.5;
} }
return $value; return $value;
} }
function isConsumableNow(string $actionType, string $command):bool{ function isConsumableNow(string $actionType, string $command):bool{
if($actionType == 'GeneralCommand' && $command == '계략'){ if($actionType == 'GeneralCommand' && $command == '계략'){
return true; return true;
} }
return false; return false;
} }
} }
@@ -0,0 +1,29 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_반계시도;
use \sammo\WarUnitTrigger\che_반계발동;
class che_반계_백우선 extends \sammo\BaseItem{
protected $id = 45;
protected $rawName = '백우선';
protected $name = '백우선(반계)';
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
new che_반계시도($unit),
new che_반계발동($unit)
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_반계시도;
use \sammo\WarUnitTrigger\che_반계발동;
class che_반계_파초선 extends \sammo\BaseItem{
protected $id = 45;
protected $rawName = '파초선';
protected $name = '파초선(반계)';
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
new che_반계시도($unit),
new che_반계발동($unit)
);
}
}
@@ -0,0 +1,34 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use sammo\BaseWarUnitTrigger;
use sammo\WarUnitTrigger\che_부상무효;
use sammo\WarUnitTrigger\WarActivateSkills;
class che_부적_태현청생부 extends \sammo\BaseItem{
protected $id = 9;
protected $rawName = '태현청생부';
protected $name = '태현청생부(부적)';
protected $info = '[전투] 저격 불가, 부상 없음';
protected $cost = 200;
protected $consumable = false;
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE),
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
);
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
);
}
}
@@ -0,0 +1,35 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도;
class che_의술_상한잡병론 extends \sammo\BaseItem{
protected $id = 24;
protected $rawName = '상한잡병론';
protected $name = '상한잡병론(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200;
protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general)
);
}
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
);
}
}
+34 -34
View File
@@ -1,35 +1,35 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\GeneralTrigger; use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller; use \sammo\GeneralTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동; use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도; use sammo\WarUnitTrigger\che_전투치료시도;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
class che_의술_청낭서 extends \sammo\BaseItem{ class che_의술_청낭서 extends \sammo\BaseItem{
protected $id = 23; protected $id = 23;
protected $rawName = '청낭서'; protected $rawName = '청낭서';
protected $name = '청낭서(의술)'; protected $name = '청낭서(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general) new GeneralTrigger\che_도시치료($general)
); );
} }
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{ {
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM), new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM) new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
); );
} }
} }
@@ -1,35 +1,35 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\GeneralTrigger; use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller; use \sammo\GeneralTriggerCaller;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동; use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도; use sammo\WarUnitTrigger\che_전투치료시도;
class che_의술_태평청령 extends \sammo\BaseItem{ class che_의술_태평청령 extends \sammo\BaseItem{
protected $id = 24; protected $id = 24;
protected $rawName = '태평청령'; protected $rawName = '태평청령';
protected $name = '태평청령(의술)'; protected $name = '태평청령(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general) new GeneralTrigger\che_도시치료($general)
); );
} }
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{ {
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM), new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM) new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
); );
} }
} }
@@ -0,0 +1,26 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동;
class che_저격_매화수전 extends \sammo\BaseItem{
protected $id = 70;
protected $rawName = '매화수전';
protected $name = '매화수전(저격)';
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
@@ -0,0 +1,26 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동;
class che_저격_비도 extends \sammo\BaseItem{
protected $id = 70;
protected $rawName = '비도';
protected $name = '비도(저격)';
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM, 0.5, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
+27 -27
View File
@@ -1,28 +1,28 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use \sammo\WarUnit; use \sammo\WarUnit;
use \sammo\WarUnitTrigger\che_저격시도; use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동; use \sammo\WarUnitTrigger\che_저격발동;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
class che_저격_수극 extends \sammo\BaseItem{ class che_저격_수극 extends \sammo\BaseItem{
protected $id = 2; protected $id = 2;
protected $rawName = '수극'; protected $rawName = '수극';
protected $name = '수극(저격)'; protected $name = '수극(저격)';
protected $info = '[전투] 전투 개시 전 20% 확률로 저격 시도. 1회용'; protected $info = '[전투] 전투 개시 전 50% 확률로 저격 시도. 1회용';
protected $cost = 1000; protected $cost = 1000;
protected $consumable = true; protected $consumable = true;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 1000; protected $reqSecu = 1000;
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.2, 20, 40), new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.5, 20, 40),
new che_저격발동($unit) new che_저격발동($unit)
); );
} }
} }
+1 -1
View File
@@ -18,7 +18,7 @@ class che_치료_환약 extends \sammo\BaseItem{
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_아이템치료($general) new GeneralTrigger\che_아이템치료($general, $general->getAuxVar('use_treatment')??10)
); );
} }
@@ -0,0 +1,21 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
class che_행동_서촉지형도 extends \sammo\BaseItem{
protected $id = 22;
protected $rawName = '서촉지형도';
protected $name = '서촉지형도(행동)';
protected $info = '[전투] 공격 시 페이즈 + 2';
protected $cost = 200;
protected $consumable = false;
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'initWarPhase'){
return $value + 2;
}
return $value;
}
}
@@ -0,0 +1,29 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_격노시도;
use sammo\WarUnitTrigger\che_격노발동;
class event_전투특기_격노 extends \sammo\BaseItem{
protected $id = 74;
protected $rawName = '비급';
protected $name = '비급(격노)';
protected $info = '[전투] 상대방 필살 시 격노(필살) 발동, 회피 시도시 25% 확률로 격노 발동, 공격 시 일정 확률로 진노(1페이즈 추가)';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_격노시도($unit),
new che_격노발동($unit)
);
}
}
@@ -0,0 +1,49 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\GameUnitConst;
use \sammo\WarUnit;
use \sammo\WarUnitCity;
class event_전투특기_공성 extends \sammo\BaseItem{
protected $id = 53;
protected $rawName = '비급';
protected $name = '비급(공성)';
protected $info = '[군사] 차병 계통 징·모병비 -10%<br>[전투] 성벽 공격 시 대미지 +100%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 차병 숙련을 가산';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_SIEGE) return $value * 0.9;
}
return $value;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->getOppose() instanceof WarUnitCity){
return [2, 1];
}
return [1, 1];
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_SIEGE;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
}
@@ -0,0 +1,44 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\GameUnitConst;
class event_전투특기_궁병 extends \sammo\BaseItem{
protected $id = 51;
protected $rawName = '비급';
protected $name = '비급(궁병)';
protected $info = '[군사] 궁병 계통 징·모병비 -10%<br>[전투] 회피 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 궁병 숙련을 가산';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_ARCHER) return $value * 0.9;
}
return $value;
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warAvoidRatio'){
return $value + 0.2;
}
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_ARCHER;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
}
@@ -0,0 +1,44 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\GameUnitConst;
use \sammo\WarUnit;
class event_전투특기_귀병 extends \sammo\BaseItem{
protected $id = 40;
protected $rawName = '비급';
protected $name = '비급(귀병)';
protected $info = '[군사] 귀병 계통 징·모병비 -10%<br>[전투] 계략 성공 확률 +20%p,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 귀병 숙련을 가산';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_WIZARD) return $value * 0.9;
}
return $value;
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicSuccessProb'){
return $value + 0.2;
}
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_WIZARD;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
}
@@ -0,0 +1,48 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\GameUnitConst;
use \sammo\WarUnit;
class event_전투특기_기병 extends \sammo\BaseItem{
protected $id = 52;
protected $rawName = '비급';
protected $name = '비급(기병)';
protected $info = '[군사] 기병 계통 징·모병비 -10%<br>[전투] 수비 시 대미지 +10%, 공격 시 대미지 +20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 기병 숙련을 가산';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_CAVALRY) return $value * 0.9;
}
return $value;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->isAttacker()){
return [1.2, 1];
}
return [1.1, 1];
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_CAVALRY;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
}
@@ -0,0 +1,41 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_돌격지속;
class event_전투특기_돌격 extends \sammo\BaseItem{
protected $id = 60;
protected $rawName = '비급';
protected $name = '비급(돌격)';
protected $info = '[전투] 공격 시 대등/유리한 병종에게는 퇴각 전까지 전투, 공격 시 페이즈 + 2, 공격 시 대미지 +5%';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'initWarPhase'){
return $value + 2;
}
return $value;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->isAttacker()){
return [1.05, 1];
}
return [1, 1];
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_돌격지속($unit)
);
}
}
@@ -0,0 +1,35 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use \sammo\Util;
class event_전투특기_무쌍 extends \sammo\BaseItem{
protected $id = 61;
protected $rawName = '비급';
protected $name = '비급(무쌍)';
protected $info = '[전투] 대미지 +10%, 공격 시 필살 확률 +10%p, <br>승리 수만큼 대미지 0.20%씩 추가 상승(최대40%)<br>승리 수만큼 피해 0.05%씩 감소(최대50%)';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warCriticalRatio' && $aux['isAttacker']??false){
return $value += 0.1;
}
return $value;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
$attackMultiplier = 1.1;
$defenceMultiplier = 1;
$killnum = $unit->getGeneral()->getRankVar('killnum');
$attackMultiplier += Util::valueFit($killnum * 0.01 * 0.2, null, 0.4);
$defenceMultiplier -= Util::valueFit($killnum * 0.01 * 0.05, null, 0.5);
return [$attackMultiplier, $defenceMultiplier];
}
}
@@ -0,0 +1,38 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_반계시도;
use \sammo\WarUnitTrigger\che_반계발동;
class event_전투특기_반계 extends \sammo\BaseItem{
protected $id = 45;
protected $rawName = '비급';
protected $name = '비급(반계)';
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림, 반목 성공시 대미지 추가(+60% → +150%)';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicSuccessDamage' && $aux === '반목'){
return $value + 0.9;
}
return $value;
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '계략약화'),
new che_반계시도($unit),
new che_반계발동($unit)
);
}
}
@@ -0,0 +1,49 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\GameUnitConst;
use \sammo\WarUnit;
class event_전투특기_보병 extends \sammo\BaseItem{
protected $id = 50;
protected $rawName = '비급';
protected $name = '비급(보병)';
protected $info = '[군사] 보병 계통 징·모병비 -10%<br>[전투] 공격 시 아군 피해 -10%, 수비 시 아군 피해 -20%,<br>공격시 상대 병종에/수비시 자신 병종 숙련에 보병 숙련을 가산';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if(in_array($turnType, ['징병', '모병'])){
if($varType == 'cost' && $aux['armType'] == GameUnitConst::T_FOOTMAN) return $value * 0.9;
}
return $value;
}
public function getWarPowerMultiplier(WarUnit $unit):array{
if($unit->isAttacker()){
return [1, 0.9];
}
return [1, 0.8];
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if(\sammo\Util::starts_with($statName, 'dex')){
$myArmType = 'dex'.GameUnitConst::T_FOOTMAN;
$opposeArmType = 'dex'.$aux['opposeType']->armType;;
if($aux['isAttacker'] && $opposeArmType === $statName){
return $value + $general->getVar($myArmType);
}
if(!$aux['isAttacker'] && $myArmType === $statName){
return $value + $general->getVar($myArmType);
}
}
return $value;
}
}
@@ -0,0 +1,36 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
class event_전투특기_신산 extends \sammo\BaseItem{
protected $id = 41;
protected $rawName = '비급';
protected $name = '비급(신산)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +10%p<br>[전투] 계략 시도 확률 +20%p, 계략 성공 확률 +20%p';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){
if($varType == 'success') return $value + 0.1;
}
return $value;
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.2;
}
if($statName === 'warMagicSuccessProb'){
return $value + 0.2;
}
return $value;
}
}
@@ -0,0 +1,25 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
class event_전투특기_신중 extends \sammo\BaseItem{
protected $id = 44;
protected $rawName = '비급';
protected $name = '비급(신중)';
protected $info = '[전투] 계략 성공 확률 100%';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicSuccessProb'){
return $value + 1;
}
return $value;
}
}
@@ -0,0 +1,31 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\WarUnitTrigger\che_위압시도;
use \sammo\WarUnitTrigger\che_위압발동;
class event_전투특기_위압 extends \sammo\BaseItem{
protected $id = 63;
protected $rawName = '비급';
protected $name = '비급(위압)';
protected $info = '[전투] 첫 페이즈 위압 발동(적 공격, 회피 불가, 사기 5 감소)';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
if($unit->getPhase() != 0){
return null;
}
return new WarUnitTriggerCaller(
new che_위압시도($unit),
new che_위압발동($unit)
);
}
}
@@ -0,0 +1,38 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use sammo\BaseGeneralTrigger;
use sammo\SpecialityHelper;
use \sammo\General;
use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller;
use \sammo\WarUnit;
use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도;
use sammo\WarUnitTriggerCaller;
class event_전투특기_의술 extends \sammo\BaseItem{
protected $id = 73;
protected $rawName = '비급';
protected $name = '비급(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 100;
protected $buyable = true;
protected $consumable = false;
protected $reqSecu = 3000;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general)
);
}
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new che_전투치료시도($unit, che_전투치료시도::TYPE_ITEM),
new che_전투치료발동($unit)
);
}
}

Some files were not shown because too many files have changed in this diff Show More