Compare commits

..
191 Commits
Author SHA1 Message Date
Hide_D f33e645113 초반 m장 스탯 관련 문제 해결, 장수 선택 term 해결 2021-01-01 21:09:43 +09:00
Hide_D 528d30c317 의병모집 버그 수정 2021-01-01 19:56:29 +09:00
Hide_D 7f0a3d320c 버그 수정
- 의병 모집
- 장수 변경 시 생성 폼 남음
2021-01-01 19:54:28 +09:00
Hide_D 8e940aeb65 버그 수정. 시간 변경 2020-12-31 16:21:57 +09:00
Hide_D a77ee60809 버그.. 2020-12-31 13:34:37 +09:00
Hide_D 83383c29cd 버그 수정2 2020-12-31 13:33:45 +09:00
Hide_D b6393141e8 버그 수정 2020-12-31 13:29:57 +09:00
Hide_D 10ce1827d8 버그 수정 2020-12-31 13:27:11 +09:00
Hide_D 605f3a12ff select pool 수 증가 2020-12-31 13:24:33 +09:00
Hide_D a33539e75f 턴 변경을 합리적으로 변경 2020-12-31 08:09:23 +09:00
Hide_D b2cca3687a 버그 수정 2020-12-31 07:49:33 +09:00
Hide_D 628c54044f general_pool 에서 장수 선택 기능 추가 2020-12-31 07:43:56 +09:00
Hide_D c0e7a3eece readme 수정 2020-12-27 19:49:39 +09:00
Hide_D c7c13c19c1 일부 수정
composer update, README.md 업데이트
2020-12-27 02:11:53 +09:00
Hide_D d5f71b5878 DummySession 준비 2020-12-26 15:48:05 +09:00
Hide_D cb589e9e26 종전수락 버그 수정 2020-12-13 22:05:07 +09:00
Hide_D eaeed47297 도시 정보 출력 순서 변경 2020-11-11 23:34:53 +09:00
Hide_D e00e5c5cd7 이벤트 빼빼로 추가 2020-11-11 23:04:08 +09:00
Hide_D b3719f7166 수극 연속 사용 버그 수정 2020-09-09 14:20:15 +09:00
Hide_D 337896974b 피장파장 로그 버그 수정 2020-09-09 14:20:15 +09:00
Hide_D bb7d1fc9ab 수몰을 아무 국가에나 쓸 수 있는 버그 수정 2020-09-09 14:20:15 +09:00
Hide_D 07765c8d44 훈사 제한 버그 2020-08-17 09:21:37 +09:00
Hide_D 85cb91071e 기본 도시 정보 데이터 대폭 추가 2020-08-15 03:46:43 +09:00
Hide_D d41839845a 귀병 첫 페이즈 매우 높은 확률로 계략 시도 2020-08-11 22:43:45 +09:00
Hide_D c3d12aa55f 전쟁/선포 중인 국가에 선포 확률 대폭 감소 2020-08-11 22:36:26 +09:00
Hide_D a781e4b84c 인탐 성공 시 확률따라 추가 보정, 인탐/의병 지장 버그 수정 2020-08-11 22:33:50 +09:00
Hide_D 1fc0989fd2 계략 강화, 탈취량 시간에 따라 증가 2020-08-11 22:33:00 +09:00
Hide_D 14752260d3 회피 필살 중첩 가능 2020-07-24 14:19:05 +09:00
Hide_D 84675c874f 이호경식 버그 수정 2020-07-21 22:38:53 +09:00
Hide_D f30e6057be 버그 테스트 2020-07-21 22:34:10 +09:00
Hide_D ba8b629f0e 격노비급 버그 수정 2020-07-21 03:41:27 +09:00
Hide_D a0a45ff2aa 격노 비급 버그 수정 2020-07-21 03:32:37 +09:00
Hide_D 325f890a0b 방랑시 버그 수정 2020-07-20 23:24:15 +09:00
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
416 changed files with 49350 additions and 29034 deletions
+53 -50
View File
@@ -1,50 +1,53 @@
.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/*.webp
d_pic/uploaded_image
d_setting/*.php
*/d_setting/*.php d_setting/*.php
*/d_setting/templates/*.php */d_setting/*.php
*/d_setting/templates/*.php
**/old/*
test.php */data/file_cache
/che **/old/*
/kwe test.php
/pwe
/nya /che
/pya /kwe
/twe /pwe
/nya
phpinfo.php /pya
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/* /twe
*.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>
+5 -5
View File
@@ -9,18 +9,18 @@
* <code>mpm_event</code> 권장 * <code>mpm_event</code> 권장
* PHP 7.3 이상 * PHP 7.3 이상
* <code>php-fpm</code> 권장 * <code>php-fpm</code> 권장
* php에서 curl, pdo-sqlite을 실행가능해야 합니다. (기본값: 지원) * php에서 curl, pdo-sqlite을 실행가능해야 합니다.
* mysqlnd가 지원되어야합니다. (기본값: 지원) * mysqli, mysqlnd
* mysqli
* gd * gd
* mbstring
* MariaDB 10.2.1 이상 * MariaDB 10.2.1 이상
* 현재 MySQL은 지원하지 않습니다. * 현재 MySQL은 지원하지 않습니다.
* <code>git</code> * <code>git</code>
* <code>curl</code> * <code>curl</code>
Linux는 Ubuntu 16.04, 18.04, Windows는 Windows 10에서 XAMPP를 사용한 환경에서 테스트되었습니다. Linux는 Ubuntu 18.04, 20.04, Windows는 Windows 10에서 XAMPP, WSL2를 사용한 환경에서 테스트되었습니다.
Docker를 이용한 설치는 계획중입니다. Docker를 이용한 설치는 테스트버전만 제공됩니다.
## Docker를 이용한 설치 ## Docker를 이용한 설치
+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"
} }
Regular → Executable
BIN
View File
Binary file not shown.
+240 -181
View File
@@ -1,182 +1,241 @@
@charset "utf-8"; @charset "utf-8";
body {
body { color: white;
color:white; background-color:black; font-family: '맑은 고딕'; background-color: black;
} font-family: '맑은 고딕';
}
table {
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black; table {
padding: 0px; border: solid 1px;
font-size: 13px; border-spacing: 0px;
word-break: break-all; border-collapse: separate;
text-align: center; border-top-color: gray;
font-family: '맑은 고딕'; border-left-color: gray;
} border-right-color: black;
th, td { border-bottom-color: black;
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black; padding: 0px;
padding: 0px; font-size: 13px;
font-size: 13px; word-break: break-all;
word-break: break-all; text-align: center;
text-align: center; font-family: '맑은 고딕';
font-family: '맑은 고딕'; }
}
th,
a.just_link { td {
text-decoration: none; border: solid 1px;
} border-spacing: 0px;
border-collapse: separate;
.with_border{ border-top-color: gray;
margin:0; border-left-color: gray;
border: solid 1px; border-right-color: black;
border-spacing: 0px; border-bottom-color: black;
border-collapse: separate; padding: 0px;
border-top-color: gray; font-size: 13px;
border-left-color: gray; word-break: break-all;
border-right-color: black; text-align: center;
border-bottom-color: black; font-family: '맑은 고딕';
} }
.section_title { a.just_link {
height:50px; text-decoration: none;
line-height:50px; }
font-size: 30px; font-weight: bold;
text-align: center; .with_border {
color:white; margin: 0;
padding:0; border: solid 1px;
} border-spacing: 0px;
border-collapse: separate;
.legacy_layout div { border-top-color: gray;
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black; border-left-color: gray;
padding: 0px; border-right-color: black;
font-size: 13px; border-bottom-color: black;
word-break: break-all; }
text-align: center;
font-family: '맑은 고딕';; .section_title {
} height: 50px;
line-height: 50px;
.obj_fill{ font-size: 30px;
display:block; font-weight: bold;
width:100%; text-align: center;
height:100%; color: white;
} padding: 0;
}
button.with_skin {
padding:0 4px; .legacy_layout div {
background-color: black; color: white; border: solid 1px;
font-family: '맑은 고딕'; border-spacing: 0px;
font-size: 13px; border-collapse: separate;
} border-top-color: gray;
border-left-color: gray;
button.with_skin:disabled { border-right-color: black;
background-color:#333333; border-bottom-color: black;
} padding: 0px;
font-size: 13px;
input.with_skin { word-break: break-all;
background-color: black; color: white; text-align: center;
font-family: '맑은 고딕'; font-family: '맑은 고딕';
font-size: 13px; ;
} }
input.with_skin:disabled { .obj_fill {
background-color: #333333; display: block;
} width: 100%;
height: 100%;
.font0 { font-size: 10px; } }
.font1 { font-size: 13px; }
.font2 { font-size: 15px; } button.with_skin {
.font3 { font-size: 20px; } padding: 0 4px;
.font4 { font-size: 30px; } background-color: black;
.font5 { font-size: 50px; } color: white;
font-family: '맑은 고딕';
caption.section_title { font-size: 13px;
caption-side:top; }
}
button.with_skin:disabled {
background-color: #333333;
.samButton{ }
float:left;
display:block; input.with_skin {
padding:0; background-color: black;
margin:0; color: white;
text-decoration: none; font-family: '맑은 고딕';
position:relative; font-size: 13px;
} }
a.samButton.disabled { input.with_skin:disabled {
pointer-events: none; background-color: #333333;
cursor: default; }
}
.font0 {
.samButtonOuter{ font-size: 10px;
display: table; }
border: outset 2px white;
box-sizing: border-box; .font1 {
font-weight:bold; font-size: 13px;
padding: 1px 6px; }
width:125px;
height:30px; .font2 {
background-color:#000000; font-size: 15px;
color:#ffffff; }
}
.font3 {
.samButtonOuter:active{ font-size: 20px;
border: inset 2px white; }
}
.font4 {
font-size: 30px;
.samButtonInner{ }
display: table-cell;
vertical-align: middle; .font5 {
width: 100%; font-size: 50px;
margin: 0 auto; }
text-align: center;
user-select: none; caption.section_title {
} caption-side: top;
}
.samToolbarButton > .samButtonOuter{
width:125px; .samButton {
height:30px; float: left;
background-color:#225500; display: block;
color:white; padding: 0;
} margin: 0;
text-decoration: none;
.samToolbarButton2 > .samButtonOuter{ position: relative;
width:125px; }
height:30px;
background-color:#225500; a.samButton.disabled {
color:magenta; pointer-events: none;
} cursor: default;
}
.samCommandButton > .samButtonOuter{
width:111px; .samButtonOuter {
height:30px; display: table;
} border: outset 2px white;
box-sizing: border-box;
.samCommandButton.disabled > .samButtonOuter{ font-weight: bold;
background-color:transparent !important; padding: 1px 6px;
color:gray !important; width: 125px;
border-color:transparent !important; height: 30px;
} background-color: #000000;
color: #ffffff;
.samCommandButton.disabled > .samButtonOuter > .samButtonInner::before{ }
content:'【'
} .samButtonOuter:active {
border: inset 2px white;
.samCommandButton.disabled > .samButtonOuter > .samButtonInner::after{ }
content:'】'
} .samButtonInner {
display: table-cell;
.tooltip_copyable_info .tooltiptext{ vertical-align: middle;
display: inline; width: 100%;
color: rgba(0,0,0,0); margin: 0 auto;
font-size: 0; text-align: center;
} user-select: none;
}
.tooltiptext {
display: none; .samToolbarButton>.samButtonOuter {
} width: 125px;
height: 30px;
.hidden_but_copyable{ background-color: #225500;
color: rgba(0,0,0,0); color: white;
font-size: 0; }
.samToolbarButton2>.samButtonOuter {
width: 125px;
height: 30px;
background-color: #225500;
color: magenta;
}
.samCommandButton>.samButtonOuter {
width: 111px;
height: 30px;
}
.samCommandButton.disabled>.samButtonOuter {
background-color: transparent !important;
color: gray !important;
border-color: transparent !important;
}
.samCommandButton.disabled>.samButtonOuter>.samButtonInner::before {
content: '【'
}
.samCommandButton.disabled>.samButtonOuter>.samButtonInner::after {
content: '】'
}
.tooltip_copyable_info .tooltiptext {
display: inline;
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.tooltiptext {
display: none;
}
.hidden_but_copyable {
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.vertical_flex {
height: 100%;
display: flex;
align-content: center;
flex-direction: column;
align-items: stretch;
}
.vertical_flex .item {
display: block;
flex-grow: 1;
}
.fill_box {
display: block;
width: 100%;
height: 100%;
} }
+155 -140
View File
@@ -1,141 +1,156 @@
@charset "utf-8"; @charset "utf-8";
body {
body{ line-height: 1.3;
line-height: 1.3; }
}
#server_notice {
#server_notice { margin: 10px 0;
margin:10px 0; border: none;
border: none; text-align: center;
text-align:center; }
}
#server_list_container {
#server_list_container{ width: 800px;
width:800px; position: absolute;
position:absolute; left: 50%;
left:50%; margin-left: -400px;
margin-left:-400px; }
}
#server_list_table {
#server_list_table{ width: 100%;
width:100%; }
}
#server_list tr {
#server_list tr{ height: 66px;
height:66px; }
}
.ignore_border {
#server_list .server_create_and_select .general_create, border: 0;
#server_list .server_create_and_select .general_select { margin: 0;
width: 120px; height: 33px; padding: 0;
float: left; }
}
#user_info {
#server_list .general_create, margin-top: 20px;
#server_list .general_login { width: 800px;
width: 120px; height: 66px; height: 130px;
float: left; }
}
#user_info button {
.ignore_border{ width: 200px;
border:0; height: 50px;
margin:0; margin: 10px 50px;
padding:0; }
}
.center_ordered_items {
#user_info { text-align: center;
margin-top:20px; }
width: 800px; height: 130px;
} .Entrance_ServerList {
width: 800px;
height: 64px;
#user_info button{ border: none;
width: 200px; float: left;
height: 50px; }
margin: 10px 50px;
} .Entrance_ServerListServer {
width: 98px;
.center_ordered_items{ height: 64px;
text-align:center; float: left;
} }
.Entrance_ServerList { .Entrance_ServerListDown {
width: 800px; height: 64px; width: 698px;
border: none; height: 64px;
float: left; float: left;
} }
.Entrance_ServerListServer { .Entrance_ServerListInfo {
width: 98px; height: 64px; width: 398px;
float: left; height: 64px;
} float: left;
}
.Entrance_ServerListDown {
width: 698px; height: 64px; .Entrance_ServerListBlock {
float: left; width: 298px;
} height: 64px;
float: left;
.Entrance_ServerListInfo { line-height: 64px;
width: 398px; height: 64px; }
float: left;
} .Entrance_ServerListCharacter {
width: 64px;
.Entrance_ServerListBlock { height: 64px;
width: 298px; height: 64px; float: left;
float: left; }
line-height: 64px;
} .Entrance_ServerListName {
width: 112px;
.Entrance_ServerListCharacter { height: 64px;
width: 64px; height: 64px; float: left;
float: left; line-height: 64px;
} }
.Entrance_ServerListName { .Entrance_ServerListSelect {
width: 112px; height: 64px; width: 120px;
float: left; height: 32px;
line-height: 64px; float: left;
} }
#Entrance_000003 {
.Entrance_ServerListSelect { width: 798px;
width: 120px; height: 32px; height: 155px;
float: left; text-align: left;
} }
#Entrance_000003 { .Entrance_Alert {
width: 798px; height: 155px; color: red;
text-align: left; font-size: 15px;
} font-weight: bold;
}
.Entrance_Alert {
color: red; font-size: 15px; font-weight: bold; .Entrance_Che {
} color: white;
font-size: 15px;
.Entrance_Che { font-weight: bold;
color: white; font-size: 15px; font-weight: bold; }
}
.Entrance_Kwe {
.Entrance_Kwe { color: yellow;
color: yellow; font-size: 15px; font-weight: bold; font-size: 15px;
} font-weight: bold;
}
.Entrance_Pwe {
color: orange; font-size: 15px; font-weight: bold; .Entrance_Pwe {
} color: orange;
font-size: 15px;
.Entrance_Twe { font-weight: bold;
color: magenta; font-size: 15px; font-weight: bold; }
}
.Entrance_Twe {
.Entrance_Nya { color: magenta;
color: #e67e22; font-size: 15px; font-weight: bold; font-size: 15px;
} font-weight: bold;
}
.Entrance_Pya {
color: #9b59b6; font-size: 15px; font-weight: bold; .Entrance_Nya {
} color: #e67e22;
font-size: 15px;
.Entrance_Hwe { font-weight: bold;
color: red; font-size: 15px; font-weight: bold; }
.Entrance_Pya {
color: #9b59b6;
font-size: 15px;
font-weight: bold;
}
.Entrance_Hwe {
color: red;
font-size: 15px;
font-weight: bold;
}
.BtnPlate {
height: inherit;
} }
+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
+64 -11
View File
@@ -148,8 +148,30 @@ echo "
unset($city); unset($city);
// 첩보된 도시까지만 허용 // 첩보된 도시까지만 허용
if($valid == 0 && $userGrade < 5) {
$showDetailedInfo = false;
if($valid){
$showDetailedInfo = true;
}
if(!key_exists($citylist, CityConst::all())){
$citylist = $me['city']; $citylist = $me['city'];
$showDetailedInfo = true;
$valid = 1;
}
if($userGrade >= 5){
$valid = true;
}
if(!$valid) {
$ownCities = Util::convertArrayToSetLike($db->queryFirstColumn('SELECT city FROM city WHERE nation = %i AND nation != 0', $me['nation']));
foreach(array_keys(CityConst::byID($citylist)->path) as $pathID){
if(key_exists($pathID, $ownCities)){
$showDetailedInfo = true;
break;
}
}
} }
@@ -172,11 +194,35 @@ if($city['trade'] === null) {
} }
$dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'], 2)[0]; $dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'], 2)[0];
$generals = $db->query( if($showDetailedInfo){
'SELECT %l from general where city=%i order by name', $generals = $db->query(
Util::formatListOfBackticks($dbColumns), 'SELECT %l from general where city=%i order by turntime',
$city['city'] Util::formatListOfBackticks($dbColumns),
); $city['city']
);
}
else{
$generals = [];
}
if($valid){
$city['trustText'] = round($city['trust'], 1);
$city['popRateText'] = round($city['pop']/$city['pop_max']*100, 2);
}
else{
$city['agri'] = '?';
$city['comm'] = '?';
$city['pop'] = '?';
$city['secu'] = '?';
$city['trustText'] = '?';
$city['popRateText'] = '?';
if($city['nation'] != 0){
$city['def'] = '?';
$city['wall'] = '?';
}
}
$generalTurnList = []; $generalTurnList = [];
@@ -257,6 +303,10 @@ foreach($generals as $general){
$crew = $general['crew']; $crew = $general['crew'];
$train = -1; $train = -1;
$atmos = -1; $atmos = -1;
if(!$valid){
$crew = -1;
}
} }
$nation = $general['nation']; $nation = $general['nation'];
@@ -331,7 +381,9 @@ foreach($generalsFormat as $general){
} }
if($general['nation'] != $myNation['nation']){ if($general['nation'] != $myNation['nation']){
$enemyCnt += 1; $enemyCnt += 1;
$enemyCrew += $general['crew']; if($general['crew'] >= 0){
$enemyCrew += $general['crew'];
}
if($general['crew'] > 0){ if($general['crew'] > 0){
$enemyArmedCnt += 1; $enemyArmedCnt += 1;
} }
@@ -402,11 +454,11 @@ foreach($generalsFormat as $general){
</tr> </tr>
<tr> <tr>
<td align=center class=bg1>민심</td> <td align=center class=bg1>민심</td>
<td align=center><?=round($city['trust'], 1)?></td> <td align=center><?=$city['trustText']?></td>
<td align=center class=bg1>시세</td> <td align=center class=bg1>시세</td>
<td align=center><?=$city['trade']?>%</td> <td align=center><?=$city['trade']?>%</td>
<td align=center class=bg1>인구</td> <td align=center class=bg1>인구</td>
<td align=center><?=round($city['pop']/$city['pop_max']*100, 2)?>%</td> <td align=center><?=$city['popRateText']?>%</td>
<td align=center class=bg1>태수</td> <td align=center class=bg1>태수</td>
<td align=center><?=$officer[4]['name']?></td> <td align=center><?=$officer[4]['name']?></td>
<td align=center class=bg1>군사</td> <td align=center class=bg1>군사</td>
@@ -430,11 +482,12 @@ foreach($generalsFormat as $general){
</tr> </tr>
<tr> <tr>
<td align=center class=bg1>장수</td> <td align=center class=bg1>장수</td>
<td colspan=11><?=join(', ', $generalsName)?></td> <td colspan=11><?=$showDetailedInfo?join(', ', $generalsName):'<span style="color:gray">알 수 없음</span>'?></td>
</tr> </tr>
</table> </table>
<br> <br>
<?php if($showDetailedInfo): ?>
<table align=center class='tb_layout bg0'> <table align=center class='tb_layout bg0'>
<thead> <thead>
<tr> <tr>
@@ -459,7 +512,7 @@ foreach($generalsFormat as $general){
?> ?>
</tbody> </tbody>
</table> </table>
<?php endif; ?>
<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>
+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>
+165 -212
View File
@@ -1,212 +1,165 @@
<?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', 'npcmode']);
}
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($){ <?php if($gameStor->npcmode==2 && $me->getNPCType()==0): ?>
다른 장수 선택 (<?=substr($me->getAuxVar('next_change')??TimeUtil::now(), 0, 19)?> 부터)<br>
$('#die_immediately').click(function(){ <a href="select_general_from_pool.php" id='select_general_from_pool'><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>다른 장수 선택</button></a><br><br>
if(!availableDieImmediately){ <?php endif; ?>
alert('삭제를 위해서는 생성 후 2턴 가량의 시간이 필요합니다.');
location.reload(); 개인용 CSS<br>
return false; <textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea>
} </td>
return confirm('정말로 삭제하시겠습니까?'); </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>
</script> </tr>
</head> <tr>
<td valign=top>
<body> <div id='generalActionPlate'>
<table align=center width=1000 class='tb_layout bg0'> <?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?>
<tr><td>내 정 보<br><?=backButton()?></td></tr> </div>
</table> <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button>
<table align=center width=1000 class='tb_layout bg0'> </td>
<tr> <td valign=top>
<td width=50%> <div id='battleDetailPlate'>
<?php generalInfo($me); ?> <?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?>
<?php generalInfo2($me); ?> </div>
</td> <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button>
<td width=50% valign=top style="padding-left:4ch;"> </td>
<form name=form1 action=b_myPage.php method=post> </tr>
토너먼트 【 <tr>
<input type=radio name=tnmt value=0 <?=$me->getVar('tnmt')==0?"checked":""; ?>>수동참여 <td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td>
<input type=radio name=tnmt value=1 <?=$me->getVar('tnmt')==1?"checked":""; ?>>자동참여 <td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
】<br> </tr>
∞<font color=orange>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</font><br><br> <tr>
수비 【 <td valign=top>
<input type=radio name=defence_train value=80 <?=$me->getVar('defence_train')==80?"checked":""; ?>>◎(훈사80) <?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?>
<input type=radio name=defence_train value=60 <?=$me->getVar('defence_train')==60?"checked":""; ?>>○(훈사60) </td>
<input type=radio name=defence_train value=999 <?=$me->getVar('defence_train')==999?"checked":""; ?>>× <td valign=top>
】<br><br> <div id='battleResultPlate'>
<input type=<?=$submit?> name=btn style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px; value=설정저장><br> <?=formatHistoryToHTML(getBattleResultRecent($generalID, 24), 'battleResult')?>
∞<font color=orange>설정저장은 이달중 <?=$myset?>회 남았습니다.</font><br><br> </div>
</form> <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleResult">이전 로그 불러오기</button>
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?> </td>
휴 가 신 청<br> </tr>
<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> </table>
<?php endif; ?> <table align=center width=1000 class='tb_layout bg0'>
<!--빙의 해제용 삭턴 조절<br> <tr><td><?=backButton()?></td></tr>
<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>--> <tr><td><?=banner()?></td></tr>
</table>
<?php if($showDieImmediatelyBtn): ?> </body>
가오픈 기간 내 장수 삭제<br> </html>
<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){
+155 -135
View File
@@ -1,40 +1,56 @@
@charset "UTF-8"; @charset "UTF-8";
/* font-boostring Block */ /* font-boostring Block */
html * {max-height:1000000px;}
html * {
html, body{ max-height: 1000000px;
background-color:black;
color:white;
line-height:1.3;
font-family:'맑은 고딕';
font-size:13px;
} }
table { font-family:'맑은 고딕'; } html,
font { font-family:'맑은 고딕'; } body {
input { font-family:'맑은 고딕'; font-size:13px; } background-color: black;
select { font-family:'굴림'; line-height:100%; } color: white;
line-height: 1.3;
.center{ font-family: '맑은 고딕';
text-align:center; font-size: 13px;
} }
table.mimic_flex{ table {
font-family: '맑은 고딕';
}
font {
font-family: '맑은 고딕';
}
input {
font-family: '맑은 고딕';
font-size: 13px;
}
select {
font-family: '굴림';
line-height: 100%;
}
.center {
text-align: center;
}
table.mimic_flex {
border-collapse: collapse; border-collapse: collapse;
border:none; border: none;
padding:0; padding: 0;
} }
.mimic_flex td, .mimic_flex th { .mimic_flex td,
border:none !important; .mimic_flex th {
border: none !important;
padding: 0px; padding: 0px;
word-break: break-all; word-break: break-all;
} }
table.tb_layout {
table.tb_layout {
border-collapse: collapse; border-collapse: collapse;
padding: 0px; padding: 0px;
font-size: 13px; font-size: 13px;
@@ -42,159 +58,161 @@ table.tb_layout {
font-family: '맑은 고딕'; font-family: '맑은 고딕';
} }
.tb_layout td, .tb_layout th { .tb_layout td,
border:solid 1px gray; .tb_layout th {
border: solid 1px gray;
padding: 0px; padding: 0px;
word-break: break-all; word-break: break-all;
font-family: '맑은 고딕';; font-family: '맑은 고딕';
;
} }
div.bar_out{ div.bar_out {
position:relative; position: relative;
border-top:solid 1px #888888; border-top: solid 1px #888888;
border-bottom:solid 1px #333333; border-bottom: solid 1px #333333;
padding:0; padding: 0;
margin:0; margin: 0;
width:100%; width: 100%;
overflow: hidden; overflow: hidden;
} }
div.bar_out div{ div.bar_out div {
position:absolute; position: absolute;
left:0; left: 0;
top:0; top: 0;
height:100%; height: 100%;
} }
div.bar_out div.bar_in{ div.bar_out div.bar_in {
width:100%; width: 100%;
} }
/* */ /* */
.ev_warning{ .ev_warning {
color:orangered; color: orangered;
} }
.ev_notice{ .ev_notice {
color:orangered; color: orangered;
} }
.ev_succes{ .ev_succes {
color:lightgreen; color: lightgreen;
} }
.ev_sell{ .ev_sell {
color:orange; color: orange;
} }
.ev_failed{ .ev_failed {
color:orangered; color: orangered;
} }
.ev_highlight{ .ev_highlight {
color:orangered; color: orangered;
} }
/* TODO: 색상값이 아니라 의미에 따라 클래스 지정 */ /* TODO: 색상값이 아니라 의미에 따라 클래스 지정 */
.o_bullet::before{ .o_bullet::before {
color:cyan; color: cyan;
content:"●"; content: "●";
} }
.o_diamond::before{ .o_diamond::before {
color:orangered; color: orangered;
content:"◆"; content: "◆";
} }
.small_war_log{ .small_war_log {
display:inline-block; display: inline-block;
} }
.small_war_log .war_type_attack{ .small_war_log .war_type_attack {
color:cyan; color: cyan;
} }
.small_war_log .war_type_defense{ .small_war_log .war_type_defense {
color:magenta; color: magenta;
} }
.small_war_log .war_type_siege{ .small_war_log .war_type_siege {
color:white; color: white;
} }
.small_war_log .name_plate {
.small_war_log .name_plate{
font-size: 0.75em; font-size: 0.75em;
} }
.small_war_log .name_plate_cover{ .small_war_log .name_plate_cover {
color:yellow; color: yellow;
} }
.small_war_log .crew_plate{ .small_war_log .crew_plate {
color:orangered; color: orangered;
font-size:90%; font-size: 90%;
} }
.t_date{ .t_date {
font-size: 0.75em; font-size: 0.75em;
} }
.t_red{ .t_red {
color:red; color: red;
} }
.t_blue{ .t_blue {
color:blue; color: blue;
} }
.t_green{ .t_green {
color:green; color: green;
} }
.t_magenta{ .t_magenta {
color:magenta; color: magenta;
} }
.t_cyan{ .t_cyan {
color:cyan; color: cyan;
} }
.t_limegreen{ .t_limegreen {
color:limegreen; color: limegreen;
} }
.t_skyblue{ .t_skyblue {
color:skyblue; color: skyblue;
} }
.t_orangered{ .t_orangered {
color:orangered; color: orangered;
} }
.t_yellow{ .t_yellow {
color:yellow; color: yellow;
} }
.t_white{ .t_white {
color:white; color: white;
} }
.float_left{ .float_left {
float:left; float: left;
} }
.tooltip{ .tooltip {
font-size:12px; font-size: 12px;
font-family: '맑은 고딕'; font-family: '맑은 고딕';
} }
.tooltip_copyable_info .tooltiptext{ .tooltip_copyable_info .tooltiptext {
display: inline; display: inline;
color: rgba(0,0,0,0); color: rgba(0, 0, 0, 0);
font-size: 0; font-size: 0;
} }
@@ -202,67 +220,69 @@ div.bar_out div.bar_in{
display: none; display: none;
} }
.hidden_but_copyable{ .hidden_but_copyable {
color: rgba(0,0,0,0); color: rgba(0, 0, 0, 0);
font-size: 0; font-size: 0;
} }
.btn-group-xs > .btn, .btn-xs { .btn-group-xs>.btn,
padding : .25rem .4rem; .btn-xs {
font-size : .875rem; padding: .25rem .4rem;
line-height : .5; font-size: .875rem;
border-radius : .2rem; line-height: .5;
border-radius: .2rem;
} }
.edit_form.viewer{ .edit_form.viewer {
max-height:200px; max-height: 200px;
overflow-y:auto; overflow-y: auto;
} }
.trumbowyg-box{ .trumbowyg-box {
margin:0; margin: 0;
border-left:none; border-left: none;
border-right:none; border-right: none;
} }
.edit_form.trumbowyg-editor{ .edit_form.trumbowyg-editor {
margin:0; margin: 0;
padding:0; padding: 0;
} }
.commandBasic{ .commandBasic {
background-color:black; background-color: black;
color:white; color: white;
} }
.compensatePositive{ .compensatePositive {
color:skyblue; color: skyblue;
} }
.compensateNegative{ .compensateNegative {
color:orange; color: orange;
} }
.compensateNeutral{ .compensateNeutral {
color:white; color: white;
} }
.commandBasic.commandImpossible{ .commandBasic.commandImpossible {
background-color:red; background-color: red;
color:white; color: white;
} }
.select2-selection--single.simple-select2-align-center .select2-selection__rendered { .select2-selection--single.simple-select2-align-center .select2-selection__rendered {
text-align: center; text-align: center;
} }
.select2-dropdown.simple-select2-align-center li.select2-results__option{ .select2-dropdown.simple-select2-align-center li.select2-results__option {
text-align: center; text-align: center;
} }
.select2-container--bootstrap4 .select2-selection--single.text-secondary .select2-selection__rendered{ .select2-container--bootstrap4 .select2-selection--single.text-secondary .select2-selection__rendered {
color:white; color: white;
} }
.select2-container--bootstrap4 .text-secondary .select2-results__option[aria-selected=false]{ .select2-container--bootstrap4 .text-secondary .select2-results__option[aria-selected=false] {
color:white; color: white;
} }
+11
View File
@@ -0,0 +1,11 @@
#amount {
width: 100px;
}
#colorType {
width: 150px;
}
.no-padding .select2-results__option {
padding: 0;
}
+64
View File
@@ -0,0 +1,64 @@
@charset "UTF-8";
.container {
width: 1000px;
margin: 0 auto;
}
.card_holder {
text-align: center;
}
.general_card {
width: 125px;
display: inline-block;
}
.general_card h4 {
margin: 0;
}
.general_card p {
margin: 0;
}
.general_card .select_btn {
width: 100%;
}
.general_card label {
display: block;
padding-left: 15px;
text-indent: -15px;
}
.general_card input {
width: 13px;
height: 13px;
padding: 0;
margin: 0;
vertical-align: bottom;
position: relative;
top: -1px;
*overflow: hidden;
}
#outdate_token {
color: red;
display: none;
}
#left_pad button {
display: none;
}
.custom_picture {
display: none;
}
.custom_personality {
display: none;
}
.custom_stat {
display: none;
}
+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'
]; ];
} }
+24
View File
@@ -378,6 +378,30 @@ function buildWarUnitTriggerClass(?string $type, WarUnit $unit, ?array $args = n
return $class->newInstanceArgs(array_merge([$unit], $args)); return $class->newInstanceArgs(array_merge([$unit], $args));
} }
function getGeneralPoolClass(string $type){
static $basePath = __NAMESPACE__.'\\GeneralPool\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 GeneralPool이 아님");
}
/**
* @param \MeekroDB $db
* @param int $owner
* @param int $pickCnt
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array{
/** @var AbsGeneralPool */
$class = getGeneralPoolClass(GameConst::$targetGeneralPool);
return $class::pickGeneralFromPool($db, $owner, $pickCnt, $prefix);
}
function countPureGeneralFromRawList(?array $rawGeneralList=null):int{ function countPureGeneralFromRawList(?array $rawGeneralList=null):int{
if(!$rawGeneralList){ if(!$rawGeneralList){
return 0; return 0;
+1130 -1136
View File
@@ -1,1136 +1,1130 @@
<?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\GeneralBuilder(
$nation['nation'], sprintf('부대장%4d', $lastAssemblerID),
null, 0,
10, null,
10, $nation['nation']
10, );
1, $npcObj->setAffinity(999)->setStat(10, 10, 10)
$admin['year'] - 15, ->setSpecialSingle('척사')->setEgo('che_은둔')
$admin['year'] + 15, ->setKillturn(70)->setGoldRice(0, 0)
'은둔', ->setNPCType(5)->fillRemainSpecAsZero($admin);
'척사' $npcObj->build($admin);
); $npcID = $npcObj->getGeneralID();
$npcObj->killturn = 70;
$npcObj->gold = 0; $db->insert('troop', [
$npcObj->rice = 0; 'troop_leader' => $npcID,
$npcObj->npc = 5; 'name' => $npcObj->getGeneralName(),
$npcObj->build($admin); 'nation' => $nation['nation'],
$npcID = $npcObj->generalID; ]);
$db->update('general', [
$db->insert('troop', [ 'troop' => $npcID
'troop_leader' => $npcID, ], 'no=%i', $npcID);
'name' => $npcObj->realName,
'nation' => $nation['nation'], $cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin);
]); _setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn)));
$db->update('general', [ $assemblerCnt += 1;
'troop' => $npcID $gameStor->assembler_id = $lastAssemblerID;
], 'no=%i', $npcID); }
}
//TODO: 5턴간 집합턴 입력 }
$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 = "killnum" 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 = "warnum" 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);
$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']}";
$nation['type'] = getNationType($nation['type']); $statGC = "{$genCnt} / {$stat['gc']}";
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
$stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic'); $statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1');
$genCnt = $db->queryFirstField('SELECT count(*) FROM general');
$nation = $nation;
$statNC = "1 / {$stat['nc']}"; $nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
$statGC = "{$genCnt} / {$stat['gc']}"; $nation['aux'] = Json::decode($nation['aux']);
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']); $nation['msg'] = $nationStor->notice;
$statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1'); $nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power;
$nation = $nation; $nation['history'] = getNationHistoryLogAll($nation['nation']);
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
$nation['aux'] = Json::decode($nation['aux']); storeOldGenerals(0, $admin['year'], $admin['month']);
$nation['msg'] = $nationStor->notice; storeOldGenerals($nation['nation'], $admin['year'], $admin['month']);
$nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power; $db->insert('ng_old_nations', [
$nation['history'] = getNationHistoryLogAll($nation['nation']); 'server_id' => UniqueConst::$serverID,
'nation' => $nation['nation'],
storeOldGenerals(0, $admin['year'], $admin['month']); 'data' => Json::encode($nation)
storeOldGenerals($nation['nation'], $admin['year'], $admin['month']); ]);
$db->insert('ng_old_nations', [ $noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0');
'server_id' => UniqueConst::$serverID, $db->insert('ng_old_nations', [
'nation' => $nation['nation'], 'server_id' => UniqueConst::$serverID,
'data' => Json::encode($nation) 'nation' => 0,
]); 'data' => Json::encode([
'nation' => 0,
$noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0'); 'name' => '재야',
$db->insert('ng_old_nations', [ 'generals' => $noNationGeneral
'server_id' => UniqueConst::$serverID, ])
'nation' => 0, ]);
'data' => Json::encode([
'nation' => 0, $nationHistory = getNationHistoryLogAll($nation['nation']);
'name' => '재야',
'generals' => $noNationGeneral $serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
]) $serverName = UniqueConst::$serverName;
]);
$db->update('ng_games', [
$nationHistory = getNationHistoryLogAll($nation['nation']); 'winner_nation' => $nation['nation']
], 'server_id=%s', UniqueConst::$serverID);
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
$serverName = UniqueConst::$serverName; $db->insert('emperior', [
'phase' => $serverName . $serverCnt . '기',
$db->update('ng_games', [ 'server_id' => UniqueConst::$serverID,
'winner_nation' => $nation['nation'] 'nation_count' => $statNC,
], 'server_id=%s', UniqueConst::$serverID); 'nation_name' => $statNation['nation_name'],
'nation_hist' => $statNation['nation_hist'],
$db->insert('emperior', [ 'gen_count' => $statGC,
'phase' => $serverName . $serverCnt . '기', 'personal_hist' => $statGeneral['personal_hist'],
'server_id' => UniqueConst::$serverID, 'special_hist' => $statGeneral['special_hist'],
'nation_count' => $statNC, 'name' => $nation['name'],
'nation_name' => $statNation['nation_name'], 'type' => $nation['type'],
'nation_hist' => $statNation['nation_hist'], 'color' => $nation['color'],
'gen_count' => $statGC, 'year' => $admin['year'],
'personal_hist' => $statGeneral['personal_hist'], 'month' => $admin['month'],
'special_hist' => $statGeneral['special_hist'], 'power' => $nation['power'],
'name' => $nation['name'], 'gennum' => $nation['gennum'],
'type' => $nation['type'], 'citynum' => $cityCnt,
'color' => $nation['color'], 'pop' => $pop,
'year' => $admin['year'], 'poprate' => $poprate,
'month' => $admin['month'], 'gold' => $nation['gold'],
'power' => $nation['power'], 'rice' => $nation['rice'],
'gennum' => $nation['gennum'], 'l12name' => $chiefs[12]['name'],
'citynum' => $cityCnt, 'l12pic' => $chiefs[12]['picture'],
'pop' => $pop, 'l11name' => $chiefs[11]['name'],
'poprate' => $poprate, 'l11pic' => $chiefs[11]['picture'],
'gold' => $nation['gold'], 'l10name' => $chiefs[10]['name'],
'rice' => $nation['rice'], 'l10pic' => $chiefs[10]['picture'],
'l12name' => $chiefs[12]['name'], 'l9name' => $chiefs[9]['name'],
'l12pic' => $chiefs[12]['picture'], 'l9pic' => $chiefs[9]['picture'],
'l11name' => $chiefs[11]['name'], 'l8name' => $chiefs[8]['name'],
'l11pic' => $chiefs[11]['picture'], 'l8pic' => $chiefs[8]['picture'],
'l10name' => $chiefs[10]['name'], 'l7name' => $chiefs[7]['name'],
'l10pic' => $chiefs[10]['picture'], 'l7pic' => $chiefs[7]['picture'],
'l9name' => $chiefs[9]['name'], 'l6name' => $chiefs[6]['name'],
'l9pic' => $chiefs[9]['picture'], 'l6pic' => $chiefs[6]['picture'],
'l8name' => $chiefs[8]['name'], 'l5name' => $chiefs[5]['name'],
'l8pic' => $chiefs[8]['picture'], 'l5pic' => $chiefs[5]['picture'],
'l7name' => $chiefs[7]['name'], 'tiger' => $tigerstr,
'l7pic' => $chiefs[7]['picture'], 'eagle' => $eaglestr,
'l6name' => $chiefs[6]['name'], 'gen' => $gen,
'l6pic' => $chiefs[6]['picture'], 'history' => JSON::encode($nationHistory),
'l5name' => $chiefs[5]['name'], 'aux' => $statGeneral['aux']
'l5pic' => $chiefs[5]['picture'], ]);
'tiger' => $tigerstr,
'eagle' => $eaglestr, $history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
'gen' => $gen, pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
'history' => JSON::encode($nationHistory),
'aux' => $statGeneral['aux'] //연감 월결산
]); LogHistory();
}
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
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;
} }
} }
+7 -5
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;
@@ -79,9 +79,11 @@ if ($gameStor->fiction == 0) {
} }
if ($gameStor->npcmode == 0) { if ($gameStor->npcmode == 0) {
$npcmode = "불가능"; $npcmode = "불가능";
} else { } else if($gameStor->npcmode == 1){
$npcmode = "가능"; $npcmode = "가능";
$valid = 1; $valid = 1;
} else {
$npcmode = "선택 생성";
} }
$color = "cyan"; $color = "cyan";
$mapTheme = $gameStor->map_theme; $mapTheme = $gameStor->map_theme;
@@ -134,7 +136,7 @@ $(function(){
<body class="img_back"> <body class="img_back">
<div id="container"> <div id="container">
<div><?=allButton($gameStor->npcmode!=0)?></div> <div><?=allButton($gameStor->npcmode==1)?></div>
<table class="tb_layout bg0" style="width:1000px;"> <table class="tb_layout bg0" style="width:1000px;">
<tr height=50> <tr height=50>
<td colspan=5 id="server_title" align=center><font size=4>삼국지 모의전투 HiDCHe <?=$serverName.$serverCnt?>기 (<font color=cyan><?=$scenario?></font>)</font></td> <td colspan=5 id="server_title" align=center><font size=4>삼국지 모의전투 HiDCHe <?=$serverName.$serverCnt?>기 (<font color=cyan><?=$scenario?></font>)</font></td>
@@ -341,7 +343,7 @@ else if($session->userGrade == 4){
<button id="msg_submit">서신전달&amp;갱신</button><br> <button id="msg_submit">서신전달&amp;갱신</button><br>
내용 없이 '서신전달&amp;갱신'을 누르면 메세지창이 갱신됩니다. 내용 없이 '서신전달&amp;갱신'을 누르면 메세지창이 갱신됩니다.
</div> </div>
<div><?=allButton($gameStor->npcmode!=0)?></div> <div><?=allButton($gameStor->npcmode==1)?></div>
<div id="message_board"><div style="left:0;" class="board_side bg0"> <div id="message_board"><div style="left:0;" class="board_side bg0">
<div class="board_header bg0" id='public_talk_position'>전체 메시지(최고99자)</div> <div class="board_header bg0" id='public_talk_position'>전체 메시지(최고99자)</div>
<section class="public_message"> <section class="public_message">
@@ -361,7 +363,7 @@ else if($session->userGrade == 4){
<button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="diplomacy">이전 메시지 불러오기</button> <button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="diplomacy">이전 메시지 불러오기</button>
</section> </section>
</div></div> </div></div>
<div style="clear:left;"><?=allButton($gameStor->npcmode!=0)?><?=banner()?></div> <div style="clear:left;"><?=allButton($gameStor->npcmode==1)?><?=banner()?></div>
</div> </div>
<?php <?php
if ($con == 1) { if ($con == 1) {
+18 -1
View File
@@ -102,7 +102,7 @@ if($session->userGrade < 5 && !$allowReset){
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="confirm_password" class="col-sm-3 col-form-label">시나리오 선택</label> <label for="scenario_sel" class="col-sm-3 col-form-label">시나리오 선택</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select class="form-control" name="scenario" size="1" id="scenario_sel"> <select class="form-control" name="scenario" size="1" id="scenario_sel">
</select> </select>
@@ -138,6 +138,20 @@ if($session->userGrade < 5 && !$allowReset){
</div> </div>
</div> </div>
<div class="form-group row">
<label for="block_general_create" class="col-sm-3 col-form-label">장수 임의 생성</label>
<div class="col-sm-9">
<div id="block_general_create" class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="radio" name="block_general_create" value="0" checked>가능
</label>
<label class="btn btn-secondary active">
<input type="radio" name="block_general_create" value="1">불가
</label>
</div>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label for="npcmode" class="col-sm-3 col-form-label">NPC 빙의</label> <label for="npcmode" class="col-sm-3 col-form-label">NPC 빙의</label>
<div class="col-sm-9"> <div class="col-sm-9">
@@ -148,6 +162,9 @@ if($session->userGrade < 5 && !$allowReset){
<label class="btn btn-secondary active"> <label class="btn btn-secondary active">
<input type="radio" name="npcmode" value="0" checked>불가 <input type="radio" name="npcmode" value="0" checked>불가
</label> </label>
<label class="btn btn-secondary">
<input type="radio" name="npcmode" value="2">선택 생성 가능
</label>
</div> </div>
</div> </div>
</div> </div>
+101 -100
View File
@@ -1,101 +1,102 @@
<?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['block_general_create'],
$options['show_img_level'], $options['npcmode'],
$options['tournament_trig'], $options['show_img_level'],
$options['join_mode'], $options['tournament_trig'],
$options['starttime'], $options['join_mode'],
$options['autorun_user']?:null $options['starttime'],
); $options['autorun_user']?:null
);
$result['affected']=1;
$result['affected']=1;
$prefix = DB::prefix();
AppConf::getList()[$prefix]->openServer(); $prefix = DB::prefix();
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);
+1 -1
View File
@@ -37,7 +37,7 @@ list(
$npcmode $npcmode
) = $gameStor->getValuesAsArray(['maxgeneral', 'turnterm', 'npcmode']); ) = $gameStor->getValuesAsArray(['maxgeneral', 'turnterm', 'npcmode']);
if(!$npcmode){ if($npcmode!=1){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'빙의 가능한 서버가 아닙니다' 'reason'=>'빙의 가능한 서버가 아닙니다'
+90
View File
@@ -0,0 +1,90 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
function sortTokens(&$tokens){
usort($tokens, function($lhs, $rhs){
return array_sum($lhs['dex'])<=>array_sum($rhs['dex']);
});
}
function putInfoText(&$info){
if(key_exists('specialDomestic', $info)){
$class = buildGeneralSpecialDomesticClass($info['specialDomestic']);
$info['specialDomesticName'] = $class->getName();
$info['specialDomesticInfo'] = $class->getInfo();
}
if(key_exists('specialWar', $info)){
$class = buildGeneralSpecialDomesticClass($info['specialWar']);
$info['specialWarName'] = $class->getName();
$info['specialWarInfo'] = $class->getInfo();
}
}
$session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$npcmode = $gameStor->getValue('npcmode');
if($npcmode!=2){
Json::die([
'result'=>false,
'reason'=>'선택 가능한 서버가 아닙니다'
]);
}
$rawGeneral = $db->queryFirstRow('SELECT no, aux FROM general WHERE `owner` = %i', $userID);
if($rawGeneral){
$generalAux = Json::decode($rawGeneral['aux']);
if(key_exists('next_change', $generalAux)&& $generalAux['next_change'] > $now){
Json::die([
'result'=>false,
'reason'=>'아직 다시 고를 수 없습니다'
]);
}
}
$tokens = $db->query('SELECT unique_name, reserved_until, info FROM `select_pool` WHERE `owner`=%i AND `reserved_until`>=%s', $userID, $now);
if($tokens){
$pick = [];
$valid_until = null;
$specialInfo = [];
foreach($tokens as $token){
$valid_until = $token['reserved_until'];
$info = Json::decode($token['info']);
putInfoText($info);
$info['uniqueName'] = $token['unique_name'];
$pick[] = $info;
}
sortTokens($pick);//좀 무식하지만..
Json::die([
'result'=>true,
'pick'=>$pick,
'validUntil'=>$valid_until
]);
}
$pick = [];
$valid_until = null;
foreach(pickGeneralFromPool($db, $userID, 14) as $pickObj){
$valid_until = $pickObj->getValidUntil();
$info = $pickObj->getInfo();
putInfoText($info);
$pick[] = $info;
}
sortTokens($pick);//좀 무식하지만..
Json::die([
'result'=>true,
'pick'=>$pick,
'validUntil'=>$valid_until
]);
+214 -208
View File
@@ -1,209 +1,215 @@
<?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', 'block_general_create',
'npcmode', 'join_mode',
'show_img_level', 'npcmode',
'autorun_user_minutes' 'show_img_level',
])->rule('integer', [ 'autorun_user_minutes'
'turnterm', ])->rule('integer', [
'sync', 'turnterm',
'scenario', 'sync',
'fiction', 'scenario',
'extend', 'fiction',
'npcmode', 'extend',
'show_img_level', 'block_general_create',
'tournament_trig', 'npcmode',
'autorun_user_minutes' 'show_img_level',
])->rule('in', 'join_mode', ['onlyRandom', 'full']); 'tournament_trig',
if(!$v->validate()){ 'autorun_user_minutes'
Json::die([ ])->rule('in', 'join_mode', ['onlyRandom', 'full']);
'result'=>false, if(!$v->validate()){
'reason'=>$v->errorStr() Json::die([
]); 'result'=>false,
} 'reason'=>$v->errorStr()
]);
$allowReset = true; }
if($session->userGrade < 5 && !$allowFullReset){
//리셋 가능한 조건인지 테스트 $allowReset = true;
$allowReset = false; if($session->userGrade < 5 && !$allowFullReset){
//리셋 가능한 조건인지 테스트
if(file_exists(__DIR__.'/.htaccess')){ $allowReset = false;
$allowReset = true;
} if(file_exists(__DIR__.'/.htaccess')){
else{ $allowReset = true;
$db = DB::db(); }
$gameStor = KVStorage::getStorage($db, 'game_env'); else{
if($gameStor->isunited){ $db = DB::db();
$allowReset = true; $gameStor = KVStorage::getStorage($db, 'game_env');
} if($gameStor->isunited){
} $allowReset = true;
} }
}
if(!$allowReset){ }
Json::die([
'result'=>false, if(!$allowReset){
'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.' Json::die([
]); 'result'=>false,
} 'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.'
]);
$turnterm = (int)$_POST['turnterm']; }
$sync = (int)$_POST['sync'];
$scenario = (int)$_POST['scenario']; $turnterm = (int)$_POST['turnterm'];
$fiction = (int)$_POST['fiction']; $sync = (int)$_POST['sync'];
$extend = (int)$_POST['extend']; $scenario = (int)$_POST['scenario'];
$npcmode = (int)$_POST['npcmode']; $fiction = (int)$_POST['fiction'];
$show_img_level = (int)$_POST['show_img_level']; $extend = (int)$_POST['extend'];
$tournament_trig = (int)$_POST['tournament_trig']; $npcmode = (int)$_POST['npcmode'];
$join_mode = $_POST['join_mode']; $block_general_create = (bool)$_POST['block_general_create'];
$autorun_user_minutes = (int)$_POST['autorun_user_minutes']; $show_img_level = (int)$_POST['show_img_level'];
$autorun_user_options = []; $tournament_trig = (int)$_POST['tournament_trig'];
foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){ $join_mode = $_POST['join_mode'];
$autorun_user_options[$autorun_option] = 1; $autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
} $autorun_user_options = [];
if($autorun_user_minutes > 0 && !$autorun_user_options){ foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){
Json::die([ $autorun_user_options[$autorun_option] = 1;
'result'=>false, }
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
]); if($autorun_user_minutes > 0 && !$autorun_user_options){
} Json::die([
'result'=>false,
if($autorun_user_minutes < 0){ 'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
Json::die([ ]);
'result'=>false, }
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
]); if($autorun_user_minutes < 0){
} Json::die([
'result'=>false,
$autorun_user = $autorun_user_minutes?[ 'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
'limit_minutes'=>$autorun_user_minutes, ]);
'options'=>$autorun_user_options }
]:null;
$autorun_user = $autorun_user_minutes?[
if($reserve_open){ 'limit_minutes'=>$autorun_user_minutes,
$reserve_open = new \DateTime($reserve_open); 'options'=>$autorun_user_options
$db = DB::db(); ]:null;
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) { if($reserve_open){
$clearResult = ResetHelper::clearDB(); $reserve_open = new \DateTime($reserve_open);
if(!$clearResult['result']){ $db = DB::db();
Json::die($clearResult);
} if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
} $clearResult = ResetHelper::clearDB();
if(!$clearResult['result']){
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) { Json::die($clearResult);
Json::die([ }
'result'=>false, }
'reason'=>'예약 테이블이 없음!'
]); if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
} Json::die([
'result'=>false,
$scenarioObj = new Scenario($scenario, true); 'reason'=>'예약 테이블이 없음!'
$open_date = $reserve_open->format('Y-m-d H:i:s'); ]);
}
$reserveInfo = [
'turnterm'=>$turnterm, $scenarioObj = new Scenario($scenario, true);
'sync'=>$sync, $open_date = $reserve_open->format('Y-m-d H:i:s');
'scenario'=>$scenario,
'scenarioName'=>$scenarioObj->getTitle(), $reserveInfo = [
'fiction'=>$fiction, 'turnterm'=>$turnterm,
'extend'=>$extend, 'sync'=>$sync,
'npcmode'=>$npcmode, 'scenario'=>$scenario,
'show_img_level'=>$show_img_level, 'scenarioName'=>$scenarioObj->getTitle(),
'tournament_trig'=>$tournament_trig, 'fiction'=>$fiction,
'gameConf'=>$scenarioObj->getGameConf(), 'extend'=>$extend,
'join_mode'=>$join_mode, 'block_general_create'=>$block_general_create,
'starttime'=>$open_date, 'npcmode'=>$npcmode,
'autorun_user'=>$autorun_user 'show_img_level'=>$show_img_level,
]; 'tournament_trig'=>$tournament_trig,
'gameConf'=>$scenarioObj->getGameConf(),
'join_mode'=>$join_mode,
if($pre_reserve_open){ 'starttime'=>$open_date,
$pre_reserve_open = new \DateTime($pre_reserve_open); 'autorun_user'=>$autorun_user
$open_date = $pre_reserve_open->format('Y-m-d H:i:s'); ];
}
if($pre_reserve_open){
$pre_reserve_open = new \DateTime($pre_reserve_open);
$db->delete('reserved_open', true); $open_date = $pre_reserve_open->format('Y-m-d H:i:s');
$db->insert('reserved_open', [ }
'options'=>Json::encode($reserveInfo),
'date'=>$open_date
]);
AppConf::getList()[DB::prefix()]->closeServer(); $db->delete('reserved_open', true);
Json::die([ $db->insert('reserved_open', [
'result'=>true, 'options'=>Json::encode($reserveInfo),
'reason'=>'예약' 'date'=>$open_date
]); ]);
} ServConfig::getServerList()[DB::prefix()]->closeServer();
Json::die([
Json::die(ResetHelper::buildScenario( 'result'=>true,
$turnterm, 'reason'=>'예약'
$sync, ]);
$scenario, }
$fiction,
$extend, Json::die(ResetHelper::buildScenario(
$npcmode, $turnterm,
$show_img_level, $sync,
$tournament_trig, $scenario,
$join_mode, $fiction,
TimeUtil::now(), $extend,
$autorun_user $block_general_create,
$npcmode,
$show_img_level,
$tournament_trig,
$join_mode,
TimeUtil::now(),
$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'=>'올바르지 않은 명령입니다.'
]); ]);
+1 -1
View File
@@ -59,7 +59,7 @@ list(
$npcmode $npcmode
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode']); ) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode']);
if(!$npcmode){ if($npcmode!=1){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'빙의 가능한 서버가 아닙니다' 'reason'=>'빙의 가능한 서버가 아닙니다'
+167
View File
@@ -0,0 +1,167 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$pick = Util::getPost('pick');
$leadership = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
$strength = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
$intel = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
$personal = Util::getPost('personal', 'string', null);
$use_own_picture = Util::getPost('use_own_picture', 'bool', false);
if(!$pick){
Json::die([
'result'=>false,
'reason'=>'장수를 선택하지 않았습니다'
]);
}
$session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$rootDB = RootDB::db();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$hasGeneralID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
if($hasGeneralID){
Json::die([
'result'=>false,
'reason'=>'이미 장수를 생성했습니다.'
]);
}
$env = $gameStor->getValues(['startyear', 'year', 'month', 'maxgeneral', 'npcmode', 'show_img_level', 'icon_path', 'turnterm', 'turntime']);
$env['fiction'] = false;
$npcmode = $env['npcmode'];
$maxgeneral = $env['maxgeneral'];
if($npcmode!=2){
Json::die([
'result'=>false,
'reason'=>'선택 가능한 서버가 아닙니다'
]);
}
$selectInfo = $db->queryFirstField('SELECT info FROM select_pool WHERE `owner` = %i AND `reserved_until`>=%s AND `unique_name`=%s', $userID, $now, $pick);
if(!$selectInfo){
Json::die([
'result'=>false,
'reason'=>'유효한 장수 목록이 없습니다.'
]);
}
$selectInfo = Json::decode($selectInfo);
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
if(!$ownerInfo){
Json::die([
'result'=>false,
'reason'=>'멤버 정보를 가져오지 못했습니다.'
]);
}
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
if ($gencount >= $maxgeneral) {
Json::die([
'result'=>false,
'reason'=>'더 이상 등록 할 수 없습니다.'
]);
}
$poolClass = getGeneralPoolClass(GameConst::$targetGeneralPool);
/** @var AbsGeneralPool */
$pickedGeneral = new $poolClass($db, $selectInfo, $now);
$builder = $pickedGeneral->getGeneralBuilder();
foreach(GameConst::$generalPoolAllowOption as $allowOption){
if($allowOption == 'stat'){
$leadership = Util::valueFit($leadership, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
$strength = Util::valueFit($strength, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
$intel = Util::valueFit($intel, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
if($leadership + $strength + $intel > GameConst::$defaultStatTotal){
Json::die([
'result'=>false,
'reason'=>'스탯의 총 합이 올바르지 않습니다.'
]);
}
$builder->setStat($leadership, $strength, $intel);
}
else if($allowOption == 'picture' && $use_own_picture){
$builder->setPicture($ownerInfo['imgsvr'], $ownerInfo['picture']);
}
else if($allowOption == 'ego'){
if(!$personal || $personal == 'Random'){
$personal = Util::choiceRandom(GameConst::$availablePersonality);
}
if(!array_search($personal, GameConst::$availablePersonality)){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 성격입니다.'
]);
}
$builder->setEgo($personal);
}
}
$builder->setOwner($userID);
$builder->setKillturn(5);
$builder->setNPCType(0);
$builder->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * $env['turnterm']));
$builder->fillRemainSpecAsZero($env);
$builder->build($env);
$generalID = $builder->getGeneralID();
if(!$generalID){
Json::die([
'result'=>false,
'reason'=>'장수 등록에 실패했습니다.'
]);
}
$pickedGeneral->occupyGeneralName();
$db->update('select_pool',[
'owner'=>null,
'reserved_until'=>null,
], '(owner=%i or reserved_until < %s) AND general_id is NULL', $userID, $now);
$userNick = $ownerInfo['name'];
$josaYi = JosaUtil::pick($userNick, '이');
$generalName = $builder->getGeneralName();
$josaRo = JosaUtil::pick($generalName, '로');
$cityName = CityConst::byID($builder->getCityID())->name;
$logger = new ActionLogger($generalID, 0, $env['year'], $env['month']);
$logger->pushGeneralHistoryLog("<Y>{$generalName}</>, <G>{$cityName}</>에서 등장");
$logger->pushGlobalActionLog("<G><b>{$cityName}</b></>에서 <Y>{$userNick}</>{$josaYi} <Y>{$generalName}</>{$josaRo} 등장합니다.");
$logger->flush();
pushAdminLog(["가입 : {$userID} // {$session->userName} // {$pick} // ".getenv("REMOTE_ADDR")]);
$rootDB->insert('member_log', [
'member_no' => $userID,
'date'=>TimeUtil::now(),
'action_type'=>'make_general',
'action'=>Json::encode([
'server'=>DB::prefix(),
'type'=>'select',
'generalID'=>$generalID,
'generalName'=>$generalName
])
]);
Json::die([
'result'=>true,
'reason'=>'success'
]);
+6 -5
View File
@@ -43,7 +43,7 @@ $session = Session::requireLogin([
'game'=>null, 'game'=>null,
'me'=>null 'me'=>null
])->setReadOnly(); ])->setReadOnly();
$userID = Session::getUserID(); $userID = $session->userID;
if(!class_exists('\\sammo\\DB')){ if(!class_exists('\\sammo\\DB')){
Json::die([ Json::die([
@@ -91,7 +91,8 @@ if(file_exists(__DIR__.'/.htaccess')){
'scenarioName'=>$options['scenarioName'], 'scenarioName'=>$options['scenarioName'],
'turnterm'=>$options['turnterm'], 'turnterm'=>$options['turnterm'],
'fictionMode'=>($options['fiction']?'가상':'사실'), 'fictionMode'=>($options['fiction']?'가상':'사실'),
'npcMode'=>($options['npcmode']?'가능':'불가'), 'block_general_create'=>(!!$options['block_general_create']),
'npcMode'=>([0=>'불가',1=>'가능',2=>'선택 생성'][$options['npcmode']]),
'openDatetime'=>$reserved['date'], 'openDatetime'=>$reserved['date'],
'starttime'=>$options['starttime'], 'starttime'=>$options['starttime'],
'gameConf'=>$options['gameConf'], 'gameConf'=>$options['gameConf'],
@@ -104,7 +105,7 @@ if(file_exists(__DIR__.'/.htaccess')){
//TODO: 천통시에도 예약 오픈 알림이 필요..? //TODO: 천통시에도 예약 오픈 알림이 필요..?
$admin = $gameStor->getValues(['isunited', 'npcmode', 'year', 'month', 'scenario', 'scenario_text', 'maxgeneral', 'turnterm', 'opentime', 'turntime', 'join_mode', 'fiction', 'autorun_user']); $admin = $gameStor->getValues(['isunited', 'npcmode', 'year', 'month', 'scenario', 'scenario_text', 'maxgeneral', 'turnterm', 'opentime', 'turntime', 'join_mode', 'fiction', 'block_general_create', 'autorun_user']);
$admin['maxUserCnt'] = $admin['maxgeneral']; $admin['maxUserCnt'] = $admin['maxgeneral'];
$admin['npcMode'] = $admin['npcmode']; $admin['npcMode'] = $admin['npcmode'];
$admin['turnTerm'] = $admin['turnterm']; $admin['turnTerm'] = $admin['turnterm'];
@@ -124,8 +125,8 @@ $admin['scenario'] = $admin['scenario_text'];
$admin['userCnt'] = $genCnt; $admin['userCnt'] = $genCnt;
$admin['npcCnt'] = $npcCnt; $admin['npcCnt'] = $npcCnt;
$admin['nationCnt'] = $nationCnt; $admin['nationCnt'] = $nationCnt;
$admin['block_general_create'] = !!$admin['block_general_create'];
$admin['npcMode'] = $admin['npcMode']?'가능':'불가'; $admin['npcMode'] = [0=>'불가',1=>'가능',2=>'선택 생성'][$admin['npcMode']];
$admin['fictionMode'] = $admin['fiction']?'가상':'사실'; $admin['fictionMode'] = $admin['fiction']?'가상':'사실';
$otherTextInfo = []; $otherTextInfo = [];
+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->increaseVarWithLimit('train', -3, 20);
$me->increaseVarWithLimit('atmos', -3, 20);
}
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);
+150
View File
@@ -0,0 +1,150 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$pick = Util::getPost('pick');
if(!$pick){
Json::die([
'result'=>false,
'reason'=>'장수를 선택하지 않았습니다'
]);
}
$session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$rootDB = RootDB::db();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$generalID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
if(!$generalID){
Json::die([
'result'=>false,
'reason'=>'장수가 생성하지 않았습니다. 이미 사망하지 않았는지 확인해보세요.'
]);
}
list(
$year,
$month,
$maxgeneral,
$npcmode,
$turnterm
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode', 'turnterm']);
if($npcmode!=2){
Json::die([
'result'=>false,
'reason'=>'선택 가능한 서버가 아닙니다'
]);
}
$info = $db->queryFirstField('SELECT info FROM select_pool WHERE `owner` = %i AND `reserved_until`>=%s AND `unique_name`=%s', $userID, $now, $pick);
if(!$info){
Json::die([
'result'=>false,
'reason'=>'유효한 장수 목록이 없습니다.'
]);
}
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
if(!$ownerInfo){
Json::die([
'result'=>false,
'reason'=>'멤버 정보를 가져오지 못했습니다.'
]);
}
$info = Json::decode($info);
$generalObj = General::createGeneralObjFromDB($generalID);
$oldGeneralName = $generalObj->getName();
$db->update('select_pool', [
'general_id'=>-$generalID,
'owner'=>null,
'reserved_until'=>null
], 'unique_name=%s AND `reserved_until` IS NOT NULL AND owner = %i', $info['uniqueName'], $userID);
if($db->affectedRows()==0){
Json::die([
'result'=>false,
'reason'=>'동시성 제어에 문제가 발생했습니다. 버그 제보를 부탁드립니다.'
]);
}
$db->update('select_pool', [
'general_id'=>null,
'owner'=>null,
'reserved_until'=>null,
], 'unique_name != %s AND general_id = %i', $info['uniqueName'], $generalID);
$db->update('select_pool', [
'general_id'=>$generalID,
], 'general_id=%i', -$generalID);
if($db->affectedRows()==0){
Json::die([
'result'=>false,
'reason'=>'장수 선택 과정에 문제가 발생했습니다.. 버그 제보를 부탁드립니다.'
]);
}
$db->update('select_pool',[
'owner'=>null,
'reserved_until'=>null,
], '(owner=%i or reserved_until < %s) AND general_id is NULL', $userID, $now);
if(key_exists('leadership', $info)){
$generalObj->updateVar('leadership', $info['leadership']);
$generalObj->updateVar('strength', $info['strength']);
$generalObj->updateVar('intel', $info['intel']);
}
if(key_exists('picture', $info)){
$generalObj->updateVar('imgsvr', $info['imgsvr']);
$generalObj->updateVar('picture', $info['picture']);
}
if(key_exists('generalName', $info)){
$generalObj->updateVar('name', $info['generalName']);
}
if(key_exists('dex', $info)){
$generalObj->updateVar('dex1', $info['dex'][0]);
$generalObj->updateVar('dex2', $info['dex'][1]);
$generalObj->updateVar('dex3', $info['dex'][2]);
$generalObj->updateVar('dex4', $info['dex'][3]);
$generalObj->updateVar('dex5', $info['dex'][4]);
}
if(key_exists('ego', $info)){
$generalObj->updateVar('personal', $info['ego']);
}
if(key_exists('specialDomestic', $info)){
$generalObj->updateVar('special', $info['specialDomestic']);
}
if(key_exists('specialWar', $info)){
$generalObj->updateVar('special2', $info['specialWar']);
}
$generalObj->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * $turnterm));
$userNick = $ownerInfo['name'];
$josaYi = JosaUtil::pick($userNick, '이');
$generalName = $info['generalName'];
$josaRo = JosaUtil::pick($generalName, '로');
$logger = $generalObj->getLogger();
$logger->pushGeneralHistoryLog("장수를 <Y>{$oldGeneralName}</>에서 <Y>{$generalName}</>{$josaRo} 변경");
$logger->pushGlobalActionLog("<Y>{$userNick}</>{$josaYi} 장수를 <Y>{$oldGeneralName}</>에서 <Y>{$generalName}</>{$josaRo} 변경합니다.");
$generalObj->applyDB($db);
Json::die([
'result'=>true,
'reason'=>'success'
]);
+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'
]);
+6 -2
View File
@@ -24,7 +24,12 @@ if (!$member) {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['block_general_create','show_img_level','maxgeneral']);
if($admin['block_general_create']){
MessageBox("잘못된 접근입니다!!!");
echo "<script>history.go(-1);</script>";
exit(1);
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@@ -66,7 +71,6 @@ echo Json::encode((object)$charInfoText);
<tr><td align=center><?=info(0)?></td></tr> <tr><td align=center><?=info(0)?></td></tr>
</table> </table>
<?php <?php
$admin = $gameStor->getValues(['show_img_level','maxgeneral']);
$gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc<2'); $gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc<2');
+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);
});
}) })
+171 -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,12 +364,54 @@ 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;
}
function initTooltip($obj) {
if ($obj === undefined) {
$obj = $('.obj_tooltip');
} else if (!$obj.hasClass('obj_tooltip')) {
$obj = $obj.find('.obj_tooltip');
}
console.log($obj);
$obj.each(function() {
$target = $(this);
if ($target.data('installHandler')) {
return true;
}
$target.data('installHandler', true);
$target.mouseover(function() {
var $objTooltip = $(this);
if ($objTooltip.data('setObjTooltip')) {
return true;
}
var tooltipClassText = $objTooltip.data('tooltip-class');
if (!tooltipClassText) {
tooltipClassText = '';
}
var template = '<div class="tooltip {0}" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'
.format(tooltipClassText);
$objTooltip.tooltip({
title: function() {
return $.trim($(this).find('.tooltiptext').html());
},
template: template,
html: true
}).tooltip('show');
$objTooltip.data('setObjTooltip', true);
});
});
} }
+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();
}); });
+74 -76
View File
@@ -1,4 +1,3 @@
/* /*
function showCityGeneral(cityIdx){ function showCityGeneral(cityIdx){
@@ -21,13 +20,13 @@ function loadScenarioPreview(scenarioIdx){
function loadScenarios(){ function loadScenarios() {
$.ajax({ $.ajax({
method:'post', method: 'post',
url:'j_load_scenarios.php', url: 'j_load_scenarios.php',
dataType:'json' dataType: 'json'
}).then(function(result){ }).then(function(result) {
if(!result.result){ if (!result.result) {
var deferred = $.Deferred(); var deferred = $.Deferred();
deferred.reject('fail'); deferred.reject('fail');
return deferred.promise(); return deferred.promise();
@@ -37,18 +36,18 @@ function loadScenarios(){
var list = {}; var list = {};
$.each(result.scenario, function(idx, value){ $.each(result.scenario, function(idx, value) {
var title = value.title || "-"; var title = value.title || "-";
var pat = /【(.*?)[0-9\-_\.a-zA-Z]*】/; var pat = /【(.*?)[0-9\-_\.a-zA-Z]*】/;
var category = pat.exec(title); var category = pat.exec(title);
category = category?category[1]:'-'; category = category ? category[1] : '-';
value.title = title; value.title = title;
value.category = category; value.category = category;
value.idx = idx; value.idx = idx;
value.year = value.year || 180; value.year = value.year || 180;
if(!(category in list)){ if (!(category in list)) {
list[category] = {}; list[category] = {};
} }
@@ -56,12 +55,12 @@ function loadScenarios(){
}); });
var $select = $('#scenario_sel'); var $select = $('#scenario_sel');
$.each(list, function(category, items){ $.each(list, function(category, items) {
var $optgroup = $('<optgroup>').attr('label', category); var $optgroup = $('<optgroup>').attr('label', category);
$.each(items, function(idx, scenario){ $.each(items, function(idx, scenario) {
var $option = $('<option>') var $option = $('<option>')
.data('scenario',scenario) .data('scenario', scenario)
.val(idx) .val(idx)
.html(scenario.title); .html(scenario.title);
$optgroup.append($option); $optgroup.append($option);
@@ -75,7 +74,7 @@ function loadScenarios(){
}); });
} }
function scenarioPreview(){ function scenarioPreview() {
var $select = $(this); var $select = $(this);
var $option = $select.find('option:selected'); var $option = $select.find('option:selected');
@@ -89,125 +88,124 @@ function scenarioPreview(){
$year.html('{0}년'.format(scenario.year)); $year.html('{0}년'.format(scenario.year));
$npc.html('{0}명'.format(scenario.npc_cnt)); $npc.html('{0}명'.format(scenario.npc_cnt));
if(scenario.npcEx_cnt == 0){ if (scenario.npcEx_cnt == 0) {
$npcEx.html(''); $npcEx.html('');
} } else {
else{
$npcEx.html('+{0}명'.format(scenario.npcEx_cnt)); $npcEx.html('+{0}명'.format(scenario.npcEx_cnt));
} }
$nation.html(''); $nation.html('');
$.each(scenario.nation, function(idx, nation){ $.each(scenario.nation, function(idx, nation) {
$nation.append('<span style="color:{0}">{1}</span> {2}명. {3}<br>'.format( $nation.append('<span style="color:{0}">{1}</span> {2}명. {3}<br>'.format(
nation.color, nation.name, nation.generals, nation.cities.join(', ') nation.color, nation.name, nation.generals, nation.cities.join(', ')
)); ));
}); });
} }
function formSetup(){ function formSetup() {
$.validator.addMethod("autorun_user", function(value,element){ $.validator.addMethod("autorun_user", function(value, element) {
var parent = $(element).parent('.input-group'); var parent = $(element).parent('.input-group');
var checkCnt = parent.find('input:checked').length; var checkCnt = parent.find('input:checked').length;
if(value <= 0){ if (value <= 0) {
if(checkCnt > 0){ if (checkCnt > 0) {
return false; return false;
} }
return true; return true;
} }
if(checkCnt == 0){ if (checkCnt == 0) {
return false; return false;
} }
return true; return true;
}, "유효 시간과 옵션은 동시에 설정해야합니다."); }, "유효 시간과 옵션은 동시에 설정해야합니다.");
$('#game_form').validate({ $('#game_form').validate({
rules:{ rules: {
turnterm:"required", turnterm: "required",
sync:"required", sync: "required",
scenario:"required", scenario: "required",
fiction:"required", fiction: "required",
extend:"required", extend: "required",
npcmode:"required", npcmode: "required",
show_img_level:"required", show_img_level: "required",
tournament_trig:"required", tournament_trig: "required",
join_mode:'required', join_mode: 'required',
autorun_user_minutes:{required: true, autorun_user: true, min:0} autorun_user_minutes: { required: true, autorun_user: true, min: 0 }
}, },
errorElement: "div", errorElement: "div",
errorPlacement: function ( error, element ) { errorPlacement: function(error, element) {
// Add the `help-block` class to the error element // Add the `help-block` class to the error element
error.addClass( "invalid-feedback" ); error.addClass("invalid-feedback");
if ( element.prop( "type" ) === "checkbox" ) { if (element.prop("type") === "checkbox") {
error.insertAfter( element.parent( "label" ) ); error.insertAfter(element.parent("label"));
} else { } else {
error.insertAfter( element ); error.insertAfter(element);
} }
}, },
highlight: function ( element, errorClass, validClass ) { highlight: function(element, errorClass, validClass) {
$( element ).addClass( "is-invalid" ).removeClass( "is-valid" ); $(element).addClass("is-invalid").removeClass("is-valid");
}, },
unhighlight: function (element, errorClass, validClass) { unhighlight: function(element, errorClass, validClass) {
$( element ).addClass( "is-valid" ).removeClass( "is-invalid" ); $(element).addClass("is-valid").removeClass("is-invalid");
} }
}); });
$('#game_form').submit(function(e){ $('#game_form').submit(function(e) {
e.preventDefault(); e.preventDefault();
if(!$("#game_form").valid()){ if (!$("#game_form").valid()) {
return; return;
} }
var autorun_user_minutes = parseInt($('#autorun_user_minutes').val()); var autorun_user_minutes = parseInt($('#autorun_user_minutes').val());
var autorun_user = []; var autorun_user = [];
if(autorun_user_minutes > 0){ if (autorun_user_minutes > 0) {
$('.autorun_user_chk:checked').each(function(){ $('.autorun_user_chk:checked').each(function() {
autorun_user.push($(this).data('key')); autorun_user.push($(this).data('key'));
}); });
} }
$.ajax({ $.ajax({
cache:false, cache: false,
type:'post', type: 'post',
url:'j_install.php', url: 'j_install.php',
dataType:'json', dataType: 'json',
data:{ data: {
turnterm:$('#turnterm input:radio:checked').val(), turnterm: $('#turnterm input:radio:checked').val(),
sync:$('#sync input:radio:checked').val(), sync: $('#sync input:radio:checked').val(),
scenario:$('#scenario_sel').val(), scenario: $('#scenario_sel').val(),
fiction:$('#fiction input:radio:checked').val(), fiction: $('#fiction input:radio:checked').val(),
extend:$('#extend input:radio:checked').val(), extend: $('#extend input:radio:checked').val(),
npcmode:$('#npcmode input:radio:checked').val(), block_general_create: $('#block_general_create input:radio:checked').val(),
show_img_level:$('#show_img_level input:radio:checked').val(), npcmode: $('#npcmode input:radio:checked').val(),
tournament_trig:$('#tournament_trig input:radio:checked').val(), show_img_level: $('#show_img_level input:radio:checked').val(),
reserve_open:$('#reserve_open').val(), tournament_trig: $('#tournament_trig input:radio:checked').val(),
pre_reserve_open:$('#pre_reserve_open').val(), reserve_open: $('#reserve_open').val(),
join_mode:$('#join_mode input:radio:checked').val(), pre_reserve_open: $('#pre_reserve_open').val(),
autorun_user_minutes:autorun_user_minutes, join_mode: $('#join_mode input:radio:checked').val(),
autorun_user:autorun_user autorun_user_minutes: autorun_user_minutes,
autorun_user: autorun_user
} }
}).then(function(result){ }).then(function(result) {
var deferred = $.Deferred(); var deferred = $.Deferred();
if(!result.result){ if (!result.result) {
alert(result.reason); alert(result.reason);
deferred.reject('fail'); deferred.reject('fail');
} } else {
else{
alert('게임이 리셋되었습니다.'); alert('게임이 리셋되었습니다.');
deferred.resolve(); deferred.resolve();
} }
return deferred.promise(); return deferred.promise();
}).then(function(){ }).then(function() {
location.href = '..'; location.href = '..';
}); });
}); });
} }
$(function(){ $(function() {
loadScenarios(); loadScenarios();
$('#scenario_sel').change(scenarioPreview); $('#scenario_sel').change(scenarioPreview);
formSetup(); formSetup();
}) })
+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 = (defaultCity << 4 ) | (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
} var id = city.id;
var nationId = city.nationId;
var clickable = 16;
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();
+210
View File
@@ -0,0 +1,210 @@
var templateGeneralCard = '<div class="general_card">\
<h4 class="bg1 with_border"><%generalName%></h4>\
<h4><img src="<%iconPath%>" height=64 width=64></h4><p>\
<%if(leadership){%>\
<%leadership%> / <%strength%> / <%intel%><br>\
<%}%>\
<%if(personalText){%><%personalText%><br><%}%>\
<%if(specialDomesticText||specialWarText){%>\
<%specialDomesticText%> / <%specialWarText%><br>\
<%}%>\
<%if(dex){%><br>\
보병: <%parseInt(dex[0]/1000)%>K<br>\
궁병: <%parseInt(dex[1]/1000)%>K<br>\
기병: <%parseInt(dex[2]/1000)%>K<br>\
귀병: <%parseInt(dex[3]/1000)%>K<br>\
차병: <%parseInt(dex[4]/1000)%>K<br>\
<%}%>\
</p>\
<button type="subject" class="with_skin with_border select_btn" data-name="<%generalName%>" value="<%uniqueName%>" name="pick">선택하기</button>\
</div>';
var templateSpecial =
'<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\
<span class="tooltiptext">\
<%info%>\
</span>\
</span>\
';
function pickGeneral() {
$btn = $(this);
if (hasGeneralID) {
if (!confirm('이 장수를 선택할까요? : {0}'.format($btn.data('name')))) {
return false;
}
$.post({
url: 'j_update_picked_general.php',
dataType: 'json',
data: {
pick: $btn.val()
}
}).then(function(result) {
if (!result.result) {
alert(result.reason);
location.refresh();
}
alert('선택한 장수로 변경했습니다.');
location.href = './';
});
return false;
}
currentGeneralInfo = cards[$btn.val()];
var $card = $btn.closest('.general_card');
var $leftPad = $('#left_pad');
$leftPad.empty();
$card.clone().appendTo($leftPad);
initTooltip($leftPad);
return false;
}
function buildGeneral() {
if (!currentGeneralInfo) {
alert('장수를 선택해주세요!');
return false;
}
if (!confirm('이 장수로 생성할까요?')) {
return false;
}
$.post({
url: 'j_select_picked_general.php',
dataType: 'json',
data: {
pick: currentGeneralInfo.uniqueName,
use_own_picture: $('#use_own_picture').is(':checked'),
leadership: parseInt($('#leadership').val()),
strength: parseInt($('#leadership').val()),
intel: parseInt($('#leadership').val()),
personal: $('#selChar').val()
}
}).then(function(result) {
if (!result.result) {
alert(result.reason);
location.refresh();
}
alert('선택한 장수로 생성했습니다.');
location.href = './';
});
return false;
}
function updateOutdateTimer() {
var $validUntilText = $('#valid_until_text');
var now = Date.now();
var validUntil = $validUntilText.data('until');
if (validUntil <= 0) {
return;
} else if (validUntil < now) {
$validUntilText.data('until', 0);
$('#valid_until').hide();
$('#outdate_token').show();
return;
} else if (validUntil - now <= 30000) {
$validUntilText.css('color', "rgb(255, {0}, {0})".format(255 * (validUntil - now) / 30000));
}
setTimeout(updateOutdateTimer, 1000);
}
function printGenerals(value) {
$('.card_holder').empty();
$('#valid_until').show();
$('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white');
$('#outdate_token').hide();
var pick = $.map(value.pick, function(value, key) {
return value;
});
var emptyCard = {
'leadership': null,
'strength': null,
'intel': null,
'personalText': null,
'specialDomesticText': null,
'specialWarText': null,
'dex': null
};
$.each(pick, function(idx, cardData) {
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
if (cardData.specialDomestic !== undefined) {
cardData.specialDomesticText = TemplateEngine(templateSpecial, {
text: cardData.specialDomesticName,
info: cardData.specialDomesticInfo
});
cardData.specialWarText = '-';
}
if (cardData.specialWar !== undefined) {
cardData.specialWarText = TemplateEngine(templateSpecial, {
text: cardData.specialWarName,
info: cardData.specialWarInfo
});
if (cardData.specialDomesticText === undefined) {
cardData.specialDomesticText = '-';
}
}
//FIXME: ego로 적었던것 같음!
if (cardData.personal in characterInfo) {
cardData.personalText = TemplateEngine(templateSpecial, {
text: characterInfo[cardData.personal].name,
info: characterInfo[cardData.personal].info
});
} else {
cardData.personalText = cardData.personal;
}
cards[cardData.uniqueName] = cardData;
var $card = $(TemplateEngine(templateGeneralCard, $.extend({}, emptyCard, cardData)));
$('.card_holder').append($card);
$card.find('.select_btn').click(pickGeneral);
$card.find('.obj_tooltip').tooltip({
title: function() {
return $.trim($(this).find('.tooltiptext').html());
},
html: true
});
});
updateOutdateTimer();
}
$(function($) {
$.post('j_get_select_pool.php').then(function(value) {
if (!value.result) {
alert(value.reason);
return;
}
console.log(value);
printGenerals(value);
});
if (hasGeneralID) {
$('#create_plate').hide();
}
$('#build_general').on('click', buildGeneral);
$.each(validCustomOption, function(idx, value) {
if (value == 'picture') {
$('.custom_picture').show();
} else if (value == 'ego') {
$('.custom_personality').show();
} else if (value == 'stat') {
$('.custom_stat').show();
}
});
});
+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;
+72
View File
@@ -0,0 +1,72 @@
<?php
namespace sammo;
use sammo\AbsGeneralPool;
use sammo\GameConst;
use sammo\Json;
use sammo\Util;
abstract class AbsFromUserPool extends AbsGeneralPool{
public function occupyGeneralName(): bool
{
$generalID = $this->getGeneralBuilder()->getGeneralID();
if($generalID === null){
throw new \RuntimeException('build되지 않음');
}
$db= $this->db;
$db->update('select_pool', [
'general_id'=>$generalID,
'owner'=>null,
'reserved_until'=>null,
], 'unique_name = %s AND owner IS NOT NULL', $this->uniqueName);
return $db->affectedRows()!=0;
}
static public function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array{
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$db->update('select_pool', [
'reserved_until'=>null,
'owner'=>null,
],'reserved_until < %s AND general_id IS NULL', $now);
$pool = [];
foreach($db->query('SELECT id, unique_name, info FROM select_pool WHERE reserved_until IS NULL AND general_id IS NULL', $pickCnt) as $cand){
$cand['info'] = Json::decode($cand['info']);
$dexTotal = array_sum($cand['info']['dex']);
$pool[] = [$cand, $dexTotal];
}
if(count($pool) < $pickCnt){
throw new \RuntimeException('pool 부족');
}
$gameStor = KVStorage::getStorage($db, 'game_env');
$result = [];
$validUntil = TimeUtil::nowAddMinutes(2 * $gameStor->turnterm);
while(count($result) < $pickCnt){
$cand = Util::choiceRandomUsingWeightPair($pool);
$poolID = $cand['id'];
if(key_exists($poolID, $result)){
continue;
}
$candInfo = $cand['info'];
$candInfo['uniqueName'] = $cand['unique_name'];
//하나씩 한다.
$db->update('select_pool', [
'owner'=>$owner,
'reserved_until'=>$validUntil,
], 'id = %i AND reserved_until IS NULL AND owner IS NULL and general_id IS NULL', $poolID);
if($db->affectedRows()==0){
continue;
}
$result[$poolID] = new static($db, $candInfo, $validUntil);
}
return array_values($result);
}
}
+111
View File
@@ -0,0 +1,111 @@
<?php
namespace sammo;
use MeekroDB;
use sammo\GameConst;
use sammo\Scenario\GeneralBuilder;
use sammo\Util;
abstract class AbsGeneralPool{
protected $builder;
protected $info;
protected $db=null;
protected $uniqueName;
protected $generalName;
protected $validUntil;
/*
* info = [
* uniqueName
* generalName
* imgsvr
* picture
*
* leadership
* strength
* intel
*
* experience
* dedication
*
* dex[5]
*
* specialDomestic
* specialWar
*/
public function __construct(\MeekroDB $db, array $info, string $validUntil)
{
$this->db = $db;
$this->info = $info;
$this->uniqueName = $info['uniqueName'];
$this->generalName = $info['generalName'];
$this->builder = new GeneralBuilder(
$info['generalName'],
$info['imgsvr'],
$info['picture'],
0
);
$this->validUntil = $validUntil;
$builder = $this->builder;
if(key_exists('leadership', $info)){
$builder->setStat($info['leadership'], $info['strength'], $info['intel']);
}
if(key_exists('experience', $info)){
$builder->setExpDed($info['experience'], $info['dedication']);
}
if(key_exists('dex', $info)){
$builder->setDex($info['dex'][0], $info['dex'][1], $info['dex'][2], $info['dex'][3], $info['dex'][4]);
}
if(key_exists('specialDomestic', $info) || key_exists('specialWar', $info)){
$builder->setSpecial($info['specialDomestic']??GameConst::$defaultSpecialDomestic, $info['specialWar']??GameConst::$defaultSpecialWar);
}
}
public function getUniqueName():string{
return $this->uniqueName;
}
public function getInfo():array{
return $this->info;
}
static protected function checkDuplicatedCnt(\MeekroDB $db, string $name):int{
$duplicateCnt = 0;
foreach(GeneralBuilder::$prefixList as $npcPrefix){
$testName = "{$npcPrefix}{$name}";
$duplicateCnt += $db->queryFirstField('SELECT count(no) FROM general WHERE name LIKE %s', $testName.'%');
}
return $duplicateCnt;
}
public function getGeneralBuilder():GeneralBuilder{
if(!$this->generalName){
throw new \RuntimeException('generalName not picked');
}
return $this->builder;
}
public function getValidUntil():string{
return $this->validUntil;
}
/**
* @param \MeekroDB $db
* @param int $owner
* @param int $pickCnt
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
static abstract public function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array;
abstract public function occupyGeneralName():bool;
abstract public static function getPoolName():string;
abstract public static function initPool(\MeekroDB $db);
}
+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)
);
}
}

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