Compare commits

...
371 Commits
Author SHA1 Message Date
Hide_D fdf0a3135a Merge pull request '스크립트 기반을 WebPack + Babel + TypeScript + Vue3으로 변경' (#191) from ts_convert into devel
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/191
2021-09-09 01:00:42 +09:00
Hide_D 3a1a455c48 [empty] this is a empty commit 2021-09-09 00:59:10 +09:00
Hide_D 3a786e835b Squashed commit of the following:
commit 3ef363a01e
Author: hide_d <hided62@gmail.com>
Date:   Mon Sep 6 02:30:00 2021 +0900

    fix: 은퇴 시 숙련 포인트를 지나치게 많이 받는 문제 수정

commit 9e68bc90c2
Author: hide_d <hided62@gmail.com>
Date:   Mon Sep 6 02:17:56 2021 +0900

    재야에서 도시보기 warning

commit d2590607c2
Author: hide_d <hided62@gmail.com>
Date:   Sun Sep 5 23:05:06 2021 +0900

    fix: div 0

commit 2bce6e4f02
Author: hide_d <hided62@gmail.com>
Date:   Sun Sep 5 23:02:52 2021 +0900

    warning 메시지 수정

commit e64812da72
Author: hide_d <hided62@gmail.com>
Date:   Sat Sep 4 03:42:09 2021 +0900

    fix: m장, 의병장 숙련이 설정되지 않는 버그 수정

commit 7cd40fca03
Author: hide_d <hided62@gmail.com>
Date:   Sat Aug 21 16:04:03 2021 +0900

    fix: 모병/징병에서 조건 검사부 통솔 계산값

commit d1568a3b2c
Author: hide_d <hided62@gmail.com>
Date:   Sat Aug 21 02:50:54 2021 +0900

    허보에 수몰이 같이 들어간 버그 수정

commit e7dcc84afc
Author: hide_d <hided62@gmail.com>
Date:   Thu Aug 19 14:51:50 2021 +0900

    REAMDME.md 버전 수정

commit 8eaa940d4e
Author: hide_d <hided62@gmail.com>
Date:   Wed Aug 18 20:40:37 2021 +0900

    Revert "fix: 7.2에서 오동작 버그 수정"

    This reverts commit 9997675b1d.

commit 9997675b1d
Author: hide_d <hided62@gmail.com>
Date:   Wed Aug 18 20:32:47 2021 +0900

    fix: 7.2에서 오동작 버그 수정

commit 9ef566f11f
Author: hide_d <hided62@gmail.com>
Date:   Wed Aug 18 20:26:31 2021 +0900

    fix: 아이템중 WarActivateSkill 관련 중첩 해제 버그 수정
2021-09-09 00:53:35 +09:00
Hide_D c70181132f build: 서버별 build가 다를 가능성 고려 2021-09-09 00:32:42 +09:00
Hide_D 538615a1f5 fix: tryNpmInstall 이후 genJS까지 실행해야 안전 2021-09-09 00:17:27 +09:00
Hide_D aa20a60a1c fix: recent_map 에러 2021-09-08 23:55:37 +09:00
Hide_D 69fa1dac6c install: php 단에서 npm 설치 환경 구성 2021-09-08 23:50:38 +09:00
Hide_D 3ab349af6e dep: build script 변경 2021-09-08 22:39:14 +09:00
Hide_D 97ac7deb2f misc: npc_control 기존 파일 제거 2021-09-08 21:06:21 +09:00
Hide_D 3230cafb9f 요구사항에 nodejs 요구 추가 2021-09-08 20:41:55 +09:00
Hide_D 394284d8de vue: NPCControl
- 외향  모사(딱히 의미는 없으나..)
- 약간 반응형
2021-09-08 20:39:04 +09:00
Hide_D 6323b174c6 webpack: 최적화 옵션 변경 2021-09-08 03:29:43 +09:00
Hide_D 3d3e0e5139 vue: NPCControl
- 일단 모든 기능 작동
2021-09-08 03:04:40 +09:00
Hide_D ffc7d4bacc vue: NPCControl(WIP) 메인 기능 동작 2021-09-08 02:48:46 +09:00
Hide_D 598236a1d2 vue: NPCControl(WIP) 2021-09-07 03:03:25 +09:00
Hide_D 69207519bd vue-component: NumberInputWithInfo 2021-09-07 00:29:38 +09:00
Hide_D 022eb1012f ts: numberWithCommas 분리 2021-09-07 00:16:28 +09:00
Hide_D 0a9c59f91e fix: 은퇴 시 숙련 포인트를 지나치게 많이 받는 문제 수정 2021-09-06 02:30:00 +09:00
Hide_D 7ebb22b892 재야에서 도시보기 warning 2021-09-06 02:17:56 +09:00
Hide_D 3dc7fc6f14 vue: NPCControl(WIP) 2021-09-06 02:12:28 +09:00
Hide_D 90dea7517b fix: div 0 2021-09-05 23:05:06 +09:00
Hide_D eae48f9564 warning 메시지 수정 2021-09-05 23:02:52 +09:00
Hide_D dd7afba5f5 delete-old: board 2021-09-05 21:27:41 +09:00
Hide_D 73357b6777 CssMinimizer 적용 2021-09-05 18:20:39 +09:00
Hide_D 53df6bbcc6 vue: board 2021-09-05 17:52:39 +09:00
Hide_D 9871559227 vue: Board(WIP) 2021-09-05 03:59:00 +09:00
Hide_D 9cbead1ddc defer 대응 2021-09-05 03:32:57 +09:00
Hide_D 6402028c17 fix: m장, 의병장 숙련이 설정되지 않는 버그 수정 2021-09-04 03:42:09 +09:00
Hide_D 76bd65cf53 vue: inheritPoint 샘플 작성 2021-09-04 00:06:54 +09:00
Hide_D 6e4113de11 vue: inheritPoint(WIP) 2021-09-03 02:42:50 +09:00
Hide_D 12f37f76c7 dep: ready for vue3 2021-09-02 23:03:19 +09:00
Hide_D acd77b2c0a web_pack_config 2021-09-02 01:51:37 +09:00
Hide_D f4fb4ec00d misc: move gateway path 2021-09-02 00:46:33 +09:00
Hide_D 46ae4669ea misc: msg template 통합 2021-08-31 02:35:50 +09:00
Hide_D 67b2dbfe98 js2ts: kingdomList 2021-08-31 02:27:00 +09:00
Hide_D 4f3b39fbfa js2ts: seleect_general_from_pool 2021-08-31 01:03:22 +09:00
Hide_D a28fc52309 js2ts: join 2021-08-30 02:11:07 +09:00
Hide_D d5f0d60794 js2ts: history 2021-08-30 02:02:53 +09:00
Hide_D 72e65587df js2ts: processing - plugin 구조 마저 변경 2021-08-30 01:47:42 +09:00
Hide_D b4d4d90784 js2ts: hallOfFame 2021-08-30 01:43:01 +09:00
Hide_D 3f81fb759d misc: 기존파일 제거 2021-08-30 01:38:24 +09:00
Hide_D d995b39e02 js2ts: currentCity 2021-08-30 01:30:56 +09:00
Hide_D 3bd09a1aa4 core: getJSFiles -> getJSPlugins
- 각각 js를 불러오기보다.. 초기화 함수를 직접 호출
- lazy loading은 어차피 나중에 새로 만들거니까 안 함.
2021-08-30 01:14:20 +09:00
Hide_D a6ff951c98 js2ts: diplomacy
- select2 관련 문제 해결?
2021-08-30 00:27:04 +09:00
Hide_D 604b1557e8 legacy: #bg0, #bg1, #bg2 제거 2021-08-29 02:16:12 +09:00
Hide_D 279bd5c71a misc: Pooper export, summernote lang 2021-08-29 02:05:16 +09:00
Hide_D 97dfb02ab6 js2ts: dipcenter(WIP)
- summernote 이식
- summernote/imageFip plugin 이식
2021-08-29 01:39:03 +09:00
Hide_D 32c7b02303 misc: 미사용 파일 제거 2021-08-28 23:40:37 +09:00
Hide_D e135835e61 jquery-redirect 제거 2021-08-28 23:34:11 +09:00
Hide_D 7ed9a8075c js2ts: main(WIP)
- jquery-redirect 제거
- linkifyStr import
2021-08-28 23:14:07 +09:00
Hide_D ead8110fb4 watch에 dev 모드 추가 2021-08-28 23:13:22 +09:00
Hide_D 586b1b6c15 dep: js package version up
- typscript
- sass
- typescript-eslint
- vue
- core-js
2021-08-28 19:03:28 +09:00
Hide_D e1727c8d80 fix: admin_member path 2021-08-28 18:56:50 +09:00
Hide_D 7bd8a7ff35 fix: msg 기본 동작 2021-08-28 17:25:33 +09:00
Hide_D de48651ae7 feat: exportWindow
- global을 지저분하게 하지 않고, window에 출력만 해줌
2021-08-28 17:20:44 +09:00
Hide_D 9902e07be0 js2ts: msg(WIP) 2021-08-28 06:26:25 +09:00
Hide_D 5e4b38895e js2ts: msg(WIP) 2021-08-28 06:23:25 +09:00
Hide_D 38bbbf261a js2ts: msg(WIP) 2021-08-28 06:22:30 +09:00
Hide_D def0a52578 String format 확장 제거 2021-08-27 03:53:15 +09:00
Hide_D 4f1f87bda0 fix: extExpandCity (format func) 2021-08-27 03:41:32 +09:00
Hide_D 15f9faa2fa js2ts: extExpandCity
- 이부분은 완벽히 새로만들어야 하므로 유지
2021-08-27 03:39:59 +09:00
Hide_D 7257491d8b js2ts: myCityInfo(wip) 2021-08-27 03:36:35 +09:00
Hide_D c19b2a9ebe luxon -> date-fns 2021-08-26 22:50:02 +09:00
Hide_D 54e7fd0293 misc: type module 지정 2021-08-26 21:50:06 +09:00
Hide_D 21f3a2082b misc: delete old gateway install.js 2021-08-26 21:20:47 +09:00
Hide_D f647eb5a7b js2ts: gateway install 2021-08-26 21:20:08 +09:00
Hide_D d7b1db0081 feat: jqValidateForm에 Values Type 지정 2021-08-26 21:10:02 +09:00
Hide_D 11511316d1 js2ts: index(login)
- fix-workaround: popper 로드
2021-08-26 18:11:51 +09:00
Hide_D 95a93c2c44 misc: 사용하지 않은 deprecated 함수 마저 제거 2021-08-26 04:00:52 +09:00
Hide_D 815ce10c25 misc: 개발용 코드 삭제 2021-08-26 03:39:33 +09:00
Hide_D 5f13bfe8a1 js2ts: join user 2021-08-26 03:35:49 +09:00
Hide_D 5cd494c00a js2ts: admin_userlist 2021-08-26 02:28:18 +09:00
Hide_D 5a0a8bedc1 refac: escapeHtml, nl2br, TemplateEngine 분리 2021-08-26 01:37:46 +09:00
Hide_D 3b9884160b js2ts: entrance, webpack(entrance/dist_js) 2021-08-26 01:25:58 +09:00
Hide_D 5b2b01328a webpack: dynamic js build on update 2021-08-25 03:35:51 +09:00
Hide_D e5b51dcd16 genJS 2021-08-25 02:55:11 +09:00
Hide_D 4d8b816acf target별 JS 생성 2021-08-25 02:44:46 +09:00
Hide_D fa109c1b0b feat: VersionGit hash 추가. dynamic추가. 버전 변수 방식 변경 2021-08-25 02:12:35 +09:00
Hide_D b987fce627 feat: VersionGit에 'hash' 추가.(WIP) 2021-08-25 02:05:27 +09:00
Hide_D b072cc3266 gitignore 준비 2021-08-25 01:22:03 +09:00
Hide_D 366b40ea90 build: boosInfo, myPage, convertFormData 2021-08-22 20:13:08 +09:00
Hide_D 3d3daa205d js2ts: bossInfo, myPage
- convertFormData에서 null -> ''
2021-08-22 15:45:10 +09:00
Hide_D 665ebbd11a js2ts: bossInfo 2021-08-22 14:49:03 +09:00
Hide_D 52a5a7697d fix: 리셋 옵션에서 '기본사령턴' 2021-08-22 02:48:14 +09:00
Hide_D 97a38d516a dep: package 2021-08-22 02:40:27 +09:00
Hide_D e89475bf52 dep: webpack cache
- 개발용
2021-08-22 02:31:10 +09:00
Hide_D 90a78b05ce dep: overwrite
- TODO: 서버에서 npm run build를 자동으로 해야함
2021-08-22 02:11:33 +09:00
Hide_D 8c6eff15f0 dep: missing select2 2021-08-22 02:06:50 +09:00
Hide_D 824c58b391 build: board 2021-08-21 21:41:43 +09:00
Hide_D b97500430c js2ts: board 2021-08-21 21:41:32 +09:00
Hide_D bacafc67c9 build: util.ts 분리 2021-08-21 20:45:24 +09:00
Hide_D f23ebcdc2d js2ts: util.ts 분리 2021-08-21 20:45:10 +09:00
Hide_D edbe8e3561 build: betting 2021-08-21 20:38:24 +09:00
Hide_D 05d1e33b30 js2ts: betting 2021-08-21 20:38:15 +09:00
Hide_D 96b60ce0f5 fix: 모병/징병에서 조건 검사부 통솔 계산값 2021-08-21 16:04:03 +09:00
Hide_D 6174bc7ffd build: select_npc 2021-08-21 05:16:07 +09:00
Hide_D 3bd022e03a js2ts: select_npc 2021-08-21 05:15:58 +09:00
Hide_D b0cc5b0b60 build: processing 2021-08-21 04:40:55 +09:00
Hide_D 5493f70458 js2ts: processing
- select2 version dependency 문제로 import는 유지
2021-08-21 04:40:40 +09:00
Hide_D 323b3d9d16 허보에 수몰이 같이 들어간 버그 수정 2021-08-21 02:50:54 +09:00
Hide_D 1b0742ad2a build: processing plugin 2021-08-21 00:30:05 +09:00
Hide_D 2eb7217f49 js2ts: processing plugin 정리 2021-08-21 00:29:50 +09:00
Hide_D b6f5a286b0 build: recent_map 2021-08-20 04:59:13 +09:00
Hide_D 66c496fb10 gateway: 입구의 지도를 iframe으로 변경 2021-08-20 04:58:45 +09:00
Hide_D 56ca588c1e gateway: 입구의 지도를 iframe으로 변경 2021-08-20 04:58:05 +09:00
Hide_D e2b09caff3 build: processing parts 2021-08-20 03:24:14 +09:00
Hide_D a5b4a4c59f js2ts: processing parts(WIP) 2021-08-20 03:24:03 +09:00
Hide_D a70312a90a build: battle_simulator 2021-08-20 02:55:07 +09:00
Hide_D 6c6a3238cb js2ts: battle_simulator 2021-08-20 02:54:57 +09:00
Hide_D 9af10d4bcb misc: showErrorLog
현재 에러로그에는 javascript가 필요하지 않음
2021-08-20 01:40:03 +09:00
Hide_D f6e1b4611e build: install & jqValidateForm 2021-08-20 01:31:32 +09:00
Hide_D 7bc762d357 js2ts-fix: install 2021-08-20 01:31:18 +09:00
Hide_D 8edf1da92b fix: jqValidateForm에서 복합 타입(radio, checkbox) 처리 오류 수정 2021-08-20 01:30:34 +09:00
Hide_D a18baf2ffe REAMDME.md 버전 수정 2021-08-19 14:51:50 +09:00
Hide_D 2d41bf8f2f Revert "fix: 7.2에서 오동작 버그 수정"
This reverts commit 9997675b1d.
2021-08-18 20:40:37 +09:00
Hide_D 334778bdae fix: 7.2에서 오동작 버그 수정 2021-08-18 20:32:47 +09:00
Hide_D 1b46a06eee fix: 아이템중 WarActivateSkill 관련 중첩 해제 버그 수정 2021-08-18 20:26:31 +09:00
Hide_D 1e860e9443 js2ts & wip: install
- jqValidateForm에 전/후처리 추가
2021-08-18 02:59:58 +09:00
Hide_D 0b973672d2 build-misc: BundleAnalyzerPlugin 2021-08-17 02:56:11 +09:00
Hide_D 868ed85c7f build: user_info 2021-08-17 02:25:15 +09:00
Hide_D 6f2a24ec66 js2ts: user_info
- moment js 사용 대상 제거
- sha512 추가
- 비어있는 func.js 제거
2021-08-17 02:25:04 +09:00
Hide_D e5d5899a15 build: entrance 2021-08-17 01:05:54 +09:00
Hide_D 243473a97d js2ts: entrance
- j_server_get_status 반환형 수정
- getDateTimeNow 추가
- common에서 TemplateEngine 코드 버그 수정
2021-08-17 01:05:41 +09:00
Hide_D 28d71b8ce2 js2ts: install_db.php
- jqValidateForm 구현
  - async-validator + 수작업
- common.js 없이 ventor -> 타겟 ts 직접
2021-08-16 23:50:12 +09:00
Hide_D 1acbf90261 gateway printJS 변경 2021-08-16 23:46:53 +09:00
Hide_D 94229f84a3 fix-dep: 로그인 대문 dependency문제로 지도 안나오는 문제 해결 2021-08-16 16:09:54 +09:00
Hide_D cead74238a build: map 2021-08-16 03:29:54 +09:00
Hide_D 73c60ea94c js2ts: map 2021-08-16 03:29:44 +09:00
Hide_D 73638da4db misc: 미사용 파일 삭제 2021-08-16 01:11:38 +09:00
Hide_D bc218b73e1 js2ts: chiefCenter
- common: unwrap_any
- jQuery export 수정
- axios로 변경
- moment -> luxon
2021-08-16 01:06:17 +09:00
Hide_D aac6632f4b js2ts: vendor, evergreen browsers
- IE11 제외(webpack)
- vendor에 bootstrap, jquery 번들
- common.js에서 번들된 jquery, bootstrap 초기화
- 기본 printJS 코드를 common_path, vendors, common으로 고정
2021-08-15 22:55:08 +09:00
Hide_D fdba3fdc74 js2ts: ext.plugin_troop
- async await 대응
- axios 준비
- troop.css
2021-08-15 21:04:06 +09:00
Hide_D 21bb61ec82 js2ts: common 분리, troop.js 2021-08-15 20:19:47 +09:00
Hide_D ce1203d64d js->ts: common.js 2021-08-15 19:59:34 +09:00
Hide_D 56daf15c8e webpack: scss, vue (#189)
WebPack에 scss와 vue를 사용할 수 있도록 세팅.

현재는 php서버와 코드가 강하게 엮여있기 때문에 vue-cli 대신 수동으로 webpack에 등록.

파일 번들링 경로는 다음과 같음

- scss + style -> css
- ts -> js

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/189
Co-authored-by: hide_d <hided62@gmail.com>
Co-committed-by: hide_d <hided62@gmail.com>
2021-08-14 05:47:16 +09:00
Hide_D 96faa924d8 Merge pull request 'PHP8 버전 대응, 버그 수정' (#188) from php8 into devel
Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/188
2021-08-13 00:00:32 +09:00
Hide_D ee8854451c fix: phan 지시에 따라 일부 버그 수정
- null && key_exists 버그
- or assign이 integer 대상이므로 직접 연산
- false 대신 0 입력한 곳 수정
- 자체 Deprecate 처리한 함수 회피
- 초기화되지 않은 [] 확인하여 처리
- sleep은 정수만 받으므로 usleep으로 변경
- 선언하지 않고 그냥 사용하던 member 변수 선언
- boolean operation 순서 틀린 부분 수정
2021-08-12 23:58:20 +09:00
Hide_D 0975e925a9 use class, function 커맨드를 php8에서 사용할 수 있도록 수정
- \ 토큰 해석 문제
- VSCode 자동 완성 문제로 use function \sammo\{ 를 모두 해제
2021-08-12 22:35:42 +09:00
Hide_D 83d6a2169b 유산 포인트 시스템, 추가 기수 대비 (#187)
- 유산 포인트
  - 기수 뒤로도 누적되는 포인트
  - 생존, 최대 임관년 수, 최대 연속 내정 성공, 병종 상성 우위 횟수, 전투 횟수, 계략 성공 횟수, 천통 기여(규모 상승, 천통 수뇌, 천통 군주), 숙련도, 토너먼트, 베팅 당첨
  - 유산 관리 페이지 제공

- 태수국
  - 181년 1월에 자동 생성되는 u장수국
  - 시간이 지나면 사실상 자동 소멸
  - 유저국과는 4칸 거리, 서로는 2칸 거리
  - 이 시스템으로 인해 m장 거병 차단

- NPC 원조시 불가침
  - 1년 세수만큼 받은 경우 24개월 불가침 제안
  - 최소 6개월
  - 불가침을 받지 않고 추가 원조한 경우 계속해서 기간 상승
  - 단, 불가침 수락 전에 선포를 할 수 있음

Reviewed-on: https://storage.hided.net/gitea/devsam/core/pulls/187
Co-authored-by: hide_d <hided62@gmail.com>
Co-committed-by: hide_d <hided62@gmail.com>
2021-08-11 21:57:52 +09:00
Hide_D 21e7a4d966 Dep: update
주로 PHAN
2021-08-06 22:39:09 +09:00
Hide_D 404cd24855 작위보상 비중 수정 2021-05-02 02:00:16 +09:00
Hide_D b4ad72ee67 환약을 유니크로 습득하는 버그 수정 2021-05-01 23:48:01 +09:00
Hide_D bea628b619 환약을 습득하게 되는 버그 수정 2021-05-01 23:46:33 +09:00
Hide_D 3637e54982 유니크 onCalcStat 버그 수정 2021-05-01 23:38:06 +09:00
Hide_D e0d1a0a612 아이템 효과 텍스트 수정 2021-04-30 22:36:24 +09:00
Hide_D 3040996671 무쌍 누락분 수정 2021-04-30 16:35:34 +09:00
Hide_D dd830e7500 TypeCode 추가 2021-04-29 22:38:46 +09:00
Hide_D d2dfe2c418 전투 수비 파트 약 상향 2021-04-29 21:10:47 +09:00
Hide_D 139fb6b6e0 국가 규모 승급시 아이템 습득 방식 변경 2021-04-29 20:31:32 +09:00
Hide_D c4f6976c42 유니크 아이템에 효과 추가 2021-04-29 19:50:12 +09:00
Hide_D ab428fc104 유니크 기본 획득 확률 변경 2021-04-29 18:49:19 +09:00
Hide_D aa97f78acd 무쌍 초반 버프, 후반 너프 2021-04-29 18:47:55 +09:00
Hide_D dbce900aeb 유니크 중복 획득 가능 2021-04-29 18:44:09 +09:00
Hide_D 30b382e2e7 초반 등록 NPC 30명 2021-04-29 18:30:46 +09:00
Hide_D 433c4abb86 fix: 이민족 종료 시점 2021-04-11 23:17:47 +09:00
Hide_D 64404e4092 fix: 이민족 종료조건 추가 2021-04-11 21:22:06 +09:00
Hide_D 08d483af8a fix: 후방 워프 인구 충분 판단 기준 수정 2021-04-10 16:01:21 +09:00
Hide_D fa19c17941 fix: AI 발령 턴 오류 수정 2021-04-10 15:39:03 +09:00
Hide_D c896a999ad fix: 전방 도시가 '관'처럼 인구가 적은 경우 후방 워프하지 않는 버그 수정
feat: 후방 발령 관련 로직도 후방 워프와 유사하게 재 적용
2021-04-10 11:51:10 +09:00
Hide_D f9bca935ac fix: 장수수 카운트에 "의병장"을 포함하여 계산하는 버그 수정 2021-04-02 14:39:57 +09:00
Hide_D 7abf274d89 이민족 난이도 기본 수치 변경 2021-03-29 22:45:43 +09:00
Hide_D e2ad417306 feat: 이민족 등장 2021-03-28 16:31:01 +09:00
Hide_D 2ea9655f6b fix: 이민족 2021-03-28 05:57:53 +09:00
Hide_D f450d5d9de fix: 수비자 도시 버그
fix: RaiseInvader 버그 수정 중
2021-03-28 04:12:10 +09:00
Hide_D f8f4b73a09 feat: RaiserInvader 초기 구현 2021-03-28 03:13:03 +09:00
Hide_D 926d96732d fix: 가상 역사 모드에서 후계자 지정이 사실 모드 설정을 따라가는 버그 수정 2021-03-23 13:24:34 +09:00
Hide_D 167113d6a3 fix: 빙의 해제시 owner 값 버그 수정 2021-03-23 13:19:40 +09:00
Hide_D 911cb614a5 fix: RegNPC 버그 수정, event handler 규격 버그 수정 2021-03-19 18:09:53 +09:00
Hide_D 7a939b7024 fix: RegNPC 버그 수정 2021-03-19 17:44:34 +09:00
Hide_D 6e57a60997 RegNPC 버그 수정 2021-03-19 17:36:13 +09:00
Hide_D 9f1151e699 fix: can부대구출발령 없음 2021-03-19 17:22:48 +09:00
Hide_D 3fbe1fb63d 디버그2 2021-02-28 01:39:47 +09:00
Hide_D d4906eec5a 디버그 코드 추가 2021-02-28 01:33:58 +09:00
Hide_D ebe0663e74 에러 로그용 추가 2021-02-28 01:05:27 +09:00
Hide_D 04c89b9711 긴급 호출 대비 2021-02-21 00:40:49 +09:00
Hide_D 4f2bc874e5 initFull을 할 필요가 없었던 것! 2021-02-10 21:24:04 +09:00
Hide_D 316ac5c3c8 불가침인데도 선포 가능한 버그 수정 2021-01-12 17:14:36 +09:00
Hide_D 7882aa667e 관리자 도구 수정 2021-01-07 22:22:04 +09:00
Hide_D 8b8d5eecbf 모반시도 버그 수정 2021-01-07 01:12:06 +09:00
Hide_D 65b76643ee feat: 빙의일람에 장수 선택 내역
fix: 장수 선택 내역에서 owner_name 미반영 버그 수정
fix: 온라인 장수에서 npc가 뜨는 버그 수정
2021-01-03 18:31:18 +09:00
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
1697 changed files with 152627 additions and 67846 deletions
+15
View File
@@ -0,0 +1,15 @@
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3,
"modules": false
}
]
],
"plugins": [
"lodash"
]
}
+27
View File
@@ -0,0 +1,27 @@
module.exports = {
root: true,
parser: "vue-eslint-parser",
parserOptions: {
"project": "./tsconfig.json"
},
ignorePatterns: ['*.test.ts', '.eslintrc.cjs', 'webpack.config.cjs', '*.js'],
overrides: [{
files: ['*.ts', '*.tsx', "*.vue"],
}],
plugins: [
"@typescript-eslint",
],
extends: [
"eslint:recommended",
'plugin:vue/essential',
'@vue/typescript',
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
rules: {
'@typescript-eslint/no-floating-promises': 'error',
"vue/no-multiple-template-root": "off",
"vue/no-v-for-template-key": "off",
}
}
+67 -50
View File
@@ -1,50 +1,67 @@
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# 체섭 ignore
*.log
logs/*.txt
d_log/*.txt
d_log/*.zip
sess_*
*/logs/*.txt
*/logs/*/*.txt
*/logs/preserved
err.txt
che/.htaccess
kwe/.htaccess
pwe/.htaccess
twe/.htaccess
hwe/.htaccess
d_shared
d_pic/*.jpg
d_pic/*.gif
d_pic/*.png
d_pic/uploaded_image
d_setting/*.php
*/d_setting/*.php
*/d_setting/templates/*.php
**/old/*
test.php
/che
/kwe
/pwe
/nya
/pya
/twe
phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
/node_modules
package-lock.json
# 체섭 ignore
*.log
logs/*.txt
d_log/*.txt
d_log/*.zip
sess_*
*/logs/*.txt
*/logs/*/*.txt
*/logs/preserved
err.txt
che/.htaccess
kwe/.htaccess
pwe/.htaccess
twe/.htaccess
hwe/.htaccess
d_shared
d_pic/*.jpg
d_pic/*.gif
d_pic/*.png
d_pic/*.webp
d_pic/uploaded_image
*/dist_misc/*
*/dist_js/*
*/dist_css/*
/dist_misc/*
/dist_js/*
/dist_css/*
d_setting/*.php
*/d_setting/*.php
*/d_setting/templates/*.php
!*.orig.php
*/data/file_cache
**/old/*
test.php
/che
/kwe
/pwe
/nya
/pya
/twe
phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
ingame/js/*
ingame/css/*
gateway/js/*
gateway/css/*
+17 -7
View File
@@ -7,7 +7,7 @@
*/
return [
// Supported values: `'5.6'`, `'7.0'`, `'7.1'`, `'7.2'`, `'7.3'`,
// `'7.4'`, `null`.
// `'7.4'`, `'8.0'`, `'8.1'`, `null`.
// If this is set to `null`,
// then Phan assumes the PHP version which is closest to the minor version
// of the php executable used to execute Phan.
@@ -15,15 +15,14 @@ return [
// Note that the **only** effect of choosing `'5.6'` is to infer
// that functions removed in php 7.0 exist.
// (See `backward_compatibility_checks` for additional options)
"target_php_version" => '7.3',
'backward_compatibility_checks ' => false,
'minimum_severity'=>\Phan\Issue::SEVERITY_NORMAL,
"target_php_version" => '7.4',
'backward_compatibility_checks ' => true,
'minimum_severity'=>\Phan\Issue::SEVERITY_CRITICAL,
'file_list' => [
'f_config/config.php',
'hwe/a_bestGeneral.php',
'hwe/a_emperior.php',
'hwe/a_emperior2.php',
'hwe/a_emperior_detail.php',
'hwe/a_genList.php',
'hwe/a_hallOfFame.php',
@@ -42,19 +41,19 @@ return [
'hwe/b_dipcenter.php',
'hwe/b_diplomacy.php',
'hwe/b_genList.php',
'hwe/v_inheritPoint.php',
'hwe/b_myBossInfo.php',
'hwe/b_myCityInfo.php',
'hwe/b_myGenInfo.php',
'hwe/b_myKingdomInfo.php',
'hwe/b_myPage.php',
'hwe/b_npc_control.php',
'hwe/b_processing.php',
'hwe/b_tournament.php',
'hwe/b_troop.php',
'hwe/c_auction.php',
'hwe/c_die_immediately.php',
'hwe/c_dipcenter.php',
'hwe/c_tournament.php',
'hwe/c_vacation.php',
'hwe/c_vote.php',
'hwe/func.php',
'hwe/func_auction.php',
@@ -83,19 +82,24 @@ return [
'hwe/j_board_comment_add.php',
'hwe/j_board_get_articles.php',
'hwe/j_chief_turn.php',
'hwe/j_die_immediately.php',
'hwe/j_diplomacy_destroy_letter.php',
'hwe/j_diplomacy_get_letter.php',
'hwe/j_diplomacy_respond_letter.php',
'hwe/j_diplomacy_rollback_letter.php',
'hwe/j_diplomacy_send_letter.php',
'hwe/j_export_simulator_object.php',
'hwe/j_general_log_old.php',
'hwe/j_general_set_permission.php',
'hwe/j_general_turn.php',
'hwe/j_getChiefTurn.php',
'hwe/j_get_basic_general_list.php',
'hwe/j_get_city_list.php',
'hwe/j_get_general_list.php',
'hwe/j_get_nation_general_list.php',
'hwe/j_get_reserved_command.php',
'hwe/j_get_select_npc_token.php',
'hwe/j_get_select_pool.php',
'hwe/j_image_upload.php',
'hwe/j_install.php',
'hwe/j_install_db.php',
@@ -109,14 +113,20 @@ return [
'hwe/j_msg_get_recent.php',
'hwe/j_msg_submit.php',
'hwe/j_myBossInfo.php',
'hwe/j_raise_event.php',
'hwe/j_select_npc.php',
'hwe/j_select_picked_general.php',
'hwe/j_server_basic_info.php',
'hwe/j_set_chief_command.php',
'hwe/j_set_general_command.php',
'hwe/j_set_my_setting.php',
'hwe/j_set_npc_control.php',
'hwe/j_simulate_battle.php',
'hwe/j_troop.php',
'hwe/j_vacation.php',
'hwe/lib.php',
'hwe/process_war.php',
'hwe/select_general_from_pool.php',
'hwe/select_npc.php',
'hwe/t_board.php',
'hwe/t_diplomacy.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>
+13 -11
View File
@@ -5,22 +5,24 @@
## 요구사항
* Apache2
* <code>mpm_event</code> 권장
* PHP 7.3 이상
* <code>php-fpm</code> 권장
* php에서 curl, pdo-sqlite을 실행가능해야 합니다. (기본값: 지원)
* mysqlnd가 지원되어야합니다. (기본값: 지원)
* mysqli
* Apache2 또는 nginx
* Apache2인 경우 `mpm_event` 권장
* PHP 8.0 이상
* `php-fpm` 권장
* php에서 curl, pdo-sqlite을 실행가능해야 합니다.
* mysqli, mysqlnd
* gd
* mbstring
* NodeJS 14 이상
* 내부의 git을 통해 upgrade 때 `webpack build` 용도로 필요합니다.
* MariaDB 10.2.1 이상
* 현재 MySQL은 지원하지 않습니다.
* <code>git</code>
* <code>curl</code>
* `git`
* `curl`
Linux는 Ubuntu 16.04, 18.04, Windows는 Windows 10에서 XAMPP를 사용한 환경에서 테스트되었습니다.
Linux는 Ubuntu 18.04, 20.04, Windows는 WSL2를 사용한 환경에서 테스트되었습니다.
Docker를 이용한 설치는 계획중입니다.
Docker를 이용한 설치도 제공하고 있습니다.
## Docker를 이용한 설치
+53 -51
View File
@@ -1,51 +1,53 @@
{
"name":"sammo-hid/sammo",
"description":"삼국지 모의전투 HiDCHe",
"license": [
"MIT",
"GPL-2.0-or-later",
"proprietary"
],
"config": {
"platform": {
"php": "7.3"
}
},
"require": {
"brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3",
"guzzlehttp/guzzle": "^6.3",
"scssphp/scssphp": "^1.0",
"monolog/monolog": "^1.23",
"firephp/firephp-core": "^0.4.0",
"vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1",
"pguardiario/phpuri": "^1.0",
"symfony/lock": "^4.1",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5",
"phan/phan": "^2.7"
},
"autoload": {
"psr-4": {
"sammo\\": [
"src/sammo"
],
"kakao\\": [
"src/kakao"
]
},
"classmap": [
"d_setting/"
],
"exclude-from-classmap": [
"**/*.orig.php"
],
"files":[
"f_config/config.php"
]
}
}
{
"name":"sammo-hid/sammo",
"description":"삼국지 모의전투 HiDCHe",
"license": [
"MIT",
"GPL-2.0-or-later",
"proprietary"
],
"config": {
"platform": {
"php": "7.4"
}
},
"require": {
"brandonwamboldt/utilphp": "^1.1",
"sergeytsalkov/meekrodb": "^2.3",
"league/plates": "^3.3",
"guzzlehttp/guzzle": "^6.3",
"scssphp/scssphp": "^1.0",
"monolog/monolog": "^1.23",
"firephp/firephp-core": "^0.4.0",
"vlucas/valitron": "^1.4",
"php-extended/php-tail": "^2.1",
"pguardiario/phpuri": "^1.0",
"symfony/lock": "^4.1",
"ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5",
"phan/phan": "*",
"erusev/parsedown-extra": "^0.8.1",
"nette/caching": "^3.0"
},
"autoload": {
"psr-4": {
"sammo\\": [
"src/sammo"
],
"kakao\\": [
"src/kakao"
]
},
"classmap": [
"d_setting/"
],
"exclude-from-classmap": [
"**/*.orig.php"
],
"files":[
"f_config/config.php"
]
}
}
Generated
+1382 -273
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "7343763bee946f23e755edecd14d6b2c",
"content-hash": "2aeb036fc53a6fdc343bd2707d4697ee",
"packages": [
{
"name": "brandonwamboldt/utilphp",
@@ -50,20 +50,24 @@
"php",
"utility"
],
"support": {
"issues": "https://github.com/brandonwamboldt/utilphp/issues",
"source": "https://github.com/brandonwamboldt/utilphp/tree/master"
},
"time": "2015-02-02T17:56:14+00:00"
},
{
"name": "catfan/medoo",
"version": "v1.7.8",
"version": "v1.7.10",
"source": {
"type": "git",
"url": "https://github.com/catfan/Medoo.git",
"reference": "dd9d570584cfb1e09ec470608479b86e41d5b60d"
"reference": "2d675f73e23f63bbaeb9a8aa33318659a3d3c32f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/catfan/Medoo/zipball/dd9d570584cfb1e09ec470608479b86e41d5b60d",
"reference": "dd9d570584cfb1e09ec470608479b86e41d5b60d",
"url": "https://api.github.com/repos/catfan/Medoo/zipball/2d675f73e23f63bbaeb9a8aa33318659a3d3c32f",
"reference": "2d675f73e23f63bbaeb9a8aa33318659a3d3c32f",
"shasum": ""
},
"require": {
@@ -110,32 +114,37 @@
"sql",
"sqlite"
],
"time": "2019-12-19T05:04:34+00:00"
"support": {
"issues": "https://github.com/catfan/Medoo/issues",
"source": "https://github.com/catfan/Medoo"
},
"time": "2020-02-11T08:20:42+00:00"
},
{
"name": "composer/semver",
"version": "1.5.1",
"version": "3.2.5",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de"
"reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/c6bea70230ef4dd483e6bbcab6005f682ed3a8de",
"reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de",
"url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9",
"reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0"
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^4.5 || ^5.0.5"
"phpstan/phpstan": "^0.12.54",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
"dev-main": "3.x-dev"
}
},
"autoload": {
@@ -171,28 +180,48 @@
"validation",
"versioning"
],
"time": "2020-01-13T12:06:48+00:00"
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.2.5"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2021-05-24T12:41:47+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "1.4.1",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7"
"reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/1ab9842d69e64fb3a01be6b656501032d1b78cb7",
"reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339",
"reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0",
"psr/log": "^1.0"
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8"
"phpstan/phpstan": "^0.12.55",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"autoload": {
@@ -215,26 +244,140 @@
"Xdebug",
"performance"
],
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/2.0.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2020-03-01T12:26:26+00:00"
"time": "2021-07-31T17:03:58+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.12.0",
"name": "erusev/parsedown",
"version": "1.7.4",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "a617e55bc62a87eec73bd456d146d134ad716f03"
"url": "https://github.com/erusev/parsedown.git",
"reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/a617e55bc62a87eec73bd456d146d134ad716f03",
"reference": "a617e55bc62a87eec73bd456d146d134ad716f03",
"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": [
{
"name": "Emanuil Rusev",
"email": "hello@erusev.com",
"homepage": "http://erusev.com"
}
],
"description": "Parser for Markdown.",
"homepage": "http://parsedown.org",
"keywords": [
"markdown",
"parser"
],
"support": {
"issues": "https://github.com/erusev/parsedown/issues",
"source": "https://github.com/erusev/parsedown/tree/1.7.x"
},
"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"
],
"support": {
"issues": "https://github.com/erusev/parsedown-extra/issues",
"source": "https://github.com/erusev/parsedown-extra/tree/0.8.x"
},
"time": "2019-12-30T23:20:37+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.13.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
"reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
"shasum": ""
},
"require": {
@@ -250,6 +393,9 @@
},
"files": [
"library/HTMLPurifier.composer.php"
],
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -268,29 +414,33 @@
"keywords": [
"html"
],
"time": "2019-10-28T03:44:26+00:00"
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/master"
},
"time": "2020-06-29T00:56:53+00:00"
},
{
"name": "felixfbecker/advanced-json-rpc",
"version": "v3.1.1",
"version": "v3.2.1",
"source": {
"type": "git",
"url": "https://github.com/felixfbecker/php-advanced-json-rpc.git",
"reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40"
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/0ed363f8de17d284d479ec813c9ad3f6834b5c40",
"reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"shasum": ""
},
"require": {
"netresearch/jsonmapper": "^1.0 || ^2.0",
"php": ">=7.0",
"phpdocumentor/reflection-docblock": "^4.0.0 || ^5.0.0"
"netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"php": "^7.1 || ^8.0",
"phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0"
},
"require-dev": {
"phpunit/phpunit": "^6.0.0"
"phpunit/phpunit": "^7.0 || ^8.0"
},
"type": "library",
"autoload": {
@@ -309,7 +459,11 @@
}
],
"description": "A more advanced JSONRPC implementation",
"time": "2020-03-11T15:21:41+00:00"
"support": {
"issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues",
"source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1"
},
"time": "2021-06-11T22:34:44+00:00"
},
{
"name": "firephp/firephp-core",
@@ -345,27 +499,33 @@
],
"description": "Traditional FirePHPCore library for sending PHP variables to the browser.",
"homepage": "https://github.com/firephp/firephp-core",
"support": {
"forum": "http://groups.google.com/group/firephp-dev",
"issues": "https://github.com/firephp/firephp-core/issues",
"source": "https://github.com/firephp/firephp-core"
},
"time": "2013-04-23T15:28:20+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.5.2",
"version": "6.5.5",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82"
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5"
"php": ">=5.5",
"symfony/polyfill-intl-idn": "^1.17.0"
},
"require-dev": {
"ext-curl": "*",
@@ -373,7 +533,6 @@
"psr/log": "^1.1"
},
"suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
@@ -412,27 +571,31 @@
"rest",
"web service"
],
"time": "2019-12-23T11:57:10+00:00"
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/6.5"
},
"time": "2020-06-16T21:01:06+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d",
"reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
"symfony/phpunit-bridge": "^4.4 || ^5.1"
},
"type": "library",
"extra": {
@@ -463,20 +626,24 @@
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
"support": {
"issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/1.4.1"
},
"time": "2021-03-07T09:25:29+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.6.1",
"version": "1.8.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a"
"reference": "dc960a912984efb74d0a90222870c72c87f10c91"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
"reference": "dc960a912984efb74d0a90222870c72c87f10c91",
"shasum": ""
},
"require": {
@@ -489,15 +656,15 @@
},
"require-dev": {
"ext-zlib": "*",
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
},
"suggest": {
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
"dev-master": "1.7-dev"
}
},
"autoload": {
@@ -534,29 +701,33 @@
"uri",
"url"
],
"time": "2019-07-01T23:21:34+00:00"
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/1.8.2"
},
"time": "2021-04-26T09:17:50+00:00"
},
{
"name": "league/plates",
"version": "3.3.0",
"version": "v3.4.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/plates.git",
"reference": "b1684b6f127714497a0ef927ce42c0b44b45a8af"
"reference": "6d3ee31199b536a4e003b34a356ca20f6f75496a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/plates/zipball/b1684b6f127714497a0ef927ce42c0b44b45a8af",
"reference": "b1684b6f127714497a0ef927ce42c0b44b45a8af",
"url": "https://api.github.com/repos/thephpleague/plates/zipball/6d3ee31199b536a4e003b34a356ca20f6f75496a",
"reference": "6d3ee31199b536a4e003b34a356ca20f6f75496a",
"shasum": ""
},
"require": {
"php": "^5.3 | ^7.0"
"php": "^7.0|^8.0"
},
"require-dev": {
"mikey179/vfsstream": "^1.4",
"phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~1.5"
"mikey179/vfsstream": "^1.6",
"phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"extra": {
@@ -578,10 +749,15 @@
"name": "Jonathan Reinink",
"email": "jonathan@reinink.ca",
"role": "Developer"
},
{
"name": "RJ Garcia",
"email": "ragboyjr@icloud.com",
"role": "Developer"
}
],
"description": "Plates, the native PHP template system that's fast, easy to use and easy to extend.",
"homepage": "http://platesphp.com",
"homepage": "https://platesphp.com",
"keywords": [
"league",
"package",
@@ -589,27 +765,31 @@
"templating",
"views"
],
"time": "2016-12-28T00:14:17+00:00"
"support": {
"issues": "https://github.com/thephpleague/plates/issues",
"source": "https://github.com/thephpleague/plates/tree/v3.4.0"
},
"time": "2020-12-25T05:00:37+00:00"
},
{
"name": "microsoft/tolerant-php-parser",
"version": "v0.0.20",
"version": "v0.1.1",
"source": {
"type": "git",
"url": "https://github.com/microsoft/tolerant-php-parser.git",
"reference": "c5e2bf5d8c9f4f27eef1370bd39ea2d1f374eeb4"
"reference": "6a965617cf484355048ac6d2d3de7b6ec93abb16"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/microsoft/tolerant-php-parser/zipball/c5e2bf5d8c9f4f27eef1370bd39ea2d1f374eeb4",
"reference": "c5e2bf5d8c9f4f27eef1370bd39ea2d1f374eeb4",
"url": "https://api.github.com/repos/microsoft/tolerant-php-parser/zipball/6a965617cf484355048ac6d2d3de7b6ec93abb16",
"reference": "6a965617cf484355048ac6d2d3de7b6ec93abb16",
"shasum": ""
},
"require": {
"php": ">=7.0"
"php": ">=7.2"
},
"require-dev": {
"phpunit/phpunit": "^6.4"
"phpunit/phpunit": "^8.5.15"
},
"type": "library",
"autoload": {
@@ -630,20 +810,24 @@
}
],
"description": "Tolerant PHP-to-AST parser designed for IDE usage scenarios",
"time": "2020-02-18T02:57:19+00:00"
"support": {
"issues": "https://github.com/microsoft/tolerant-php-parser/issues",
"source": "https://github.com/microsoft/tolerant-php-parser/tree/v0.1.1"
},
"time": "2021-07-16T21:28:12+00:00"
},
{
"name": "monolog/monolog",
"version": "1.25.3",
"version": "1.26.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "fa82921994db851a8becaf3787a9e73c5976b6f1"
"reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/fa82921994db851a8becaf3787a9e73c5976b6f1",
"reference": "fa82921994db851a8becaf3787a9e73c5976b6f1",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/c6b00f05152ae2c9b04a448f99c7590beb6042f5",
"reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5",
"shasum": ""
},
"require": {
@@ -657,11 +841,10 @@
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"graylog2/gelf-php": "~1.0",
"jakub-onderka/php-parallel-lint": "0.9",
"php-amqplib/php-amqplib": "~2.4",
"php-console/php-console": "^3.1.3",
"phpstan/phpstan": "^0.12.59",
"phpunit/phpunit": "~4.5",
"phpunit/phpunit-mock-objects": "2.3.0",
"ruflin/elastica": ">=0.90 <3.0",
"sentry/sentry": "^0.13",
"swiftmailer/swiftmailer": "^5.3|^6.0"
@@ -680,11 +863,6 @@
"sentry/sentry": "Allow sending log messages to a Sentry server"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Monolog\\": "src/Monolog"
@@ -708,20 +886,34 @@
"logging",
"psr-3"
],
"time": "2019-12-20T14:15:16+00:00"
"support": {
"issues": "https://github.com/Seldaek/monolog/issues",
"source": "https://github.com/Seldaek/monolog/tree/1.26.1"
},
"funding": [
{
"url": "https://github.com/Seldaek",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
"type": "tidelift"
}
],
"time": "2021-05-28T08:32:12+00:00"
},
{
"name": "netresearch/jsonmapper",
"version": "v2.1.0",
"version": "v4.0.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e"
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/e0f1e33a71587aca81be5cffbb9746510e1fe04e",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"shasum": ""
},
"require": {
@@ -729,10 +921,10 @@
"ext-pcre": "*",
"ext-reflection": "*",
"ext-spl": "*",
"php": ">=5.6"
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~4.8.35 || ~5.7 || ~6.4 || ~7.0",
"phpunit/phpunit": "~7.5 || ~8.0 || ~9.0",
"squizlabs/php_codesniffer": "~3.5"
},
"type": "library",
@@ -754,7 +946,235 @@
}
],
"description": "Map nested JSON structures onto PHP classes",
"time": "2020-04-16T18:48:43+00:00"
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
"source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0"
},
"time": "2020-12-01T19:48:11+00:00"
},
{
"name": "nette/caching",
"version": "v3.1.1",
"source": {
"type": "git",
"url": "https://github.com/nette/caching.git",
"reference": "3e771c589dee414724be473c24ad16dae50c1960"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/caching/zipball/3e771c589dee414724be473c24ad16dae50c1960",
"reference": "3e771c589dee414724be473c24ad16dae50c1960",
"shasum": ""
},
"require": {
"nette/finder": "^2.4 || ^3.0",
"nette/utils": "^2.4 || ^3.0",
"php": ">=7.2 <8.1"
},
"require-dev": {
"latte/latte": "^2.10",
"nette/di": "^v3.0",
"nette/tester": "^2.0",
"phpstan/phpstan": "^0.12",
"tracy/tracy": "^2.4"
},
"suggest": {
"ext-pdo_sqlite": "to use SQLiteStorage or SQLiteJournal"
},
"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 Caching: library with easy-to-use API and many cache backends.",
"homepage": "https://nette.org",
"keywords": [
"cache",
"journal",
"memcached",
"nette",
"sqlite"
],
"support": {
"issues": "https://github.com/nette/caching/issues",
"source": "https://github.com/nette/caching/tree/v3.1.1"
},
"time": "2021-03-06T14:07:38+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"
],
"support": {
"issues": "https://github.com/nette/finder/issues",
"source": "https://github.com/nette/finder/tree/v2.5.2"
},
"time": "2020-01-03T20:35:40+00:00"
},
{
"name": "nette/utils",
"version": "v3.2.2",
"source": {
"type": "git",
"url": "https://github.com/nette/utils.git",
"reference": "967cfc4f9a1acd5f1058d76715a424c53343c20c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nette/utils/zipball/967cfc4f9a1acd5f1058d76715a424c53343c20c",
"reference": "967cfc4f9a1acd5f1058d76715a424c53343c20c",
"shasum": ""
},
"require": {
"php": ">=7.2 <8.1"
},
"conflict": {
"nette/di": "<3.0.6"
},
"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.2-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"
],
"support": {
"issues": "https://github.com/nette/utils/issues",
"source": "https://github.com/nette/utils/tree/v3.2.2"
},
"time": "2021-03-03T22:53:25+00:00"
},
{
"name": "pguardiario/phpuri",
@@ -778,47 +1198,52 @@
},
"notification-url": "https://packagist.org/downloads/",
"description": "A php library for converting relative urls to absolute.",
"support": {
"issues": "https://github.com/monkeysuffrage/phpuri/issues",
"source": "https://github.com/monkeysuffrage/phpuri/tree/1.0.0"
},
"time": "2015-05-24T09:13:17+00:00"
},
{
"name": "phan/phan",
"version": "2.7.1",
"version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/phan/phan.git",
"reference": "67c51bb1593e5c30271fc16d691b82e318b90b77"
"reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phan/phan/zipball/67c51bb1593e5c30271fc16d691b82e318b90b77",
"reference": "67c51bb1593e5c30271fc16d691b82e318b90b77",
"url": "https://api.github.com/repos/phan/phan/zipball/f36b6b9a2f4143a25f35ce94d712ceb0527e9d90",
"reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90",
"shasum": ""
},
"require": {
"composer/semver": "^1.4",
"composer/xdebug-handler": "^1.3.2",
"composer/semver": "^1.4|^2.0|^3.0",
"composer/xdebug-handler": "^1.3.2|^2.0.0",
"ext-filter": "*",
"ext-json": "*",
"ext-tokenizer": "*",
"felixfbecker/advanced-json-rpc": "^3.0.4",
"microsoft/tolerant-php-parser": "0.0.20",
"netresearch/jsonmapper": "^1.6.0|^2.0",
"php": "^7.1.0",
"sabre/event": "^5.0",
"symfony/console": "^2.3|^3.0|^4.0|^5.0",
"microsoft/tolerant-php-parser": "^0.1.0",
"netresearch/jsonmapper": "^1.6.0|^2.0|^3.0|^4.0",
"php": "^7.2.0|^8.0.0",
"sabre/event": "^5.0.3",
"symfony/console": "^3.2|^4.0|^5.0",
"symfony/polyfill-mbstring": "^1.11.0",
"symfony/polyfill-php72": "^1.15"
"symfony/polyfill-php80": "^1.20.0",
"tysonandre/var_representation_polyfill": "^0.0.2"
},
"require-dev": {
"brianium/paratest": "^4.0.0",
"phpunit/phpunit": "^7.5.0"
"phpunit/phpunit": "^8.5.0"
},
"suggest": {
"ext-ast": "Needed for parsing ASTs (unless --use-fallback-parser is used). 1.0.1+ is needed, 1.0.6+ is recommended.",
"ext-ast": "Needed for parsing ASTs (unless --use-fallback-parser is used). 1.0.1+ is needed, 1.0.14+ is recommended.",
"ext-iconv": "Either iconv or mbstring is needed to ensure issue messages are valid utf-8",
"ext-igbinary": "Improves performance of polyfill when ext-ast is unavailable",
"ext-mbstring": "Either iconv or mbstring is needed to ensure issue messages are valid utf-8",
"ext-tokenizer": "Needed for fallback/polyfill parser support and file/line-based suppressions."
"ext-tokenizer": "Needed for fallback/polyfill parser support and file/line-based suppressions.",
"ext-var_representation": "Suggested for converting values to strings in issue messages"
},
"bin": [
"phan",
@@ -852,7 +1277,11 @@
"php",
"static"
],
"time": "2020-04-12T01:25:29+00:00"
"support": {
"issues": "https://github.com/phan/phan/issues",
"source": "https://github.com/phan/phan/tree/5.0.0"
},
"time": "2021-08-01T18:17:28+00:00"
},
{
"name": "php-extended/php-system",
@@ -892,6 +1321,10 @@
"php",
"system"
],
"support": {
"issues": "https://gitlab.com/php-extended/php-system/issues",
"source": "https://gitlab.com/php-extended/php-system"
},
"time": "2018-06-07T06:03:27+00:00"
},
{
@@ -936,29 +1369,33 @@
"php",
"tail"
],
"support": {
"issues": "https://gitlab.com/php-extended/php-tail/issues",
"source": "https://gitlab.com/php-extended/php-tail"
},
"time": "2018-06-07T06:04:58+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.1.0",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
"dev-2.x": "2.x-dev"
}
},
"autoload": {
@@ -985,32 +1422,35 @@
"reflection",
"static analysis"
],
"time": "2020-04-27T09:25:28+00:00"
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
"source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
},
"time": "2020-06-27T09:03:43+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.1.0",
"version": "5.2.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e"
"reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
"reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
"shasum": ""
},
"require": {
"ext-filter": "^7.1",
"php": "^7.2",
"phpdocumentor/reflection-common": "^2.0",
"phpdocumentor/type-resolver": "^1.0",
"webmozart/assert": "^1"
"ext-filter": "*",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.3",
"webmozart/assert": "^1.9.1"
},
"require-dev": {
"doctrine/instantiator": "^1",
"mockery/mockery": "^1"
"mockery/mockery": "~1.3.2"
},
"type": "library",
"extra": {
@@ -1038,34 +1478,37 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2020-02-22T12:28:44+00:00"
"support": {
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/master"
},
"time": "2020-09-03T19:13:55+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.1.0",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "7462d5f123dfc080dfdf26897032a6513644fc95"
"reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95",
"reference": "7462d5f123dfc080dfdf26897032a6513644fc95",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
"reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
"shasum": ""
},
"require": {
"php": "^7.2",
"php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "^7.2",
"mockery/mockery": "~1"
"ext-tokenizer": "*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
"dev-1.x": "1.x-dev"
}
},
"autoload": {
@@ -1084,31 +1527,30 @@
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"time": "2020-02-18T18:59:58+00:00"
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
"source": "https://github.com/phpDocumentor/TypeResolver/tree/1.4.0"
},
"time": "2020-09-17T18:55:26+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
"php": ">=7.2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
@@ -1121,7 +1563,7 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
@@ -1133,7 +1575,11 @@
"container-interop",
"psr"
],
"time": "2017-02-14T16:28:37+00:00"
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.1"
},
"time": "2021-03-05T17:36:06+00:00"
},
{
"name": "psr/http-message",
@@ -1183,20 +1629,23 @@
"request",
"response"
],
"support": {
"source": "https://github.com/php-fig/http-message/tree/master"
},
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/log",
"version": "1.1.2",
"version": "1.1.4",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801"
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801",
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": ""
},
"require": {
@@ -1220,7 +1669,7 @@
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
@@ -1230,7 +1679,10 @@
"psr",
"psr-3"
],
"time": "2019-11-01T11:05:21+00:00"
"support": {
"source": "https://github.com/php-fig/log/tree/1.1.4"
},
"time": "2021-05-03T11:20:27+00:00"
},
{
"name": "ralouphie/getallheaders",
@@ -1270,28 +1722,33 @@
}
],
"description": "A polyfill for getallheaders.",
"support": {
"issues": "https://github.com/ralouphie/getallheaders/issues",
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "sabre/event",
"version": "5.1.0",
"version": "5.1.2",
"source": {
"type": "git",
"url": "https://github.com/sabre-io/event.git",
"reference": "d00a17507af0e7544cfe17096372f5d733e3b276"
"reference": "c120bec57c17b6251a496efc82b732418b49d50a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sabre-io/event/zipball/d00a17507af0e7544cfe17096372f5d733e3b276",
"reference": "d00a17507af0e7544cfe17096372f5d733e3b276",
"url": "https://api.github.com/repos/sabre-io/event/zipball/c120bec57c17b6251a496efc82b732418b49d50a",
"reference": "c120bec57c17b6251a496efc82b732418b49d50a",
"shasum": ""
},
"require": {
"php": "^7.1"
"php": "^7.1 || ^8.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2.16.1",
"phpunit/phpunit": "^7 || ^8"
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.0"
},
"type": "library",
"autoload": {
@@ -1330,20 +1787,25 @@
"reactor",
"signal"
],
"time": "2020-01-31T18:52:29+00:00"
"support": {
"forum": "https://groups.google.com/group/sabredav-discuss",
"issues": "https://github.com/sabre-io/event/issues",
"source": "https://github.com/fruux/sabre-event"
},
"time": "2020-10-03T11:02:22+00:00"
},
{
"name": "scssphp/scssphp",
"version": "1.0.6",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/scssphp/scssphp.git",
"reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c"
"reference": "b83594e2323c5d6e80785df3f91b9d1d32aad530"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/5b3c9d704950d8f9637f5110c36c281ec47dc13c",
"reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/b83594e2323c5d6e80785df3f91b9d1d32aad530",
"reference": "b83594e2323c5d6e80785df3f91b9d1d32aad530",
"shasum": ""
},
"require": {
@@ -1352,11 +1814,19 @@
"php": ">=5.6.0"
},
"require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3",
"squizlabs/php_codesniffer": "~2.5",
"twbs/bootstrap": "~4.3",
"bamarni/composer-bin-plugin": "^1.4",
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4",
"sass/sass-spec": "*",
"squizlabs/php_codesniffer": "~3.5",
"symfony/phpunit-bridge": "^5.1",
"twbs/bootstrap": "~5.0",
"twbs/bootstrap4": "4.6.0",
"zurb/foundation": "~6.5"
},
"suggest": {
"ext-iconv": "Can be used as fallback when ext-mbstring is not available",
"ext-mbstring": "For best performance, mbstring should be installed as it is faster than ext-iconv"
},
"bin": [
"bin/pscss"
],
@@ -1391,24 +1861,28 @@
"scss",
"stylesheet"
],
"time": "2019-12-12T05:00:52+00:00"
"support": {
"issues": "https://github.com/scssphp/scssphp/issues",
"source": "https://github.com/scssphp/scssphp/tree/v1.6.0"
},
"time": "2021-07-02T16:28:10+00:00"
},
{
"name": "sergeytsalkov/meekrodb",
"version": "v2.3",
"version": "v2.4",
"source": {
"type": "git",
"url": "https://github.com/SergeyTsalkov/meekrodb.git",
"reference": "eb36858f1aff94ae1665900e681a1cfb78563ee1"
"reference": "e30c240d54bc81f58c58507a9ed768032eb494a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/SergeyTsalkov/meekrodb/zipball/eb36858f1aff94ae1665900e681a1cfb78563ee1",
"reference": "eb36858f1aff94ae1665900e681a1cfb78563ee1",
"url": "https://api.github.com/repos/SergeyTsalkov/meekrodb/zipball/e30c240d54bc81f58c58507a9ed768032eb494a5",
"reference": "e30c240d54bc81f58c58507a9ed768032eb494a5",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
@@ -1434,39 +1908,49 @@
"mysqli",
"pdo"
],
"time": "2014-06-16T22:40:22+00:00"
"support": {
"email": "support@meekro.com",
"issues": "https://github.com/SergeyTsalkov/meekrodb/issues",
"source": "https://github.com/SergeyTsalkov/meekrodb/tree/v2.4"
},
"time": "2021-06-29T04:31:23+00:00"
},
{
"name": "symfony/console",
"version": "v5.0.8",
"version": "v5.3.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935"
"reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5fa1caadc8cdaa17bcfb25219f3b53fe294a9935",
"reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935",
"url": "https://api.github.com/repos/symfony/console/zipball/51b71afd6d2dc8f5063199357b9880cea8d8bfe2",
"reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2",
"shasum": ""
},
"require": {
"php": "^7.2.5",
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php73": "^1.8",
"symfony/service-contracts": "^1.1|^2"
"symfony/polyfill-php80": "^1.16",
"symfony/service-contracts": "^1.1|^2",
"symfony/string": "^5.1"
},
"conflict": {
"psr/log": ">=3",
"symfony/dependency-injection": "<4.4",
"symfony/dotenv": "<5.1",
"symfony/event-dispatcher": "<4.4",
"symfony/lock": "<4.4",
"symfony/process": "<4.4"
},
"provide": {
"psr/log-implementation": "1.0"
"psr/log-implementation": "1.0|2.0"
},
"require-dev": {
"psr/log": "~1.0",
"psr/log": "^1|^2",
"symfony/config": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.4|^5.0",
@@ -1481,11 +1965,6 @@
"symfony/process": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
@@ -1508,8 +1987,17 @@
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Console Component",
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.3.6"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
@@ -1524,40 +2012,102 @@
"type": "tidelift"
}
],
"time": "2020-03-30T11:42:42+00:00"
"time": "2021-07-27T19:10:22+00:00"
},
{
"name": "symfony/lock",
"version": "v4.4.3",
"name": "symfony/deprecation-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/lock.git",
"reference": "6c4f5b620871cfef5b004fc57f2ca74572ae03b3"
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/lock/zipball/6c4f5b620871cfef5b004fc57f2ca74572ae03b3",
"reference": "6c4f5b620871cfef5b004fc57f2ca74572ae03b3",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"psr/log": "~1.0"
},
"conflict": {
"doctrine/dbal": "<2.5"
},
"require-dev": {
"doctrine/dbal": "~2.5",
"mongodb/mongodb": "~1.1",
"predis/predis": "~1.0"
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.4-dev"
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
},
"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": "2021-03-23T23:28:01+00:00"
},
{
"name": "symfony/lock",
"version": "v4.4.27",
"source": {
"type": "git",
"url": "https://github.com/symfony/lock.git",
"reference": "6ca476d4ac992802f2a4043929f68f1818449486"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/lock/zipball/6ca476d4ac992802f2a4043929f68f1818449486",
"reference": "6ca476d4ac992802f2a4043929f68f1818449486",
"shasum": ""
},
"require": {
"php": ">=7.1.3",
"psr/log": "^1|^2|^3",
"symfony/polyfill-php80": "^1.16"
},
"conflict": {
"doctrine/dbal": "<2.6"
},
"require-dev": {
"doctrine/dbal": "^2.6|^3.0",
"predis/predis": "~1.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Lock\\": ""
@@ -1580,7 +2130,7 @@
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Lock Component",
"description": "Creates and manages locks, a mechanism to provide exclusive access to a shared resource",
"homepage": "https://symfony.com",
"keywords": [
"cas",
@@ -1590,24 +2140,41 @@
"redlock",
"semaphore"
],
"time": "2020-01-04T13:00:46+00:00"
"support": {
"source": "https://github.com/symfony/lock/tree/v4.4.27"
},
"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": "2021-07-23T15:41:52+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.15.0",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14"
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=7.1"
},
"suggest": {
"ext-ctype": "For best performance"
@@ -1615,7 +2182,11 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
@@ -1648,6 +2219,9 @@
"polyfill",
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
@@ -1662,24 +2236,276 @@
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.15.0",
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "16880ba9c5ebe3642d1995ab866db29270b36535"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535",
"reference": "16880ba9c5ebe3642d1995ab866db29270b36535",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1"
},
"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": "2021-05-27T12:26:48+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "65bd267525e82759e7d8c4e8ceea44f398838e65"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65",
"reference": "65bd267525e82759e7d8c4e8ceea44f398838e65",
"shasum": ""
},
"require": {
"php": ">=7.1",
"symfony/polyfill-intl-normalizer": "^1.10",
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Trevor Rowbotham",
"email": "trevor.rowbotham@pm.me"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0"
},
"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": "2021-05-27T09:27:20+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
"reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
"files": [
"bootstrap.php"
],
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"intl",
"normalizer",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
},
"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": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
"reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"suggest": {
"ext-mbstring": "For best performance"
@@ -1687,7 +2513,11 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
@@ -1721,6 +2551,9 @@
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
@@ -1735,29 +2568,33 @@
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
"time": "2021-05-27T12:26:48+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.15.0",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "37b0976c78b94856543260ce09b460a7bc852747"
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747",
"reference": "37b0976c78b94856543260ce09b460a7bc852747",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
"reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
@@ -1790,6 +2627,9 @@
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
@@ -1804,29 +2644,33 @@
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
"time": "2021-05-27T09:17:38+00:00"
},
{
"name": "symfony/polyfill-php73",
"version": "v1.15.0",
"version": "v1.23.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7"
"reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7",
"reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010",
"reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
@@ -1862,6 +2706,9 @@
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
@@ -1876,25 +2723,108 @@
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
"time": "2021-02-19T12:13:01+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.0.1",
"name": "symfony/polyfill-php80",
"version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "144c5e51266b281231e947b51223ba14acf1a749"
"url": "https://github.com/symfony/polyfill-php80.git",
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749",
"reference": "144c5e51266b281231e947b51223ba14acf1a749",
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
"reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
"shasum": ""
},
"require": {
"php": "^7.2.5",
"psr/container": "^1.0"
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php80\\": ""
},
"files": [
"bootstrap.php"
],
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ion Bazan",
"email": "ion.bazan@gmail.com"
},
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
},
"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": "2021-07-28T13:41:28+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1"
},
"suggest": {
"symfony/service-implementation": ""
@@ -1902,7 +2832,11 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
@@ -1934,27 +2868,178 @@
"interoperability",
"standards"
],
"time": "2019-11-18T17:27:11+00:00"
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.4.0"
},
"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": "2021-04-01T10:43:52+00:00"
},
{
"name": "vlucas/valitron",
"version": "v1.4.7",
"name": "symfony/string",
"version": "v5.3.3",
"source": {
"type": "git",
"url": "https://github.com/vlucas/valitron.git",
"reference": "a03072bed1679660200766d134507a30193eaf6d"
"url": "https://github.com/symfony/string.git",
"reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vlucas/valitron/zipball/a03072bed1679660200766d134507a30193eaf6d",
"reference": "a03072bed1679660200766d134507a30193eaf6d",
"url": "https://api.github.com/repos/symfony/string/zipball/bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
"reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "~1.15"
},
"require-dev": {
"symfony/error-handler": "^4.4|^5.0",
"symfony/http-client": "^4.4|^5.0",
"symfony/translation-contracts": "^1.1|^2",
"symfony/var-exporter": "^4.4|^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"files": [
"Resources/functions.php"
],
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.3.3"
},
"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": "2021-06-27T11:44:38+00:00"
},
{
"name": "tysonandre/var_representation_polyfill",
"version": "0.0.2",
"source": {
"type": "git",
"url": "https://github.com/TysonAndre/var_representation_polyfill.git",
"reference": "3f17999ee1f257319ddc6721dd26ebbc5d175f33"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/TysonAndre/var_representation_polyfill/zipball/3f17999ee1f257319ddc6721dd26ebbc5d175f33",
"reference": "3f17999ee1f257319ddc6721dd26ebbc5d175f33",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": "^7.2.0|^8.0.0"
},
"require-dev": {
"phan/phan": "^4.0",
"phpunit/phpunit": "^8.5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"VarRepresentation\\": "src/VarRepresentation"
},
"files": [
"src/var_representation.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Tyson Andre"
}
],
"description": "Polyfill for var_representation",
"keywords": [
"var_export",
"var_representation"
],
"support": {
"issues": "https://github.com/TysonAndre/var_representation_polyfill/issues",
"source": "https://github.com/TysonAndre/var_representation_polyfill/tree/0.0.2"
},
"time": "2021-06-26T18:55:02+00:00"
},
{
"name": "vlucas/valitron",
"version": "v1.4.10",
"source": {
"type": "git",
"url": "https://github.com/vlucas/valitron.git",
"reference": "5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vlucas/valitron/zipball/5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb",
"reference": "5ebd5d7af82cc0a9d798e816a2ecad63f1b59ceb",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.5 || ^6.5"
"phpunit/phpunit": ">=4.8.35"
},
"suggest": {
"ext-mbstring": "It can support the multiple bytes string length."
@@ -1973,43 +3058,59 @@
{
"name": "Vance Lucas",
"email": "vance@vancelucas.com",
"homepage": "http://www.vancelucas.com"
"homepage": "https://www.vancelucas.com"
}
],
"description": "Simple, elegant, stand-alone validation library with NO dependencies",
"homepage": "http://github.com/vlucas/valitron",
"homepage": "https://github.com/vlucas/valitron",
"keywords": [
"valid",
"validation",
"validator"
],
"time": "2019-08-29T19:49:43+00:00"
"support": {
"issues": "https://github.com/vlucas/valitron/issues",
"source": "https://github.com/vlucas/valitron/tree/v1.4.10"
},
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/vlucas/valitron",
"type": "tidelift"
}
],
"time": "2021-07-08T16:18:03+00:00"
},
{
"name": "webmozart/assert",
"version": "1.8.0",
"version": "1.10.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6"
"url": "https://github.com/webmozarts/assert.git",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
"reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0",
"php": "^7.2 || ^8.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"vimeo/psalm": "<3.9.1"
"phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13"
"phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
@@ -2031,7 +3132,11 @@
"check",
"validate"
],
"time": "2020-04-18T12:12:48+00:00"
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/1.10.0"
},
"time": "2021-03-09T10:59:23+00:00"
},
{
"name": "xemlock/htmlpurifier-html5",
@@ -2082,6 +3187,10 @@
"validator",
"xss"
],
"support": {
"issues": "https://github.com/xemlock/htmlpurifier-html5/issues",
"source": "https://github.com/xemlock/htmlpurifier-html5/tree/master"
},
"time": "2019-08-07T17:19:21+00:00"
}
],
@@ -2096,5 +3205,5 @@
"platform-overrides": {
"php": "7.3"
},
"plugin-api-version": "1.1.0"
"plugin-api-version": "2.0.0"
}
Regular → Executable
BIN
View File
Binary file not shown.
+240 -181
View File
@@ -1,182 +1,241 @@
@charset "utf-8";
body {
color:white; 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;
padding: 0px;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';
}
th, td {
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;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';
}
a.just_link {
text-decoration: none;
}
.with_border{
margin:0;
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;
}
.section_title {
height:50px;
line-height:50px;
font-size: 30px; font-weight: bold;
text-align: center;
color:white;
padding:0;
}
.legacy_layout div {
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;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';;
}
.obj_fill{
display:block;
width:100%;
height:100%;
}
button.with_skin {
padding:0 4px;
background-color: black; color: white;
font-family: '맑은 고딕';
font-size: 13px;
}
button.with_skin:disabled {
background-color:#333333;
}
input.with_skin {
background-color: black; color: white;
font-family: '맑은 고딕';
font-size: 13px;
}
input.with_skin:disabled {
background-color: #333333;
}
.font0 { font-size: 10px; }
.font1 { font-size: 13px; }
.font2 { font-size: 15px; }
.font3 { font-size: 20px; }
.font4 { font-size: 30px; }
.font5 { font-size: 50px; }
caption.section_title {
caption-side:top;
}
.samButton{
float:left;
display:block;
padding:0;
margin:0;
text-decoration: none;
position:relative;
}
a.samButton.disabled {
pointer-events: none;
cursor: default;
}
.samButtonOuter{
display: table;
border: outset 2px white;
box-sizing: border-box;
font-weight:bold;
padding: 1px 6px;
width:125px;
height:30px;
background-color:#000000;
color:#ffffff;
}
.samButtonOuter:active{
border: inset 2px white;
}
.samButtonInner{
display: table-cell;
vertical-align: middle;
width: 100%;
margin: 0 auto;
text-align: center;
user-select: none;
}
.samToolbarButton > .samButtonOuter{
width:125px;
height:30px;
background-color:#225500;
color:white;
}
.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;
@charset "utf-8";
body {
color: white;
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;
padding: 0px;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';
}
th,
td {
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;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';
}
a.just_link {
text-decoration: none;
}
.with_border {
margin: 0;
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;
}
.section_title {
height: 50px;
line-height: 50px;
font-size: 30px;
font-weight: bold;
text-align: center;
color: white;
padding: 0;
}
.legacy_layout div {
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;
font-size: 13px;
word-break: break-all;
text-align: center;
font-family: '맑은 고딕';
;
}
.obj_fill {
display: block;
width: 100%;
height: 100%;
}
button.with_skin {
padding: 0 4px;
background-color: black;
color: white;
font-family: '맑은 고딕';
font-size: 13px;
}
button.with_skin:disabled {
background-color: #333333;
}
input.with_skin {
background-color: black;
color: white;
font-family: '맑은 고딕';
font-size: 13px;
}
input.with_skin:disabled {
background-color: #333333;
}
.font0 {
font-size: 10px;
}
.font1 {
font-size: 13px;
}
.font2 {
font-size: 15px;
}
.font3 {
font-size: 20px;
}
.font4 {
font-size: 30px;
}
.font5 {
font-size: 50px;
}
caption.section_title {
caption-side: top;
}
.samButton {
float: left;
display: block;
padding: 0;
margin: 0;
text-decoration: none;
position: relative;
}
a.samButton.disabled {
pointer-events: none;
cursor: default;
}
.samButtonOuter {
display: table;
border: outset 2px white;
box-sizing: border-box;
font-weight: bold;
padding: 1px 6px;
width: 125px;
height: 30px;
background-color: #000000;
color: #ffffff;
}
.samButtonOuter:active {
border: inset 2px white;
}
.samButtonInner {
display: table-cell;
vertical-align: middle;
width: 100%;
margin: 0 auto;
text-align: center;
user-select: none;
}
.samToolbarButton>.samButtonOuter {
width: 125px;
height: 30px;
background-color: #225500;
color: white;
}
.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";
body{
line-height: 1.3;
}
#server_notice {
margin:10px 0;
border: none;
text-align:center;
}
#server_list_container{
width:800px;
position:absolute;
left:50%;
margin-left:-400px;
}
#server_list_table{
width:100%;
}
#server_list tr{
height:66px;
}
#server_list .server_create_and_select .general_create,
#server_list .server_create_and_select .general_select {
width: 120px; height: 33px;
float: left;
}
#server_list .general_create,
#server_list .general_login {
width: 120px; height: 66px;
float: left;
}
.ignore_border{
border:0;
margin:0;
padding:0;
}
#user_info {
margin-top:20px;
width: 800px; height: 130px;
}
#user_info button{
width: 200px;
height: 50px;
margin: 10px 50px;
}
.center_ordered_items{
text-align:center;
}
.Entrance_ServerList {
width: 800px; height: 64px;
border: none;
float: left;
}
.Entrance_ServerListServer {
width: 98px; height: 64px;
float: left;
}
.Entrance_ServerListDown {
width: 698px; height: 64px;
float: left;
}
.Entrance_ServerListInfo {
width: 398px; height: 64px;
float: left;
}
.Entrance_ServerListBlock {
width: 298px; height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListCharacter {
width: 64px; height: 64px;
float: left;
}
.Entrance_ServerListName {
width: 112px; height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListSelect {
width: 120px; height: 32px;
float: left;
}
#Entrance_000003 {
width: 798px; height: 155px;
text-align: left;
}
.Entrance_Alert {
color: red; font-size: 15px; font-weight: bold;
}
.Entrance_Che {
color: white; font-size: 15px; font-weight: bold;
}
.Entrance_Kwe {
color: yellow; font-size: 15px; font-weight: bold;
}
.Entrance_Pwe {
color: orange; font-size: 15px; font-weight: bold;
}
.Entrance_Twe {
color: magenta; font-size: 15px; font-weight: bold;
}
.Entrance_Nya {
color: #e67e22; 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;
@charset "utf-8";
body {
line-height: 1.3;
}
#server_notice {
margin: 10px 0;
border: none;
text-align: center;
}
#server_list_container {
width: 800px;
position: absolute;
left: 50%;
margin-left: -400px;
}
#server_list_table {
width: 100%;
}
#server_list tr {
height: 66px;
}
.ignore_border {
border: 0;
margin: 0;
padding: 0;
}
#user_info {
margin-top: 20px;
width: 800px;
height: 130px;
}
#user_info button {
width: 200px;
height: 50px;
margin: 10px 50px;
}
.center_ordered_items {
text-align: center;
}
.Entrance_ServerList {
width: 800px;
height: 64px;
border: none;
float: left;
}
.Entrance_ServerListServer {
width: 98px;
height: 64px;
float: left;
}
.Entrance_ServerListDown {
width: 698px;
height: 64px;
float: left;
}
.Entrance_ServerListInfo {
width: 398px;
height: 64px;
float: left;
}
.Entrance_ServerListBlock {
width: 298px;
height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListCharacter {
width: 64px;
height: 64px;
float: left;
}
.Entrance_ServerListName {
width: 112px;
height: 64px;
float: left;
line-height: 64px;
}
.Entrance_ServerListSelect {
width: 120px;
height: 32px;
float: left;
}
#Entrance_000003 {
width: 798px;
height: 155px;
text-align: left;
}
.Entrance_Alert {
color: red;
font-size: 15px;
font-weight: bold;
}
.Entrance_Che {
color: white;
font-size: 15px;
font-weight: bold;
}
.Entrance_Kwe {
color: yellow;
font-size: 15px;
font-weight: bold;
}
.Entrance_Pwe {
color: orange;
font-size: 15px;
font-weight: bold;
}
.Entrance_Twe {
color: magenta;
font-size: 15px;
font-weight: bold;
}
.Entrance_Nya {
color: #e67e22;
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;
}
+133 -130
View File
@@ -1,131 +1,134 @@
body, html{
height: 100%;
background-repeat: no-repeat;
}
.main{
margin-top: 70px;
}
h1.title {
font-size: 50px;
font-family: 'Passion One', cursive;
font-weight: 400;
}
hr{
width: 10%;
/*color: #fff;*/
}
.form-group{
margin-bottom: 15px;
}
label{
margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder {
font-size: 11px;
padding-top: 3px;
}
.main-login{
/*background-color: #fff;*/
/* shadows and rounded borders */
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-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{
margin-top: 30px;
margin: 0 auto;
max-width: 330px;
padding: 40px 40px;
}
.login_btn_group{
margin-top: 5px;
}
.login-register{
font-size: 11px;
text-align: center;
}
.col-form-label{
text-align:center;
}
.terms{
max-height: 200px; overflow-y: auto;
}
.terms pre{
width:100%;
white-space: pre-wrap; /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
.vertical-center {
min-height: 100%; /* Fallback for browsers do NOT support vh unit */
min-height: 100vh; /* These two lines are counted as one :-) */
display: flex;
align-items: center;
}
.full-content {
position:fixed;
left:0;
top:0;
width:100%;
height:100%;
margin:0;
padding:0;
z-index:800;
}
#login_card{
z-index:801;
}
#btn_kakao_login{
cursor: pointer;
height:46px;
width:116px;
background-color: transparent;
color:transparent;
border:0;
background-size: 100%; /* To fill the dimensions of container (button), or */
background-repeat: no-repeat;
background-position: bottom center;
margin-top:5px;
background-image:url('../oauth_kakao/kakao_login_join.png');
}
#btn_kakao_login:hover {
background-image:url('../oauth_kakao/kakao_login_join_ov.png');
}
#bottom_box{
position:fixed;
bottom:0;
width:100%;
left:0;
}
#bottom_box .container{
text-align:center;
body,
html {
height: 100%;
background-repeat: no-repeat;
}
.main {
margin-top: 70px;
}
h1.title {
font-size: 50px;
font-family: 'Passion One', cursive;
font-weight: 400;
}
hr {
width: 10%;
/*color: #fff;*/
}
.form-group {
margin-bottom: 15px;
}
label {
margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder {
font-size: 11px;
padding-top: 3px;
}
.main-login {
/*background-color: #fff;*/
/* shadows and rounded borders */
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-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 {
margin-top: 30px;
margin: 0 auto;
max-width: 330px;
padding: 40px 40px;
}
.login_btn_group {
margin-top: 5px;
}
.login-register {
font-size: 11px;
text-align: center;
}
.col-form-label {
text-align: center;
}
.terms {
max-height: 200px;
overflow-y: auto;
}
.terms pre {
width: 100%;
white-space: pre-wrap;
/* Since CSS 2.1 */
white-space: -moz-pre-wrap;
/* Mozilla, since 1999 */
white-space: -pre-wrap;
/* Opera 4-6 */
white-space: -o-pre-wrap;
/* Opera 7 */
word-wrap: break-word;
/* Internet Explorer 5.5+ */
}
.vertical-center {
min-height: 100%;
/* Fallback for browsers do NOT support vh unit */
min-height: 100vh;
/* These two lines are counted as one :-) */
display: flex;
align-items: center;
}
#login_card {
z-index: 801;
}
#btn_kakao_login {
cursor: pointer;
height: 46px;
width: 116px;
background-color: transparent;
color: transparent;
border: 0;
background-size: 100%;
/* To fill the dimensions of container (button), or */
background-repeat: no-repeat;
background-position: bottom center;
margin-top: 5px;
background-image: url('../oauth_kakao/kakao_login_join.png');
}
#btn_kakao_login:hover {
background-image: url('../oauth_kakao/kakao_login_join_ov.png');
}
#bottom_box .container {
text-align: center;
}
.btn-group-xs>.btn,
.btn-xs {
padding: .25rem .4rem;
font-size: .875rem;
line-height: .5;
border-radius: .2rem;
}
#running_map{
overflow: hidden;
border: none;
width:700px;
}
+3 -3
View File
File diff suppressed because one or more lines are too long
+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-container--bootstrap4 { color: black; }
.select2-container--bootstrap4 .select2-selection { background-color: #fff; border: 1px solid #ced4da; border-radius: 0.25rem; color: #495057; font-size: 1rem; outline: 0; }
.select2-container--bootstrap4 .select2-selection.form-control { border-radius: 0.25rem; }
.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; }
.select2-container--bootstrap4 .select2-search__field { outline: 0; }
.select2-container--bootstrap4 .select2-search__field::-webkit-input-placeholder { color: #6c757d; }
.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-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-results__option[role=group] { padding: 0; }
.select2-container--bootstrap4 .select2-results__option[aria-disabled=true] { color: #6c757d; cursor: not-allowed; }
.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-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-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-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-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; }
.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-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; }
@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-container--open .select2-selection .select2-selection__arrow b { border-color: transparent transparent #6c757d transparent; border-width: 0 0.25rem 0.25rem 0.25rem; }
.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-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-container--disabled .select2-selection { border-color: #ced4da; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection, .select2-container--bootstrap4.select2-container--disabled .select2-search__field { cursor: not-allowed; }
.select2-container--bootstrap4.select2-container--disabled .select2-selection, .select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice { background-color: #e9ecef; }
.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-dropdown--above { margin-top: 1px; }
.select2-container--bootstrap4 .select2-results > .select2-results__options { 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; } }
/* select2-bootstrap4 with Darkly */
.select2-container--bootstrap4 {
color: black;
}
.select2-container--bootstrap4 .select2-selection {
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
color: #495057;
font-size: 1rem;
outline: 0;
}
.select2-container--bootstrap4 .select2-selection.form-control {
border-radius: 0.25rem;
}
.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;
}
.select2-container--bootstrap4 .select2-search__field {
outline: 0;
}
.select2-container--bootstrap4 .select2-search__field::-webkit-input-placeholder {
color: #6c757d;
}
.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-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-results__option[role=group] {
padding: 0;
}
.select2-container--bootstrap4 .select2-results__option[aria-disabled=true] {
color: #6c757d;
cursor: not-allowed;
}
.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-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-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-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-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;
}
.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-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;
}
@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-container--open .select2-selection .select2-selection__arrow b {
border-color: transparent transparent #6c757d transparent;
border-width: 0 0.25rem 0.25rem 0.25rem;
}
.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-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-container--disabled .select2-selection {
border-color: #ced4da;
}
.select2-container--bootstrap4.select2-container--disabled .select2-selection,
.select2-container--bootstrap4.select2-container--disabled .select2-search__field {
cursor: not-allowed;
}
.select2-container--bootstrap4.select2-container--disabled .select2-selection,
.select2-container--bootstrap4.select2-container--disabled .select2-selection--multiple .select2-selection__choice {
background-color: #e9ecef;
}
.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-dropdown--above {
margin-top: 1px;
}
.select2-container--bootstrap4 .select2-results>.select2-results__options {
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 {
border: 0 !important;
clip: rect(0 0 0 0) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
margin: -1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important; }
width: 1px !important;
white-space: nowrap !important; }
.select2-container--default .select2-selection--single {
background-color: #fff;
@@ -186,16 +188,13 @@
width: 100%; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
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 {
cursor: pointer;
float: right;
font-weight: bold;
margin-top: 5px;
margin-right: 10px; }
margin-right: 10px;
padding: 1px; }
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
border: 1px solid #aaa;
@@ -214,7 +213,7 @@
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
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; }
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
@@ -420,9 +419,7 @@
color: #555; }
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
float: right; }
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
float: right;
margin-left: 5px;
margin-right: auto; }
+583 -220
View File
@@ -1,11 +1,11 @@
/*!
* Select2 4.0.5
* Select2 4.0.13
* https://select2.github.io
*
* Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md
*/
(function (factory) {
;(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
@@ -574,10 +574,10 @@ S2.define('select2/utils',[
DecoratedClass.prototype = new ctr();
for (var m = 0; m < superMethods.length; m++) {
var superMethod = superMethods[m];
var superMethod = superMethods[m];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
}
var calledMethod = function (methodName) {
@@ -772,6 +772,70 @@ S2.define('select2/utils',[
$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;
});
@@ -791,7 +855,7 @@ S2.define('select2/results',[
Results.prototype.render = function () {
var $results = $(
'<ul class="select2-results__options" role="tree"></ul>'
'<ul class="select2-results__options" role="listbox"></ul>'
);
if (this.options.get('multiple')) {
@@ -814,7 +878,7 @@ S2.define('select2/results',[
this.hideLoading();
var $message = $(
'<li role="treeitem" aria-live="assertive"' +
'<li role="alert" aria-live="assertive"' +
' class="select2-results__option"></li>'
);
@@ -907,7 +971,7 @@ S2.define('select2/results',[
$options.each(function () {
var $option = $(this);
var item = $.data(this, 'data');
var item = Utils.GetData(this, 'data');
// id needs to be converted to a string when comparing
var id = '' + item.id;
@@ -948,11 +1012,16 @@ S2.define('select2/results',[
option.className = 'select2-results__option';
var attrs = {
'role': 'treeitem',
'role': 'option',
'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'];
attrs['aria-disabled'] = 'true';
}
@@ -1012,7 +1081,7 @@ S2.define('select2/results',[
this.template(data, option);
}
$.data(option, 'data', data);
Utils.StoreData(option, 'data', data);
return option;
};
@@ -1053,7 +1122,10 @@ S2.define('select2/results',[
}
self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
});
container.on('unselect', function () {
@@ -1062,7 +1134,10 @@ S2.define('select2/results',[
}
self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
});
container.on('open', function () {
@@ -1098,7 +1173,7 @@ S2.define('select2/results',[
return;
}
var data = $highlighted.data('data');
var data = Utils.GetData($highlighted[0], 'data');
if ($highlighted.attr('aria-selected') == 'true') {
self.trigger('close', {});
@@ -1116,8 +1191,9 @@ S2.define('select2/results',[
var currentIndex = $options.index($highlighted);
// If we are already at te top, don't move further
if (currentIndex === 0) {
// If we are already at the top, don't move further
// If no options, currentIndex will be -1
if (currentIndex <= 0) {
return;
}
@@ -1210,7 +1286,7 @@ S2.define('select2/results',[
function (evt) {
var $this = $(this);
var data = $this.data('data');
var data = Utils.GetData(this, 'data');
if ($this.attr('aria-selected') === 'true') {
if (self.options.get('multiple')) {
@@ -1233,7 +1309,7 @@ S2.define('select2/results',[
this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
function (evt) {
var data = $(this).data('data');
var data = Utils.GetData(this, 'data');
self.getHighlightedResults()
.removeClass('select2-results__option--highlighted');
@@ -1348,14 +1424,15 @@ S2.define('select2/selection/base',[
this._tabindex = 0;
if (this.$element.data('old-tabindex') != null) {
this._tabindex = this.$element.data('old-tabindex');
if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
} else if (this.$element.attr('tabindex') != null) {
this._tabindex = this.$element.attr('tabindex');
}
$selection.attr('title', this.$element.attr('title'));
$selection.attr('tabindex', this._tabindex);
$selection.attr('aria-disabled', 'false');
this.$selection = $selection;
@@ -1365,7 +1442,6 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.bind = function (container, $container) {
var self = this;
var id = container.id + '-container';
var resultsId = container.id + '-results';
this.container = container;
@@ -1408,17 +1484,19 @@ S2.define('select2/selection/base',[
self.$selection.removeAttr('aria-activedescendant');
self.$selection.removeAttr('aria-owns');
self.$selection.focus();
self.$selection.trigger('focus');
self._detachCloseHandler(container);
});
container.on('enable', function () {
self.$selection.attr('tabindex', self._tabindex);
self.$selection.attr('aria-disabled', 'false');
});
container.on('disable', function () {
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) {
var self = this;
$(document.body).on('mousedown.select2.' + container.id, function (e) {
var $target = $(e.target);
@@ -1451,13 +1528,11 @@ S2.define('select2/selection/base',[
var $all = $('.select2.select2-container--open');
$all.each(function () {
var $this = $(this);
if (this == $select[0]) {
return;
}
var $element = $this.data('element');
var $element = Utils.GetData(this, 'element');
$element.select2('close');
});
@@ -1481,6 +1556,27 @@ S2.define('select2/selection/base',[
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;
});
@@ -1518,7 +1614,10 @@ S2.define('select2/selection/single',[
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.on('mousedown', function (evt) {
@@ -1542,17 +1641,15 @@ S2.define('select2/selection/single',[
container.on('focus', function (evt) {
if (!container.isOpen()) {
self.$selection.focus();
self.$selection.trigger('focus');
}
});
container.on('selection:update', function (params) {
self.update(params.data);
});
};
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) {
@@ -1578,7 +1675,14 @@ S2.define('select2/selection/single',[
var formatted = this.display(selection, $rendered);
$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;
@@ -1623,14 +1727,14 @@ S2.define('select2/selection/multiple',[
'.select2-selection__choice__remove',
function (evt) {
// Ignore the event if it is disabled
if (self.options.get('disabled')) {
if (self.isDisabled()) {
return;
}
var $remove = $(this);
var $selection = $remove.parent();
var data = $selection.data('data');
var data = Utils.GetData($selection[0], 'data');
self.trigger('unselect', {
originalEvent: evt,
@@ -1641,7 +1745,9 @@ S2.define('select2/selection/multiple',[
};
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) {
@@ -1679,9 +1785,14 @@ S2.define('select2/selection/multiple',[
var formatted = this.display(selection, $selection);
$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);
}
@@ -1746,8 +1857,9 @@ S2.define('select2/selection/placeholder',[
S2.define('select2/selection/allowClear',[
'jquery',
'../keys'
], function ($, KEYS) {
'../keys',
'../utils'
], function ($, KEYS, Utils) {
function AllowClear () { }
AllowClear.prototype.bind = function (decorated, container, $container) {
@@ -1776,7 +1888,7 @@ S2.define('select2/selection/allowClear',[
AllowClear.prototype._handleClear = function (_, evt) {
// Ignore the event if it is disabled
if (this.options.get('disabled')) {
if (this.isDisabled()) {
return;
}
@@ -1789,10 +1901,22 @@ S2.define('select2/selection/allowClear',[
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++) {
var unselectData = {
unselectData = {
data: data[d]
};
@@ -1802,11 +1926,12 @@ S2.define('select2/selection/allowClear',[
// If the event was prevented, don't clear it out.
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
}
this.$element.val(this.placeholder.id).trigger('change');
this.$element.trigger('input').trigger('change');
this.trigger('toggle', {});
};
@@ -1829,12 +1954,14 @@ S2.define('select2/selection/allowClear',[
return;
}
var removeAll = this.options.get('translations').get('removeAllItems');
var $remove = $(
'<span class="select2-selection__clear">' +
'<span class="select2-selection__clear" title="' + removeAll() +'">' +
'&times;' +
'</span>'
);
$remove.data('data', data);
Utils.StoreData($remove[0], 'data', data);
this.$selection.find('.select2-selection__rendered').prepend($remove);
};
@@ -1856,7 +1983,7 @@ S2.define('select2/selection/search',[
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</li>'
);
@@ -1873,14 +2000,18 @@ S2.define('select2/selection/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
container.on('open', function () {
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus');
});
container.on('close', function () {
self.$search.val('');
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.trigger('focus');
});
@@ -1900,7 +2031,11 @@ S2.define('select2/selection/search',[
});
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) {
@@ -1925,7 +2060,7 @@ S2.define('select2/selection/search',[
.prev('.select2-selection__choice');
if ($previousChoice.length > 0) {
var item = $previousChoice.data('data');
var item = Utils.GetData($previousChoice[0], 'data');
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
// is stored on the document. This is only implemented in IE and is
// slightly cleaner than doing a user agent check.
@@ -2019,7 +2160,7 @@ S2.define('select2/selection/search',[
this.resizeSearch();
if (searchHadFocus) {
this.$search.focus();
this.$search.trigger('focus');
}
};
@@ -2052,7 +2193,7 @@ S2.define('select2/selection/search',[
var width = '';
if (this.$search.attr('placeholder') !== '') {
width = this.$selection.find('.select2-selection__rendered').innerWidth();
width = this.$selection.find('.select2-selection__rendered').width();
} else {
var minimumWidth = this.$search.val().length + 1;
@@ -2076,10 +2217,13 @@ S2.define('select2/selection/eventRelay',[
'open', 'opening',
'close', 'closing',
'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);
@@ -2412,6 +2556,7 @@ S2.define('select2/diacritics',[
'\u019F': 'O',
'\uA74A': 'O',
'\uA74C': 'O',
'\u0152': 'OE',
'\u01A2': 'OI',
'\uA74E': 'OO',
'\u0222': 'OU',
@@ -2821,6 +2966,7 @@ S2.define('select2/diacritics',[
'\uA74B': 'o',
'\uA74D': 'o',
'\u0275': 'o',
'\u0153': 'oe',
'\u01A3': 'oi',
'\u0223': 'ou',
'\uA74F': 'oo',
@@ -2989,8 +3135,9 @@ S2.define('select2/diacritics',[
'\u03CD': '\u03C5',
'\u03CB': '\u03C5',
'\u03B0': '\u03C5',
'\u03C9': '\u03C9',
'\u03C2': '\u03C3'
'\u03CE': '\u03C9',
'\u03C2': '\u03C3',
'\u2019': '\''
};
return diacritics;
@@ -3075,7 +3222,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) {
data.element.selected = true;
this.$element.trigger('change');
this.$element.trigger('input').trigger('change');
return;
}
@@ -3096,13 +3243,13 @@ S2.define('select2/data/select',[
}
self.$element.val(val);
self.$element.trigger('change');
self.$element.trigger('input').trigger('change');
});
} else {
var val = data.id;
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')) {
data.element.selected = false;
this.$element.trigger('change');
this.$element.trigger('input').trigger('change');
return;
}
@@ -3136,7 +3283,7 @@ S2.define('select2/data/select',[
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
this.$element.find('*').each(function () {
// 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;
// Override the option's data with the combined data
$.data(option, 'data', normalizedData);
Utils.StoreData(option, 'data', normalizedData);
return $option;
};
@@ -3239,7 +3386,7 @@ S2.define('select2/data/select',[
SelectAdapter.prototype.item = function ($option) {
var data = {};
data = $.data($option[0], 'data');
data = Utils.GetData($option[0], 'data');
if (data != null) {
return data;
@@ -3277,13 +3424,13 @@ S2.define('select2/data/select',[
data = this._normalizeItem(data);
data.element = $option[0];
$.data($option[0], 'data', data);
Utils.StoreData($option[0], 'data', data);
return data;
};
SelectAdapter.prototype._normalizeItem = function (item) {
if (!$.isPlainObject(item)) {
if (item !== Object(item)) {
item = {
id: item,
text: item
@@ -3329,15 +3476,19 @@ S2.define('select2/data/array',[
'jquery'
], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) {
var data = options.get('data') || [];
this._dataToConvert = options.get('data') || [];
ArrayAdapter.__super__.constructor.call(this, $element, options);
this.addOptions(this.convertToOptions(data));
}
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) {
var $option = this.$element.find('option').filter(function (i, elm) {
return elm.value == data.id.toString();
@@ -3487,7 +3638,8 @@ S2.define('select2/data/ajax',[
}, function () {
// Attempt to detect if a request was aborted
// 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;
}
@@ -3626,8 +3778,6 @@ S2.define('select2/data/tags',[
};
Tags.prototype._removeOldTags = function (_) {
var tag = this._lastTag;
var $options = this.$element.find('option[data-select2-tag]');
$options.each(function () {
@@ -3702,7 +3852,7 @@ S2.define('select2/data/tokenizer',[
// Replace the search term if we have the search box
if (this.$search.length) {
this.$search.val(tokenData.term);
this.$search.focus();
this.$search.trigger('focus');
}
params.term = tokenData.term;
@@ -3831,10 +3981,30 @@ S2.define('select2/data/maximumSelectionLength',[
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 =
function (decorated, params, callback) {
var self = this;
this._checkIfMaximumSelected(function () {
decorated.call(self, params, callback);
});
};
MaximumSelectionLength.prototype._checkIfMaximumSelected =
function (_, successCallback) {
var self = this;
this.current(function (currentData) {
var count = currentData != null ? currentData.length : 0;
if (self.maximumSelectionLength > 0 &&
@@ -3847,7 +4017,10 @@ S2.define('select2/data/maximumSelectionLength',[
});
return;
}
decorated.call(self, params, callback);
if (successCallback) {
successCallback();
}
});
};
@@ -3886,7 +4059,7 @@ S2.define('select2/dropdown',[
};
Dropdown.prototype.position = function ($dropdown, $container) {
// Should be implmented in subclasses
// Should be implemented in subclasses
};
Dropdown.prototype.destroy = function () {
@@ -3910,7 +4083,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" />' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</span>'
);
@@ -3925,6 +4098,8 @@ S2.define('select2/dropdown/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
this.$search.on('keydown', function (evt) {
@@ -3947,23 +4122,27 @@ S2.define('select2/dropdown/search',[
container.on('open', function () {
self.$search.attr('tabindex', 0);
self.$search.attr('aria-controls', resultsId);
self.$search.focus();
self.$search.trigger('focus');
window.setTimeout(function () {
self.$search.focus();
self.$search.trigger('focus');
}, 0);
});
container.on('close', function () {
self.$search.attr('tabindex', -1);
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.val('');
self.$search.trigger('blur');
});
container.on('focus', function () {
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) {
@@ -4062,6 +4249,7 @@ S2.define('select2/dropdown/infiniteScroll',[
if (this.showLoadingMore(data)) {
this.$results.append(this.$loadingMore);
this.loadMoreIfNeeded();
}
};
@@ -4080,25 +4268,27 @@ S2.define('select2/dropdown/infiniteScroll',[
self.loading = true;
});
this.$results.on('scroll', function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
self.$loadingMore[0]
);
this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
};
if (self.loading || !isLoadMoreVisible) {
return;
}
InfiniteScroll.prototype.loadMoreIfNeeded = function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
this.$loadingMore[0]
);
var currentOffset = self.$results.offset().top +
self.$results.outerHeight(false);
var loadingMoreOffset = self.$loadingMore.offset().top +
self.$loadingMore.outerHeight(false);
if (this.loading || !isLoadMoreVisible) {
return;
}
if (currentOffset + 50 >= loadingMoreOffset) {
self.loadMore();
}
});
var currentOffset = this.$results.offset().top +
this.$results.outerHeight(false);
var loadingMoreOffset = this.$loadingMore.offset().top +
this.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) {
this.loadMore();
}
};
InfiniteScroll.prototype.loadMore = function () {
@@ -4119,7 +4309,7 @@ S2.define('select2/dropdown/infiniteScroll',[
var $option = $(
'<li ' +
'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');
@@ -4137,7 +4327,7 @@ S2.define('select2/dropdown/attachBody',[
'../utils'
], function ($, Utils) {
function AttachBody (decorated, $element, options) {
this.$dropdownParent = options.get('dropdownParent') || $(document.body);
this.$dropdownParent = $(options.get('dropdownParent') || document.body);
decorated.call(this, $element, options);
}
@@ -4145,27 +4335,14 @@ S2.define('select2/dropdown/attachBody',[
AttachBody.prototype.bind = function (decorated, container, $container) {
var self = this;
var setupResultsEvents = false;
decorated.call(this, container, $container);
container.on('open', function () {
self._showDropdown();
self._attachPositioningHandler(container);
if (!setupResultsEvents) {
setupResultsEvents = true;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
}
// Must bind after the results handlers to ensure correct sizing
self._bindContainerResultHandlers(container);
});
container.on('close', function () {
@@ -4214,6 +4391,44 @@ S2.define('select2/dropdown/attachBody',[
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 =
function (decorated, container) {
var self = this;
@@ -4224,14 +4439,14 @@ S2.define('select2/dropdown/attachBody',[
var $watchers = this.$container.parents().filter(Utils.hasScroll);
$watchers.each(function () {
$(this).data('select2-scroll-position', {
Utils.StoreData(this, 'select2-scroll-position', {
x: $(this).scrollLeft(),
y: $(this).scrollTop()
});
});
$watchers.on(scrollEvent, function (ev) {
var position = $(this).data('select2-scroll-position');
var position = Utils.GetData(this, 'select2-scroll-position');
$(this).scrollTop(position.y);
});
@@ -4290,16 +4505,26 @@ S2.define('select2/dropdown/attachBody',[
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;
// 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
if ($offsetParent.css('position') === 'static') {
$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.left -= parentOffset.left;
@@ -4396,8 +4621,8 @@ S2.define('select2/dropdown/minimumResultsForSearch',[
});
S2.define('select2/dropdown/selectOnClose',[
], function () {
'../utils'
], function (Utils) {
function SelectOnClose () { }
SelectOnClose.prototype.bind = function (decorated, container, $container) {
@@ -4428,7 +4653,7 @@ S2.define('select2/dropdown/selectOnClose',[
return;
}
var data = $highlightedResults.data('data');
var data = Utils.GetData($highlightedResults[0], 'data');
// Don't re-select already selected resulte
if (
@@ -4469,7 +4694,7 @@ S2.define('select2/dropdown/closeOnSelect',[
var originalEvent = evt.originalEvent;
// Don't close if the control key is being held
if (originalEvent && originalEvent.ctrlKey) {
if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
return;
}
@@ -4523,6 +4748,9 @@ S2.define('select2/i18n/en',[],function () {
},
searching: function () {
return 'Searching…';
},
removeAllItems: function () {
return 'Remove all items';
}
};
});
@@ -4761,66 +4989,29 @@ S2.define('select2/defaults',[
);
}
if (typeof options.language === 'string') {
// Check if the language is specified with a region
if (options.language.indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = options.language.split('-');
var baseLanguage = languageParts[0];
// If the defaults were not previously applied from an element, it is
// possible for the language option to have not been resolved
options.language = this._resolveLanguage(options.language);
options.language = [options.language, baseLanguage];
} else {
options.language = [options.language];
// Always fall back to English since it will always be complete
options.language.push('en');
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)) {
var languages = new Translation();
options.language.push('en');
options.language = uniqueLanguages;
var languageNames = options.language;
for (var l = 0; l < languageNames.length; l++) {
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;
}
options.translations = this._processTranslations(
options.language,
options.debug
);
return options;
};
@@ -4887,13 +5078,14 @@ S2.define('select2/defaults',[
debug: false,
dropdownAutoWidth: false,
escapeMarkup: Utils.escapeMarkup,
language: EnglishTranslation,
language: {},
matcher: matcher,
minimumInputLength: 0,
maximumInputLength: 0,
maximumSelectionLength: 0,
minimumResultsForSearch: 0,
selectOnClose: false,
scrollAfterSelect: false,
sorter: function (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) {
var camelKey = $.camelCase(key);
@@ -4916,7 +5205,7 @@ S2.define('select2/defaults',[
var convertedData = Utils._convertData(data);
$.extend(this.defaults, convertedData);
$.extend(true, this.defaults, convertedData);
};
var defaults = new Defaults();
@@ -4937,6 +5226,10 @@ S2.define('select2/options',[
this.fromElement($element);
}
if ($element != null) {
this.options = Defaults.applyFromElement(this.options, $element);
}
this.options = Defaults.apply(this.options);
if ($element && $element.is('input')) {
@@ -4960,14 +5253,6 @@ S2.define('select2/options',[
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 ($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('multiple', this.options.multiple);
if ($e.data('select2Tags')) {
if (Utils.GetData($e[0], 'select2Tags')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'Select2: The `data-select2-tags` attribute has been changed to ' +
@@ -4990,11 +5275,11 @@ S2.define('select2/options',[
);
}
$e.data('data', $e.data('select2Tags'));
$e.data('tags', true);
Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
Utils.StoreData($e[0], 'tags', true);
}
if ($e.data('ajaxUrl')) {
if (Utils.GetData($e[0], 'ajaxUrl')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'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.data('ajax--url', $e.data('ajaxUrl'));
$e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
}
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
// jQuery 1.x does not correctly handle data attributes with multiple dashes
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
dataset = $.extend(true, {}, $e[0].dataset, $e.data());
} else {
dataset = $e.data();
dataset = $.extend(true, {}, $e[0].dataset, dataset);
}
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);
@@ -5054,8 +5363,8 @@ S2.define('select2/core',[
'./keys'
], function ($, Options, Utils, KEYS) {
var Select2 = function ($element, options) {
if ($element.data('select2') != null) {
$element.data('select2').destroy();
if (Utils.GetData($element[0], 'select2') != null) {
Utils.GetData($element[0], 'select2').destroy();
}
this.$element = $element;
@@ -5071,7 +5380,7 @@ S2.define('select2/core',[
// Set up the tabindex
var tabindex = $element.attr('tabindex') || 0;
$element.data('old-tabindex', tabindex);
Utils.StoreData($element[0], 'old-tabindex', tabindex);
$element.attr('tabindex', '-1');
// Set up containers and adapters
@@ -5132,6 +5441,9 @@ S2.define('select2/core',[
// Synchronize any monitored attributes
this._syncAttributes();
Utils.StoreData($element[0], 'select2', this);
// Ensure backwards compatibility with $element.data('select2').
$element.data('select2', this);
};
@@ -5208,6 +5520,12 @@ S2.define('select2/core',[
return null;
}
if (method == 'computedstyle') {
var computedStyle = window.getComputedStyle($element[0]);
return computedStyle.width;
}
return method;
};
@@ -5248,8 +5566,8 @@ S2.define('select2/core',[
if (observer != null) {
this._observer = new observer(function (mutations) {
$.each(mutations, self._syncA);
$.each(mutations, self._syncS);
self._syncA();
self._syncS(null, mutations);
});
this._observer.observe(this.$element[0], {
attributes: true,
@@ -5371,7 +5689,7 @@ S2.define('select2/core',[
if (self.isOpen()) {
if (key === KEYS.ESC || key === KEYS.TAB ||
(key === KEYS.UP && evt.altKey)) {
self.close();
self.close(evt);
evt.preventDefault();
} else if (key === KEYS.ENTER) {
@@ -5405,7 +5723,7 @@ S2.define('select2/core',[
Select2.prototype._syncAttributes = function () {
this.options.set('disabled', this.$element.prop('disabled'));
if (this.options.get('disabled')) {
if (this.isDisabled()) {
if (this.isOpen()) {
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 self = this;
@@ -5444,7 +5762,22 @@ S2.define('select2/core',[
}
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
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
if (changed) {
@@ -5466,7 +5799,8 @@ S2.define('select2/core',[
'open': 'opening',
'close': 'closing',
'select': 'selecting',
'unselect': 'unselecting'
'unselect': 'unselecting',
'clear': 'clearing'
};
if (args === undefined) {
@@ -5494,7 +5828,7 @@ S2.define('select2/core',[
};
Select2.prototype.toggleDropdown = function () {
if (this.options.get('disabled')) {
if (this.isDisabled()) {
return;
}
@@ -5510,15 +5844,40 @@ S2.define('select2/core',[
return;
}
if (this.isDisabled()) {
return;
}
this.trigger('query', {});
};
Select2.prototype.close = function () {
Select2.prototype.close = function (evt) {
if (!this.isOpen()) {
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 () {
@@ -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 () {
@@ -5621,10 +5980,12 @@ S2.define('select2/core',[
this._syncS = null;
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.attr('aria-hidden', 'false');
Utils.RemoveData(this.$element[0]);
this.$element.removeData('select2');
this.dataAdapter.destroy();
@@ -5652,7 +6013,7 @@ S2.define('select2/core',[
this.$container.addClass('select2-container--' + this.options.get('theme'));
$container.data('element', this.$element);
Utils.StoreData($container[0], 'element', this.$element);
return $container;
};
@@ -5862,8 +6223,9 @@ S2.define('select2/compat/initSelection',[
});
S2.define('select2/compat/inputData',[
'jquery'
], function ($) {
'jquery',
'../utils'
], function ($, Utils) {
function InputData (decorated, $element, options) {
this._currentData = [];
this._valueSeparator = options.get('valueSeparator') || ',';
@@ -5927,13 +6289,13 @@ S2.define('select2/compat/inputData',[
});
this.$element.val(data.id);
this.$element.trigger('change');
this.$element.trigger('input').trigger('change');
} else {
var value = this.$element.val();
value += this._valueSeparator + data.id;
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.trigger('change');
self.$element.trigger('input').trigger('change');
});
};
@@ -5980,7 +6342,7 @@ S2.define('select2/compat/inputData',[
InputData.prototype.addOptions = function (_, $options) {
var options = $.map($options, function ($option) {
return $.data($option[0], 'data');
return Utils.GetData($option[0], 'data');
});
this._currentData.push.apply(this._currentData, options);
@@ -6383,8 +6745,9 @@ S2.define('jquery.select2',[
'jquery-mousewheel',
'./select2/core',
'./select2/defaults'
], function ($, _, Select2, Defaults) {
'./select2/defaults',
'./select2/utils'
], function ($, _, Select2, Defaults, Utils) {
if ($.fn.select2 == null) {
// All methods that should return the element
var thisMethods = ['open', 'close', 'destroy'];
@@ -6405,7 +6768,7 @@ S2.define('jquery.select2',[
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = $(this).data('select2');
var instance = Utils.GetData(this, 'select2');
if (instance == null && window.console && 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
*
* Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md
*/
(function (factory) {
;(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
@@ -574,10 +574,10 @@ S2.define('select2/utils',[
DecoratedClass.prototype = new ctr();
for (var m = 0; m < superMethods.length; m++) {
var superMethod = superMethods[m];
var superMethod = superMethods[m];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
DecoratedClass.prototype[superMethod] =
SuperClass.prototype[superMethod];
}
var calledMethod = function (methodName) {
@@ -772,6 +772,70 @@ S2.define('select2/utils',[
$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;
});
@@ -791,7 +855,7 @@ S2.define('select2/results',[
Results.prototype.render = function () {
var $results = $(
'<ul class="select2-results__options" role="tree"></ul>'
'<ul class="select2-results__options" role="listbox"></ul>'
);
if (this.options.get('multiple')) {
@@ -814,7 +878,7 @@ S2.define('select2/results',[
this.hideLoading();
var $message = $(
'<li role="treeitem" aria-live="assertive"' +
'<li role="alert" aria-live="assertive"' +
' class="select2-results__option"></li>'
);
@@ -907,7 +971,7 @@ S2.define('select2/results',[
$options.each(function () {
var $option = $(this);
var item = $.data(this, 'data');
var item = Utils.GetData(this, 'data');
// id needs to be converted to a string when comparing
var id = '' + item.id;
@@ -948,11 +1012,16 @@ S2.define('select2/results',[
option.className = 'select2-results__option';
var attrs = {
'role': 'treeitem',
'role': 'option',
'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'];
attrs['aria-disabled'] = 'true';
}
@@ -1012,7 +1081,7 @@ S2.define('select2/results',[
this.template(data, option);
}
$.data(option, 'data', data);
Utils.StoreData(option, 'data', data);
return option;
};
@@ -1053,7 +1122,10 @@ S2.define('select2/results',[
}
self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
});
container.on('unselect', function () {
@@ -1062,7 +1134,10 @@ S2.define('select2/results',[
}
self.setClasses();
self.highlightFirstItem();
if (self.options.get('scrollAfterSelect')) {
self.highlightFirstItem();
}
});
container.on('open', function () {
@@ -1098,7 +1173,7 @@ S2.define('select2/results',[
return;
}
var data = $highlighted.data('data');
var data = Utils.GetData($highlighted[0], 'data');
if ($highlighted.attr('aria-selected') == 'true') {
self.trigger('close', {});
@@ -1116,8 +1191,9 @@ S2.define('select2/results',[
var currentIndex = $options.index($highlighted);
// If we are already at te top, don't move further
if (currentIndex === 0) {
// If we are already at the top, don't move further
// If no options, currentIndex will be -1
if (currentIndex <= 0) {
return;
}
@@ -1210,7 +1286,7 @@ S2.define('select2/results',[
function (evt) {
var $this = $(this);
var data = $this.data('data');
var data = Utils.GetData(this, 'data');
if ($this.attr('aria-selected') === 'true') {
if (self.options.get('multiple')) {
@@ -1233,7 +1309,7 @@ S2.define('select2/results',[
this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
function (evt) {
var data = $(this).data('data');
var data = Utils.GetData(this, 'data');
self.getHighlightedResults()
.removeClass('select2-results__option--highlighted');
@@ -1348,14 +1424,15 @@ S2.define('select2/selection/base',[
this._tabindex = 0;
if (this.$element.data('old-tabindex') != null) {
this._tabindex = this.$element.data('old-tabindex');
if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
} else if (this.$element.attr('tabindex') != null) {
this._tabindex = this.$element.attr('tabindex');
}
$selection.attr('title', this.$element.attr('title'));
$selection.attr('tabindex', this._tabindex);
$selection.attr('aria-disabled', 'false');
this.$selection = $selection;
@@ -1365,7 +1442,6 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.bind = function (container, $container) {
var self = this;
var id = container.id + '-container';
var resultsId = container.id + '-results';
this.container = container;
@@ -1408,17 +1484,19 @@ S2.define('select2/selection/base',[
self.$selection.removeAttr('aria-activedescendant');
self.$selection.removeAttr('aria-owns');
self.$selection.focus();
self.$selection.trigger('focus');
self._detachCloseHandler(container);
});
container.on('enable', function () {
self.$selection.attr('tabindex', self._tabindex);
self.$selection.attr('aria-disabled', 'false');
});
container.on('disable', function () {
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) {
var self = this;
$(document.body).on('mousedown.select2.' + container.id, function (e) {
var $target = $(e.target);
@@ -1451,13 +1528,11 @@ S2.define('select2/selection/base',[
var $all = $('.select2.select2-container--open');
$all.each(function () {
var $this = $(this);
if (this == $select[0]) {
return;
}
var $element = $this.data('element');
var $element = Utils.GetData(this, 'element');
$element.select2('close');
});
@@ -1481,6 +1556,27 @@ S2.define('select2/selection/base',[
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;
});
@@ -1518,7 +1614,10 @@ S2.define('select2/selection/single',[
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.on('mousedown', function (evt) {
@@ -1542,17 +1641,15 @@ S2.define('select2/selection/single',[
container.on('focus', function (evt) {
if (!container.isOpen()) {
self.$selection.focus();
self.$selection.trigger('focus');
}
});
container.on('selection:update', function (params) {
self.update(params.data);
});
};
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) {
@@ -1578,7 +1675,14 @@ S2.define('select2/selection/single',[
var formatted = this.display(selection, $rendered);
$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;
@@ -1623,14 +1727,14 @@ S2.define('select2/selection/multiple',[
'.select2-selection__choice__remove',
function (evt) {
// Ignore the event if it is disabled
if (self.options.get('disabled')) {
if (self.isDisabled()) {
return;
}
var $remove = $(this);
var $selection = $remove.parent();
var data = $selection.data('data');
var data = Utils.GetData($selection[0], 'data');
self.trigger('unselect', {
originalEvent: evt,
@@ -1641,7 +1745,9 @@ S2.define('select2/selection/multiple',[
};
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) {
@@ -1679,9 +1785,14 @@ S2.define('select2/selection/multiple',[
var formatted = this.display(selection, $selection);
$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);
}
@@ -1746,8 +1857,9 @@ S2.define('select2/selection/placeholder',[
S2.define('select2/selection/allowClear',[
'jquery',
'../keys'
], function ($, KEYS) {
'../keys',
'../utils'
], function ($, KEYS, Utils) {
function AllowClear () { }
AllowClear.prototype.bind = function (decorated, container, $container) {
@@ -1776,7 +1888,7 @@ S2.define('select2/selection/allowClear',[
AllowClear.prototype._handleClear = function (_, evt) {
// Ignore the event if it is disabled
if (this.options.get('disabled')) {
if (this.isDisabled()) {
return;
}
@@ -1789,10 +1901,22 @@ S2.define('select2/selection/allowClear',[
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++) {
var unselectData = {
unselectData = {
data: data[d]
};
@@ -1802,11 +1926,12 @@ S2.define('select2/selection/allowClear',[
// If the event was prevented, don't clear it out.
if (unselectData.prevented) {
this.$element.val(previousVal);
return;
}
}
this.$element.val(this.placeholder.id).trigger('change');
this.$element.trigger('input').trigger('change');
this.trigger('toggle', {});
};
@@ -1829,12 +1954,14 @@ S2.define('select2/selection/allowClear',[
return;
}
var removeAll = this.options.get('translations').get('removeAllItems');
var $remove = $(
'<span class="select2-selection__clear">' +
'<span class="select2-selection__clear" title="' + removeAll() +'">' +
'&times;' +
'</span>'
);
$remove.data('data', data);
Utils.StoreData($remove[0], 'data', data);
this.$selection.find('.select2-selection__rendered').prepend($remove);
};
@@ -1856,7 +1983,7 @@ S2.define('select2/selection/search',[
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</li>'
);
@@ -1873,14 +2000,18 @@ S2.define('select2/selection/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
container.on('open', function () {
self.$search.attr('aria-controls', resultsId);
self.$search.trigger('focus');
});
container.on('close', function () {
self.$search.val('');
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.trigger('focus');
});
@@ -1900,7 +2031,11 @@ S2.define('select2/selection/search',[
});
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) {
@@ -1925,7 +2060,7 @@ S2.define('select2/selection/search',[
.prev('.select2-selection__choice');
if ($previousChoice.length > 0) {
var item = $previousChoice.data('data');
var item = Utils.GetData($previousChoice[0], 'data');
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
// is stored on the document. This is only implemented in IE and is
// slightly cleaner than doing a user agent check.
@@ -2019,7 +2160,7 @@ S2.define('select2/selection/search',[
this.resizeSearch();
if (searchHadFocus) {
this.$search.focus();
this.$search.trigger('focus');
}
};
@@ -2052,7 +2193,7 @@ S2.define('select2/selection/search',[
var width = '';
if (this.$search.attr('placeholder') !== '') {
width = this.$selection.find('.select2-selection__rendered').innerWidth();
width = this.$selection.find('.select2-selection__rendered').width();
} else {
var minimumWidth = this.$search.val().length + 1;
@@ -2076,10 +2217,13 @@ S2.define('select2/selection/eventRelay',[
'open', 'opening',
'close', 'closing',
'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);
@@ -2412,6 +2556,7 @@ S2.define('select2/diacritics',[
'\u019F': 'O',
'\uA74A': 'O',
'\uA74C': 'O',
'\u0152': 'OE',
'\u01A2': 'OI',
'\uA74E': 'OO',
'\u0222': 'OU',
@@ -2821,6 +2966,7 @@ S2.define('select2/diacritics',[
'\uA74B': 'o',
'\uA74D': 'o',
'\u0275': 'o',
'\u0153': 'oe',
'\u01A3': 'oi',
'\u0223': 'ou',
'\uA74F': 'oo',
@@ -2989,8 +3135,9 @@ S2.define('select2/diacritics',[
'\u03CD': '\u03C5',
'\u03CB': '\u03C5',
'\u03B0': '\u03C5',
'\u03C9': '\u03C9',
'\u03C2': '\u03C3'
'\u03CE': '\u03C9',
'\u03C2': '\u03C3',
'\u2019': '\''
};
return diacritics;
@@ -3075,7 +3222,7 @@ S2.define('select2/data/select',[
if ($(data.element).is('option')) {
data.element.selected = true;
this.$element.trigger('change');
this.$element.trigger('input').trigger('change');
return;
}
@@ -3096,13 +3243,13 @@ S2.define('select2/data/select',[
}
self.$element.val(val);
self.$element.trigger('change');
self.$element.trigger('input').trigger('change');
});
} else {
var val = data.id;
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')) {
data.element.selected = false;
this.$element.trigger('change');
this.$element.trigger('input').trigger('change');
return;
}
@@ -3136,7 +3283,7 @@ S2.define('select2/data/select',[
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
this.$element.find('*').each(function () {
// 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;
// Override the option's data with the combined data
$.data(option, 'data', normalizedData);
Utils.StoreData(option, 'data', normalizedData);
return $option;
};
@@ -3239,7 +3386,7 @@ S2.define('select2/data/select',[
SelectAdapter.prototype.item = function ($option) {
var data = {};
data = $.data($option[0], 'data');
data = Utils.GetData($option[0], 'data');
if (data != null) {
return data;
@@ -3277,13 +3424,13 @@ S2.define('select2/data/select',[
data = this._normalizeItem(data);
data.element = $option[0];
$.data($option[0], 'data', data);
Utils.StoreData($option[0], 'data', data);
return data;
};
SelectAdapter.prototype._normalizeItem = function (item) {
if (!$.isPlainObject(item)) {
if (item !== Object(item)) {
item = {
id: item,
text: item
@@ -3329,15 +3476,19 @@ S2.define('select2/data/array',[
'jquery'
], function (SelectAdapter, Utils, $) {
function ArrayAdapter ($element, options) {
var data = options.get('data') || [];
this._dataToConvert = options.get('data') || [];
ArrayAdapter.__super__.constructor.call(this, $element, options);
this.addOptions(this.convertToOptions(data));
}
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) {
var $option = this.$element.find('option').filter(function (i, elm) {
return elm.value == data.id.toString();
@@ -3487,7 +3638,8 @@ S2.define('select2/data/ajax',[
}, function () {
// Attempt to detect if a request was aborted
// 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;
}
@@ -3626,8 +3778,6 @@ S2.define('select2/data/tags',[
};
Tags.prototype._removeOldTags = function (_) {
var tag = this._lastTag;
var $options = this.$element.find('option[data-select2-tag]');
$options.each(function () {
@@ -3702,7 +3852,7 @@ S2.define('select2/data/tokenizer',[
// Replace the search term if we have the search box
if (this.$search.length) {
this.$search.val(tokenData.term);
this.$search.focus();
this.$search.trigger('focus');
}
params.term = tokenData.term;
@@ -3831,10 +3981,30 @@ S2.define('select2/data/maximumSelectionLength',[
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 =
function (decorated, params, callback) {
var self = this;
this._checkIfMaximumSelected(function () {
decorated.call(self, params, callback);
});
};
MaximumSelectionLength.prototype._checkIfMaximumSelected =
function (_, successCallback) {
var self = this;
this.current(function (currentData) {
var count = currentData != null ? currentData.length : 0;
if (self.maximumSelectionLength > 0 &&
@@ -3847,7 +4017,10 @@ S2.define('select2/data/maximumSelectionLength',[
});
return;
}
decorated.call(self, params, callback);
if (successCallback) {
successCallback();
}
});
};
@@ -3886,7 +4059,7 @@ S2.define('select2/dropdown',[
};
Dropdown.prototype.position = function ($dropdown, $container) {
// Should be implmented in subclasses
// Should be implemented in subclasses
};
Dropdown.prototype.destroy = function () {
@@ -3910,7 +4083,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
' spellcheck="false" role="textbox" />' +
' spellcheck="false" role="searchbox" aria-autocomplete="list" />' +
'</span>'
);
@@ -3925,6 +4098,8 @@ S2.define('select2/dropdown/search',[
Search.prototype.bind = function (decorated, container, $container) {
var self = this;
var resultsId = container.id + '-results';
decorated.call(this, container, $container);
this.$search.on('keydown', function (evt) {
@@ -3947,23 +4122,27 @@ S2.define('select2/dropdown/search',[
container.on('open', function () {
self.$search.attr('tabindex', 0);
self.$search.attr('aria-controls', resultsId);
self.$search.focus();
self.$search.trigger('focus');
window.setTimeout(function () {
self.$search.focus();
self.$search.trigger('focus');
}, 0);
});
container.on('close', function () {
self.$search.attr('tabindex', -1);
self.$search.removeAttr('aria-controls');
self.$search.removeAttr('aria-activedescendant');
self.$search.val('');
self.$search.trigger('blur');
});
container.on('focus', function () {
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) {
@@ -4062,6 +4249,7 @@ S2.define('select2/dropdown/infiniteScroll',[
if (this.showLoadingMore(data)) {
this.$results.append(this.$loadingMore);
this.loadMoreIfNeeded();
}
};
@@ -4080,25 +4268,27 @@ S2.define('select2/dropdown/infiniteScroll',[
self.loading = true;
});
this.$results.on('scroll', function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
self.$loadingMore[0]
);
this.$results.on('scroll', this.loadMoreIfNeeded.bind(this));
};
if (self.loading || !isLoadMoreVisible) {
return;
}
InfiniteScroll.prototype.loadMoreIfNeeded = function () {
var isLoadMoreVisible = $.contains(
document.documentElement,
this.$loadingMore[0]
);
var currentOffset = self.$results.offset().top +
self.$results.outerHeight(false);
var loadingMoreOffset = self.$loadingMore.offset().top +
self.$loadingMore.outerHeight(false);
if (this.loading || !isLoadMoreVisible) {
return;
}
if (currentOffset + 50 >= loadingMoreOffset) {
self.loadMore();
}
});
var currentOffset = this.$results.offset().top +
this.$results.outerHeight(false);
var loadingMoreOffset = this.$loadingMore.offset().top +
this.$loadingMore.outerHeight(false);
if (currentOffset + 50 >= loadingMoreOffset) {
this.loadMore();
}
};
InfiniteScroll.prototype.loadMore = function () {
@@ -4119,7 +4309,7 @@ S2.define('select2/dropdown/infiniteScroll',[
var $option = $(
'<li ' +
'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');
@@ -4137,7 +4327,7 @@ S2.define('select2/dropdown/attachBody',[
'../utils'
], function ($, Utils) {
function AttachBody (decorated, $element, options) {
this.$dropdownParent = options.get('dropdownParent') || $(document.body);
this.$dropdownParent = $(options.get('dropdownParent') || document.body);
decorated.call(this, $element, options);
}
@@ -4145,27 +4335,14 @@ S2.define('select2/dropdown/attachBody',[
AttachBody.prototype.bind = function (decorated, container, $container) {
var self = this;
var setupResultsEvents = false;
decorated.call(this, container, $container);
container.on('open', function () {
self._showDropdown();
self._attachPositioningHandler(container);
if (!setupResultsEvents) {
setupResultsEvents = true;
container.on('results:all', function () {
self._positionDropdown();
self._resizeDropdown();
});
container.on('results:append', function () {
self._positionDropdown();
self._resizeDropdown();
});
}
// Must bind after the results handlers to ensure correct sizing
self._bindContainerResultHandlers(container);
});
container.on('close', function () {
@@ -4214,6 +4391,44 @@ S2.define('select2/dropdown/attachBody',[
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 =
function (decorated, container) {
var self = this;
@@ -4224,14 +4439,14 @@ S2.define('select2/dropdown/attachBody',[
var $watchers = this.$container.parents().filter(Utils.hasScroll);
$watchers.each(function () {
$(this).data('select2-scroll-position', {
Utils.StoreData(this, 'select2-scroll-position', {
x: $(this).scrollLeft(),
y: $(this).scrollTop()
});
});
$watchers.on(scrollEvent, function (ev) {
var position = $(this).data('select2-scroll-position');
var position = Utils.GetData(this, 'select2-scroll-position');
$(this).scrollTop(position.y);
});
@@ -4290,16 +4505,26 @@ S2.define('select2/dropdown/attachBody',[
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;
// 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
if ($offsetParent.css('position') === 'static') {
$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.left -= parentOffset.left;
@@ -4396,8 +4621,8 @@ S2.define('select2/dropdown/minimumResultsForSearch',[
});
S2.define('select2/dropdown/selectOnClose',[
], function () {
'../utils'
], function (Utils) {
function SelectOnClose () { }
SelectOnClose.prototype.bind = function (decorated, container, $container) {
@@ -4428,7 +4653,7 @@ S2.define('select2/dropdown/selectOnClose',[
return;
}
var data = $highlightedResults.data('data');
var data = Utils.GetData($highlightedResults[0], 'data');
// Don't re-select already selected resulte
if (
@@ -4469,7 +4694,7 @@ S2.define('select2/dropdown/closeOnSelect',[
var originalEvent = evt.originalEvent;
// Don't close if the control key is being held
if (originalEvent && originalEvent.ctrlKey) {
if (originalEvent && (originalEvent.ctrlKey || originalEvent.metaKey)) {
return;
}
@@ -4523,6 +4748,9 @@ S2.define('select2/i18n/en',[],function () {
},
searching: function () {
return 'Searching…';
},
removeAllItems: function () {
return 'Remove all items';
}
};
});
@@ -4761,66 +4989,29 @@ S2.define('select2/defaults',[
);
}
if (typeof options.language === 'string') {
// Check if the language is specified with a region
if (options.language.indexOf('-') > 0) {
// Extract the region information if it is included
var languageParts = options.language.split('-');
var baseLanguage = languageParts[0];
// If the defaults were not previously applied from an element, it is
// possible for the language option to have not been resolved
options.language = this._resolveLanguage(options.language);
options.language = [options.language, baseLanguage];
} else {
options.language = [options.language];
// Always fall back to English since it will always be complete
options.language.push('en');
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)) {
var languages = new Translation();
options.language.push('en');
options.language = uniqueLanguages;
var languageNames = options.language;
for (var l = 0; l < languageNames.length; l++) {
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;
}
options.translations = this._processTranslations(
options.language,
options.debug
);
return options;
};
@@ -4887,13 +5078,14 @@ S2.define('select2/defaults',[
debug: false,
dropdownAutoWidth: false,
escapeMarkup: Utils.escapeMarkup,
language: EnglishTranslation,
language: {},
matcher: matcher,
minimumInputLength: 0,
maximumInputLength: 0,
maximumSelectionLength: 0,
minimumResultsForSearch: 0,
selectOnClose: false,
scrollAfterSelect: false,
sorter: function (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) {
var camelKey = $.camelCase(key);
@@ -4916,7 +5205,7 @@ S2.define('select2/defaults',[
var convertedData = Utils._convertData(data);
$.extend(this.defaults, convertedData);
$.extend(true, this.defaults, convertedData);
};
var defaults = new Defaults();
@@ -4937,6 +5226,10 @@ S2.define('select2/options',[
this.fromElement($element);
}
if ($element != null) {
this.options = Defaults.applyFromElement(this.options, $element);
}
this.options = Defaults.apply(this.options);
if ($element && $element.is('input')) {
@@ -4960,14 +5253,6 @@ S2.define('select2/options',[
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 ($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('multiple', this.options.multiple);
if ($e.data('select2Tags')) {
if (Utils.GetData($e[0], 'select2Tags')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'Select2: The `data-select2-tags` attribute has been changed to ' +
@@ -4990,11 +5275,11 @@ S2.define('select2/options',[
);
}
$e.data('data', $e.data('select2Tags'));
$e.data('tags', true);
Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
Utils.StoreData($e[0], 'tags', true);
}
if ($e.data('ajaxUrl')) {
if (Utils.GetData($e[0], 'ajaxUrl')) {
if (this.options.debug && window.console && console.warn) {
console.warn(
'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.data('ajax--url', $e.data('ajaxUrl'));
$e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
}
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
// jQuery 1.x does not correctly handle data attributes with multiple dashes
if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
dataset = $.extend(true, {}, $e[0].dataset, $e.data());
} else {
dataset = $e.data();
dataset = $.extend(true, {}, $e[0].dataset, dataset);
}
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);
@@ -5054,8 +5363,8 @@ S2.define('select2/core',[
'./keys'
], function ($, Options, Utils, KEYS) {
var Select2 = function ($element, options) {
if ($element.data('select2') != null) {
$element.data('select2').destroy();
if (Utils.GetData($element[0], 'select2') != null) {
Utils.GetData($element[0], 'select2').destroy();
}
this.$element = $element;
@@ -5071,7 +5380,7 @@ S2.define('select2/core',[
// Set up the tabindex
var tabindex = $element.attr('tabindex') || 0;
$element.data('old-tabindex', tabindex);
Utils.StoreData($element[0], 'old-tabindex', tabindex);
$element.attr('tabindex', '-1');
// Set up containers and adapters
@@ -5132,6 +5441,9 @@ S2.define('select2/core',[
// Synchronize any monitored attributes
this._syncAttributes();
Utils.StoreData($element[0], 'select2', this);
// Ensure backwards compatibility with $element.data('select2').
$element.data('select2', this);
};
@@ -5208,6 +5520,12 @@ S2.define('select2/core',[
return null;
}
if (method == 'computedstyle') {
var computedStyle = window.getComputedStyle($element[0]);
return computedStyle.width;
}
return method;
};
@@ -5248,8 +5566,8 @@ S2.define('select2/core',[
if (observer != null) {
this._observer = new observer(function (mutations) {
$.each(mutations, self._syncA);
$.each(mutations, self._syncS);
self._syncA();
self._syncS(null, mutations);
});
this._observer.observe(this.$element[0], {
attributes: true,
@@ -5371,7 +5689,7 @@ S2.define('select2/core',[
if (self.isOpen()) {
if (key === KEYS.ESC || key === KEYS.TAB ||
(key === KEYS.UP && evt.altKey)) {
self.close();
self.close(evt);
evt.preventDefault();
} else if (key === KEYS.ENTER) {
@@ -5405,7 +5723,7 @@ S2.define('select2/core',[
Select2.prototype._syncAttributes = function () {
this.options.set('disabled', this.$element.prop('disabled'));
if (this.options.get('disabled')) {
if (this.isDisabled()) {
if (this.isOpen()) {
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 self = this;
@@ -5444,7 +5762,22 @@ S2.define('select2/core',[
}
} else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
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
if (changed) {
@@ -5466,7 +5799,8 @@ S2.define('select2/core',[
'open': 'opening',
'close': 'closing',
'select': 'selecting',
'unselect': 'unselecting'
'unselect': 'unselecting',
'clear': 'clearing'
};
if (args === undefined) {
@@ -5494,7 +5828,7 @@ S2.define('select2/core',[
};
Select2.prototype.toggleDropdown = function () {
if (this.options.get('disabled')) {
if (this.isDisabled()) {
return;
}
@@ -5510,15 +5844,40 @@ S2.define('select2/core',[
return;
}
if (this.isDisabled()) {
return;
}
this.trigger('query', {});
};
Select2.prototype.close = function () {
Select2.prototype.close = function (evt) {
if (!this.isOpen()) {
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 () {
@@ -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 () {
@@ -5621,10 +5980,12 @@ S2.define('select2/core',[
this._syncS = null;
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.attr('aria-hidden', 'false');
Utils.RemoveData(this.$element[0]);
this.$element.removeData('select2');
this.dataAdapter.destroy();
@@ -5652,7 +6013,7 @@ S2.define('select2/core',[
this.$container.addClass('select2-container--' + this.options.get('theme'));
$container.data('element', this.$element);
Utils.StoreData($container[0], 'element', this.$element);
return $container;
};
@@ -5672,8 +6033,9 @@ S2.define('jquery.select2',[
'jquery-mousewheel',
'./select2/core',
'./select2/defaults'
], function ($, _, Select2, Defaults) {
'./select2/defaults',
'./select2/utils'
], function ($, _, Select2, Defaults, Utils) {
if ($.fn.select2 == null) {
// All methods that should return the element
var thisMethods = ['open', 'close', 'destroy'];
@@ -5694,7 +6056,7 @@ S2.define('jquery.select2',[
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = $(this).data('select2');
var instance = Utils.GetData(this, 'select2');
if (instance == null && window.console && 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
+1 -1
View File
@@ -117,7 +117,7 @@ function logError(string $err, string $errstr, string $errpath, array $trace)
]);
}
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext)
function logErrorByCustomHandler(int $errno, string $errstr, string $errfile, int $errline, array $errcontext=null)
{
if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting, so let it fall
+22 -25
View File
@@ -11,12 +11,9 @@ require(__DIR__.'/../vendor/autoload.php');
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>설치</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.validate.min.js')?>
<?=WebUtil::printJS('../e_lib/sha512.min.js')?>
<?=WebUtil::printJS('../js/common.js')?>
<?=WebUtil::printJS('../js/install.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js') ?>
<?=WebUtil::printJS('../dist_js/vendors.js') ?>
<?=WebUtil::printJS('../dist_js/install.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../css/install.css')?>
</head>
@@ -29,13 +26,13 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="card" id="db_form_card" style="display:none">
<h3 class="card-header">
설치(DB 설정)
</h3>
</h3>
<div class="card-body">
<form id="db_form" method="post" action="#">
<div class="form-group row">
<label for="db_host" class="col-sm-4 col-form-label">DB호스트</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_host" id="db_host"
<input type="text" class="form-control" name="db_host" id="db_host"
placeholder="호스트" value="localhost" />
</div>
</div>
@@ -43,11 +40,11 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="db_port" class="col-sm-4 col-form-label">DB포트</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_port" id="db_port"
<input type="text" class="form-control" name="db_port" id="db_port"
placeholder="접속 포트" value="3306" />
</div>
</div>
<div class="form-group row">
<label for="db_id" class="col-sm-4 col-form-label">DB계정명</label>
<div class="col-sm-8">
@@ -55,11 +52,11 @@ require(__DIR__.'/../vendor/autoload.php');
</div>
</div>
<div class="form-group row">
<label for="db_pw" class="col-sm-4 col-form-label">DB비밀번호</label>
<div class="col-sm-8">
<input type="password" class="form-control" name="db_pw" id="db_pw"
<input type="password" class="form-control" name="db_pw" id="db_pw"
placeholder="DB비밀번호"/>
</div>
</div>
@@ -67,7 +64,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="db_name" class="col-sm-4 col-form-label">DB명</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="db_name" id="db_name"
<input type="text" class="form-control" name="db_name" id="db_name"
placeholder="DB명(예:sammo)"/>
</div>
</div>
@@ -75,7 +72,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="serv_host" class="col-sm-4 col-form-label">접속 경로</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="serv_host" id="serv_host"
<input type="text" class="form-control" name="serv_host" id="serv_host"
placeholder="접속경로(예:http://www.example.com)"/>
</div>
</div>
@@ -83,7 +80,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="shared_icon_path" class="col-sm-4 col-form-label">공용 아이콘 주소</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="shared_icon_path" id="shared_icon_path"
<input type="text" class="form-control" name="shared_icon_path" id="shared_icon_path"
placeholder="공용 아이콘 주소(웹 주소, 또는 접속 경로에 따른 상대 주소)"
value="../image/icons" />
</div>
@@ -92,7 +89,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="game_image_path" class="col-sm-4 col-form-label">게임 이미지 주소</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="game_image_path" id="game_image_path"
<input type="text" class="form-control" name="game_image_path" id="game_image_path"
placeholder="게임 이미지 주소(웹 주소, 또는 접속 경로에 따른 상대 주소)"
value="../image/game" />
</div>
@@ -101,7 +98,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="image_request_key" class="col-sm-4 col-form-label">이미지 갱신 </label>
<div class="input-group col-sm-8">
<input type="text" class="form-control" name="image_request_key" id="image_request_key"
<input type="text" class="form-control" name="image_request_key" id="image_request_key"
placeholder="이미지 서버의 hook/HashKey.php의 값과 동일하게"
value="" />
<div class="input-group-append">
@@ -115,7 +112,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="kakao_rest_key" class="col-sm-4 col-form-label">카카오 API Rest Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_rest_key" id="kakao_rest_key"
<input type="text" class="form-control" name="kakao_rest_key" id="kakao_rest_key"
placeholder="카카오톡 API의 Rest Key"
value="" />
</div>
@@ -124,7 +121,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="kakao_admin_key" class="col-sm-4 col-form-label">카카오 API Admin Key</label>
<div class="col-sm-8">
<input type="text" class="form-control" name="kakao_admin_key" id="kakao_admin_key"
<input type="text" class="form-control" name="kakao_admin_key" id="kakao_admin_key"
placeholder="카카오톡 API의 Admin Key"
value="" />
</div>
@@ -133,7 +130,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<div class="col-sm-4"></div>
<div class="col-sm-8">
<button type="submit"
<button type="submit"
class="btn btn-primary btn-lg btn-block login-button">설정 파일 생성</button>
</div>
</div>
@@ -144,7 +141,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="card" id="admin_form_card" style="display:none">
<h3 class="card-header">
설치(관리자 생성)
</h3>
</h3>
<div class="card-body">
<form id="admin_form" method="post" action="#">
<div class="form-group row">
@@ -155,11 +152,11 @@ require(__DIR__.'/../vendor/autoload.php');
</div>
</div>
<div class="form-group row">
<label for="password" class="col-sm-3 col-form-label">비밀번호</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="password" id="password"
<input type="password" class="form-control" name="password" id="password"
placeholder="비밀번호"/>
</div>
</div>
@@ -167,7 +164,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="confirm_password" class="col-sm-3 col-form-label">비밀번호 확인</label>
<div class="col-sm-9">
<input type="password" class="form-control" name="confirm_password" id="confirm_password"
<input type="password" class="form-control" name="confirm_password" id="confirm_password"
placeholder="비밀번호 확인"/>
</div>
</div>
@@ -175,7 +172,7 @@ require(__DIR__.'/../vendor/autoload.php');
<div class="form-group row">
<label for="nickname" class="col-sm-3 col-form-label">닉네임</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="nickname" id="nickname"
<input type="text" class="form-control" name="nickname" id="nickname"
placeholder="닉네임" value="운영자"/>
</div>
</div>
+313 -305
View File
@@ -1,305 +1,313 @@
<?php
namespace sammo;
require(__DIR__ . '/../vendor/autoload.php');
$host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id');
$password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name');
$servHost = Util::getPost('serv_host');
$sharedIconPath = Util::getPost('shared_icon_path');
$gameImagePath = Util::getPost('game_image_path');
$imageRequestKey = Util::getPost('image_request_key');
$kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', '');
$kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', '');
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
Json::die([
'result' => false,
'reason' => '입력 값이 올바르지 않습니다'
]);
}
if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
Json::die([
'result' => false,
'reason' => '접속 경로가 올바르지 않습니다.'
]);
}
if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) {
Json::die([
'result' => false,
'reason' => 'd_setting/RootDB.php 가 디렉토리입니다'
]);
}
if (class_exists('\\sammo\\RootDB')) {
Json::die([
'result' => false,
'reason' => '이미 RootDB.php 파일이 있습니다'
]);
}
//파일 권한 검사
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
Json::die([
'result' => false,
'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) {
Json::die([
'result' => false,
'reason' => 'd_log 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) {
Json::die([
'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) {
Json::die([
'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다'
]);
}
if (
!file_exists(ROOT . '/d_log')
|| !file_exists(ROOT . '/d_shared')
|| !file_exists(ROOT . '/d_setting')
|| !file_exists(AppConf::getUserIconPathFS())
) {
if (!is_writable(ROOT)) {
Json::die([
'result' => false,
'reason' => '하위 디렉토리 생성 권한이 없습니다'
]);
}
//기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS());
}
if (!file_exists(ROOT . '/d_log')) {
mkdir(ROOT . '/d_log');
}
if (!file_exists(ROOT . '/d_setting')) {
mkdir(ROOT . '/d_setting');
}
if (!file_exists(ROOT . '/d_shared')) {
mkdir(ROOT . '/d_shared');
}
}
if (!is_writable(AppConf::getUserIconPathFS())) {
Json::die([
'result' => false,
'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_log')) {
Json::die([
'result' => false,
'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_shared')) {
Json::die([
'result' => false,
'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_setting')) {
Json::die([
'result' => false,
'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.'
]);
}
if (!file_exists(ROOT . '/d_log/.htaccess')) {
@file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all');
}
if (!file_exists(ROOT . '/d_setting/.htaccess')) {
@file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all');
}
//DB 접근 권한 검사
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'DB 접속에 실패했습니다.'
]);
};
$rootDB->error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]);
};
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) {
while (true) {
if (!$mysqli_obj->more_results()) {
break;
}
if (!$mysqli_obj->next_result()) {
break;
}
}
}
$rootDB->insert('system', array(
'REG' => 'N',
'LOGIN' => 'N',
'CRT_DATE' => TimeUtil::now(),
'MDF_DATE' => TimeUtil::now()
));
$globalSalt = bin2hex(random_bytes(16));
'@phan-var-force string $servHost';
'@phan-var-force string $sharedIconPath';
'@phan-var-force string $gameImagePath';
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost);
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/ServConfig.orig.php',
ROOT . '/d_setting/ServConfig.php',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath,
'imageRequestPath' => $imageRequestPath,
'imageRequestKey' => $imageRequestKey
],
true
);
if ($imageRequestKey) {
@file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey);
}
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common_path.orig.js',
ROOT . '/d_shared/common_path.js',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
],
true
);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/menu.orig.json',
ROOT . '/d_shared/menu.json',
[],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common.orig.css',
ROOT . '/d_shared/common.css',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/RootDB.orig.php',
ROOT . '/d_setting/RootDB.php',
[
'host' => $host,
'user' => $username,
'password' => $password,
'dbName' => $dbName,
'port' => $port,
'globalSalt' => $globalSalt,
]
);
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/');
Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/KakaoKey.orig.php',
ROOT . '/d_setting/KakaoKey.php',
[
'REST_API_KEY' => $kakaoRESTKey,
'ADMIN_KEY' => $kakaoAdminKey,
'REDIRECT_URI' => $kakaoRedirectURI
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
Json::die([
'result' => true,
'reason' => 'success',
'globalSalt' => $globalSalt
]);
<?php
namespace sammo;
require(__DIR__ . '/../vendor/autoload.php');
$host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id');
$password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name');
$servHost = Util::getPost('serv_host');
$sharedIconPath = Util::getPost('shared_icon_path');
$gameImagePath = Util::getPost('game_image_path');
$imageRequestKey = Util::getPost('image_request_key');
$kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', '');
$kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', '');
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
Json::die([
'result' => false,
'reason' => '입력 값이 올바르지 않습니다'
]);
}
if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
Json::die([
'result' => false,
'reason' => '접속 경로가 올바르지 않습니다.'
]);
}
if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) {
Json::die([
'result' => false,
'reason' => 'd_setting/RootDB.php 가 디렉토리입니다'
]);
}
if (class_exists('\\sammo\\RootDB')) {
Json::die([
'result' => false,
'reason' => '이미 RootDB.php 파일이 있습니다'
]);
}
//파일 권한 검사
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
Json::die([
'result' => false,
'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) {
Json::die([
'result' => false,
'reason' => 'd_log 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) {
Json::die([
'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다'
]);
}
if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) {
Json::die([
'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다'
]);
}
if (
!file_exists(ROOT . '/d_log')
|| !file_exists(ROOT . '/d_shared')
|| !file_exists(ROOT . '/d_setting')
|| !file_exists(AppConf::getUserIconPathFS())
) {
if (!is_writable(ROOT)) {
Json::die([
'result' => false,
'reason' => '하위 디렉토리 생성 권한이 없습니다'
]);
}
//기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS());
}
if (!file_exists(ROOT . '/d_log')) {
mkdir(ROOT . '/d_log');
}
if (!file_exists(ROOT . '/d_setting')) {
mkdir(ROOT . '/d_setting');
}
if (!file_exists(ROOT . '/d_shared')) {
mkdir(ROOT . '/d_shared');
}
}
if (!is_writable(AppConf::getUserIconPathFS())) {
Json::die([
'result' => false,
'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_log')) {
Json::die([
'result' => false,
'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_shared')) {
Json::die([
'result' => false,
'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다'
]);
}
if (!is_writable(ROOT . '/d_setting')) {
Json::die([
'result' => false,
'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.'
]);
}
if (!file_exists(ROOT . '/d_log/.htaccess')) {
@file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all');
}
if (!file_exists(ROOT . '/d_setting/.htaccess')) {
@file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all');
}
//DB 접근 권한 검사
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'DB 접속에 실패했습니다.'
]);
};
$rootDB->error_handler = function ($params) {
Json::die([
'result' => false,
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]);
};
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) {
while (true) {
if (!$mysqli_obj->more_results()) {
break;
}
if (!$mysqli_obj->next_result()) {
break;
}
}
}
$rootDB->insert('system', array(
'REG' => 'N',
'LOGIN' => 'N',
'CRT_DATE' => TimeUtil::now(),
'MDF_DATE' => TimeUtil::now()
));
$globalSalt = bin2hex(random_bytes(16));
'@phan-var-force string $servHost';
'@phan-var-force string $sharedIconPath';
'@phan-var-force string $gameImagePath';
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost);
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/ServConfig.orig.php',
ROOT . '/d_setting/ServConfig.php',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath,
'imageRequestPath' => $imageRequestPath,
'imageRequestKey' => $imageRequestKey,
'serverList' => [
['che', '체', 'white'],
['kwe', '퀘', 'yellow'],
['pwe', '풰', 'orange'],
['twe', '퉤', 'magenta'],
['nya', '냐', '#e67e22'],
['pya', '퍄', '#9b59b6']
]
],
true
);
if ($imageRequestKey) {
@file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey);
}
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common_path.orig.js',
ROOT . '/d_shared/common_path.js',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
],
true
);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/menu.orig.json',
ROOT . '/d_shared/menu.json',
[],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common.orig.css',
ROOT . '/d_shared/common.css',
[
'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/RootDB.orig.php',
ROOT . '/d_setting/RootDB.php',
[
'host' => $host,
'user' => $username,
'password' => $password,
'dbName' => $dbName,
'port' => $port,
'globalSalt' => $globalSalt,
]
);
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/');
Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/KakaoKey.orig.php',
ROOT . '/d_setting/KakaoKey.php',
[
'REST_API_KEY' => $kakaoRESTKey,
'ADMIN_KEY' => $kakaoAdminKey,
'REDIRECT_URI' => $kakaoRedirectURI
],
true
);
if ($result !== true) {
Json::die([
'result' => false,
'reason' => $result
]);
}
Json::die([
'result' => true,
'reason' => 'success',
'globalSalt' => $globalSalt
]);
+1
View File
@@ -1,6 +1,7 @@
<?php
namespace kakao;
// @suppress PhanRedefineClass
class KakaoKey{
const REST_KEY = '_tK_REST_API_KEY_';
const ADMIN_KEY = '_tK_ADMIN_KEY_';
+74 -55
View File
@@ -1,55 +1,74 @@
<?php
namespace sammo;
class ServConfig
{
private function __construct()
{
}
public static $serverWebPath = '_tK_serverBasePath_';
public static $sharedIconPath = '_tK_sharedIconPath_';
public static $gameImagePath = "_tK_gameImagePath_";
public static $imageRequestPath = "_tK_imageRequestPath_";
public static $imageRequestKey = '_tK_imageRequestKey_';
public static function getSharedIconPath(string $filepath = ''): string
{
if ($filepath) {
return static::$sharedIconPath . "/{$filepath}";
}
return static::$sharedIconPath;
}
public static function getUserIconPath(string $filepath = ''): string
{
return AppConf::getUserIconPathWeb($filepath);
}
public static function getGameImagePath(string $filepath = ''): string
{
if ($filepath) {
return static::$gameImagePath . "/{$filepath}";
}
return static::$gameImagePath;
}
public static function getImagePullURI(): string
{
$now = time();
$req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey);
return static::$imageRequestPath . "?req={$req_hash}&time={$now}";
}
/**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
*
* @return string
*/
public static function getServerBasepath(): string
{
return self::$serverWebPath;
}
}
<?php
namespace sammo;
class ServConfig
{
private function __construct()
{
}
public static $serverWebPath = '_tK_serverBasePath_';
public static $sharedIconPath = '_tK_sharedIconPath_';
public static $gameImagePath = "_tK_gameImagePath_";
public static $imageRequestPath = "_tK_imageRequestPath_";
public static $imageRequestKey = '_tK_imageRequestKey_';
private static $serverList = null;
public static function getSharedIconPath(string $filepath = ''): string
{
if ($filepath) {
return static::$sharedIconPath . "/{$filepath}";
}
return static::$sharedIconPath;
}
public static function getUserIconPath(string $filepath = ''): string
{
return AppConf::getUserIconPathWeb($filepath);
}
public static function getGameImagePath(string $filepath = ''): string
{
if ($filepath) {
return static::$gameImagePath . "/{$filepath}";
}
return static::$gameImagePath;
}
public static function getImagePullURI(): string
{
$now = time();
$req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey);
return static::$imageRequestPath . "?req={$req_hash}&time={$now}";
}
/**
* 서버 설정 반환
*
* @return \sammo\Setting[]
*/
public static function getServerList(): array{
$servKeyList = [/*_tK_serverList_*/];
$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;
}
}
+5 -10
View File
@@ -6,38 +6,33 @@
.img_back {background-image:url('_tK_gameImagePath_/back.jpg'); }
/* 레거시. */
#bg0 { background-image:url('_tK_gameImagePath_/back_walnut.jpg'); }
#bg1 { background-image:url('_tK_gameImagePath_/back_green.jpg'); }
#bg2 { background-image:url('_tK_gameImagePath_/back_blue.jpg'); }
.map_detail .map_title{
background:
url('_tK_gameImagePath_/ltitle.jpg') no-repeat left,
url('_tK_gameImagePath_/ltitle.jpg') no-repeat left,
url('_tK_gameImagePath_/rtitle.jpg') no-repeat right;
}
.map_detail.map_spring .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/spring.gif') no-repeat right;
}
.map_detail.map_summer .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/summer.gif') no-repeat right;
}
.map_detail.map_fall .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/fall.gif') no-repeat right;
}
.map_detail.map_winter .map_title_text{
background:
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/ad.gif') no-repeat left,
url('_tK_gameImagePath_/winter.gif') no-repeat right;
}
+1 -1
View File
@@ -38,7 +38,7 @@ $admin = getAdmin();
</tr>
<tr>
<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=285><?=$admin['city_rate']?></td>
</tr>
+2 -2
View File
@@ -99,7 +99,7 @@ $sel2[$type2] = "selected";
</table>
<table align=center width=1600 class="tb_layout bg0">
<tr id=bg1>
<tr class='bg1'>
<td align=center>국명</td>
<td align=center>접률</td>
<td align=center>단접</td>
@@ -278,7 +278,7 @@ from city where nation=%i', $nation['nation']);
</table>
<table align=center width=1760 class="tb_layout bg0">
<tr id=bg1>
<tr class='bg1'>
<td width=30 align=center></td>
<td width=30 align=center></td>
<td width=50 align=center>국가수</td>
+9 -9
View File
@@ -52,9 +52,9 @@ if ($reqArgType === 0) {
$generalBasicList = $db->query('SELECT no, name, nation, npc, turntime, %b FROM general', $reqQueryType);
} else if ($reqArgType === 2) {
$generalBasicList = $db->query(
'SELECT no, name, nation, npc, turntime, value as %b
FROM general LEFT JOIN rank_data
ON general.no = rank_data.general_id
'SELECT no, name, nation, npc, turntime, value as %b
FROM general LEFT JOIN rank_data
ON general.no = rank_data.general_id
WHERE rank_data.type = %s',
$reqQueryType,
$reqQueryType
@@ -117,10 +117,10 @@ $generalObj = General::createGeneralObjFromDB($gen);
</table>
<table width=1000 align=center class='tb_layout bg0'>
<tr>
<td width=50% align=center id=bg1>
<td width=50% align=center class='bg1'>
<font color=skyblue size=3> </font>
</td>
<td width=50% align=center id=bg1>
<td width=50% align=center class='bg1'>
<font color=orange size=3>-</font>
</td>
</tr>
@@ -133,10 +133,10 @@ $generalObj = General::createGeneralObjFromDB($gen);
</td>
</tr>
<tr>
<td align=center id=bg1>
<td align=center class='bg1'>
<font color=skyblue size=3>개인 기록</font>
</td>
<td align=center id=bg1>
<td align=center class='bg1'>
<font color=orange size=3>전투 기록</font>
</td>
</tr>
@@ -149,10 +149,10 @@ $generalObj = General::createGeneralObjFromDB($gen);
</td>
</tr>
<tr>
<td align=center id=bg1>
<td align=center class='bg1'>
<font color=skyblue size=3>장수 열전</font>
</td>
<td align=center id=bg1>
<td align=center class='bg1'>
<font color=orange size=3>전투 결과</font>
</td>
</tr>
+4 -4
View File
@@ -49,10 +49,10 @@ $sel[$type] = "selected";
<table width=1000 align=center class='tb_layout bg0'>
<tr><td colspan=9 align=center bgcolor=blue> </td></tr>
<tr>
<td width=130 align=center id=bg1> </td>
<td width=130 align=center id=bg1> </td>
<td width=80 align=center id=bg1> </td>
<td width=60 align=center id=bg1> </td>
<td width=130 align=center class='bg1'> </td>
<td width=130 align=center class='bg1'> </td>
<td width=80 align=center class='bg1'> </td>
<td width=60 align=center class='bg1'> </td>
</tr>
<?php
+4
View File
@@ -24,3 +24,7 @@ foreach ($db->queryFirstColumn(
) as $generalNo) {
CheckHall($generalNo);
}
foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
$genObj->mergeTotalInheritancePoint();
}
+27 -18
View File
@@ -29,10 +29,9 @@ $templates = new \League\Plates\Engine(__DIR__.'/templates');
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/hallOfFame.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
</head>
<body>
@@ -74,7 +73,7 @@ $types = [
}
$v['nationName'] = '???';
$v['pictureFullPath'] = GetImageURL(0)."/default.jpg";
$v['name'] = '???';
$v['name'] = '???';
$v['ownerName'] = null;
$v['bgColor'] = GameConst::$basecolor4;
$v['fgColor'] = newColor($v['bgColor']);
@@ -91,6 +90,7 @@ $types = [
}
return $v;
}],
["점 령", "int", function($v){$v['value'] = $v['occupied']; return $v; }],
["사 살", "int", function($v){$v['value'] = $v['killcrew']; return $v; }],
["살 상 률", "percent", function($v){
if($v['warnum'] < 10){
@@ -101,6 +101,16 @@ $types = [
}
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['dex2']; return $v; }],
["기 병 숙 련 도", "int", function($v){$v['value'] = $v['dex3']; return $v; }],
@@ -112,9 +122,9 @@ $types = [
$v['value'] = 0;
}
else{
$v['value'] = $v['ttw']/max(1, $totalCnt);
$v['value'] = $v['ttw']/max(1, $totalCnt);
}
return $v;
return $v;
}],
["통 솔 전 승 률", "percent", function($v){
$totalCnt = $v['tlw']+$v['tld']+$v['tll'];
@@ -124,7 +134,7 @@ $types = [
else{
$v['value'] = $v['tlw']/max(1, $totalCnt);
}
return $v;
return $v;
}],
["일 기 토 승 률", "percent", function($v){
$totalCnt = $v['tsw']+$v['tsd']+$v['tsl'];
@@ -144,7 +154,7 @@ $types = [
else{
$v['value'] = $v['tiw']/max(1, $totalCnt);
}
return $v;
}],
["베 팅 투 자 액", "int", function($v){$v['value'] = $v['betgold']; return $v; }],
@@ -163,17 +173,17 @@ $types = [
$generals = [];
foreach($db->query(
"SELECT nation,no,name,owner_name as ownerName, owner, picture, imgsvr,
"SELECT nation,no,name,owner_name as ownerName, owner, picture, imgsvr,
experience, dedication,
dex1, dex2, dex3, dex4, dex5,
horse, weapon, book, item
dex1, dex2, dex3, dex4, dex5,
horse, weapon, book, item
FROM general WHERE %l", $btn == "NPC 보기"?"npc>=2":"npc<2") as $general
){
$generalID = $general['no'];
$general['bgColor'] = $nationColor[$general['nation']]??GameConst::$basecolor4;
$general['fgColor'] = newColor($general['bgColor']);
$general['nationName'] = $nationName[$general['nation']];
if(key_exists('picture', $general)){
$imageTemp = GetImageURL($general['imgsvr']);
$general['pictureFullPath'] = "$imageTemp/{$general['picture']}";
@@ -254,7 +264,7 @@ foreach($generals as $general){
else{
$itemOwners[$itemClassName] = [$general];
}
}
}
@@ -269,7 +279,7 @@ foreach(GameConst::$allItems as $itemType=>$itemList){
continue;
}
$itemClass = buildItemClass($itemClassName);
if($itemClass->isBuyable()){
continue;
}
@@ -277,7 +287,7 @@ foreach(GameConst::$allItems as $itemType=>$itemList){
$info = $itemClass->getInfo();
$name = $itemClass->getName();
if($info){
$name = $templates->render('tooltip', [
'text'=>$name,
@@ -312,7 +322,7 @@ foreach(GameConst::$allItems as $itemType=>$itemList){
$itemRanker[] = $card;
}
}
echo $templates->render('hallOfFrame', [
'typeName'=>$itemNameType,
'generals'=>$itemRanker
@@ -326,4 +336,3 @@ foreach(GameConst::$allItems as $itemType=>$itemList){
</table>
</body>
</html>
+17 -17
View File
@@ -16,9 +16,9 @@ increaseRefresh("왕조일람", 1);
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 왕조일람</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -70,9 +70,9 @@ foreach($emperiors as $emperior){
<tr>
<td bgcolor=skyblue align=center colspan=8>
<font size=5><?=$emperior['phase']?></font>
<a href="a_emperior_detail.php?select=<?=$emperior['no']?>"><button type='button'>자세히</button></a>
<?php if($emperior['server_id']): ?>
<a href="a_history.php?serverID=<?=$emperior['server_id']?>"><button type='button'>역사 보기</button></a>
<?php endif ?>
@@ -84,33 +84,33 @@ foreach($emperiors as $emperior){
</td>
</tr>
<tr>
<td id=bg1 align=center width=80> </td>
<td class='bg1' align=center width=80> </td>
<td align=center width=170><?=$emperior['power']?></td>
<td id=bg1 align=center width=80> </td>
<td class='bg1' align=center width=80> </td>
<td align=center width=170><?=$emperior['gennum']?></td>
<td id=bg1 align=center width=80> </td>
<td class='bg1' align=center width=80> </td>
<td align=center width=170><?=$emperior['citynum']?></td>
<td id=bg1 align=center width=80> </td>
<td class='bg1' align=center width=80> </td>
<td align=center width=170><?=$emperior['type']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l12name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l11name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l10name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l9name']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l8name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l7name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l6name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center><?=$emperior['l5name']?></td>
</tr>
</table>
+28 -31
View File
@@ -26,9 +26,6 @@ $serverID = $emperior['server_id']??($emperior['serverID']??null);
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 왕조일람</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -57,25 +54,25 @@ if($emperior):
</td>
</tr>
<tr>
<td id=bg1 width=98 align=center> <br>(최종 / 최대)</td>
<td class='bg1' width=98 align=center> <br>(최종 / 최대)</td>
<td align=center width=398 colspan=2><?=$emperior['nation_count']?></td>
<td id=bg1 width=98 align=center> <br>(최종 / 최대)</td>
<td class='bg1' width=98 align=center> <br>(최종 / 최대)</td>
<td align=center width=398 colspan=2><?=$emperior['gen_count']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td colspan=5><?=$emperior['nation_name']?></td>
</tr>
<tr>
<td id=bg1 align=center>국가별 성향</td>
<td class='bg1' align=center>국가별 성향</td>
<td colspan=5><?=$emperior['nation_hist']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td colspan=5><?=$emperior['personal_hist']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td colspan=5><?=$emperior['special_hist']?></td>
</tr>
<tr>
@@ -84,75 +81,75 @@ if($emperior):
</td>
</tr>
<tr>
<td id=bg1 width=98 align=center> </td>
<td class='bg1' width=98 align=center> </td>
<td align=center width=398 colspan=2><?=$emperior['power']?></td>
<td id=bg1 width=98 align=center> </td>
<td class='bg1' width=98 align=center> </td>
<td align=center width=398 colspan=2><?=$emperior['type']?></td>
</tr>
<tr>
<td id=bg1 width=98 align=center> </td>
<td class='bg1' width=98 align=center> </td>
<td align=center width=398 colspan=2><?=$emperior['gennum']?></td>
<td id=bg1 width=98 align=center> </td>
<td class='bg1' width=98 align=center> </td>
<td align=center width=398 colspan=2><?=$emperior['citynum']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center colspan=2><?=$emperior['pop']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center colspan=2><?=$emperior['poprate']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center colspan=2><?=$emperior['gold']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td align=center colspan=2><?=$emperior['rice']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l12name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l11name']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l10name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l9name']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l8name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l7name']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l6name']?></td>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td width=64>&nbsp;</td>
<td width=332><?=$emperior['l5name']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td colspan=5><?=$emperior['tiger']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td colspan=5><?=$emperior['eagle']?></td>
</tr>
<tr>
<td id=bg1 align=center> <br>(공헌도 순서)</td>
<td class='bg1' align=center> <br>(공헌도 순서)</td>
<td colspan=5><?=$emperior['gen']?></td>
</tr>
<tr>
<td id=bg1 align=center> </td>
<td class='bg1' align=center> </td>
<td colspan=5><?=formatHistoryToHTML(Json::decode($emperior['history']))?></td>
</tr>
</table>
@@ -178,7 +175,7 @@ if($showServers){
$nation['levelName'] = getNationLevel($nation['level']);
/** @var int[]|null $nationGenerals */
$nationGenerals = $nation['generals'];
if($nationGenerals){
$generals = $db->query('SELECT `general_no`, `name`, `last_yearmonth` FROM ng_old_generals WHERE server_id=%s AND general_no IN %li', $serverID, $nationGenerals);
@@ -203,7 +200,7 @@ if($showServers){
if(key_exists('aux', $nation) && !is_array($nation['aux'])){
$nation += Json::decode($nation['aux']);
}
echo $templates->render('oldNation', $nation);
}
}
+214 -215
View File
@@ -1,215 +1,214 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$type = Util::getReq('type', 'int', 9);
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
if ($type <= 0 || $type > 15) {
$type = 9;
}
$ownerNameList = [];
if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 장수일람</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=closeButton()?></td></tr>
<tr><td><form name=form1 method=post>정렬순서 :
<select id='viewType' name='type' size=1>
<option value=1>국가</option>
<option value=2>통솔</option>
<option value=3></option>
<option value=4>지력</option>
<option value=5>명성</option>
<option value=6>계급</option>
<option value=7>관직</option>
<option value=8>삭턴</option>
<option value=9>벌점</option>
<option value=10>Lv</option>
<option value=11>성격</option>
<option value=12></option>
<option value=13>전특</option>
<option value=14>연령</option>
<option value=15>NPC</option>
</select>
<input type=submit value='정렬하기'></form>
</td></tr>
</table>
<?php
$nationname = [];
$nationlevel = [];
$nationname[0] = "-";
foreach (getAllNationStaticInfo() as $nation) {
$nationname[$nation['nation']] = $nation['name'];
$nationlevel[$nation['nation']] = $nation['level'];
}
[$orderKey, $orderDesc] = [
1=>['nation', false],
2=>['leadership', true],
3=>['strength', true],
4=>['intel', true],
5=>['experience', true],
6=>['dedication', true],
7=>['officer_level', true],
8=>['killturn', false],
9=>['connect', true],
10=>['experience', true],
11=>['personal', true],
12=>['special', true],
13=>['special2', true],
14=>['age', true],
15=>['npc', true],
][$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':'');
echo"
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=64 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=80 align=center id=bg1>특기</td>
<td width=45 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=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=70 align=center id=bg1>벌점</td>
</tr>";
foreach($generalList as $general){
$nation = $nationname[$general['nation']];
$lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0);
if ($lbonus > 0) {
$lbonusText = "<font color=cyan>+{$lbonus}</font>";
} else {
$lbonusText = "";
}
if ($general['injury'] > 0) {
$leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100);
$strength = intdiv($general['strength'] * (100 - $general['injury']), 100);
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
$leadership = "<font color=red>{$leadership}</font>{$lbonusText}";
$strength = "<font color=red>{$strength}</font>";
$intel = "<font color=red>{$intel}</font>";
} else {
$leadership = "{$general['leadership']}{$lbonusText}";
$strength = "{$general['strength']}";
$intel = "{$general['intel']}";
}
if ($general['npc'] >= 2) {
$name = "<font color=cyan>{$general['name']}</font>";
} elseif ($general['npc'] == 1) {
$name = "<font color=skyblue>{$general['name']}</font>";
} else {
$name = "{$general['name']}";
}
if(key_exists($general['owner'], $ownerNameList)){
$name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>';
}
$general['connect'] = Util::round($general['connect'], -1);
$imageTemp = GetImageURL($general['imgsvr']);
echo "
<tr data-general-id='{$general['no']}'
data-general-wounded='{$general['injury']}'
data-general-leadership='{$general['leadership']}'
data-general-leadership-bonus='{$lbonus}'
data-general-strength='{$general['strength']}'
data-general-intel='{$general['intel']}'
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>$name</td>
<td align=center>{$general['age']}</td>
<td align=center>".displayCharInfo($general['personal'])."</td>
<td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td>
<td align=center>Lv ".getExpLevel($general['experience'])."</td>
<td align=center>{$nation}</td>
<td align=center>".getHonor($general['experience'])."</td>
<td align=center>".getDed($general['dedication'])."</td>
<td align=center>";
echo getOfficerLevelText($general['officer_level']);
echo "</td>
<td align=center>$leadership</td>
<td align=center>$strength</td>
<td align=center>$intel</td>
<td align=center>{$general['killturn']}</td>
<td align=center>{$general['connect']}";
echo "<br>【".getConnect($general['connect'])."】</td>
</tr>";
}
echo "
</table>
";
?>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=closeButton()?></td></tr>
<tr><td><?=banner()?></td></tr>
</table>
<script type="text/javascript">
$(document).ready(function() {
$("#viewType").val("<?=$type?>").attr("selected", "selected");
});
</script>
</body>
</html>
<?php
namespace sammo;
include "lib.php";
include "func.php";
$type = Util::getReq('type', 'int', 9);
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
if ($type <= 0 || $type > 15) {
$type = 9;
}
$ownerNameList = [];
if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 장수일람</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=closeButton()?></td></tr>
<tr><td><form name=form1 method=post>정렬순서 :
<select id='viewType' name='type' size=1>
<option value=1>국가</option>
<option value=2>통솔</option>
<option value=3>무력</option>
<option value=4></option>
<option value=5>명성</option>
<option value=6>계급</option>
<option value=7>관직</option>
<option value=8>삭턴</option>
<option value=9>벌점</option>
<option value=10>Lv</option>
<option value=11>성격</option>
<option value=12>내특</option>
<option value=13></option>
<option value=14>연령</option>
<option value=15>NPC</option>
</select>
<input type=submit value='정렬하기'></form>
</td></tr>
</table>
<?php
$nationname = [];
$nationlevel = [];
$nationname[0] = "-";
foreach (getAllNationStaticInfo() as $nation) {
$nationname[$nation['nation']] = $nation['name'];
$nationlevel[$nation['nation']] = $nation['level'];
}
[$orderKey, $orderDesc] = [
1=>['nation', false],
2=>['leadership', true],
3=>['strength', true],
4=>['intel', true],
5=>['experience', true],
6=>['dedication', true],
7=>['officer_level', true],
8=>['killturn', false],
9=>['connect', true],
10=>['experience', true],
11=>['personal', true],
12=>['special', true],
13=>['special2', true],
14=>['age', true],
15=>['npc', true],
][$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':'');
echo"
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=64 align=center class='bg1'> </td>
<td width=140 align=center class='bg1'> </td>
<td width=45 align=center class='bg1'>연령</td>
<td width=45 align=center class='bg1'>성격</td>
<td width=80 align=center class='bg1'>특기</td>
<td width=45 align=center class='bg1'> </td>
<td width=140 align=center class='bg1'> </td>
<td width=55 align=center class='bg1'> </td>
<td width=55 align=center class='bg1'> </td>
<td width=75 align=center class='bg1'> </td>
<td width=45 align=center class='bg1'>통솔</td>
<td width=45 align=center class='bg1'>무력</td>
<td width=45 align=center class='bg1'></td>
<td width=45 align=center class='bg1'>삭턴</td>
<td width=70 align=center class='bg1'>벌점</td>
</tr>";
foreach($generalList as $general){
$nation = $nationname[$general['nation']];
$lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0);
if ($lbonus > 0) {
$lbonusText = "<font color=cyan>+{$lbonus}</font>";
} else {
$lbonusText = "";
}
if ($general['injury'] > 0) {
$leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100);
$strength = intdiv($general['strength'] * (100 - $general['injury']), 100);
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
$leadership = "<font color=red>{$leadership}</font>{$lbonusText}";
$strength = "<font color=red>{$strength}</font>";
$intel = "<font color=red>{$intel}</font>";
} else {
$leadership = "{$general['leadership']}{$lbonusText}";
$strength = "{$general['strength']}";
$intel = "{$general['intel']}";
}
if ($general['npc'] >= 2) {
$name = "<font color=cyan>{$general['name']}</font>";
} elseif ($general['npc'] == 1) {
$name = "<font color=skyblue>{$general['name']}</font>";
} else {
$name = "{$general['name']}";
}
if(key_exists($general['owner'], $ownerNameList)){
$name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>';
}
$general['connect'] = Util::round($general['connect'], -1);
$imageTemp = GetImageURL($general['imgsvr']);
echo "
<tr data-general-id='{$general['no']}'
data-general-wounded='{$general['injury']}'
data-general-leadership='{$general['leadership']}'
data-general-leadership-bonus='{$lbonus}'
data-general-strength='{$general['strength']}'
data-general-intel='{$general['intel']}'
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>$name</td>
<td align=center>{$general['age']}</td>
<td align=center>".displayCharInfo($general['personal'])."</td>
<td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td>
<td align=center>Lv ".getExpLevel($general['experience'])."</td>
<td align=center>{$nation}</td>
<td align=center>".getHonor($general['experience'])."</td>
<td align=center>".getDed($general['dedication'])."</td>
<td align=center>";
echo getOfficerLevelText($general['officer_level']);
echo "</td>
<td align=center>$leadership</td>
<td align=center>$strength</td>
<td align=center>$intel</td>
<td align=center>{$general['killturn']}</td>
<td align=center>{$general['connect']}";
echo "<br>【".getConnect($general['connect'])."】</td>
</tr>";
}
echo "
</table>
";
?>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=closeButton()?></td></tr>
<tr><td><?=banner()?></td></tr>
</table>
<script type="text/javascript">
$(document).ready(function() {
$("#viewType").val("<?=$type?>").attr("selected", "selected");
});
</script>
</body>
</html>
+12 -13
View File
@@ -28,7 +28,7 @@ $scenarioList = (function(){
if($scenarioIdx !== null || key_exists($scenarioIdx, $scenarioList)){
if($scenarioIdx !== null && key_exists($scenarioIdx, $scenarioList)){
$searchScenarioName = $scenarioList[$seasonIdx][$scenarioIdx]['name'];
$searchFilter = $db->sqleval('season = %i AND scenario = %i', $seasonIdx, $scenarioIdx);
}
@@ -50,12 +50,9 @@ else{
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/hallOfFame.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.redirect.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJs('js/hallOfFame.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJs('dist_js/hallOfFame.js')?>
</head>
<body>
@@ -64,14 +61,14 @@ else{
<tr><td>
시나리오 검색 : <select id="by_scenario" name="by_scenario">
<?php foreach($scenarioList as $iterSeasonIdx=>$subScenarioList): ?>
<option
data-season="<?=$iterSeasonIdx?>"
value=""
<option
data-season="<?=$iterSeasonIdx?>"
value=""
<?=($iterSeasonIdx == $seasonIdx && $scenarioIdx === null)?"selected='selected'":''?>
>* 시즌 : <?=$iterSeasonIdx?> 종합 *</option>
<?php foreach($subScenarioList as $info): ?>
<option
data-season="<?=$iterSeasonIdx?>"
data-season="<?=$iterSeasonIdx?>"
value="<?=$info['scenario']?>"
<?=($iterSeasonIdx == $seasonIdx && $info['scenario']===$scenarioIdx)?"selected='selected'":''?>
><?=$info['name']?>(<?=$info['cnt']?>회)</option>
@@ -90,8 +87,11 @@ $types = [
'warnum'=>['전 투 횟 수', 'int'],
'killnum'=>['승 리', 'int'],
'winrate'=>['승 률', 'percent'],
'occupied'=>['점 령', 'int'],
'killcrew'=>['사 살', 'int'],
'killrate'=>['살 상 률', 'percent'],
'killcrew_person'=>['대 인 사 살', 'int'],
'killrate_person'=>['대 인 살 상 률', 'percent'],
'dex1'=>['보 병 숙 련 도', 'int'],
'dex2'=>['궁 병 숙 련 도', 'int'],
'dex3'=>['기 병 숙 련 도', 'int'],
@@ -133,7 +133,7 @@ foreach($types as $typeName=>[$typeDescribe, $typeValue]) {
$general['bgColor'] = $general['color'];
}
}
if(!key_exists('fgColor', $general)){
$general['fgColor'] = newColor($general['bgColor']);
}
@@ -172,4 +172,3 @@ foreach($types as $typeName=>[$typeDescribe, $typeValue]) {
</table>
</body>
</html>
+5 -8
View File
@@ -99,13 +99,10 @@ $nations = Json::decode($history['nations']);
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 연감</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS("js/map/theme_{$mapTheme}.js")?>
<?=WebUtil::printJS('js/map.js')?>
<?=WebUtil::printJS('js/history.js')?>
<?=WebUtil::printJS('dist_js/history.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -139,7 +136,7 @@ var nations = <?=$nations?$history['nations']:'{}'?>;
</td></tr>
</table>
<table align=center width=1000 height=520 class='tb_layout bg0'>
<thead><tr><th colspan=5 align=center id=bg1> </th></tr></thead>
<thead><tr><th colspan=5 align=center class='bg1'> </th></tr></thead>
<tbody>
<tr height=520>
<td width=698>
@@ -169,13 +166,13 @@ var nations = <?=$nations?$history['nations']:'{}'?>;
</table>
</td>
</tr>
<tr><th colspan=5 align=center id=bg1> </th></tr>
<tr><th colspan=5 align=center class='bg1'> </th></tr>
<tr>
<td colspan=5 valign=top>
<?=formatHistoryToHTML(Json::decode($history['global_history']))?>
</td>
</tr>
<tr><th colspan=5 align=center id=bg1> </th></tr>
<tr><th colspan=5 align=center class='bg1'> </th></tr>
<tr>
<td colspan=5 valign=top>
<?=formatHistoryToHTML(Json::decode($history['global_action']))?>
+13 -14
View File
@@ -25,10 +25,9 @@ if($con >= 2) { printLimitMsg($me['turntime']); exit(); }
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 세력일람</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/ext.kingdoms.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/extKingdoms.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -48,7 +47,7 @@ $nations[0] = getNationStaticInfo(0);
foreach($db->query('SELECT npc,name,city,nation,officer_level,penalty,permission FROM general ORDER BY dedication DESC') as $general){
$nationID = $general['nation'];
if(!key_exists('generals', $nations[$nationID])){
$nations[$nationID]['generals'] = [];
}
@@ -92,13 +91,13 @@ foreach ($nations as $nation) {
<td colspan=8 align=center style=color:".newColor($nation['color'])."; bgcolor={$nation['color']}> {$nation['name']} </td>
</tr>
<tr>
<td width=80 align=center id=bg1> </td>
<td width=80 align=center class='bg1'> </td>
<td width=170 align=center><font color=yellow>".getNationType($nation['type'])."</font></td>
<td width=80 align=center id=bg1> </td>
<td width=80 align=center class='bg1'> </td>
<td width=170 align=center>".getNationLevel($nation['level'])."</td>
<td width=80 align=center id=bg1> </td>
<td width=80 align=center class='bg1'> </td>
<td width=170 align=center>{$nation['power']}</td>
<td width=80 align=center id=bg1>장수 / 속령</td>
<td width=80 align=center class='bg1'>장수 / 속령</td>
<td width=170 align=center>{$nation['gennum']} / ".count($nation['cities']??[])."</td>
";
for($chiefLevel = 12; $chiefLevel >= 5; $chiefLevel--){
@@ -113,9 +112,9 @@ foreach ($nations as $nation) {
}
echo "</tr>
<tr>
<td align=center id=bg1>외교권자</td><td colspan=5>";
<td align=center class='bg1'>외교권자</td><td colspan=5>";
echo join(', ', $ambassadors);
echo "</td><td align=center id=bg1>조언자</td><td align=center >";
echo "</td><td align=center class='bg1'>조언자</td><td align=center >";
echo count($auditors).'명';
echo "</td></tr>
<tr>
@@ -160,9 +159,9 @@ echo "
</tr>
<tr>
<td width=498 align=center>&nbsp;</td>
<td width=123 align=center id=bg1> </td>
<td width=123 align=center class='bg1'> </td>
<td width=123 align=center>{$nations[0]['gennum']}</td>
<td width=123 align=center id=bg1> </td>
<td width=123 align=center class='bg1'> </td>
<td width=123 align=center>".count($nations[0]['cities']??[])."</td>
</tr>
<tr>
@@ -177,7 +176,7 @@ echo"
<td colspan=5> 장수 일람 : ";
foreach($nations[0]['generals'] as $general) {
$generalText = getColoredName($general['name'], $general['npc']);
echo "{$generalText}, ";
echo "{$generalText}, ";
}
echo"
</td>
+21 -16
View File
@@ -26,9 +26,9 @@ $sel[$type] = "selected";
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 빙의일람</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -59,8 +59,13 @@ foreach (getAllNationStaticInfo() as $nation) {
$nationName[$nation['nation']] = $nation['name'];
}
$generalList = $db->query('SELECT npc,nation,name,owner_name,special,special2,personal,leadership,strength,intel,leadership+strength+intel as sum,explevel,experience,dedication from general where npc=1');
$generalListFromPool = $db->query('SELECT npc,nation,name,owner_name,special,special2,personal,leadership,strength,intel,leadership+strength+intel as sum,explevel,experience,dedication from general JOIN select_pool on general.no = select_pool.general_id where npc=0');
if($generalListFromPool){
$generalList = array_merge($generalListFromPool, $generalList);
}
$sortType = [
1 => ['name', true],
2 => ['nation', true],
@@ -88,18 +93,18 @@ else{
?>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=102 align=center id=bg1>희생된 장수</td>
<td width=102 align=center id=bg1>악령 이름</td>
<td width=68 align=center id=bg1>레벨</td>
<td width=118 align=center id=bg1>국가</td>
<td width=68 align=center id=bg1>성격</td>
<td width=88 align=center id=bg1>특기</td>
<td width=68 align=center id=bg1>종능</td>
<td width=68 align=center id=bg1>통솔</td>
<td width=68 align=center id=bg1>무력</td>
<td width=68 align=center id=bg1>지력</td>
<td width=78 align=center id=bg1>명성</td>
<td width=78 align=center id=bg1>계급</td>
<td width=102 align=center class='bg1'>희생된 장수</td>
<td width=102 align=center class='bg1'>악령 이름</td>
<td width=68 align=center class='bg1'>레벨</td>
<td width=118 align=center class='bg1'>국가</td>
<td width=68 align=center class='bg1'>성격</td>
<td width=88 align=center class='bg1'>특기</td>
<td width=68 align=center class='bg1'>종능</td>
<td width=68 align=center class='bg1'>통솔</td>
<td width=68 align=center class='bg1'>무력</td>
<td width=68 align=center class='bg1'>지력</td>
<td width=78 align=center class='bg1'>명성</td>
<td width=78 align=center class='bg1'>계급</td>
</tr>
<?php foreach($generalList as $general): ?>
<tr>
+3 -5
View File
@@ -27,12 +27,11 @@ if($con >= 2) { printLimitMsg($me['turntime']); exit(); }
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 세력도</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<?=WebUtil::printJS('dist_js/map.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
@@ -80,4 +79,3 @@ $(function(){
</body>
</html>
+16 -16
View File
@@ -52,9 +52,9 @@ if ($admin['maxonline'] < $curonline) {
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -92,7 +92,7 @@ span.out_bar{
<table align=center width=1016>
<tr><td align=left>
<table align=center class='tb_layout bg0'>
<tr><td colspan=4 align=center id=bg2><font size=5> </font></td></tr>
<tr><td colspan=4 align=center class='bg2'><font size=5> </font></td></tr>
<?php
$refresh[] = $admin['refresh'];
foreach($refresh as $i=>$value){
@@ -101,8 +101,8 @@ foreach($refresh as $i=>$value){
$dt = substr($date[$i], 11, 5); ?>
<tr height=30>
<td width=100 align=center><?=$year[$i]?>년 <?=$month[$i]?>월</td>
<td width=60 align=center id=bg2><?=$dt?></td>
<td width=2 align=center id=bg1></td>
<td width=60 align=center class='bg2'><?=$dt?></td>
<td width=2 align=center class='bg1'></td>
<td width=320>
<?php if($w == 0): ?>
<span class="out_bar"><?=$value?></span>
@@ -111,15 +111,15 @@ foreach($refresh as $i=>$value){
<?php else:?>
<div class='big_bar' style='width:<?=$w?>%;background-color:<?=$color?>;'><span><?=$value?></span></div>
<?php endif;?>
</td>
</tr>
<?php
}
?>
<tr><td colspan=4 height=5 align=center id=bg1></td></tr>
<tr><td colspan=4 height=5 align=center class='bg1'></td></tr>
<tr>
<td colspan=4 height=30 align=center id=bg0>최고기록: <?=$admin['maxrefresh']?></td>
<td colspan=4 height=30 align=center class='bg0'>최고기록: <?=$admin['maxrefresh']?></td>
</tr>
@@ -127,7 +127,7 @@ foreach($refresh as $i=>$value){
</td>
<td align=right>
<table align=center class='tb_layout bg0'>
<tr><td colspan=4 align=center id=bg2><font size=5> </font></td></tr>
<tr><td colspan=4 align=center class='bg2'><font size=5> </font></td></tr>
<?php
$online[] = $curonline;
foreach($online as $i=>$value){
@@ -136,8 +136,8 @@ foreach($online as $i=>$value){
$dt = substr($date[$i], 11, 5); ?>
<tr height=30>
<td width=100 align=center><?=$year[$i]?>년 <?=$month[$i]?>월</td>
<td width=60 align=center id=bg2><?=$dt?></td>
<td width=2 align=center id=bg1></td>
<td width=60 align=center class='bg2'><?=$dt?></td>
<td width=2 align=center class='bg1'></td>
<td width=320>
<?php if($w == 0): ?>
<span class="out_bar"><?=$value?></span>
@@ -146,22 +146,22 @@ foreach($online as $i=>$value){
<?php else:?>
<div class='big_bar' style='width:<?=$w?>%;background-color:<?=$color?>;'><span><?=$value?></span></div>
<?php endif;?>
</td>
</tr>
<?php
}
?>
<tr><td colspan=4 height=5 align=center id=bg1></td></tr>
<tr><td colspan=4 height=5 align=center class='bg1'></td></tr>
<tr>
<td colspan=4 height=30 align=center id=bg0>최고기록: <?=$admin['maxonline']?></td>
<td colspan=4 height=30 align=center class='bg0'>최고기록: <?=$admin['maxonline']?></td>
</tr>
</table>
</td></tr>
</table>
<br>
<table align=center class='tb_layout bg0'>
<tr><td colspan=3 align=center id=bg2><font size=5> (순간과도갱신)</font></td></tr>
<tr><td colspan=3 align=center class='bg2'><font size=5> (순간과도갱신)</font></td></tr>
<?php
$max_refresh = $db->queryFirstRow('SELECT sum(refresh) as refresh, sum(`connect`) as `connect` from general');
$max_refresh['name'] = '접속자 총합';
+13 -13
View File
@@ -12,7 +12,7 @@ $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("설문조사", 1);
$isVoteAdmin = in_array('vote', $session->acl[DB::prefix()]??[]);
$isVoteAdmin |= $session->userGrade >= 5;
$isVoteAdmin = $isVoteAdmin || $session->userGrade >= 5;
$me = $db->queryFirstRow('SELECT no,vote from general where owner=%i', $userID);
@@ -28,9 +28,9 @@ $vote = $admin['vote']?:['-'];
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -60,7 +60,7 @@ function captureKey(e) {
</table>
<table align=center width=1000 class='tb_layout bg0'>
<form name=form1 action=c_vote.php method=post>
<tr><td colspan=3 align=center id=bg2><font size=5> (<?=$admin['develcost']*5?>금과 추첨으로 유니크템 증정!)</font></td></tr>
<tr><td colspan=3 align=center class='bg2'><font size=5> (<?=$admin['develcost']*5?>금과 추첨으로 유니크템 증정!)</font></td></tr>
<?php
if ($isVoteAdmin) {
@@ -76,7 +76,7 @@ if ($isVoteAdmin) {
$vote_title = Tag2Code($vote_title);
echo "
<tr>
<td colspan=2 width=148 align=center id=bg1> </td>
<td colspan=2 width=148 align=center class='bg1'> </td>
<td width=848 align=left>&nbsp;{$vote_title}</td>
</tr>
";
@@ -151,7 +151,7 @@ echo "
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td colspan=4 align=center id=bg1> </td>
<td colspan=4 align=center class='bg1'> </td>
</tr>
";
for ($i=0; $i < $commentCount; $i++) {
@@ -180,7 +180,7 @@ if ($me['no'] > 0) {
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=3 align=center id=bg2><font size=5>
<tr><td colspan=3 align=center class='bg2'><font size=5>
<?php
if ($isVoteAdmin) {
@@ -238,8 +238,8 @@ if ($admin['voteopen'] >= 1 || $isVoteAdmin) {
else{
$totalPer += $per;
}
// if($per < 5) { $vote['cnt'] = "&nbsp;"; }
?>
<?php if($per == 0): ?>
@@ -303,7 +303,7 @@ if ($admin['voteopen'] >= 2 || $isVoteAdmin) {
foreach($db->query('SELECT nation,color,name,gennum from nation order by gennum desc') as $i=>$nation){
$memCount = $db->queryFirstField('SELECT count(no) FROM general WHERE nation=%i AND npc<2', $nation['nation']);
$voteCount = $nationVoteCount[$nation['nation']] ?? 0;
if($memCount == 0){
@@ -312,7 +312,7 @@ if ($admin['voteopen'] >= 2 || $isVoteAdmin) {
else{
$percentage = round($voteCount / $memCount * 100, 1);
}
echo "
<tr>
@@ -336,7 +336,7 @@ if ($admin['voteopen'] >= 2 || $isVoteAdmin) {
else{
$totalPer += $per;
}
// if($per < 5) { $vote['cnt'] = "&nbsp;"; }
?>
<?php if($per == 0): ?>
+14 -14
View File
@@ -49,9 +49,9 @@ if ($msg2 == "") {
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -59,12 +59,12 @@ if ($msg2 == "") {
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=closeButton()?></td></tr>
<tr><td align=center id=bg2><font color=orange size=6><b> </b></font><input type=button value='갱신' onclick="location.replace('b_auction.php')"></td></tr>
<tr><td align=center class='bg2'><font color=orange size=6><b> </b></font><input type=button value='갱신' onclick="location.replace('b_auction.php')"></td></tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<form method=post action=c_auction.php>
<tr><td colspan=11 align=center bgcolor=orange><font size=5> </font></td></tr>
<tr align=center id=bg1>
<tr align=center class='bg1'>
<td width=68>거래번호</td>
<td width=48>선택</td>
<td width=98>판매자</td>
@@ -118,18 +118,18 @@ foreach($db->query('SELECT * from auction where type=0 order by expire') as $auc
}
?>
<tr height=25>
<td align=center id=bg1>등록결과</td>
<td align=center class='bg1'>등록결과</td>
<td colspan=10><?=ConvertLog($msg)?></td>
</tr>
<tr>
<td align=center id=bg1>입찰등록</td>
<td align=center class='bg1'>입찰등록</td>
<td colspan=10>
 지불할 금액: <input type=text style=color:white;background-color:black; size=6 maxlength=6 name=value>
<input type=<?=$btn?> name=btn value='구매시도' onclick='return confirm("정말 입찰하시겠습니까?");'>
</td>
</tr>
<tr>
<td align=center id=bg1>거래등록</td>
<td align=center class='bg1'>거래등록</td>
<td colspan=10>
 종료: <input type=text style=color:white;background-color:black; size=2 maxlength=2 name=term value=12>
 물품:
@@ -152,7 +152,7 @@ foreach($db->query('SELECT * from auction where type=0 order by expire') as $auc
<table align=center width=1000 class='tb_layout bg0'>
<form method=post action=c_auction.php>
<tr><td colspan=11 align=center bgcolor=skyblue><font size=5> </font></td></tr>
<tr align=center id=bg1>
<tr align=center class='bg1'>
<td width=68>거래번호</td>
<td width=48>선택</td>
<td width=98>구매자</td>
@@ -205,18 +205,18 @@ foreach($db->query('SELECT * from auction where type=1 order by expire') as $auc
}
?>
<tr height=25>
<td align=center id=bg1>등록결과</td>
<td align=center class='bg1'>등록결과</td>
<td colspan=10><?=ConvertLog($msg2)?></td>
</tr>
<tr>
<td align=center id=bg1>입찰등록</td>
<td align=center class='bg1'>입찰등록</td>
<td colspan=10>
 수령할 금액: <input type=text style=color:white;background-color:black; size=6 maxlength=6 name=value>
<input type=<?=$btn?> name=btn value='판매시도' onclick='return confirm("정말 입찰하시겠습니까?");'>
</td>
</tr>
<tr>
<td align=center id=bg1>거래등록</td>
<td align=center class='bg1'>거래등록</td>
<td colspan=10>
 종료: <input type=text style=color:white;background-color:black; size=2 maxlength=2 name=term value=12>
 물품:
@@ -237,11 +237,11 @@ foreach($db->query('SELECT * from auction where type=1 order by expire') as $auc
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td align=center id=bg2><font size=5> </font></td></tr>
<tr><td align=center class='bg2'><font size=5> </font></td></tr>
<tr><td>
<?=getAuctionLogRecent(20)?>
</td></tr>
<tr><td align=center id=bg2><font size=5> </font></td></tr>
<tr><td align=center class='bg2'><font size=5> </font></td></tr>
<tr><td>
<font color=white size=2>
ㆍ판매거래는 거래자가 판매할 물품을 거래하면, 구입을 희망하는 사람이 현재가보다 높게 입찰하여 구입하는 방식입니다.<br>
+13 -13
View File
@@ -87,10 +87,10 @@ else if($reqArgType===1){
$generalBasicList = $db->query('SELECT no, name, npc, turntime, officer_level, %b FROM general WHERE nation = %i', $reqQueryType, $nationID);
}
else if($reqArgType===2){
$generalBasicList = $db->query('SELECT no, name, npc, turntime, officer_level, value as %b
FROM general LEFT JOIN rank_data
ON general.no = rank_data.general_id
WHERE rank_data.type = %s AND general.nation = %i',
$generalBasicList = $db->query('SELECT no, name, npc, turntime, officer_level, value as %b
FROM general LEFT JOIN rank_data
ON general.no = rank_data.general_id
WHERE rank_data.type = %s AND general.nation = %i',
$reqQueryType, $reqQueryType, $nationID
);
}
@@ -120,9 +120,9 @@ $showGeneral = General::createGeneralObjFromDB($gen);
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -153,8 +153,8 @@ $showGeneral = General::createGeneralObjFromDB($gen);
</table>
<table width=1000 align=center class='tb_layout bg0'>
<tr>
<td width=50% align=center id=bg1><font color=skyblue size=3> </font></td>
<td width=50% align=center id=bg1><font color=orange size=3> </font></td>
<td width=50% align=center class='bg1'><font color=skyblue size=3> </font></td>
<td width=50% align=center class='bg1'><font color=orange size=3> </font></td>
</tr>
<tr>
<td valign=top>
@@ -165,8 +165,8 @@ $showGeneral = General::createGeneralObjFromDB($gen);
</td>
</tr>
<tr>
<td align=center id=bg1><font color=orange size=3>전투 기록</font></td>
<td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
<td align=center class='bg1'><font color=orange size=3>전투 기록</font></td>
<td align=center class='bg1'><font color=orange size=3>전투 결과</font></td>
</tr>
<tr>
<td valign=top>
@@ -178,8 +178,8 @@ $showGeneral = General::createGeneralObjFromDB($gen);
</tr>
<?php if($showGeneral->getNPCType() > 1 || $permission >= 2): ?>
<tr>
<td align=center id=bg1><font color=orange size=3>개인 기록</font></td>
<td align=center id=bg1><font color=orange size=3>&nbsp;</font></td>
<td align=center class='bg1'><font color=orange size=3>개인 기록</font></td>
<td align=center class='bg1'><font color=orange size=3>&nbsp;</font></td>
</tr>
<tr>
<td valign=top>
+10 -11
View File
@@ -63,10 +63,9 @@ if($str3){
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 베팅장</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/betting.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/betting.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -79,7 +78,7 @@ if($str3){
<table align=center width=1120 class='tb_layout bg0'>
<tr><td colspan=16><input type=button value='갱신' onclick='location.reload()'></td></tr>
<tr><td colspan=16 align=center><font color=white size=6><?=$tnmt_type?> (<?=$str1.$str2.$str3?>)</font></td></tr>
<tr><td height=50 colspan=16 align=center id=bg2><font color=limegreen size=6>16 상황</font><br><font color=orange size=3>(전체 금액 : <?=$globalBetTotal?> / 내 투자 금액 : <?=$myBetTotal?>)</font></td></tr>
<tr><td height=50 colspan=16 align=center class='bg2'><font color=limegreen size=6>16 상황</font><br><font color=orange size=3>(전체 금액 : <?=$globalBetTotal?> / 내 투자 금액 : <?=$myBetTotal?>)</font></td></tr>
</table>
<table align=center width=1120 class='mimic_flex bg0' style='border:solid 1px gray;font-size:10px;'>
<tr align=center><td height=10 colspan=16></td></tr>
@@ -311,7 +310,7 @@ for ($i=0; $i < 16; $i++) {
else{
$gold[$i] = Util::round($myBet[$i] * $bet[$i]);
}
}
?>
</tr>
@@ -393,8 +392,8 @@ if ($admin['tournament'] == 6) {
<tr align=center><td height=10 colspan=16></td></tr>
</table>
<table align=center width=1120 class='tb_layout bg0'>
<tr align=center><td height=50 colspan=4 id=bg2><font color=yellow size=6>토너먼트 랭킹</font></td></tr>
<tr align=center><td colspan=4 id=bg2><font color=skyblue size=3>순위 / 장수명 / 능력치 / 경기수 / 승리 / 무승부 / 패배 / 집계점수 / 우승횟수</font></td></tr>
<tr align=center><td height=50 colspan=4 class='bg2'><font color=yellow size=6>토너먼트 랭킹</font></td></tr>
<tr align=center><td colspan=4 class='bg2'><font color=skyblue size=3>순위 / 장수명 / 능력치 / 경기수 / 승리 / 무승부 / 패배 / 집계점수 / 우승횟수</font></td></tr>
<tr align=center>
<?php
@@ -430,7 +429,7 @@ foreach($tournamentType as $tournamentTypeText=>[$statTypeText,$statFunc,$rankCo
<td>
<table align=center width=280 class='tb_layout bg0'>
<tr><td colspan=9 align=center style=color:white;background-color:black;><font size=4><?=$tournamentTypeText?></font></td></tr>
<tr id=bg1><td align=center></td><td align=center>장수</td><td align=center><?=$statTypeText?></td><td align=center>경</td><td align=center>승</td><td align=center>무</td><td align=center>패</td><td align=center>점</td><td align=center>勝</td></tr>
<tr class='bg1'><td align=center></td><td align=center>장수</td><td align=center><?=$statTypeText?></td><td align=center>경</td><td align=center>승</td><td align=center>무</td><td align=center>패</td><td align=center>점</td><td align=center>勝</td></tr>
<?php
$prizeColumn = "{$rankColumn}p";
$gameColumn = "{$rankColumn}g";
@@ -446,8 +445,8 @@ foreach($tournamentType as $tournamentTypeText=>[$statTypeText,$statFunc,$rankCo
$result = -($lhs->getRankVar($gameColumn) <=> $rhs->getRankVar($gameColumn));
if($result !== 0) return $result;
$result = -(
($lhs->getRankVar($winColumn)+$lhs->getRankVar($drawColumn)+$lhs->getRankVar($loseColumn))
<=>
($lhs->getRankVar($winColumn)+$lhs->getRankVar($drawColumn)+$lhs->getRankVar($loseColumn))
<=>
($rhs->getRankVar($winColumn)+$rhs->getRankVar($drawColumn)+$rhs->getRankVar($loseColumn))
);
if($result !== 0) return $result;
+4 -8
View File
@@ -15,12 +15,9 @@ $generalObj = General::createGeneralObjFromDB($session->generalID);
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 사령부</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.redirect.js')?>
<?=WebUtil::printJS('../e_lib/moment.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/chiefCenter.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/chiefCenter.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -72,7 +69,7 @@ var maxChiefTurn = <?=GameConst::$maxChiefTurn?>;
></div
><div
><?=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
@@ -108,4 +105,3 @@ var maxChiefTurn = <?=GameConst::$maxChiefTurn?>;
</div>
</body>
</html>
+79 -24
View File
@@ -16,7 +16,11 @@ $db = DB::db();
increaseRefresh("현재도시", 1);
$me = $db->queryFirstRow('SELECT no,nation,officer_level,city from general where owner=%i', $userID);
$myNation = $db->queryFirstRow('SELECT nation,level,spy FROM nation WHERE nation=%i', $me['nation']);
$myNation = $db->queryFirstRow('SELECT nation,level,spy FROM nation WHERE nation=%i', $me['nation'])??[
'nation'=>0,
'level'=>0,
'spy'=>''
];
$templates = new \League\Plates\Engine('templates');
@@ -29,11 +33,9 @@ $templates = new \League\Plates\Engine('templates');
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/select2/select2.full.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/currentCity.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/currentCity.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css')?>
@@ -148,8 +150,31 @@ echo "
unset($city);
// 첩보된 도시까지만 허용
if($valid == 0 && $userGrade < 5) {
$showDetailedInfo = false;
if($valid){
$showDetailedInfo = true;
}
if(!key_exists($citylist, CityConst::all())){
$citylist = $me['city'];
$showDetailedInfo = true;
$valid = 1;
}
if($userGrade >= 5){
$valid = true;
$showDetailedInfo = 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,17 +197,41 @@ 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];
$generals = $db->query(
'SELECT %l from general where city=%i order by name',
Util::formatListOfBackticks($dbColumns),
$city['city']
);
if($showDetailedInfo){
$generals = $db->query(
'SELECT %l from general where city=%i order by turntime',
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 = [];
if($generals){
foreach($db->queryAllLists(
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
array_column($generals, 'no')
) as [$generalID, $turnIdx, $brief]
){
@@ -221,7 +270,7 @@ foreach($generals as $general){
$isNPC = $general['npc']>1;
$wounded = $general['injury'];
$name = $general['name'];
$nameText = formatName($name, $general['npc']);
@@ -257,6 +306,10 @@ foreach($generals as $general){
$crew = $general['crew'];
$train = -1;
$atmos = -1;
if(!$valid){
$crew = -1;
}
}
$nation = $general['nation'];
@@ -274,7 +327,7 @@ foreach($generals as $general){
else{
$turnText = '';
}
$generalsFormat[] = [
'ourGeneral'=>$ourGeneral,
'iconPath'=>GetImageURL($general['imgsvr']).'/'.$general['picture'],
@@ -326,12 +379,14 @@ $genTotal = 0;
foreach($generalsFormat as $general){
if($general['nation'] == 0){
if(!$general['nation'] || !$myNation['nation']){
continue;
}
if($general['nation'] != $myNation['nation']){
$enemyCnt += 1;
$enemyCrew += $general['crew'];
if($general['crew'] >= 0){
$enemyCrew += $general['crew'];
}
if($general['crew'] > 0){
$enemyArmedCnt += 1;
}
@@ -354,7 +409,7 @@ foreach($generalsFormat as $general){
}
$chkDef = false;
if($minTrain >= 80){
$crew80 += $general['crew'];
$gen80 += 1;
@@ -371,7 +426,7 @@ foreach($generalsFormat as $general){
$chkDef = true;
}
}
@@ -402,11 +457,11 @@ foreach($generalsFormat as $general){
</tr>
<tr>
<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><?=$city['trade']?>%</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><?=$officer[4]['name']?></td>
<td align=center class=bg1>군사</td>
@@ -430,11 +485,12 @@ foreach($generalsFormat as $general){
</tr>
<tr>
<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>
</table>
<br>
<?php if($showDetailedInfo): ?>
<table align=center class='tb_layout bg0'>
<thead>
<tr>
@@ -459,11 +515,10 @@ foreach($generalsFormat as $general){
?>
</tbody>
</table>
<?php endif; ?>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?> </td></tr>
</table>
</body>
</html>
+11 -15
View File
@@ -55,20 +55,16 @@ $nationStor->cacheValues(['notice', 'scout_msg']);
<title><?=UniqueConst::$serverName?>: 내무부</title>
<script>
var editable = <?=(($me['officer_level']>=5||$permission==4)?'true':'false')?>;
var nationMsg = <?=Json::encode($nationStor->notice??'')?>;
var scoutmsg = <?=Json::encode($nationStor->scout_msg??'')?>;
var storedData = <?=Json::encode([
"nationMsg"=>$nationStor->notice??'',
"scoutMsg"=>$nationStor->scout_msg??''
])?>;
</script>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/summernote/summernote-bs4.min.js')?>
<?=WebUtil::printJS('../e_lib/summernote/lang/summernote-ko-KR.js')?>
<?=WebUtil::printJS('../e_lib/summernote/plugin/image-sammo/summernote-image-flip.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/dipcenter.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/dipcenter.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/summernote/summernote-bs4.css')?>
<?=WebUtil::printCSS('dist_css/vendors.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/dipcenter.css')?>
@@ -116,14 +112,14 @@ foreach($nationsList as $staticNation):
0 => "<font color=red>교 전</font>",
1 => "<font color=magenta>선포중</font>",
2 => "통 상",
7 => "<font color=green>불가침</font>",
7 => "<font color=green>불가침</font>",
][$diplomacyState['state']];
if($diplomacyState['term']){
$dipEndMonth = $admin['month'] + $diplomacyState['term'] - 1;
$dipEndYear = $admin['year'] + intdiv($dipEndMonth, 12);
$dipEndMonth = $dipEndMonth % 12 + 1;
$dipTermText = $diplomacyState['term'].'개월';
$dipEndDateText = "{$dipEndYear}{$dipEndMonth}";
}
@@ -200,12 +196,12 @@ if ($budgetricediff > 0) {
</div>
</div>
<div style='border-bottom:solid gray 0.5px;'>870px x 200px를 넘어서는 내용은 표시되지 않습니다.</div>
<input type='hidden' class='input_form' name='scoutmsg' data-global='scoutmsg'>
<input type='hidden' class='input_form' name='scoutMsg' data-global='scoutMsg'>
<div style="width:870px;margin-left:auto;">
<div class='edit_form viewer'></div>
</div>
</div>
</div></td></tr>
<tr><td colspan=2 align=center bgcolor=green> &amp; </td></tr>
<tr>
+11 -12
View File
@@ -31,8 +31,8 @@ foreach($db->queryAllLists('SELECT nation, count(city) FROM city WHERE nation !=
$realConflict = [];
foreach ($db->queryAllLists('SELECT city, `name`, conflict FROM city WHERE conflict!=%s', '{}') as [
$cityID,
$cityName,
$cityID,
$cityName,
$rawConflict
])
{
@@ -62,7 +62,7 @@ foreach($db->queryAllLists('SELECT me, you, state FROM diplomacy') as [$me, $you
if(!key_exists($me, $diplomacyList)){
$diplomacyList[$me] = [];
}
$diplomacyList[$me][$you] = $state;
}
@@ -90,12 +90,11 @@ $neutralStateCharMap = [
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 중원 정보</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<?=WebUtil::printJS('dist_js/map.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
@@ -163,9 +162,9 @@ else{
<table class='tb_layout bg0' style='width:100%;'>
<?php foreach($conflict as $item): ?>
<tr>
<td
<td
width=130
align=right
align=right
style='color:<?=newColor($item['color'])?>;background-color:<?=$item['color']?>;'
><?=$item['name']?>&nbsp;</td>
<td width=48 align=right><?=(float)$item['percent']?> %&nbsp;</td>
@@ -175,14 +174,14 @@ else{
</tr>
<?php endforeach; ?>
</table>
</td>
</tr>
<?php endforeach; ?>
<tr><td colspan=2 height=5 id=bg1></td></tr>
<tr><td colspan=2 height=5 class='bg1'></td></tr>
</table>
<?php endif; ?>
<?php endif; ?>
<br>
<table align=center width=1000 class='tb_layout bg0'>
+6 -6
View File
@@ -56,9 +56,9 @@ $templates = new \League\Plates\Engine('templates');
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
</head>
<body>
@@ -93,7 +93,7 @@ switch ($type) {
case 5: $orderSQL = "order by crew desc"; break;
case 6: $orderSQL = "order by killturn"; 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(
@@ -105,7 +105,7 @@ $generals = $db->query(
$generalTurnList = [];
foreach($db->queryAllLists(
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
array_column($generals, 'no')
) as [$generalID, $turnIdx, $brief]
){
@@ -157,7 +157,7 @@ foreach ($generals as &$general) {
$general['modeText'] = formatDefenceTrain($general['defence_train']);
$general['crewtypeText'] = GameUnitConst::byId($general['crewtype'])->name??'-';
if ($general['npc'] < 2) {
$turntext = [];
foreach($generalTurnList[$general['no']] as $turnRawIdx=>$turn){
+526 -527
View File
@@ -1,527 +1,526 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
increaseRefresh("인사부", 1);
//훼섭 추방을 위해 갱신
TurnExecutionHelper::executeAllCommand();
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$nationID = $me['nation'];
$meLevel = $me['officer_level'];
if($meLevel == 0) {
echo "재야입니다.";
exit();
}
$nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nation where nation=%i', $nationID); //국가정보
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 인사부</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/select2/select2.full.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/bossInfo.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<script type="text/javascript">
var chiefStatMin = <?=GameConst::$chiefStatMin?>;
var myLevel = <?=$meLevel?>;
</script>
<?php
$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);
$candidateAmbassadors = [];
$candidateAuditors = [];
foreach($ambassadors as $ambassador){
$candidateAmbassadors[] = $ambassador;
}
foreach($auditors as $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){
$maxPermission = checkSecretMaxPermission($candidate);
if($maxPermission == 4){
$candidateAmbassadors[] = $candidate;
}
if($maxPermission >= 3){
$candidateAuditors[] = $candidate;
}
}
?>
<script>
var candidateAmbassadors = <?=Json::encode(array_map(function($value){
return [
'id'=>$value['no'],
'text'=>$value['name'],
"selected"=>($value['permission']!='normal')
];
}, $candidateAmbassadors))?>;
var candidateAuditors = <?=Json::encode(array_map(function($value){
return [
'id'=>$value['no'],
'text'=>$value['name'],
"selected"=>($value['permission']!='normal')
];
}, $candidateAuditors))?>;
</script>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=backButton()?></td></tr>
</table>
<br>
<?php
$lv = getNationChiefLevel($nation['level']);
if($meLevel >= 5) { $btn = "button"; }
else { $btn = "hidden"; }
$level = Util::convertArrayToDict(
$db->query(
'SELECT name,officer_level,city,picture,imgsvr,belong from general where nation=%i and officer_level>=%i order by officer_level desc',
$nationID, $lv
),
'officer_level'
);
$tigers = $db->query('SELECT value, name
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',
$nationID
);// 오호장군
$tigerstr = join(', ', array_map(function($arr){
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $tigers));
$eagles = $db->query('SELECT value, name
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',
$nationID
);// 건안칠자
$eaglestr = join(', ', array_map(function($arr){
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $eagles));
?>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td align=center style='color:<?=newColor($nation['color'])?>; background-color:<?=$nation['color']?>' colspan=6>
<font size=5> <?=$nation['name']?> 】</font>
</td>
</tr>
<?php
for($i=12; $i >= $lv; $i-=2) {
$i1 = $i; $i2 = $i - 1;
$imageTemp1 = GetImageURL($level[$i1]['imgsvr']??0);
$imageTemp2 = GetImageURL($level[$i2]['imgsvr']??0);
?>
<tr>
<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=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=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>
</tr>
<?php
}
?>
<tr>
<td width=98 align=center id=bg1>오호장군【승전】</td>
<td colspan=5><?=$tigerstr?></td>
</tr>
<tr>
<td width=98 align=center id=bg1>건안칠자【계략】</td>
<td colspan=5><?=$eaglestr?></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=6 height=5></td></tr>
<tr><td colspan=2 align=center bgcolor=red> </td></tr>
<tr>
<td width=498 align=right id=bg1>대상 장수</td>
<td width=498>
<?php
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);
$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); //추방 때문에 조금 더 김
}
else{
$candidateStrength = [];
$candidateIntel = [];
$candidateAny = [];
}
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $meLevel)) {
echo "
<select id='genlist_kick' size=1 style=color:white;background-color:black;>";
foreach($candidateAny as $general) {
if($general['no'] === $me['no']){
continue;
}
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>";
}
echo "
</select>
<input type=$btn id='btn_kick' value=추방>";
}
$officerLevelText = getOfficerLevelText(11, $nation['level']);
echo "
</td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=4 height=5></td></tr>
<tr><td colspan=4 align=center bgcolor=blue> </td></tr>
<tr>
<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=98 align=right id=bg1>{$officerLevelText}</td>
<td width=398>
";
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], 11)) {
echo "
<select id='genlist_11' size=1 maxlength=15 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>";
foreach($candidateAny as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='11' data-officer_level_text='{$officerLevelText}' value=임명>";
} else {
if(key_exists(11, $level)){
echo "{$level[11]['name']}".CityConst::byID($level[11]['city'])->name."";
}
}
echo "
</td>
</tr>
";
for($i=10; $i >= $lv; $i--) {
if($i % 2 == 0) { echo "<tr>"; }
$officerLevelText = getOfficerLevelText($i, $nation['level']);
echo "
<td width=98 align=right id=bg1>{$officerLevelText}</td>
<td width=398>
";
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $i)) {
echo "
<select id='genlist_{$i}' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>";
foreach(($i%2==0?$candidateStrength:$candidateIntel) as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='{$i}' data-officer_level_text='$officerLevelText' value=임명>";
} else {
$general = $level[$i]??null;
if($general){
echo "{$general['name']}".CityConst::byID($general['city'])->name."";
}
}
echo "</td>";
if($i % 2 == 1) { echo "</tr>"; }
}
echo "
<tr><td colspan=4> <font color=red>빨간색</font> 현재 임명중인 장수, <font color=orange>노란색</font> 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr>
</table>
";
if($meLevel == 12):
?>
<table align='center' width='1000' class='tb_layout bg0'>
<tr><td colspan='4' height='5'></td></tr>
<tr><td colspan='4' align='center' bgcolor='purple'> </td></tr>
<tr>
<td width=98 align=right id=bg1>외교권자</td>
<td width=398>
<select id="selectAmbassador" multiple="multiple">
</select>
<button id='changeAmbassador' type='button'>임명</button>
</td>
<td width=98 align=right id=bg1>조언자</td>
<td width=398>
<select id="selectAuditor" multiple="multiple">
</select>
<button id='changeAuditor' type='button'>임명</button>
</td>
</tr>
</table>
<?php
endif;
?>
<table align=center width=1000 id='officer_list' class='tb_layout bg0'>
<tr><td colspan=5 height=5></td></tr>
<?php
if($meLevel >= 5) {
$officerLevelText = getOfficerLevelText(4, $nation['level']);
echo "
<tr><td colspan=5 align=center bgcolor=orange> </td></tr>
<tr>
<td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td>
<td colspan=2>
<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);
$region = 0;
foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 4)){
continue;
}
if($region != $city['region']) {
if($region != 0) {
echo "</optgroup>";
}
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region'];
}
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
}
echo "</optgroup>";
echo "
</select>
<select id='genlist_4' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>
";
foreach($candidateStrength as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='4' data-officer_level_text='{$officerLevelText}' value=임명>
</td>
</tr>";
$officerLevelText = getOfficerLevelText(3, $nation['level']);
echo "<tr>
<td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td>
<td colspan=2>
<select id='citylist_3' size=1 style=color:white;background-color:black;>
";
$region = 0;
foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 3)){
continue;
}
if($region != $city['region']) {
if($region != 0) {
echo "</optgroup>";
}
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region'];
}
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
}
echo "</optgroup>";
echo "
</select>
<select id='genlist_3' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>
";
foreach($candidateIntel as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='3' data-officer_level_text='{$officerLevelText}' value=임명>
</td>
</tr>";
$officerLevelText = getOfficerLevelText(2, $nation['level']);
echo "<tr>
<td colspan=3 align=right id=bg2>{$officerLevelText} 임명</td>
<td colspan=2>
<select id='citylist_2' size=1 style=color:white;background-color:black;>
";
$region = 0;
foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 2)){
continue;
}
if($region != $city['region']) {
if($region != 0) {
echo "</optgroup>";
}
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region'];
}
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
}
echo "</optgroup>";
echo "
</select>
<select id='genlist_2' size=1 style=color:white;background-color:black;>
<option value=0>____<span class='name_field'>공석</span>____</option>
";
foreach ($candidateAny as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='2' data-officer_level_text='{$officerLevelText}' value=임명>
</td>
</tr>
<tr><td colspan=5> <font color=red>빨간색</font> 현재 임명중인 장수, <font color=orange>노란색</font> 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr>
";
}
echo "
<tr>
<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>
</tr>
";
$citylevel = getCityLevelList();
$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){
$officerCityID = $officer['officer_city'];
if(!key_exists($officerCityID, $officerList)){
$officerList[$officerCityID] = [];
}
$officerList[$officerCityID][$officer['officer_level']] = $officer;
}
$region = 0;
$dummyOfficer = [
'name'=>'-',
'belong'=>0,
];
$textColor = newColor($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) {
$cityID = $city['city'];
$cityOfficerList = $officerList[$cityID]??[];
?>
<?php if($region != $city['region']): ?>
<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>
<?php endif; $region = $city['region']; ?>
<tr>
<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>
<?php foreach(Util::range(4, 1, -1) as $officerLevel): ?>
<?php if(key_exists($officerLevel, $cityOfficerList)):
$officer = $cityOfficerList[$officerLevel];
?>
<td><?=$officer['name']?>(<?=$officer['belong']?>년) 【<?=CityConst::byID($officer['city'])->name?>】</td>
<?php else: ?>
<td>-</td>
<?php endif; ?>
<?php endforeach; ?>
</tr>
<?php
}
?>
<tr><td colspan=5> <font color=orange>노란색</font> 변경 불가능, 하얀색은 변경 가능 관직입니다.</td></tr>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?></td></tr>
</table>
</body>
</html>
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
increaseRefresh("인사부", 1);
//훼섭 추방을 위해 갱신
TurnExecutionHelper::executeAllCommand();
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$nationID = $me['nation'];
$meLevel = $me['officer_level'];
if($meLevel == 0) {
echo "재야입니다.";
exit();
}
$nation = $db->queryFirstRow('SELECT nation,name,level,color,chief_set from nation where nation=%i', $nationID); //국가정보
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 인사부</title>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printJS('dist_js/bossInfo.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<script type="text/javascript">
var chiefStatMin = <?=GameConst::$chiefStatMin?>;
var myLevel = <?=$meLevel?>;
</script>
<?php
$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);
$candidateAmbassadors = [];
$candidateAuditors = [];
foreach($ambassadors as $ambassador){
$candidateAmbassadors[] = $ambassador;
}
foreach($auditors as $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){
$maxPermission = checkSecretMaxPermission($candidate);
if($maxPermission == 4){
$candidateAmbassadors[] = $candidate;
}
if($maxPermission >= 3){
$candidateAuditors[] = $candidate;
}
}
?>
<script>
var candidateAmbassadors = <?=Json::encode(array_map(function($value){
return [
'id'=>$value['no'],
'text'=>$value['name'],
"selected"=>($value['permission']!='normal')
];
}, $candidateAmbassadors))?>;
var candidateAuditors = <?=Json::encode(array_map(function($value){
return [
'id'=>$value['no'],
'text'=>$value['name'],
"selected"=>($value['permission']!='normal')
];
}, $candidateAuditors))?>;
</script>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=backButton()?></td></tr>
</table>
<br>
<?php
$lv = getNationChiefLevel($nation['level']);
if($meLevel >= 5) { $btn = "button"; }
else { $btn = "hidden"; }
$level = Util::convertArrayToDict(
$db->query(
'SELECT name,officer_level,city,picture,imgsvr,belong from general where nation=%i and officer_level>=%i order by officer_level desc',
$nationID, $lv
),
'officer_level'
);
$tigers = $db->query('SELECT value, name
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5',
$nationID
);// 오호장군
$tigerstr = join(', ', array_map(function($arr){
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $tigers));
$eagles = $db->query('SELECT value, name
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',
$nationID
);// 건안칠자
$eaglestr = join(', ', array_map(function($arr){
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $eagles));
?>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td align=center style='color:<?=newColor($nation['color'])?>; background-color:<?=$nation['color']?>' colspan=6>
<font size=5> <?=$nation['name']?> 】</font>
</td>
</tr>
<?php
for($i=12; $i >= $lv; $i-=2) {
$i1 = $i; $i2 = $i - 1;
$imageTemp1 = GetImageURL($level[$i1]['imgsvr']??0);
$imageTemp2 = GetImageURL($level[$i2]['imgsvr']??0);
?>
<tr>
<td width=98 align=center class='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=332><font size=4><?=$level[$i1]['name']??'-'?>(<?=$level[$i1]['belong']??'-'?>년)</font></td>
<td width=98 align=center class='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=332><font size=4><?=$level[$i2]['name']??'-'?>(<?=$level[$i2]['belong']??'-'?>년)</font></td>
</tr>
<?php
}
?>
<tr>
<td width=98 align=center class='bg1'>오호장군【승전】</td>
<td colspan=5><?=$tigerstr?></td>
</tr>
<tr>
<td width=98 align=center class='bg1'>건안칠자【계략】</td>
<td colspan=5><?=$eaglestr?></td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=6 height=5></td></tr>
<tr><td colspan=2 align=center bgcolor=red> </td></tr>
<tr>
<td width=498 align=right class='bg1'>대상 장수</td>
<td width=498>
<?php
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);
$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); //추방 때문에 조금 더 김
}
else{
$candidateStrength = [];
$candidateIntel = [];
$candidateAny = [];
}
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $meLevel)) {
echo "
<select id='genlist_kick' size=1 style=color:white;background-color:black;>";
foreach($candidateAny as $general) {
if($general['no'] === $me['no']){
continue;
}
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>";
}
echo "
</select>
<input type=$btn id='btn_kick' value=추방>";
}
$officerLevelText = getOfficerLevelText(11, $nation['level']);
echo "
</td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td colspan=4 height=5></td></tr>
<tr><td colspan=4 align=center bgcolor=blue> </td></tr>
<tr>
<td width=98 align=right class='bg1'>".getOfficerLevelText(12, $nation['level'])."</td>
<td width=398>{$level[12]['name']} ".CityConst::byID($level[12]['city'])->name."</td>
<td width=98 align=right class='bg1'>{$officerLevelText}</td>
<td width=398>
";
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], 11)) {
echo "
<select id='genlist_11' size=1 maxlength=15 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>";
foreach($candidateAny as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='11' data-officer_level_text='{$officerLevelText}' value=임명>";
} else {
if(key_exists(11, $level)){
echo "{$level[11]['name']}".CityConst::byID($level[11]['city'])->name."";
}
}
echo "
</td>
</tr>
";
for($i=10; $i >= $lv; $i--) {
if($i % 2 == 0) { echo "<tr>"; }
$officerLevelText = getOfficerLevelText($i, $nation['level']);
echo "
<td width=98 align=right class='bg1'>{$officerLevelText}</td>
<td width=398>
";
if($meLevel >= 5 && !isOfficerSet($nation['chief_set'], $i)) {
echo "
<select id='genlist_{$i}' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>";
foreach(($i%2==0?$candidateStrength:$candidateIntel) as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='{$i}' data-officer_level_text='$officerLevelText' value=임명>";
} else {
$general = $level[$i]??null;
if($general){
echo "{$general['name']}".CityConst::byID($general['city'])->name."";
}
}
echo "</td>";
if($i % 2 == 1) { echo "</tr>"; }
}
echo "
<tr><td colspan=4> <font color=red>빨간색</font> 현재 임명중인 장수, <font color=orange>노란색</font> 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr>
</table>
";
if($meLevel == 12):
?>
<table align='center' width='1000' class='tb_layout bg0'>
<tr><td colspan='4' height='5'></td></tr>
<tr><td colspan='4' align='center' bgcolor='purple'> </td></tr>
<tr>
<td width=98 align=right class='bg1'>외교권자</td>
<td width=398>
<select id="selectAmbassador" multiple="multiple">
</select>
<button id='changeAmbassador' type='button'>임명</button>
</td>
<td width=98 align=right class='bg1'>조언자</td>
<td width=398>
<select id="selectAuditor" multiple="multiple">
</select>
<button id='changeAuditor' type='button'>임명</button>
</td>
</tr>
</table>
<?php
endif;
?>
<table align=center width=1000 id='officer_list' class='tb_layout bg0'>
<tr><td colspan=5 height=5></td></tr>
<?php
if($meLevel >= 5) {
$officerLevelText = getOfficerLevelText(4, $nation['level']);
echo "
<tr><td colspan=5 align=center bgcolor=orange> </td></tr>
<tr>
<td colspan=3 align=right class='bg2'>{$officerLevelText} 임명</td>
<td colspan=2>
<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);
$region = 0;
foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 4)){
continue;
}
if($region != $city['region']) {
if($region != 0) {
echo "</optgroup>";
}
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region'];
}
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
}
echo "</optgroup>";
echo "
</select>
<select id='genlist_4' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>
";
foreach($candidateStrength as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='4' data-officer_level_text='{$officerLevelText}' value=임명>
</td>
</tr>";
$officerLevelText = getOfficerLevelText(3, $nation['level']);
echo "<tr>
<td colspan=3 align=right class='bg2'>{$officerLevelText} 임명</td>
<td colspan=2>
<select id='citylist_3' size=1 style=color:white;background-color:black;>
";
$region = 0;
foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 3)){
continue;
}
if($region != $city['region']) {
if($region != 0) {
echo "</optgroup>";
}
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region'];
}
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
}
echo "</optgroup>";
echo "
</select>
<select id='genlist_3' size=1 style=color:white;background-color:black;>
<option value=0 data-officer_level='0' data-name=''>____공석____</option>
";
foreach($candidateIntel as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='3' data-officer_level_text='{$officerLevelText}' value=임명>
</td>
</tr>";
$officerLevelText = getOfficerLevelText(2, $nation['level']);
echo "<tr>
<td colspan=3 align=right class='bg2'>{$officerLevelText} 임명</td>
<td colspan=2>
<select id='citylist_2' size=1 style=color:white;background-color:black;>
";
$region = 0;
foreach($cityList as $city){
if(isOfficerSet($city['officer_set'], 2)){
continue;
}
if($region != $city['region']) {
if($region != 0) {
echo "</optgroup>";
}
echo "<optgroup label=' 【 ".CityConst::$regionMap[$city['region']]." 】 ' style=color:skyblue;>";
$region = $city['region'];
}
echo "<option value='{$city['city']}' style=color:white;><span class='name_field'>{$city['name']}</span></option>";
}
echo "</optgroup>";
echo "
</select>
<select id='genlist_2' size=1 style=color:white;background-color:black;>
<option value=0>____<span class='name_field'>공석</span>____</option>
";
foreach ($candidateAny as $general) {
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>";
} 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>";
} 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 "
</select>
<input class='btn_appoint' type=$btn data-officer_level='2' data-officer_level_text='{$officerLevelText}' value=임명>
</td>
</tr>
<tr><td colspan=5> <font color=red>빨간색</font> 현재 임명중인 장수, <font color=orange>노란색</font> 다른 관직에 임명된 장수, 하얀색은 일반 장수를 뜻합니다.</td></tr>
";
}
echo "
<tr>
<td width=158 align=center class='bg1' colspan=2><font size=4> </font></td>
<td width=278 align=center class='bg1'><font size=4> (사관) 【현재도시】</font></td>
<td width=278 align=center class='bg1'><font size=4> (사관) 【현재도시】</font></td>
<td width=278 align=center class='bg1'><font size=4> (사관) 【현재도시】</font></td>
</tr>
";
$citylevel = getCityLevelList();
$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){
$officerCityID = $officer['officer_city'];
if(!key_exists($officerCityID, $officerList)){
$officerList[$officerCityID] = [];
}
$officerList[$officerCityID][$officer['officer_level']] = $officer;
}
$region = 0;
$dummyOfficer = [
'name'=>'-',
'belong'=>0,
];
$textColor = newColor($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) {
$cityID = $city['city'];
$cityOfficerList = $officerList[$cityID]??[];
?>
<?php if($region != $city['region']): ?>
<tr><td colspan=5 height=3 class='bg1'></td></tr>
<tr><td colspan=5 class='bg1'><font size=4 color=skyblue> <?=CityConst::$regionMap[$city['region']]?> 】 </font></td></tr>
<?php endif; $region = $city['region']; ?>
<tr>
<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>
<?php foreach(Util::range(4, 1, -1) as $officerLevel): ?>
<?php if(key_exists($officerLevel, $cityOfficerList)):
$officer = $cityOfficerList[$officerLevel];
?>
<td style="color:<?=isOfficerSet($city['officer_set'], $officerLevel)?'orange':'white'?>;"><?=$officer['name']?>(<?=$officer['belong']?>년) 【<?=CityConst::byID($officer['city'])->name?>】</td>
<?php else: ?>
<td>-</td>
<?php endif; ?>
<?php endforeach; ?>
</tr>
<?php
}
?>
<tr><td colspan=5> <font color=orange>노란색</font> 변경 불가능, 하얀색은 변경 가능 관직입니다.</td></tr>
</table>
<br>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?></td></tr>
</table>
</body>
</html>
+18 -22
View File
@@ -37,13 +37,10 @@ $sel = [$type => "selected"];
<title><?=UniqueConst::$serverName?>: 세력도시</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('../e_lib/jquery-ui.min.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery-ui.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/ext.expand_city.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/extExpandCity.js')?>
</head>
@@ -129,10 +126,10 @@ foreach($cityList as $city){
];
$cityOfficerList = $officerList[$cityID]??[];
foreach($cityOfficerList as $cityOfficer){
foreach($cityOfficerList as $cityOfficer){
$officerName[$cityOfficer['officer_level']] = getColoredName($cityOfficer['name'], $cityOfficer['npc']);
}
if ($type == 10 && $city['region'] != $region) {
echo "<br>";
$region = $city['region'];
@@ -151,41 +148,41 @@ foreach($cityList as $city){
<td colspan=12 style=color:".newColor($nation['color'])."; bgcolor={$nation['color']}><font size=2> ".CityConst::$regionMap[$city['region']]." | ".CityConst::$levelMap[$city['level']]." {$city['name']}</font></td>
</tr>
<tr>
<td align=center width=46 id=bg1>주민</td>
<td align=center width=46 class='bg1'>주민</td>
<td align=center width=140>{$city['pop']}/{$city['pop_max']}</td>
<td align=center width=46 id=bg1>농업</td>
<td align=center width=46 class='bg1'>농업</td>
<td align=center width=140>{$city['agri']}/{$city['agri_max']}</td>
<td align=center width=46 id=bg1>상업</td>
<td align=center width=46 class='bg1'>상업</td>
<td align=center width=140>{$city['comm']}/{$city['comm_max']}</td>
<td align=center width=46 id=bg1>치안</td>
<td align=center width=46 class='bg1'>치안</td>
<td align=center width=140>{$city['secu']}/{$city['secu_max']}</td>
<td align=center width=46 id=bg1>수비</td>
<td align=center width=46 class='bg1'>수비</td>
<td align=center width=140>{$city['def']}/{$city['def_max']}</td>
<td align=center width=46 id=bg1>성벽</td>
<td align=center width=46 class='bg1'>성벽</td>
<td align=center width=140>{$city['wall']}/{$city['wall_max']}</td>
</tr>
<tr>
<td align=center id=bg1>민심</td>
<td align=center class='bg1'>민심</td>
<td align=center>".round($city['trust'], 1)."</td>
<td align=center id=bg1>시세</td>
<td align=center class='bg1'>시세</td>
<td align=center>{$city['trade']}%</td>
<td align=center id=bg1>인구</td>
<td align=center class='bg1'>인구</td>
<td align=center>".round($city['pop']/$city['pop_max']*100, 2)." %</td>
<td align=center id=bg1>태수</td>
<td align=center class='bg1'>태수</td>
<td align=center>";
echo $officerName[4];
echo "</td>
<td align=center id=bg1>군사</td>
<td align=center class='bg1'>군사</td>
<td align=center>";
echo $officerName[3];
echo "</td>
<td align=center id=bg1>종사</td>
<td align=center class='bg1'>종사</td>
<td align=center>";
echo $officerName[2];
echo "</td>
</tr>
<tr>
<td align=center id=bg1>장수</td>
<td align=center class='bg1'>장수</td>
<td colspan=11>";
$generalList = $db->query('SELECT npc, name FROM general WHERE city = %i AND nation = %i', $city['city'], $me['nation']);
if (!$generalList) {
@@ -209,4 +206,3 @@ foreach($cityList as $city){
</body>
<div id="helper_genlist" style="display:none;"></div>
</html>
+18 -19
View File
@@ -47,9 +47,9 @@ if($gameStor->isunited){
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
</head>
@@ -104,21 +104,21 @@ $generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special
echo"
<table align=center class='tb_layout bg0'>
<tr>
<td width=64 align=center id=bg1> </td>
<td width=98 align=center id=bg1> </td>
<td width=78 align=center id=bg1> </td>
<td width=68 align=center id=bg1> </td>
<td width=68 align=center id=bg1> </td>
<td width=68 align=center id=bg1> </td>
<td width=48 align=center id=bg1>통솔</td>
<td width=48 align=center id=bg1>무력</td>
<td width=48 align=center id=bg1>지력</td>
<td width=68 align=center id=bg1> </td>
<td width=68 align=center id=bg1> </td>
<td width=48 align=center id=bg1> </td>
<td width=78 align=center id=bg1> </td>
<td width=48 align=center id=bg1> </td>
<td width=70 align=center id=bg1>벌점</td>
<td width=64 align=center class='bg1'> </td>
<td width=98 align=center class='bg1'> </td>
<td width=78 align=center class='bg1'> </td>
<td width=68 align=center class='bg1'> </td>
<td width=68 align=center class='bg1'> </td>
<td width=68 align=center class='bg1'> </td>
<td width=48 align=center class='bg1'>통솔</td>
<td width=48 align=center class='bg1'>무력</td>
<td width=48 align=center class='bg1'>지력</td>
<td width=68 align=center class='bg1'> </td>
<td width=68 align=center class='bg1'> </td>
<td width=48 align=center class='bg1'> </td>
<td width=78 align=center class='bg1'> </td>
<td width=48 align=center class='bg1'> </td>
<td width=70 align=center class='bg1'>벌점</td>
</tr>";
foreach($generalList as $general){
@@ -183,4 +183,3 @@ foreach($generalList as $general){
</body>
</html>
+23 -24
View File
@@ -27,9 +27,9 @@ if($nationID == 0) {
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 세력정보</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
@@ -96,57 +96,57 @@ if ($budgetricediff > 0) {
<td colspan=8 align=center style='color:<?=newColor($nation['color'])?>;background-color:<?=$nation['color']?>'><?=$nation['name']?>】</td>
</tr>
<tr>
<td width=98 align=center id=bg1>총주민</td>
<td width=98 align=center class='bg1'>총주민</td>
<td width=198 align=center><?=number_format($currPop)?>/<?=number_format($maxPop)?></td>
<td width=98 align=center id=bg1>총병사</td>
<td width=98 align=center class='bg1'>총병사</td>
<td width=198 align=center><?=number_format($currCrew)?>/<?=number_format($maxCrew)?></td>
<td width=98 align=center id=bg1> </td>
<td width=98 align=center class='bg1'> </td>
<td width=298 align=center colspan=3><?=$nation['power']?></td>
</tr>
<tr>
<td align=center id=bg1> </td>
<td align=center class='bg1'> </td>
<td align=center><?=number_format($nation['gold'])?></td>
<td align=center id=bg1> </td>
<td align=center class='bg1'> </td>
<td align=center><?=number_format($nation['rice'])?></td>
<td align=center id=bg1> </td>
<td align=center class='bg1'> </td>
<td align=center colspan=3><?=$nation['rate']?> %</td>
</td>
</tr>
<tr>
<td align=center id=bg1>세금/단기</td>
<td align=center class='bg1'>세금/단기</td>
<td align=center>+<?=number_format($goldIncome)?> / +<?=number_format($warIncome)?></td>
<td align=center id=bg1>세곡/둔전</td>
<td align=center class='bg1'>세곡/둔전</td>
<td align=center>+<?=number_format($riceIncome)?> / +<?=number_format($wallIncome)?></td>
<td align=center id=bg1>지급률</td>
<td align=center class='bg1'>지급률</td>
<td align=center colspan=3><?=$nation['bill']?> %</td>
</tr>
<tr>
<td align=center id=bg1>수입/지출</td>
<td align=center class='bg1'>수입/지출</td>
<td align=center>+<?=number_format($totalGoldIncome)?> / -<?=number_format($outcome)?></td>
<td align=center id=bg1>수입/지출</td>
<td align=center class='bg1'>수입/지출</td>
<td align=center>+<?=number_format($totalRiceIncome)?> / -<?=number_format($outcome)?></td>
<td align=center id=bg1> </td>
<td align=center class='bg1'> </td>
<td width=98 align=center><?=count($cityList)?></td>
<td width=98 align=center id=bg1> </td>
<td width=98 align=center class='bg1'> </td>
<td width=98 align=center><?=$nation['gennum']?></td>
</tr>
<tr>
<td align=center id=bg1>국고 예산</td>
<td align=center class='bg1'>국고 예산</td>
<td align=center><?=number_format($budgetgold)?> (<?=$budgetgolddiff?>)</td>
<td align=center id=bg1>병량 예산</td>
<td align=center class='bg1'>병량 예산</td>
<td align=center><?=number_format($budgetrice)?> (<?=$budgetricediff?>)</td>
<td align=center id=bg1>기술력</td>
<td align=center class='bg1'>기술력</td>
<td align=center><?=number_format(floor($nation['tech']))?></td>
<td align=center id=bg1> </td>
<td align=center class='bg1'> </td>
<td align=center><?=getNationLevel($nation['level'])?></td>
</tr>
<tr>
<td align=center valign=top id=bg1> 속령일람 :</td>
<td align=center valign=top class='bg1'> 속령일람 :</td>
<td colspan=7><?=join(', ', $cityNames)?></td>
</tr>
<tr>
<td align=center valign=top id=bg1>국가열전</td>
<td colspan=7 id=bg0><?=formatHistoryToHTML(getNationHistoryLogAll($nation['nation']))?></td>
<td align=center valign=top class='bg1'>국가열전</td>
<td colspan=7 class='bg0'><?=formatHistoryToHTML(getNationHistoryLogAll($nation['nation']))?></td>
</tr>
</table>
<br>
@@ -158,4 +158,3 @@ if ($budgetricediff > 0) {
</body>
</html>
+164 -212
View File
@@ -1,212 +1,164 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$btn = Util::getPost('btn');
$defence_train = Util::getPost('defence_train', 'int', 2);
$tnmt = Util::getPost('tnmt', 'int', 1);
//$detachNPC = Util::getPost('detachNPC', 'bool');
$detachNPC = false;
$showDieImmediatelyBtn = false;
$availableDieImmediately = false;
if ($defence_train <= 60) {
$defence_train = 60;
}
else if($defence_train <= 80){
$defence_train = 80;
}
else{
$defence_train = 999;
}
if($tnmt < 0 || $tnmt > 1){
$tnmt = 1;
}
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$generalID = $session->generalID;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("내정보", 1);
$me = General::createGeneralObjFromDB($generalID);
$myset = $me->getVar('myset');
if ($myset > 0) {
$submit = 'submit';
} else {
$submit = 'hidden';
}
if (($btn == "설정저장" || $detachNPC) && $myset > 0) {
if ($myset > 1) {
$submit = 'submit';
} else {
$submit = 'hidden';
}
if($defence_train != $me->getVar('defence_train')){
if($defence_train == 999){
$me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train);
$me->increaseVar('train', -3);
$me->increaseVar('atmos', -3);
}
else{
$me->increaseVar('myset', -1);
$me->setVar('defence_train', $defence_train);
}
$myset -= 1;
}
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);
if($gameStor->turntime <= $gameStor->opentime){
//서버 가오픈시 할 수 있는 행동
if($me->getNPCType() == 0){
$showDieImmediatelyBtn = true;
if(addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2) <= TimeUtil::now()){
$availableDieImmediately = true;
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 내정보</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/myPage.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<script>
var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>;
jQuery(function($){
$('#die_immediately').click(function(){
if(!availableDieImmediately){
alert('삭제를 위해서는 생성 후 2턴 가량의 시간이 필요합니다.');
location.reload();
return false;
}
return confirm('정말로 삭제하시겠습니까?');
});
});
</script>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=backButton()?></td></tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=50%>
<?php generalInfo($me); ?>
<?php generalInfo2($me); ?>
</td>
<td width=50% valign=top style="padding-left:4ch;">
<form name=form1 action=b_myPage.php method=post>
토너먼트
<input type=radio name=tnmt value=0 <?=$me->getVar('tnmt')==0?"checked":""; ?>>수동참여
<input type=radio name=tnmt value=1 <?=$me->getVar('tnmt')==1?"checked":""; ?>>자동참여
<br>
<font color=orange>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</font><br><br>
수비
<input type=radio name=defence_train value=80 <?=$me->getVar('defence_train')==80?"checked":""; ?>>◎(훈사80)
<input type=radio name=defence_train value=60 <?=$me->getVar('defence_train')==60?"checked":""; ?>>○(훈사60)
<input type=radio name=defence_train value=999 <?=$me->getVar('defence_train')==999?"checked":""; ?>>×
<br><br>
<input type=<?=$submit?> name=btn style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px; value=설정저장><br>
<font color=orange>설정저장은 이달중 <?=$myset?>회 남았습니다.</font><br><br>
</form>
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?>
<br>
<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>
<?php endif; ?>
<!--빙의 해제용 삭턴 조절<br>
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>빙의 해체 요청</button></a>-->
<?php if($showDieImmediatelyBtn): ?>
가오픈 기간 장수 삭제<br>
<a href="c_die_immediately.php" id='die_immediately'><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>장수 삭제</button></a><br><br>
<?php endif; ?>
개인용 CSS<br>
<textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea>
</td>
</tr>
<tr>
<td align=center id=bg1><font color=skyblue size=3>개인 기록</font></td>
<td align=center id=bg1><font color=orange size=3>전투 기록</font></td>
</tr>
<tr>
<td valign=top>
<div id='generalActionPlate'>
<?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?>
</div>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button>
</td>
<td valign=top>
<div id='battleDetailPlate'>
<?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?>
</div>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button>
</td>
</tr>
<tr>
<td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td>
<td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
</tr>
<tr>
<td valign=top>
<?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?>
</td>
<td valign=top>
<div id='battleResultPlate'>
<?=formatHistoryToHTML(getBattleResultRecent($generalID, 24), 'battleResult')?>
</div>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleResult">이전 로그 불러오기</button>
</td>
</tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?></td></tr>
</table>
</body>
</html>
<?php
namespace sammo;
include "lib.php";
include "func.php";
$showDieImmediatelyBtn = false;
$availableDieImmediately = false;
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$generalID = $session->generalID;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
increaseRefresh("내정보", 1);
$me = General::createGeneralObjFromDB($generalID);
$myset = $me->getVar('myset');
if ($myset > 0) {
$submit = 'button';
} else {
$submit = 'hidden';
}
$targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
if($gameStor->turntime <= $gameStor->opentime){
//서버 가오픈시 할 수 있는 행동
if($me->getNPCType() == 0){
$showDieImmediatelyBtn = true;
if($targetTime <= TimeUtil::now()){
$availableDieImmediately = true;
}
}
}
$use_treatment = $me->getAuxVar('use_treatment')??10;
$use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn')??1;
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 내정보</title>
<script>
var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>;
</script>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printJS('dist_js/myPage.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'>
<tr><td> <br><?=backButton()?></td></tr>
</table>
<table align=center width=1000 class='tb_layout bg0'>
<tr>
<td width=50%>
<?php generalInfo($me); ?>
<?php generalInfo2($me); ?>
</td>
<td width=50% valign=top style="padding-left:4ch;">
토너먼트
<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":""; ?>>자동참여
<br>
<span style='color:orange'>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</span><br><br>
환약 사용 <select id='use_treatment' name='use_treatment'>
<option value=10 <?=($use_treatment==10)?"selected":""; ?>>경상</option>
<option value=21 <?=($use_treatment==21)?"selected":""; ?>>중상</option>
<option value=41 <?=($use_treatment==41)?"selected":""; ?>>심각</option>
<option value=61 <?=($use_treatment==61)?"selected":""; ?>>위독</option>
<option value=100 <?=($use_treatment==100)?"selected":""; ?>>사용안함</option>
</select><br>
<span style='color:orange'>부상을 입었을 환약을 사용하는 기준입니다.</span><br><br>
<?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>
<option value=0 <?=(!$use_auto_nation_turn)?"selected":""; ?>>허용 안함</option>
</select><br>
<span style='color:orange'>수뇌가 되었을 휴식 턴이어도 적당한 턴을 알아서 넣는 것을 허용합니다.</span><br><br>
<?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>
</select>
<br><br>
<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>
<span style='color:orange'>설정저장은 이달중 <?=$myset?>회 남았습니다.</span><br><br>
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?>
<br>
<button type="button" id='vacation' style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button><br><br>
<?php endif; ?>
<!--빙의 해제용 삭턴 조절<br>
<a href="b_myPage.php?detachNPC=1"><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>빙의 해체 요청</button></a>-->
<?php if($showDieImmediatelyBtn): ?>
가오픈 기간 장수 삭제 (<?=substr($targetTime, 0, 19)?> 부터)<br>
<a href="c_die_immediately.php" id='die_immediately'><button type="button" style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>장수 삭제</button></a><br><br>
<?php endif; ?>
<?php if($gameStor->npcmode==2 && $me->getNPCType()==0): ?>
다른 장수 선택 (<?=substr($me->getAuxVar('next_change')??TimeUtil::now(), 0, 19)?> 부터)<br>
<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>
<?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 class='bg1'><font color=skyblue size=3>개인 기록</font></td>
<td align=center class='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 class='bg1'><font color=skyblue size=3>장수 열전</font></td>
<td align=center class='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>
-419
View File
@@ -1,419 +0,0 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['autorun_user', 'develcost']);
increaseRefresh("NPC 정책", 1);
$me = $db->queryFirstRow('SELECT no, npc, nation, city, officer_level, con, turntime, belong, permission, penalty FROM general WHERE owner=%i', $userID);
$nationID = $me['nation'];
$nation = $db->queryFirstRow('SELECT nation,level,name,color,type,gold,rice,bill,tech,rate,scout,war,secretlimit,capital FROM nation WHERE nation = %i', $nationID);
$con = checkLimit($me['con']);
if ($con >= 2) {
printLimitMsg($me['turntime']);
exit();
}
$permission = checkSecretPermission($me);
if ($permission < 0) {
echo '국가에 소속되어있지 않습니다.';
die();
} else if ($permission < 1) {
echo "권한이 부족합니다. 수뇌부가 아니거나 사관년도가 부족합니다.";
die();
}
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheValues(['npc_nation_policy', 'npc_general_policy']);
$gameStor->cacheAll();
$general = new General($me, null, null, $nation, $gameStor->year, $gameStor->month, false);
$rawServerPolicy = $gameStor->getValue('npc_nation_policy') ?? [];
$rawNationPolicy = $nationStor->getValue('npc_nation_policy') ?? [];
$rawServerGeneralPolicy = $gameStor->getValue('npc_general_policy') ?? [];
$rawNationGeneralPolicy = $nationStor->getValue('npc_general_policy') ?? [];
$defaultNationPolicy = ($rawServerPolicy['values'] ?? []) + AutorunNationPolicy::$defaultPolicy;
$currentNationPolicy = ($rawNationPolicy['values'] ?? []) + $defaultNationPolicy;
$defaultNationPriority = $rawServerPolicy['priority'] ?? (AutorunNationPolicy::$defaultPriority);
$currentNationPriority = $rawNationPolicy['priority'] ?? $defaultNationPriority;
$defaultGeneralActionPriority = $rawServerGeneralPolicy['priority'] ?? (AutorunGeneralPolicy::$default_priority);
$currentGeneralActionPriority = $rawNationGeneralPolicy['priority'] ?? $defaultGeneralActionPriority;
$autoPolicyVariable = [];
if ($currentNationPolicy['reqHumanWarUrgentRice'] ?? 0) {
$autoPolicyVariable['reqHumanWarUrgentRice'] = $currentNationPolicy['reqHumanWarUrgentRice'];
}
if ($currentNationPolicy['reqHumanWarUrgentGold'] ?? 0) {
$autoPolicyVariable['reqHumanWarUrgentGold'] = $currentNationPolicy['reqHumanWarUrgentGold'];
}
$autoPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['options'], ['values' => $autoPolicyVariable], null, $nation, $gameStor->getAll(true));
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?= UniqueConst::$serverName ?>: 임시 NPC 정책</title>
<script>
var nationID = <?= $nationID ?>;
var defaultNationPolicy = <?= Json::encode($defaultNationPolicy) ?>;
var currentNationPolicy = <?= Json::encode($currentNationPolicy) ?>;
var defaultNationPriority = <?= Json::encode($defaultNationPriority) ?>;
var currentNationPriority = <?= Json::encode($currentNationPriority) ?>;
var availableNationPriorityItems = <?= Json::encode(AutorunNationPolicy::$defaultPriority) ?>;
var defaultGeneralActionPriority = <?= Json::encode($defaultGeneralActionPriority) ?>;
var currentGeneralActionPriority = <?= Json::encode($currentGeneralActionPriority) ?>;
var availableGeneralActionPriorityItems = <?= Json::encode(AutorunGeneralPolicy::$default_priority) ?>;
var btnHelpMessage = {
'선전포고': '군주가 NPC이고, 전쟁중이 아닐 때,<br>주변국중 하나를 골라 선포합니다.<br><br>선포 시점은 다음을 참고합니다.<br>- 인구율<br>- 도시내정률<br>- NPC전투장권장 금 충족률<br>- NPC전투장권장 쌀 충족률<br><br>국력이 낮은 국가를 조금 더 선호합니다.',
'천도': '인구가 많은 곳을 찾아 천도를 시도합니다.<br>영토의 가운데를 선호합니다.<br><br>도시 인구가 충분하다면, 굳이 천도하지는 않습니다.',
'유저장긴급포상': '금/쌀이 부족한 유저전투장에게 긴급하게 포상합니다.<br>국고가 권장량보다 적어지더라도 시도합니다.',
'부대전방발령': '(작동하지 않음)<br>전투 부대를 접경으로 발령합니다.<br>수도->시작점->도착점 경로를 따릅니다.',
'유저장구출발령': '아군 영토에 있지 않은 유저장을 아군 영토로 발령합니다.<br>곧 집합하는 부대에 탑승한 경우는 제외합니다.',
'유저장후방발령': '유저전투장 중에<br>- 병력이 충분하지 않고,<br>- 도시의 인구가 제자리 징병할 수 있을 정도로 충분하지 않고,<br>- 부대에 탑승하지 않았다면,<br>인구가 충분한 후방도시로 발령합니다.',
'부대유저장후방발령': '접경에 위치한 부대에 탑승한 유저전투장 중에,<br>- 병력이 충분하지 않고,<br>- 첫 턴이 징병턴이며,<br>- 부대장 집합 턴 사이라면,<br>인구가 충분한 후방도시로 발령합니다.<br><br>부대장의 위치와 유저장의 위치가 다르다면 발령하지 않습니다.',
'유저장전방발령': '후방에 있는 유저장이<br>- 병력을 가지고 있으며,<br>- 곧 훈련/사기진작이 완료될 것 같으면,<br>전방으로 발령합니다.<br><br>도시 관직이 많이 임명된 도시를 선호합니다.',
'유저장포상': '금/쌀이 부족한 유저장에게 포상합니다.<br>유저전투장과 유저내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.',
'부대후방발령': '(작동하지 않음)<br>후방 부대가 위치한 도시의 인구가 충분하지 않을 경우,<br>인구가 충분한 도시로 발령합니다.',
'부대구출발령': '전투 부대, 후방 부대가 아닌 부대가 아군 영토에 있지 않을 때,<br>전방 도시 중 하나를 골라 발령합니다.',
'NPC긴급포상': '금/쌀이 부족한 NPC전투장에게 긴급하게 포상합니다.<br>국고가 권장량보다 \'약간\' 적어지더라도 시도합니다.',
'NPC구출발령': '아군 영토에 있지 않은 NPC장을 아군 영토로 발령합니다.',
'NPC후방발령': 'NPC전투장 중에<br>- 병력이 충분하지 않고,<br>- 도시의 인구가 제자리 징병할 수 있을 정도로 충분하지 않고,<br>- 부대에 탑승하지 않았다면,<br>인구가 충분한 후방도시로 발령합니다.',
'NPC포상': '금/쌀이 부족한 유저장에게 포상합니다.<br>NPC전투장과 NPC내정장은 각각 기준을 따릅니다.<br>국고 권장량을 가급적 지킵니다.',
'NPC전방발령': '후방에 있는 유저장이<br>- 병력을 가지고 있으며,<br>- 곧 훈련/사기진작이 완료될 것 같으면,<br>전방으로 발령합니다.<br><br>도시 관직이 많이 임명된 도시를 선호합니다.',
'유저장내정발령': '내정중인 유저장이 위치한 도시의 내정률이 95% 이상이면<br>개발되지 않은 도시로 발령합니다.',
'NPC내정발령': '내정중인 NPC장이 위치한 도시의 내정률이 95% 이상이면<br>개발되지 않은 도시로 발령합니다.',
'NPC몰수': '국고가 부족하다면 NPC에게서 몰수합니다. 내정NPC장은 국고가 부족하지 않아도 몰수합니다.',
'NPC사망대비': 'NPC의 사망까지 5턴 이내인 경우, 헌납합니다.<br>헌납할 금쌀이 없다면 물자조달을 수행합니다.',
'귀환': '아국 도시에 있지 않다면 귀환합니다.',
'금쌀구매': '전쟁 중에 금쌀의 비율이 크게 차이난다면 금쌀을 거래하여 비슷하게 맞춥니다.<br>금쌀 비율이 적절하는지 판단하는데 살상률을 포함합니다.<br>NPC는 상인이 없어도 금쌀을 구매할 수 있습니다.<br><br>또는 금쌀 한쪽이 지나치게 적은 경우에는 내정 중에도 금쌀을 거래합니다.',
'출병': '충분한 병력과 충분한 훈련/사기를 가지고 있는 경우 출병합니다.<br>접경이 여럿인 경우 무작위로 선택합니다.<br><br>타국과 전쟁중인 경우 공백지로는 출병하지 않습니다.',
'긴급내정': '전쟁중에 민심이 70 미만이거나,<br>인구가 제자리 징병이 가능하지 않을 정도로 적을 경우,<br>일정확률로 주민선정과 정착장려를 수행합니다.<br><br>통솔이 높을 수록 수행할 확률이 높습니다.',
'전투준비': '충분한 병력을 가지고 있지만 훈련과 사기가 부족한 경우 훈련과 사기진작을 수행합니다.',
'전방워프': '전투장이 충분한 병력을 가지고 있다면 전방으로 이동합니다.',
'NPC헌납': '국고가 부족한데 NPC장수가 충분한 금쌀을 가지고 있다면 일부를 헌납합니다. <br>NPC내정장은 국고가 넉넉하더라도 충분한 금쌀을 가지고 있다면 일부를 헌납합니다.',
'징병': '전쟁 중 병력을 소진하였다면 재 징병합니다.<br><br>기존에 사용한 병종군 중에서 사용가능한 병종을 랜덤하게 선택합니다.<br>고급 병종을 선택할 확률이 조금 더 높습니다.<br><br>NPC의 경우 도시의 인구가 충분하지 않다면 징병을 할 확률이 감소합니다.<br><br>유저장은 최대한 고급병종을 유지하며,<br>유저장 모병이 허용되는 경우 모병을 3회할 수 있다면 모병합니다.',
'후방워프': '전쟁 중 병력을 소진하였는데 도시의 인구가 충분하지 않다면,<br>인구가 많은 도시로 이동합니다.',
'전쟁내정': '전쟁 중 수행하는 내정입니다.<br>정착장려, 기술연구의 확률이 좀 더 높고,<br>치안강화, 농지개간, 상업투자의 확률이 낮습니다.<br><br>내정이 가능하다 하더라도 전시임을 고려해,<br>30% 확률로 다른 턴을 수행합니다.',
'소집해제': '전쟁 중이 아닌 데 병력이 남아있는 경우,<br>3/4 확률로 소집해제합니다.',
'일반내정': '도시에서 내정을 수행합니다. 낮은 내정일 수록 수행할 확률이 높습니다.<br>기술 연구는 1등급 이상 뒤쳐지지 않도록 노력합니다.',
'내정워프': '도시에서 더이상 내정을 수행할 수 없는 경우,<br>일정확률로 내정이 부족한 다른 도시로 이동합니다.',
};
</script>
<?= WebUtil::printJS('../e_lib/jquery-3.3.1.min.js') ?>
<?= WebUtil::printJS('../e_lib/Sortable.min.js') ?>
<?= WebUtil::printJS('../e_lib/jquery-sortable.js') ?>
<?= WebUtil::printJS('../e_lib/bootstrap.bundle.min.js') ?>
<?= WebUtil::printJS('../e_lib/jquery_toast/toast.js') ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= WebUtil::printJS('js/common.js') ?>
<?= WebUtil::printJS('js/npc_control.js') ?>
<?= WebUtil::printCSS('../e_lib/bootstrap.min.css') ?>
<?= WebUtil::printCSS('../e_lib/font_awesome/css/all.min.css') ?>
<?= WebUtil::printCSS('../e_lib/jquery_toast/toast.css') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('css/common.css') ?>
<?= WebUtil::printCSS('css/npc_control.css') ?>
</head>
<body>
<div id='container' class='tb_layout bg0' style='width:1000px;margin:auto;border:solid 1px #888888;'>
<div class='tb_layout bg0'>임시 NPC 정책<br>
<?= backButton() ?></div>
<div class='bg1 section_bar'>국가 정책</div>
<div class="text-right px-3"><small class="form-text text-muted">
최근 설정: <?= $rawNationPolicy['valueSetter'] ?? '-없음-' ?> (<?= $rawNationPolicy['valueSetTime'] ?? '설정 기록 없음' ?>)
</small></div>
<div class="form_list">
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="reqNationGold" class="col-sm-6 col-form-label">국가 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqNationGold" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">이보다 많으면 포상, 적으면 몰수/헌납합니다.(긴급포상 제외)</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="reqNationRice" class="col-sm-6 col-form-label">국가 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqNationRice" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">이보다 많으면 포상, 적으면 몰수/헌납합니다.(긴급포상 제외)</small></div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="reqHumanWarUrgentGold" class="col-sm-6 col-form-label">유저전투장 긴급포상 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqHumanWarUrgentGold" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">
유저장긴급포상시 이보다 금이 적은 장수에게 포상합니다.<br>
0이면 보병 6 징병(<?= number_format(GameConst::$defaultStatMax * 100) ?> * 6) 가능한 금을 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqHumanWarUrgentGold) ?>입니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="reqHumanWarUrgentRice" class="col-sm-6 col-form-label">유저전투장 긴급포상 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqHumanWarUrgentRice" min="0" value="0">
</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>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="reqHumanWarRecommandGold" class="col-sm-6 col-form-label">유저전투장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqHumanWarRecommandGold" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">유저전투장에게 주는 금입니다. 이보다 적으면 포상합니다. <br>
0이면 유저전투장 긴급포상 금의 3배를 기준으로 하며, 수치는 현재 <?= number_format($autoPolicy->reqHumanWarRecommandGold) ?>입니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="reqHumanWarRecommandRice" class="col-sm-6 col-form-label">유저전투장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqHumanWarRecommandRice" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">유저전투장에게 주는 쌀입니다. 이보다 적으면 포상합니다. <br>
0이면 유저전투장 긴급포상 쌀의 3배를 기준으로 하며, 수치는 현재 <?= number_format($autoPolicy->reqHumanWarRecommandRice) ?>입니다.</small></div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="reqHumanDevelGold" class="col-sm-6 col-form-label">유저내정장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqHumanDevelGold" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">유저내정장에게 주는 금입니다. 이보다 적으면 포상합니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="reqHumanDevelRice" class="col-sm-6 col-form-label">유저내정장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqHumanDevelRice" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">유저내정장에게 주는 쌀입니다. 이보다 적으면 포상합니다.</small></div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="reqNPCWarGold" class="col-sm-6 col-form-label">NPC전투장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqNPCWarGold" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">NPC전투장에게 주는 금입니다. 이보다 적으면 포상합니다. <br>
0이면 기본 병종 4(<?= number_format(GameConst::$defaultStatNPCMax * 100) ?> * 4) 징병비를 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqNPCWarGold) ?>입니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="reqNPCWarRice" class="col-sm-6 col-form-label">NPC전투장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqNPCWarRice" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">NPC전투장에게 주는 쌀입니다. 이보다 적으면 포상합니다. <br>
0이면 기본 병종으로 <?= number_format(GameConst::$defaultStatNPCMax * 100 * 4) ?>명 사살 가능한 쌀을 기준으로 하며, 그 수치는 현재 <?= number_format($autoPolicy->reqNPCWarRice) ?>입니다.</small></div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="reqNPCDevelGold" class="col-sm-6 col-form-label">NPC내정장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqNPCDevelGold" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">NPC내정장에게 주는 금입니다. 이보다 5 많다면 헌납합니다.<br>0이면 30 내정 가능한 금을 기준으로 하며, 수치는 현재 <?= number_format($autoPolicy->reqNPCDevelGold) ?>입니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="reqNPCDevelRice" class="col-sm-6 col-form-label">NPC내정장 권장 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="reqNPCDevelRice" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">NPC내정장에게 주는 쌀입니다. 이보다 5 많다면 헌납합니다.</small></div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="minimumResourceActionAmount" class="col-sm-6 col-form-label">포상/몰수/헌납// 최소 단위</label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="minimumResourceActionAmount" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">연산결과가 단위보다 적다면 수행하지 않습니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="minWarCrew" class="col-sm-6 col-form-label">최소 전투 가능 병력 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="minWarCrew" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">이보다 적을 때에는 징병을 시도합니다.</small></div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="minNPCRecruitCityPopulation" class="col-sm-6 col-form-label">NPC 최소 징병 가능 인구 </label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="minNPCRecruitCityPopulation" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">이보다 낮으면 NPC는 도시에서 징병하지 않고 후방 워프합니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="safeRecruitCityPopulationRatio" class="col-sm-6 col-form-label">제자리 징병 허용 인구율(%)</label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="percent" id="safeRecruitCityPopulationRatio" min="0" max="100" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">전쟁 후방 발령, 후방 워프의 기준 인구입니다. 이보다 많다면 '충분하다' 판단합니다.</small></div>
</div>
</div>
<div class="form-group row">
<div class="col-sm-6">
<div class="row">
<label for="minNPCWarLeadership" class="col-sm-6 col-form-label">NPC 전투 참여 통솔 기준</label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="minNPCWarLeadership" min="0" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted"> 수치보다 같거나 높으면 NPC전투장으로 분류됩니다.</small></div>
</div>
<div class="col-sm-6">
<div class="row">
<label for="properWarTrainAtmos" class="col-sm-6 col-form-label">훈련/사기진작 목표치</label>
<div class="col-sm-6">
<input type="number" class="form-control" data-type="integer" id="properWarTrainAtmos" min="0" max="100" value="0">
</div>
</div>
<div style='text-align:right;'><small class="form-text text-muted">훈련/사기진작 기준치입니다. 이보다 같거나 높으면 출병합니다.</small></div>
</div>
</div>
<div class="alert alert-secondary">
전투 부대는 작업중입니다(json양식: {부대번호:[시작도시번호(아국),도착도시번호(적군)],...})<br>
후방 징병 부대는 작업중입니다(json양식: [부대번호,...])<br>
내정 부대는 작업중입니다(json양식: [부대번호,...])
<input type="hidden" value="{}" data-type="json" id="CombatForce">
<input type="hidden" value="[]" data-type="json" id="SupportForce">
<input type="hidden" value="[]" data-type="json" id="DevelopForce">
<input type="hidden" value="true" data-type="json" id="allowNpcAttackCity">
<!--allowNpcAttackCity는 현재 게임 비활성-->
</div>
<div class='control_bar' data-type="nationPolicy">
<div class="btn-group" role="group">
<button type="button" class="btn btn-dark reset_btn">초기값으로</button>
<button type="button" class="btn btn-secondary revert_btn">이전값으로</button>
</div><button type="button" class="btn btn-primary submit_btn">설정</button>
</div>
</div>
<div class="row">
<div class="col-sm-6 half_section_left">
<div class='bg1 section_bar'>NPC 사령턴 우선순위</div>
<div class="float-right px-3"><small class="form-text text-muted">
최근 설정: <?= $rawNationPolicy['prioritySetter'] ?? '-없음-' ?> (<?= $rawNationPolicy['prioritySetTime'] ?? '설정 기록 없음' ?>)
</small></div>
<div class='text-left px-2'><small class="text-muted">예턴이 없거나, 지정되어 있더라도 실패할경우<br>아래 순위에 따라 사령턴을 시도합니다.</small></div>
<div class="form_list">
<div class="row">
<div class="col-sm-6">
<div class="bg2 sub_bar">비활성</div>
<div id="nationPriorityDisabled" class="list-group col" data-type="list">
</div>
</div>
<div class="col-sm-6">
<div class="bg2 sub_bar">활성</div>
<div id="nationPriority" class="list-group col" data-type="list">
</div>
</div>
</div>
<div class='control_bar' data-type="nationPriority">
<div class="btn-group" role="group">
<button type="button" class="btn btn-dark reset_btn">초기값으로</button>
<button type="button" class="btn btn-secondary revert_btn">이전값으로</button>
</div><button type="button" class="btn btn-primary submit_btn">설정</button>
</div>
</div>
</div>
<div class="col-sm-6 half_section_right">
<div class='bg1 section_bar'>NPC 일반턴 우선순위</div>
<div class="float-right px-3"><small class="form-text text-muted">
최근 설정: <?= $rawNationGeneralPolicy['prioritySetter'] ?? '-없음-' ?> (<?= $rawNationGeneralPolicy['prioritySetTime'] ?? '설정 기록 없음' ?>)
</small></div>
<div class='text-left px-2'><small class="text-muted">순위가 높은 것부터 시도합니다. <br>아무것도 실행할 없으면 물자조달이나 인재탐색을 합니다.</small></div>
<div class="form_list">
<div class="row">
<div class="col-sm-6">
<div class="bg2 sub_bar">비활성</div>
<div id="generalPriorityDisabled" class="list-group col" data-type="list">
</div>
</div>
<div class="col-sm-6">
<div class="bg2 sub_bar">활성</div>
<div id="generalPriority" class="list-group col" data-type="list">
</div>
</div>
</div>
<div class='control_bar' data-type="generalPriority">
<div class="btn-group" role="group">
<button type="button" class="btn btn-dark reset_btn">초기값으로</button>
<button type="button" class="btn btn-secondary revert_btn">이전값으로</button>
</div><button type="button" class="btn btn-primary submit_btn">설정</button>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+125 -127
View File
@@ -1,127 +1,125 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$commandType = Util::getReq('command', 'string');
$turnList = array_map('intval', explode('_', Util::getReq('turnList', 'string', '0')));
$isChiefTurn = Util::getReq('is_chief', 'bool', false);
function die_redirect()
{
global $isChiefTurn;
if(!$isChiefTurn){
header('location:index.php', true, 303);
}
else{
header('location:b_chiefcenter.php', true, 303);
}
die();
}
if(!$turnList || !$commandType){
die_redirect();
}
if(!is_array($turnList)){
die_redirect();
}
$session = Session::requireGameLogin()->setReadOnly();
$db = DB::db();
if(!$isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableGeneralCommand))){
die_redirect();
}
if($isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableChiefCommand))){
die_redirect();
}
$gameStor = KVStorage::getStorage($db, 'game_env')->turnOnCache();
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($session->generalID);
if(!$isChiefTurn){
$commandObj = buildGeneralCommandClass($commandType, $general, $env);
}
else{
if($general->getVar('officer_level') < 5){
die_redirect();
}
$commandObj = buildNationCommandClass($commandType, $general, $env, new LastTurn());
}
if($commandObj->isArgValid()){
//인자가 필요없는 타입의 경우 processing에서 '전혀' 처리하지 않음!
die_redirect();
}
if(!$commandObj->hasPermissionToReserve()){
die_redirect();
}
$jsList = $commandObj->getJSFiles();
$cssList = $commandObj->getCSSFiles();
?>
<!DOCTYPE html>
<html>
<head>
<title><?=$commandObj->getName()?></title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<?=WebUtil::printJS('js/processing.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
window.command = '<?=$commandType?>';
window.turnList = [<?=join(', ',$turnList)?>];
window.isChiefTurn = <?=$isChiefTurn?'true':'false'?>;
</script>
<?php
foreach($jsList as $js){
print(WebUtil::printJS($js));
}
?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/main.css')?>
<?=WebUtil::printCSS('css/map.css')?>
<?php
foreach($cssList as $css){
print(WebUtil::printCSS($css));
}
?>
</head>
<body class="img_back">
<table class="tb_layout bg0" style="width:1000px;margin:auto;">
<tr><td class="bg1" style='text-align:center;'><?=$commandObj->getName()?></td></tr>
<tr><td>
<input type=button value='돌아가기' onclick="history.back();"><br>
</td></tr></table>
<div class="tb_layout bg0" style="width:1000px;margin:auto;padding-bottom:2em;border:solid 1px gray;">
<?=$commandObj->getForm()?>
</div>
<table class="tb_layout bg0" style="width:1000px;margin:auto;">
<tr><td>
<input type=button value='돌아가기' onclick="history.back();"><br>
<?=banner()?>
</td></tr></table>
</body>
</html>
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$commandType = Util::getReq('command', 'string');
$turnList = array_map('intval', explode('_', Util::getReq('turnList', 'string', '0')));
$isChiefTurn = Util::getReq('is_chief', 'bool', false);
function die_redirect()
{
global $isChiefTurn;
if(!$isChiefTurn){
header('location:index.php', true, 303);
}
else{
header('location:b_chiefcenter.php', true, 303);
}
die();
}
if(!$turnList || !$commandType){
die_redirect();
}
if(!is_array($turnList)){
die_redirect();
}
$session = Session::requireGameLogin()->setReadOnly();
$db = DB::db();
if(!$isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableGeneralCommand))){
die_redirect();
}
if($isChiefTurn && !in_array($commandType, Util::array_flatten(GameConst::$availableChiefCommand))){
die_redirect();
}
$gameStor = KVStorage::getStorage($db, 'game_env')->turnOnCache();
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($session->generalID);
if(!$isChiefTurn){
$commandObj = buildGeneralCommandClass($commandType, $general, $env);
}
else{
if($general->getVar('officer_level') < 5){
die_redirect();
}
$commandObj = buildNationCommandClass($commandType, $general, $env, new LastTurn());
}
if($commandObj->isArgValid()){
//인자가 필요없는 타입의 경우 processing에서 '전혀' 처리하지 않음!
die_redirect();
}
if(!$commandObj->hasPermissionToReserve()){
die_redirect();
}
$jsList = $commandObj->getJSPlugins();
$cssList = $commandObj->getCSSFiles();
?>
<!DOCTYPE html>
<html>
<head>
<title><?=$commandObj->getName()?></title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('dist_js/processing.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
window.command = '<?=$commandType?>';
window.turnList = [<?=join(', ',$turnList)?>];
window.isChiefTurn = <?=$isChiefTurn?'true':'false'?>;
var jsPlugins = <?=Json::encode($jsList)?>;
</script>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2.min.css')?>
<?=WebUtil::printCSS('../e_lib/select2/select2-bootstrap4.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/main.css')?>
<?=WebUtil::printCSS('css/map.css')?>
<?=WebUtil::printCSS('css/processing.css')?>
<?php
foreach($cssList as $css){
print(WebUtil::printCSS($css));
}
?>
</head>
<body class="img_back">
<table class="tb_layout bg0" style="width:1000px;margin:auto;">
<tr><td class="bg1" style='text-align:center;'><?=$commandObj->getName()?></td></tr>
<tr><td>
<input type=button value='돌아가기' onclick="history.back();"><br>
</td></tr></table>
<div class="tb_layout bg0" style="width:1000px;margin:auto;padding-bottom:2em;border:solid 1px gray;">
<?=$commandObj->getForm()?>
</div>
<table class="tb_layout bg0" style="width:1000px;margin:auto;">
<tr><td>
<input type=button value='돌아가기' onclick="history.back();"><br>
<?=banner()?>
</td></tr></table>
</body>
</html>
+5 -5
View File
@@ -145,7 +145,7 @@ if($str3){
?>
<tr><td colspan=8>운영자 메세지 : <font color=orange size=5><?=$admin['tnmt_msg']?></font></td></tr>
<tr><td colspan=8 align=center><font color=white size=6><?=$tnmt_type?> (<?=$str1.$str2.$str3?>)</font></td></tr>
<tr><td colspan=8 align=center id=bg2><font color=magenta size=5>16 승자전</font></td></tr>
<tr><td colspan=8 align=center class='bg2'><font color=magenta size=5>16 승자전</font></td></tr>
<tr><td height=10 colspan=8 align=center></td></tr>
<?php
@@ -398,7 +398,7 @@ if ($admin['tournament'] >= 7 || $admin['tournament'] == 0) {
}
echo "
<tr><td height=10 colspan=8 align=center></td></tr>
<tr><td colspan=8 align=center id=bg2><font color=orange size=5>조별 본선 순위</font></td></tr>
<tr><td colspan=8 align=center class='bg2'><font color=orange size=5>조별 본선 순위</font></td></tr>
<tr>";
$num = array("", "", "", "", "", "", "", "");
@@ -409,7 +409,7 @@ for ($i=0; $i < 8; $i++) {
<td>
<table align=center width=250 class='tb_layout bg0'>
<tr><td colspan=9 style=background-color:black;>{$num[$i]}</td></tr>
<tr id=bg1><td align=center></td><td align=center>장수</td><td align=center>{$tp2}</td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td></tr>";
<tr class='bg1'><td align=center></td><td align=center>장수</td><td align=center>{$tp2}</td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td></tr>";
$generalList = $db->query('SELECT npc,name,leadership,strength,intel,leadership+strength+intel as total,prmt,win+draw+lose as game,win,draw,lose,gl,win*3+draw as gd from tournament where grp=%i order by gd desc, gl desc, seq',$grp);
foreach($generalList as $k=>$general) {
@@ -427,7 +427,7 @@ if ($admin['tournament'] == 4 || $admin['tournament'] == 5) {
printFighting($admin['tournament'], $admin['phase']);
}
echo "
<tr><td colspan=8 align=center id=bg2><font color=yellow size=5>조별 예선 순위</font></td></tr>
<tr><td colspan=8 align=center class='bg2'><font color=yellow size=5>조별 예선 순위</font></td></tr>
<tr>";
for ($i=0; $i < 8; $i++) {
@@ -436,7 +436,7 @@ for ($i=0; $i < 8; $i++) {
<td>
<table align=center width=250 class='tb_layout bg0'>
<tr><td colspan=9 style=background-color:black;>{$num[$i]}</td></tr>
<tr id=bg1><td align=center></td><td align=center>장수</td><td align=center>{$tp2}</td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td></tr>";
<tr class='bg1'><td align=center></td><td align=center>장수</td><td align=center>{$tp2}</td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td><td align=center></td></tr>";
$generalList = $db->query('SELECT npc,name,leadership,strength,intel,leadership+strength+intel as total,prmt,win+draw+lose as game,win,draw,lose,gl,win*3+draw as gd from tournament where grp=%i order by gd desc, gl desc, seq',$grp);
foreach($generalList as $k=>$general) {
+10 -11
View File
@@ -44,7 +44,7 @@ if($troops){
$generalTurnList = [];
foreach($db->queryAllLists(
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
'SELECT general_id, turn_idx, brief FROM general_turn WHERE general_id IN %li AND turn_idx < 5 ORDER BY general_id ASC, turn_idx ASC',
array_column($troopLeaders, 'no')
) as [$generalID, $turnIdx, $brief]
){
@@ -53,10 +53,10 @@ if($troops){
}
$generalTurnList[$generalID][$turnIdx] = $brief;
}
foreach($troopLeaders as $troopLeader){
$imageTemp = GetImageURL($troopLeader['imgsvr']);
$troopLeader['pictureFullPath'] = "$imageTemp/{$troopLeader['picture']}";
$troopLeader['cityText'] = CityConst::byID($troopLeader['city'])->name;
@@ -85,15 +85,14 @@ uasort($troops, function($lhs, $rhs){
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 부대편성</title>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/troop.js')?>
<?=WebUtil::printJS('js/ext.plugin_troop.js')?>
<?=WebUtil::preloadJS('dist_js/troop.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/troops.css')?>
<?=WebUtil::printCSS('dist_css/troop.css')?>
<script>
</script>
@@ -195,7 +194,7 @@ foreach ($troops as $troopNo=>$troop) {
<br>
<table width=1000 class='tb_layout bg0'>
<tr>
<td width=80 id=bg1> </td>
<td width=80 class='bg1'> </td>
<td width=130><input type=text style=color:white;background-color:black; size=18 maxlength=18 id='nameplate'></td>
<?php if($me['troop'] == 0): ?>
<td><input type=button id='btnCreateTroop' value='부 대 창 설'></td>
@@ -210,6 +209,6 @@ foreach ($troops as $troopNo=>$troop) {
<tr><td><?=banner()?> </td></tr>
</table>
</div>
<?=WebUtil::printJS('dist_js/troop.js')?>
</body>
</html>
+547 -480
View File
@@ -1,481 +1,548 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
$session = Session::requireLogin()->setReadOnly();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->getValue('startyear');
?>
<!DOCTYPE html>
<html>
<head>
<title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1100" />
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/battle_simulator.css')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/moment.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/download2.js')?>
<?=WebUtil::printJS('js/common.js')?>
<script>
var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
</script>
<?=WebUtil::printJS('js/battle_simulator.js')?>
</head>
<body>
<div id="container">
<div class="card mb-3">
<div class="card-header">
전역 설정
</div>
<div class="card-body dragpad_battle">
<div class="row">
<div class="col-sm-6">
<div class="input-group">
<input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled>
<div class="input-group-append">
<span class="input-group-text"> 시작</span>
</div>
<input type="number" class="form-control" id="year" value="<?=$startYear+3?>" min="<?=$startYear?>">
<div class="input-group-append">
<span class="input-group-text"></span>
</div>
<input type="number" class="form-control" id="month" value="1" min="1" max="12">
<div class="input-group-append">
<span class="input-group-text"></span>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="btn-toolbar" role="toolbar">
<div class="input-group mr-2" role="group">
<div class="input-group-prepend">
<span class="input-group-text">반복 횟수</span>
</div>
<select class="custom-select" id="repeat_cnt">
<option value="1">1 (로그 표기)</option>
<option value="1000">1000 (요약 표기)</option>
</select>
</div>
<div class="btn-group mr-2" role="group">
<button type="button" class="btn btn-danger btn-begin_battle">전투</button>
</div>
<div class="btn-group mr-2" role="group">
<button type="button" class="btn btn-info btn-battle-save">모두 저장</button>
<input type="file" class="form_load_battle_file" accept=".json" style="display: none;" />
<button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="card mb-2 attacker_nation">
<div class="card-header">
출병국 설정
</div>
<div class="card-body nation_detail dragpad_battle">
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">국가 성향</span>
</div>
<select class="custom-select form_nation_type" style="width:25ch;">
<?php foreach(GameConst::$availableNationType as $typeID): ?>
<?php $nationTypeClass = buildNationTypeClass($typeID) ?>
<option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">기술</span>
</div>
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
<div class="input-group-append">
<span class="input-group-text">등급</span>
</div>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">국가 규모</span>
</div>
<select class="custom-select form_nation_level">
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
<option value="<?=$nationLevel?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">도시 규모</span>
</div>
<select class="custom-select form_city_level">
<?php foreach(getCityLevelList() as $levelID => $name): ?>
<option value="<?=$levelID?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">수도</span>
</div>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y
</label>
<label class="btn btn-secondary active">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="2" autocomplete="off" checked>N
</label>
</div>
</div>
<div class="input-group mb-1">
</div>
</div>
</div>
<div class="card mb-2 attacker_form general_form" data-general_no='1'>
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-info btn-general-save">저장</button>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div>
</div>
</div>
</div>
</div><!-- <div class="col-sm"> -->
<div class="col-sm defender-column">
<div class="card mb-2 defender_nation">
<div class="card-header">
수비국 설정
</div>
<div class="card-body dragpad_battle">
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">국가 성향</span>
</div>
<select class="custom-select form_nation_type" style="width:25ch;">
<?php foreach(GameConst::$availableNationType as $typeID): ?>
<?php $nationTypeObj = buildNationTypeClass($typeID) ?>
<option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">기술</span>
</div>
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
<div class="input-group-append">
<span class="input-group-text">등급</span>
</div>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">국가 규모</span>
</div>
<select class="custom-select form_nation_level">
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
<option value="<?=$nationLevel?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">도시 규모</span>
</div>
<select class="custom-select form_city_level">
<?php foreach(getCityLevelList() as $levelID => $name): ?>
<option value="<?=$levelID?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">수도</span>
</div>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y
</label>
<label class="btn btn-secondary active">
<input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off" checked>N
</label>
</div>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">수비</span>
</div>
<input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10">
<div class="input-group-prepend">
<span class="input-group-text">성벽</span>
</div>
<input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10">
</div>
</div>
</div>
<div class="card mb-2 defender_add_form">
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-success add-defender">추가</button>
</div>
</div>
</div>
</div>
<div class="card mb-2 form_sample">
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-info btn-general-save">저장</button>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-warning copy-defender">복제</button>
<button type="button" class="btn btn-danger delete-defender">제거</button>
</div>
</div>
</div>
<div class="card-body general_detail">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">이름</span>
</div>
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
<div class="input-group-prepend">
<span class="input-group-text">직위</span>
</div>
<select class="custom-select form_officer_level" style="width:8ch;">
<option value="1">일반</option>
<option value="4">태수</option>
<option value="3">군사</option>
<option value="2">종사</option>
<option value="10">무장 수뇌</option>
<option value="9">지장 수뇌</option>
<option value="11">참모</option>
<option value="12">군주</option>
</select>
<div class="input-group-prepend">
<span class="input-group-text">Level</span>
</div>
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">통솔</span>
</div>
<input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1">
<div class="input-group-prepend">
<span class="input-group-text">무력</span>
</div>
<input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1">
<div class="input-group-prepend">
<span class="input-group-text">지력</span>
</div>
<input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1">
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">명마</span>
</div>
<select class="custom-select form_general_horse">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?>
<option value="<?=$horseID?>"><?=getItemName($horseID)?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">무기</span>
</div>
<select class="custom-select form_general_weap">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?>
<option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">서적</span>
</div>
<select class="custom-select form_general_book">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?>
<option value="<?=$bookID?>"><?=getItemName($bookID)?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">부상</span>
</div>
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
<div class="input-group-append">
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
</div>
<div class="input-group-prepend">
<span class="input-group-text">군량</span>
</div>
<input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50">
<div class="input-group-prepend">
<span class="input-group-text">도구</span>
</div>
<select class="custom-select form_general_item">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?>
<option value="<?=$itemID?>"><?=getItemName($itemID)?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">병종</span>
</div>
<select class="custom-select form_crewtype">
<?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?>
<?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?>
<option value="<?=$crewTypeID?>"><?=$crewType->name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">병사</span>
</div>
<input type="number" class="form-control form_crew" value="7000" min="100" step="100">
<div class="input-group-prepend">
<span class="input-group-text">성격</span>
</div>
<select class="custom-select form_general_character">
<?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?>
<option value="<?=$characterID?>"><?=$name?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">훈련</span>
</div>
<input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1">
<div class="input-group-prepend">
<span class="input-group-text">사기</span>
</div>
<input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1">
<div class="input-group-prepend">
<span class="input-group-text">전특</span>
</div>
<select class="custom-select form_general_special_war">
<?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?>
<option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">보병숙련</span>
</div>
<select class="custom-select form_dex1">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">궁병숙련</span>
</div>
<select class="custom-select form_dex2">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">기병숙련</span>
</div>
<select class="custom-select form_dex3">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">귀병숙련</span>
</div>
<select class="custom-select form_dex4">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">차병숙련</span>
</div>
<select class="custom-select form_dex5">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend only_defender">
<span class="input-group-text">수비여부</span>
</div>
<select class="custom-select form_defence_train only_defender">
<option value="80">훈사 80</option>
<option value="60">훈사 60</option>
<option value="999">안함</option>
</select>
</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>
</body>
<?php
namespace sammo;
include "lib.php";
include "func.php";
$session = Session::requireLogin()->setReadOnly();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['startyear', 'year']);
$startYear = $gameStor->startyear;
$year = $gameStor->year;
$me = $db->queryFirstRow('SELECT no, nation, city FROM general WHERE owner =%i', Session::getUserID());
if($me){
$generalID = $me['no'];
$nationID = $me['nation'];
$city = $db->queryFirstRow('SELECT city, level, def, wall FROM city WHERE city = %i', $me['city']);
}
else{
$generalID = 0;
$nationID = 0;
$city = [
'city'=>0,
'level'=>5,
'def'=>1000,
'wall'=>1000,
];
}
if($nationID){
$nation = $db->queryFirstRow('SELECT level, type, tech, capital FROM nation WHERE nation = %i', $nationID);
}
else{
$nation = null;
}
?>
<!DOCTYPE html>
<html>
<head>
<title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1100" />
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printCSS('css/battle_simulator.css')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<script>
var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
var city = <?=Json::encode($city)?>;
var nation = <?=Json::encode($nation)?>;
</script>
<?=WebUtil::printJS('dist_js/battle_simulator.js')?>
</head>
<body>
<div id="container">
<div class="card mb-3">
<div class="card-header">
전역 설정
</div>
<div class="card-body dragpad_battle">
<div class="row">
<div class="col-sm-6">
<div class="input-group">
<input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled>
<div class="input-group-append">
<span class="input-group-text"> 시작</span>
</div>
<input type="number" class="form-control" id="year" value="<?=$year?>" min="<?=$startYear?>">
<div class="input-group-append">
<span class="input-group-text"></span>
</div>
<input type="number" class="form-control" id="month" value="1" min="1" max="12">
<div class="input-group-append">
<span class="input-group-text"></span>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="btn-toolbar" role="toolbar">
<div class="input-group mr-2" role="group">
<div class="input-group-prepend">
<span class="input-group-text">반복 횟수</span>
</div>
<select class="custom-select" id="repeat_cnt">
<option value="1">1 (로그 표기)</option>
<option value="1000">1000 (요약 표기)</option>
</select>
</div>
<div class="btn-group mr-2" role="group">
<button type="button" class="btn btn-danger btn-begin_battle">전투</button>
</div>
<div class="btn-group mr-2" role="group">
<button type="button" class="btn btn-info btn-battle-save">모두 저장</button>
<input type="file" class="form_load_battle_file" accept=".json" style="display: none;" />
<button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm">
<div class="card mb-2 attacker_nation">
<div class="card-header">
출병국 설정
</div>
<div class="card-body nation_detail dragpad_battle">
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">국가 성향</span>
</div>
<select class="custom-select form_nation_type" style="width:25ch;">
<?php foreach(GameConst::$availableNationType as $typeID): ?>
<?php $nationTypeClass = buildNationTypeClass($typeID) ?>
<option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">기술</span>
</div>
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
<div class="input-group-append">
<span class="input-group-text">등급</span>
</div>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">국가 규모</span>
</div>
<select class="custom-select form_nation_level">
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
<option value="<?=$nationLevel?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">도시 규모</span>
</div>
<select class="custom-select form_city_level">
<?php foreach(getCityLevelList() as $levelID => $name): ?>
<option value="<?=$levelID?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">수도</span>
</div>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y
</label>
<label class="btn btn-secondary active">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="0" autocomplete="off">N
</label>
</div>
</div>
<div class="input-group mb-1">
</div>
</div>
</div>
<div class="card mb-2 attacker_form general_form" data-general_no='1'>
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
</div>
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-info btn-general-save">저장</button>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div>
</div>
</div>
</div>
</div><!-- <div class="col-sm"> -->
<div class="col-sm defender-column">
<div class="card mb-2 defender_nation">
<div class="card-header">
수비국 설정
</div>
<div class="card-body dragpad_battle">
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">국가 성향</span>
</div>
<select class="custom-select form_nation_type" style="width:25ch;">
<?php foreach(GameConst::$availableNationType as $typeID): ?>
<?php $nationTypeObj = buildNationTypeClass($typeID) ?>
<option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">기술</span>
</div>
<input type="number" class="form-control form_tech" value="1" min="0" max="12">
<div class="input-group-append">
<span class="input-group-text">등급</span>
</div>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">국가 규모</span>
</div>
<select class="custom-select form_nation_level">
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
<option value="<?=$nationLevel?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">도시 규모</span>
</div>
<select class="custom-select form_city_level">
<?php foreach(getCityLevelList() as $levelID => $name): ?>
<option value="<?=$levelID?>"><?=$name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">수도</span>
</div>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y
</label>
<label class="btn btn-secondary active">
<input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off">N
</label>
</div>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">수비</span>
</div>
<input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10">
<div class="input-group-prepend">
<span class="input-group-text">성벽</span>
</div>
<input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10">
</div>
</div>
</div>
<div class="card mb-2 defender_add_form">
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-success add-defender">추가</button>
</div>
</div>
</div>
</div>
<div class="card mb-2 form_sample">
<div class="card-header">
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<div class="float-sm-right btn-toolbar" role="toolbar">
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
</div>
<div class="btn-group btn-group-sm mr-2" role="group">
<button type="button" class="btn btn-info btn-general-save">저장</button>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-warning copy-defender">복제</button>
<button type="button" class="btn btn-danger delete-defender">제거</button>
</div>
</div>
</div>
<div class="card-body general_detail">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">이름</span>
</div>
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
<div class="input-group-prepend">
<span class="input-group-text">직위</span>
</div>
<select class="custom-select form_officer_level" style="width:8ch;">
<option value="1">일반</option>
<option value="4">태수</option>
<option value="3">군사</option>
<option value="2">종사</option>
<option value="10">무장 수뇌</option>
<option value="9">지장 수뇌</option>
<option value="11">참모</option>
<option value="12">군주</option>
</select>
<div class="input-group-prepend">
<span class="input-group-text">Level</span>
</div>
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">통솔</span>
</div>
<input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1">
<div class="input-group-prepend">
<span class="input-group-text">무력</span>
</div>
<input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1">
<div class="input-group-prepend">
<span class="input-group-text">지력</span>
</div>
<input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1">
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">명마</span>
</div>
<select class="custom-select form_general_horse">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?>
<option value="<?=$horseID?>"><?=getItemName($horseID)?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">무기</span>
</div>
<select class="custom-select form_general_weap">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?>
<option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">서적</span>
</div>
<select class="custom-select form_general_book">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?>
<option value="<?=$bookID?>"><?=getItemName($bookID)?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">부상</span>
</div>
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
<div class="input-group-append">
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
</div>
<div class="input-group-prepend">
<span class="input-group-text">군량</span>
</div>
<input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50">
<div class="input-group-prepend">
<span class="input-group-text">도구</span>
</div>
<select class="custom-select form_general_item">
<option value='None'>-</option>
<?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?>
<option value="<?=$itemID?>"><?=getItemName($itemID)?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">병종</span>
</div>
<select class="custom-select form_crewtype">
<?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?>
<?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?>
<option value="<?=$crewTypeID?>"><?=$crewType->name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">병사</span>
</div>
<input type="number" class="form-control form_crew" value="7000" min="100" step="100">
<div class="input-group-prepend">
<span class="input-group-text">성격</span>
</div>
<select class="custom-select form_general_character">
<?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?>
<option value="<?=$characterID?>"><?=$name?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">훈련</span>
</div>
<input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1">
<div class="input-group-prepend">
<span class="input-group-text">사기</span>
</div>
<input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1">
<div class="input-group-prepend">
<span class="input-group-text">전특</span>
</div>
<select class="custom-select form_general_special_war">
<?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?>
<option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">보병숙련</span>
</div>
<select class="custom-select form_dex1">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">궁병숙련</span>
</div>
<select class="custom-select form_dex2">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">기병숙련</span>
</div>
<select class="custom-select form_dex3">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">귀병숙련</span>
</div>
<select class="custom-select form_dex4">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend">
<span class="input-group-text">차병숙련</span>
</div>
<select class="custom-select form_dex5">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<?php endforeach; ?>
</select>
<div class="input-group-prepend only_defender">
<span class="input-group-text">수비여부</span>
</div>
<select class="custom-select form_defence_train only_defender">
<option value="90">훈사 90</option>
<option value="80">훈사 80</option>
<option value="60">훈사 60</option>
<option value="40">훈사 40</option>
<option value="999">안함</option>
</select>
</div>
<div class="input-group mb-1">
<div class="input-group-prepend">
<span class="input-group-text">전투 </span>
</div>
<input type="number" class="form-control form_warnum" value="0" step="1">
<div class="input-group-prepend">
<span class="input-group-text">승리 </span>
</div>
<input type="number" class="form-control form_killnum" value="0" step="1">
<div class="input-group-prepend">
<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>
+1 -2
View File
@@ -7,7 +7,7 @@ include "func.php";
$btn = Util::getPost('btn');
$msg = Util::getPost('msg');
$scoutmsg = Util::getPost('scoutmsg');
$scoutmsg = Util::getPost('scoutMsg');
$rate = Util::getPost('rate', 'int');
$bill = Util::getPost('bill', 'int');
$secretlimit = Util::getPost('secretlimit', 'int');
@@ -75,4 +75,3 @@ if($btn == "국가방침 수정") {
}
header('location:b_dipcenter.php');
+1 -1
View File
@@ -49,6 +49,7 @@ if($btn == '참가') {
$general['gold'] -= $admin['develcost'];
$freeSlot = [
0=>8,
1=>8,
2=>8,
3=>8,
@@ -56,7 +57,6 @@ if($btn == '참가') {
5=>8,
6=>8,
7=>8,
8=>8,
];
foreach($db->query('SELECT count(*) as cnt, grp FROM tournament WHERE grp < 10 GROUP BY grp') as $grpInfo){
if($grpInfo['cnt'] == 8){
+1 -1
View File
@@ -15,7 +15,7 @@ $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$isVoteAdmin = in_array('vote', $session->acl[DB::prefix()]??[]);
$isVoteAdmin |= $session->userGrade >= 5;
$isVoteAdmin = $isVoteAdmin || $session->userGrade >= 5;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
-56
View File
@@ -1,56 +0,0 @@
#newArticle{
width:1000px;
margin: 0 auto;
}
.titleInput{
width:100%;
color:white;
background-color:transparent;
border:none;
margin:1px 5px;
}
.contentInput{
width:100%;
min-height:3em;
color:white;
background-color:transparent;
border:none;
padding:1px 5px;
}
.articleFrame{
width:1000px;
margin: 20px auto;
}
.commentText{
width:100%;
}
.authorName, .comment .author{
width:110px;
font-size:85%;
}
.date{
width:125px;
font-size:85%;
}
.text{
text-align:left;
padding:1px 5px;
}
.submitComment{
width:100%;
}
.commentText{
color:white;
background-color:transparent;
border:none;
padding:1px 5px;
}
+155 -135
View File
@@ -1,40 +1,56 @@
@charset "UTF-8";
/* font-boostring Block */
html * {max-height:1000000px;}
html, body{
background-color:black;
color:white;
line-height:1.3;
font-family:'맑은 고딕';
font-size:13px;
html * {
max-height: 1000000px;
}
table { font-family:'맑은 고딕'; }
font { font-family:'맑은 고딕'; }
input { font-family:'맑은 고딕'; font-size:13px; }
select { font-family:'굴림'; line-height:100%; }
.center{
text-align:center;
html,
body {
background-color: black;
color: white;
line-height: 1.3;
font-family: '맑은 고딕';
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:none;
padding:0;
border: none;
padding: 0;
}
.mimic_flex td, .mimic_flex th {
border:none !important;
.mimic_flex td,
.mimic_flex th {
border: none !important;
padding: 0px;
word-break: break-all;
}
table.tb_layout {
table.tb_layout {
border-collapse: collapse;
padding: 0px;
font-size: 13px;
@@ -42,159 +58,161 @@ table.tb_layout {
font-family: '맑은 고딕';
}
.tb_layout td, .tb_layout th {
border:solid 1px gray;
.tb_layout td,
.tb_layout th {
border: solid 1px gray;
padding: 0px;
word-break: break-all;
font-family: '맑은 고딕';;
font-family: '맑은 고딕';
;
}
div.bar_out{
position:relative;
border-top:solid 1px #888888;
border-bottom:solid 1px #333333;
padding:0;
margin:0;
width:100%;
div.bar_out {
position: relative;
border-top: solid 1px #888888;
border-bottom: solid 1px #333333;
padding: 0;
margin: 0;
width: 100%;
overflow: hidden;
}
div.bar_out div{
position:absolute;
left:0;
top:0;
height:100%;
div.bar_out div {
position: absolute;
left: 0;
top: 0;
height: 100%;
}
div.bar_out div.bar_in{
width:100%;
div.bar_out div.bar_in {
width: 100%;
}
/* */
.ev_warning{
color:orangered;
.ev_warning {
color: orangered;
}
.ev_notice{
color:orangered;
.ev_notice {
color: orangered;
}
.ev_succes{
color:lightgreen;
.ev_succes {
color: lightgreen;
}
.ev_sell{
color:orange;
.ev_sell {
color: orange;
}
.ev_failed{
color:orangered;
.ev_failed {
color: orangered;
}
.ev_highlight{
color:orangered;
.ev_highlight {
color: orangered;
}
/* TODO: 색상값이 아니라 의미에 따라 클래스 지정 */
.o_bullet::before{
color:cyan;
content:"●";
.o_bullet::before {
color: cyan;
content: "●";
}
.o_diamond::before{
color:orangered;
content:"◆";
.o_diamond::before {
color: orangered;
content: "◆";
}
.small_war_log{
display:inline-block;
.small_war_log {
display: inline-block;
}
.small_war_log .war_type_attack{
color:cyan;
.small_war_log .war_type_attack {
color: cyan;
}
.small_war_log .war_type_defense{
color:magenta;
.small_war_log .war_type_defense {
color: magenta;
}
.small_war_log .war_type_siege{
color:white;
.small_war_log .war_type_siege {
color: white;
}
.small_war_log .name_plate{
.small_war_log .name_plate {
font-size: 0.75em;
}
.small_war_log .name_plate_cover{
color:yellow;
.small_war_log .name_plate_cover {
color: yellow;
}
.small_war_log .crew_plate{
color:orangered;
font-size:90%;
.small_war_log .crew_plate {
color: orangered;
font-size: 90%;
}
.t_date{
.t_date {
font-size: 0.75em;
}
.t_red{
color:red;
.t_red {
color: red;
}
.t_blue{
color:blue;
.t_blue {
color: blue;
}
.t_green{
color:green;
.t_green {
color: green;
}
.t_magenta{
color:magenta;
.t_magenta {
color: magenta;
}
.t_cyan{
color:cyan;
.t_cyan {
color: cyan;
}
.t_limegreen{
color:limegreen;
.t_limegreen {
color: limegreen;
}
.t_skyblue{
color:skyblue;
.t_skyblue {
color: skyblue;
}
.t_orangered{
color:orangered;
.t_orangered {
color: orangered;
}
.t_yellow{
color:yellow;
.t_yellow {
color: yellow;
}
.t_white{
color:white;
.t_white {
color: white;
}
.float_left{
float:left;
.float_left {
float: left;
}
.tooltip{
font-size:12px;
.tooltip {
font-size: 12px;
font-family: '맑은 고딕';
}
.tooltip_copyable_info .tooltiptext{
.tooltip_copyable_info .tooltiptext {
display: inline;
color: rgba(0,0,0,0);
color: rgba(0, 0, 0, 0);
font-size: 0;
}
@@ -202,67 +220,69 @@ div.bar_out div.bar_in{
display: none;
}
.hidden_but_copyable{
color: rgba(0,0,0,0);
.hidden_but_copyable {
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.btn-group-xs > .btn, .btn-xs {
padding : .25rem .4rem;
font-size : .875rem;
line-height : .5;
border-radius : .2rem;
.btn-group-xs>.btn,
.btn-xs {
padding: .25rem .4rem;
font-size: .875rem;
line-height: .5;
border-radius: .2rem;
}
.edit_form.viewer{
max-height:200px;
overflow-y:auto;
.edit_form.viewer {
max-height: 200px;
overflow-y: auto;
}
.trumbowyg-box{
margin:0;
border-left:none;
border-right:none;
.trumbowyg-box {
margin: 0;
border-left: none;
border-right: none;
}
.edit_form.trumbowyg-editor{
margin:0;
padding:0;
.edit_form.trumbowyg-editor {
margin: 0;
padding: 0;
}
.commandBasic{
background-color:black;
color:white;
.commandBasic {
background-color: black;
color: white;
}
.compensatePositive{
color:skyblue;
.compensatePositive {
color: skyblue;
}
.compensateNegative{
color:orange;
.compensateNegative {
color: orange;
}
.compensateNeutral{
color:white;
.compensateNeutral {
color: white;
}
.commandBasic.commandImpossible{
background-color:red;
color:white;
.commandBasic.commandImpossible {
background-color: red;
color: white;
}
.select2-selection--single.simple-select2-align-center .select2-selection__rendered {
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;
}
.select2-container--bootstrap4 .select2-selection--single.text-secondary .select2-selection__rendered{
color:white;
.select2-container--bootstrap4 .select2-selection--single.text-secondary .select2-selection__rendered {
color: white;
}
.select2-container--bootstrap4 .text-secondary .select2-results__option[aria-selected=false]{
color:white;
}
.select2-container--bootstrap4 .text-secondary .select2-results__option[aria-selected=false] {
color: white;
}
-49
View File
@@ -1,49 +0,0 @@
.section_bar{
text-align:center;
border:0.5px solid #aaa;
padding-right:0;
padding-left:0;
}
.sub_bar{
text-align:center;
border:0.5px solid #aaa;
margin-left:-5px;
margin-right:-5px;
}
.reset_btn{
width:15ch;
}
.submit_btn{
margin-left:1em;
width:15ch;
}
.control_bar{
margin-top:8pt;
text-align:right;
}
.col-form-label{
text-align:right;
padding-right:2ch;
}
.form_list{
padding:8pt;
}
.half_section_left{
padding-right:0;
border-right:0.5px solid #aaa;
}
.half_section_right{
padding-left:0;
}
.popover{
max-width:100%;
}
+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;
}
@@ -0,0 +1,6 @@
<?php
namespace sammo;
class VersionGit extends VersionGitDynamic {
}
//{"version":"dynamic","hash":"dynamic"}
+9 -2
View File
@@ -2,8 +2,15 @@
namespace sammo;
class VersionGit{
public static $version = '_tK_verionGit_';
static function getVersion()
{
return '_tK_verionGit_';
}
static function getHash(){
return '_tK_hash_';
}
private function __construct(){}
}
//{"version":"_tK_verionGit_"}
//{"version":"_tK_verionGit_","hash":"_tK_hash_"}
+2177 -2105
View File
File diff suppressed because it is too large Load Diff
+447 -447
View File
@@ -1,448 +1,448 @@
<?php
namespace sammo;
use sammo\Command\GeneralCommand;
use sammo\Command\NationCommand;
function getGeneralTurnBrief(General $generalObj, array $turnList) {
$result = [];
foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg);
$turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText;
}
return $result;
}
function getNationTurnBrief(General $generalObj, array $turnList) {
$result = [];
$tmpTurn = new LastTurn();
foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg);
$turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText;
}
return $result;
}
function pushGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pullGeneralCommand($generalID, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxTurn){
return;
}
$db = DB::db();
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식'
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
}
function pullGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pushGeneralCommand($generalID, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxTurn){
return;
}
$db = DB::db();
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식'
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
}
function repeatGeneralCommand(int $generalId, int $turnCnt){
if($turnCnt <= 0){
return;
}
if($turnCnt >= GameConst::$maxTurn){
return;
}
$db = DB::db();
$reqTurn = $turnCnt;
if($turnCnt * 2 > GameConst::$maxTurn){
$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);
foreach($turnList as $turnItem){
$turnIdx = $turnItem['turn_idx'];
$turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt));
$db->update('general_turn', [
'action'=>$turnItem['action'],
'arg'=>$turnItem['arg'],
'brief'=>$turnItem['brief']
], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget);
}
}
function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
if($nationID == 0){
return;
}
if($officerLevel < 5){
return;
}
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pullNationCommand($nationID, $officerLevel, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxChiefTurn){
return;
}
$db = DB::db();
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식'
], '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){
if($nationID == 0){
return;
}
if($officerLevel < 5){
return;
}
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pushNationCommand($nationID, $officerLevel, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxChiefTurn){
return;
}
$db = DB::db();
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식',
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
}
function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
if(!$turnList){
return;
}
$db = DB::db();
$generalID = $command->getGeneral()->getID();
$commandName = $command->getRawClassName();
$arg = $command->getArg();
$brief = $command->getBrief();
$db->update('general_turn', [
'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
}
function _setNationCommand(NationCommand $command, array $turnList):void {
if(!$turnList){
return;
}
$db = DB::db();
$nationID = $command->getNationID();
$officerLevel = $command->getOfficerLevel();
$commandName = $command->getRawClassName();
$arg = $command->getArg();
$brief = $command->getBrief();
$db->update('nation_turn', [
'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
}
function sanitizeArg(?array $args):?array{
if($args === null){
return $args;
}
$result = [];
foreach($args as $key=>$value){
if(is_array($value)){
$result[$key] = sanitizeArg($value);
}
else if(is_string($value)){
$result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value));
}
else{
$result[$key] = $value;
}
}
return $result;
}
function checkCommandArg(?array $arg):?string{
if($arg === null){
return null;
}
$defaultCheck = [
/*'string'=>[
'nationName', 'optionText', 'itemType', 'nationType'
],*/
'integer'=>[
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
'amount', 'colorType',
'srcArmType', 'destArmType', //숙련전환 전용
],
'boolean'=>[
'isGold', 'buyRice',
],
'between'=>[
['month', [1, 12]]
],
'min'=>[
['year', 0],
['destGeneralID', 1],
['destCityID', 1],
['destNationID', 1],
['amount', 1],
['crewType', 0]
],
'integerArray'=>[
'destNationIDList', 'destGeneralIDList', 'amountList'
],
'stringWidthBetween'=>[
['nationName', 1, 18]
]
];
$v = new Validator($arg);
$v->rules($defaultCheck);
if (!$v->validate()){
return $v->errorStr();
}
return null;
}
function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{
$turnList = [];
foreach($rawTurnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){
return [
'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx',
'target'=>$turnIdx,
];
}
if($turnIdx >= 0){
$turnList[$turnIdx] = true;
}
else if($turnIdx == -1){
//홀수
foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true;
}
}
else if($turnIdx == -2){
//짝수
foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true;
}
}
else if($turnIdx == -3){
//모두
foreach(Util::range(GameConst::$maxTurn) as $subIdx){
$turnList[$subIdx] = true;
}
}
}
$turnList = array_keys($turnList);
$arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){
return [
'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg',
'target'=>'arg'
];
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID);
try{
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
}
catch (\InvalidArgumentException $e){
return [
'result'=>false,
'reason'=>$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
catch (\Exception $e){
return [
'result'=>false,
'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
if(!$commandObj->isArgValid()){
return [
'result'=>false,
'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid',
'target'=>'arg'
];
}
if(!$commandObj->hasPermissionToReserve()){
return [
'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve',
'target'=>'command'
];
}
_setGeneralCommand($commandObj, $turnList);
return [
'result'=>true,
'reason'=>'success'
];
}
function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{
$turnList = array_unique($turnList);
foreach($turnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){
return [
'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx',
'target'=>$turnIdx,
];
}
}
$arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){
return [
'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg',
'target'=>'arg'
];
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID);
if($general->getVar('officer_level') < 5){
return [
'result'=>false,
'reason'=>'수뇌가 아닙니다'
];
}
try{
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
}
catch (\InvalidArgumentException $e){
return [
'result'=>false,
'reason'=>$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
catch (\Exception $e){
return [
'result'=>false,
'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
if(!$commandObj->isArgValid()){
return [
'result'=>false,
'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid',
'target'=>'arg'
];
}
if(!$commandObj->hasPermissionToReserve()){
return [
'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve',
'target'=>'command'
];
}
_setNationCommand($commandObj, $turnList);
return [
'result'=>true,
'arg_test'=>true,
'reason'=>'success'
];
<?php
namespace sammo;
use sammo\Command\GeneralCommand;
use sammo\Command\NationCommand;
function getGeneralTurnBrief(General $generalObj, array $turnList) {
$result = [];
foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg);
$turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText;
}
return $result;
}
function getNationTurnBrief(General $generalObj, array $turnList) {
$result = [];
$tmpTurn = new LastTurn();
foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg);
$turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText;
}
return $result;
}
function pushGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pullGeneralCommand($generalID, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxTurn){
return;
}
$db = DB::db();
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식'
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
}
function pullGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pushGeneralCommand($generalID, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxTurn){
return;
}
$db = DB::db();
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식'
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
$db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
}
function repeatGeneralCommand(int $generalId, int $turnCnt){
if($turnCnt <= 0){
return;
}
if($turnCnt >= GameConst::$maxTurn){
return;
}
$db = DB::db();
$reqTurn = $turnCnt;
if($turnCnt * 2 > GameConst::$maxTurn){
$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);
foreach($turnList as $turnItem){
$turnIdx = $turnItem['turn_idx'];
$turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt));
$db->update('general_turn', [
'action'=>$turnItem['action'],
'arg'=>$turnItem['arg'],
'brief'=>$turnItem['brief']
], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget);
}
}
function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
if($nationID == 0){
return;
}
if($officerLevel < 5){
return;
}
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pullNationCommand($nationID, $officerLevel, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxChiefTurn){
return;
}
$db = DB::db();
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식'
], '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){
if($nationID == 0){
return;
}
if($officerLevel < 5){
return;
}
if($turnCnt == 0){
return;
}
if($turnCnt < 0){
pushNationCommand($nationID, $officerLevel, -$turnCnt);
return;
}
if($turnCnt >= GameConst::$maxChiefTurn){
return;
}
$db = DB::db();
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
'action'=>'휴식',
'arg'=>'{}',
'brief'=>'휴식',
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
$db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
}
function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
if(!$turnList){
return;
}
$db = DB::db();
$generalID = $command->getGeneral()->getID();
$commandName = $command->getRawClassName();
$arg = $command->getArg();
$brief = $command->getBrief();
$db->update('general_turn', [
'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
}
function _setNationCommand(NationCommand $command, array $turnList):void {
if(!$turnList){
return;
}
$db = DB::db();
$nationID = $command->getNationID();
$officerLevel = $command->getOfficerLevel();
$commandName = $command->getRawClassName();
$arg = $command->getArg();
$brief = $command->getBrief();
$db->update('nation_turn', [
'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
}
function sanitizeArg(?array $args):?array{
if($args === null){
return $args;
}
$result = [];
foreach($args as $key=>$value){
if(is_array($value)){
$result[$key] = sanitizeArg($value);
}
else if(is_string($value)){
$result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value));
}
else{
$result[$key] = $value;
}
}
return $result;
}
function checkCommandArg(?array $arg):?string{
if($arg === null){
return null;
}
$defaultCheck = [
/*'string'=>[
'nationName', 'optionText', 'itemType', 'nationType', 'commandType',
],*/
'integer'=>[
'crewType', 'destGeneralID', 'destCityID', 'destNationID',
'amount', 'colorType',
'srcArmType', 'destArmType', //숙련전환 전용
],
'boolean'=>[
'isGold', 'buyRice',
],
'between'=>[
['month', [1, 12]]
],
'min'=>[
['year', 0],
['destGeneralID', 1],
['destCityID', 1],
['destNationID', 1],
['amount', 1],
['crewType', 0]
],
'integerArray'=>[
'destNationIDList', 'destGeneralIDList', 'amountList'
],
'stringWidthBetween'=>[
['nationName', 1, 18]
]
];
$v = new Validator($arg);
$v->rules($defaultCheck);
if (!$v->validate()){
return $v->errorStr();
}
return null;
}
function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{
$turnList = [];
foreach($rawTurnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){
return [
'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx',
'target'=>$turnIdx,
];
}
if($turnIdx >= 0){
$turnList[$turnIdx] = true;
}
else if($turnIdx == -1){
//홀수, 0부터 맞다.
foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true;
}
}
else if($turnIdx == -2){
//짝수, 1부터 맞다.
foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true;
}
}
else if($turnIdx == -3){
//모두
foreach(Util::range(GameConst::$maxTurn) as $subIdx){
$turnList[$subIdx] = true;
}
}
}
$turnList = array_keys($turnList);
$arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){
return [
'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg',
'target'=>'arg'
];
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID);
try{
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
}
catch (\InvalidArgumentException $e){
return [
'result'=>false,
'reason'=>$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
catch (\Exception $e){
return [
'result'=>false,
'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
if(!$commandObj->isArgValid()){
return [
'result'=>false,
'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid',
'target'=>'arg'
];
}
if(!$commandObj->hasPermissionToReserve()){
return [
'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve',
'target'=>'command'
];
}
_setGeneralCommand($commandObj, $turnList);
return [
'result'=>true,
'reason'=>'success'
];
}
function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{
$turnList = array_unique($turnList);
foreach($turnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){
return [
'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx',
'target'=>$turnIdx,
];
}
}
$arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){
return [
'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg',
'target'=>'arg'
];
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID);
if($general->getVar('officer_level') < 5){
return [
'result'=>false,
'reason'=>'수뇌가 아닙니다'
];
}
try{
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
}
catch (\InvalidArgumentException $e){
return [
'result'=>false,
'reason'=>$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
catch (\Exception $e){
return [
'result'=>false,
'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build',
'target'=>'arg'
];
}
if(!$commandObj->isArgValid()){
return [
'result'=>false,
'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid',
'target'=>'arg'
];
}
if(!$commandObj->hasPermissionToReserve()){
return [
'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve',
'target'=>'command'
];
}
_setNationCommand($commandObj, $turnList);
return [
'result'=>true,
'arg_test'=>true,
'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));
}
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{
if(!$rawGeneralList){
return 0;
+1180 -1136
View File
@@ -1,1136 +1,1180 @@
<?php
namespace sammo;
use Monolog\Logger;
/**
* 게임 룰에 해당하는 함수 모음
*/
function getNationLevelList(): array
{
$table = [
0 => ['방랑군', 2, 0],
1 => ['호족', 2, 1],
2 => ['군벌', 4, 2],
3 => ['주자사', 4, 5],
4 => ['주목', 6, 8],
5 => ['공', 6, 11],
6 => ['왕', 8, 16],
7 => ['황제', 8, 21],
];
return $table;
}
function getCityLevelList(): array
{
return [
1 => '수',
2 => '진',
3 => '관',
4 => '이',
5 => '소',
6 => '중',
7 => '대',
8 => '특'
];
}
//한국가의 전체 전방 설정
function SetNationFront($nationNo)
{
if (!$nationNo) {
return;
}
// 도시소유 국가와 선포,교전중인 국가
$adj3 = [];
$adj2 = [];
$adj1 = [];
$db = DB::db();
foreach ($db->queryFirstColumn(
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i',
$nationNo
) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj3[$adjKey] = $adjVal;
}
};
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',
$nationNo
) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj1[$adjKey] = $adjVal;
}
}
if (!$adj3 && !$adj1) {
//평시이면 공백지
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj2[$adjKey] = $adjVal;
}
}
}
$db->update('city', [
'front' => 0
], 'nation=%i', $nationNo);
if ($adj1) {
$db->update('city', [
'front' => 1,
], 'nation=%i and city in %li', $nationNo, array_keys($adj1));
}
if ($adj2) {
$db->update('city', [
'front' => 2,
], 'nation=%i and city in %li', $nationNo, array_keys($adj2));
}
if ($adj3) {
$db->update('city', [
'front' => 3,
], 'nation=%i and city in %li', $nationNo, array_keys($adj3));
}
}
function checkSupply()
{
$db = DB::db();
$cities = [];
foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) {
$newCity = new \stdClass();
$newCity->id = Util::toInt($city['city']);
$newCity->nation = Util::toInt($city['nation']);
$newCity->supply = false;
$cities[$newCity->id] = $newCity;
}
$queue = new \SplQueue();
foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) {
if (!key_exists($capitalID, $cities)) {
continue;
}
$city = $cities[$capitalID];
if ($nationID != $city->nation) {
continue;
}
$city->supply = true;
$queue->enqueue($city);
}
while (!$queue->isEmpty()) {
$cityLink = $queue->dequeue();
$city = CityConst::byID($cityLink->id);
foreach (array_keys($city->path) as $connCityID) {
if (!key_exists($connCityID, $cities)) {
continue;
}
$connCity = $cities[$connCityID];
if ($connCity->nation != $cityLink->nation) {
continue;
}
if ($connCity->supply) {
continue;
}
$connCity->supply = true;
$queue->enqueue($connCity);
}
}
$db->update('city', [
'supply' => 1
], 'nation=0');
$db->update('city', [
'supply' => 0
], 'nation!=0');
$supply = [];
foreach ($cities as $city) {
if ($city->supply) {
$supply[] = $city->id;
}
}
if ($supply) {
$db->update('city', [
'supply' => 1
], 'city IN %li', $supply);
}
}
function updateGeneralNumber(){
$db = DB::db();
foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){
if($nationID === 0){
continue;
}
$db->update('nation', [
'gennum'=>$gennum
], 'nation=%i', $nationID);
}
refreshNationStaticInfo();
}
function updateYearly()
{
//통계
checkStatistic();
}
//관직 변경 해제
function updateQuaterly()
{
$db = DB::db();
//천도 제한 해제, 관직 변경 제한 해제
$db->update('nation', [
'chief_set' => 0,
], true);
//관직 변경 제한 해제
$db->update('city', [
'officer_set' => 0,
], true);
}
// 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
function preUpdateMonthly()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//연감 월결산
$result = LogHistory();
if ($result == false) {
return false;
}
$admin = $gameStor->getValues(['startyear', 'year', 'month']);
$logger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//보급선 체크
checkSupply();
//미보급도시 10% 감소
$db->update('city', [
'pop' => $db->sqleval('pop * 0.9'),
'trust' => $db->sqleval('trust * 0.9'),
'agri' => $db->sqleval('agri * 0.9'),
'comm' => $db->sqleval('comm * 0.9'),
'secu' => $db->sqleval('secu * 0.9'),
'def' => $db->sqleval('def * 0.9'),
'wall' => $db->sqleval('wall * 0.9'),
], 'supply = 0');
//미보급도시 장수 병 훈 사 5%감소
//NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게.
$unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0');
foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) {
$cityIDList = Util::squeezeFromArray($cityList, 'city');
$db->update('general', [
'crew' => $db->sqleval('crew*0.95'),
'atmos' => $db->sqleval('atmos*0.95'),
'train' => $db->sqleval('train*0.95'),
], 'city IN %li AND nation = %i', $cityIDList, $nationID);
}
//민심30이하 공백지 처리
$lostCities = [];
foreach ($unsuppliedCities as $unsuppliedCity) {
if ($unsuppliedCity['trust'] >= 30) {
continue;
}
$lostCities[$unsuppliedCity['city']] = $unsuppliedCity;
}
if ($lostCities) {
foreach ($lostCities as $lostCity) {
$josaYi = JosaUtil::pick($lostCity['name'], '이');
$logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다.");
}
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0
], 'officer_city IN %li', array_keys($lostCities));
$db->update('city', [
'nation' => 0,
'officer_set' => 0,
'conflict' => '{}',
'term' => 0,
'front' => 0
], 'city IN %li', array_keys($lostCities));
}
//접률감소, 건국제한-1
$db->update('general', [
'connect' => $db->sqleval('floor(connect*0.99)'),
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
], true);
//전략제한-1, 외교제한-1, 세율동기화
$db->update('nation', [
'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'),
'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'),
'rate_tmp' => $db->sqleval('rate')
], true);
//도시훈사 180년 60, 220년 87, 240년 100
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
if ($rate > 100) $rate = 100;
// 20 ~ 140원
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
$gameStor->city_rate = $rate;
$gameStor->develcost = $develcost;
//매달 사망자 수입 결산
processWarIncome();
//계략, 전쟁표시 해제
$db->update('city', [
'state' => $db->sqleval(<<<EOD
(CASE
WHEN state=31 THEN 0
WHEN state=32 THEN 31
WHEN state=33 THEN 0
WHEN state=34 THEN 33
WHEN state=41 THEN 0
WHEN state=42 THEN 41
WHEN state=43 THEN 42
ELSE state END)
EOD),
'term' => $db->sqleval('greatest(0, term - 1)'),
'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'),
], true);
//첩보-1
foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) {
$spyInfo = Json::decode($rawSpy);
foreach ($spyInfo as $cityNo => $remainMonth) {
if ($remainMonth <= 1) {
unset($spyInfo[$cityNo]);
} else {
$spyInfo[$cityNo] -= 1;
}
}
$db->update('nation', [
'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
], 'nation=%i', $nationNo);
}
return true;
}
// 외교 로그처리, 외교 상태 처리
function postUpdateMonthly()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']);
$globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//도시 수 측정
$cityNations = [];
foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) {
if (!key_exists($cityNation, $cityNations)) {
$cityNations[$cityNation] = [];
}
$cityNations[$cityNation][] = $cityName;
}
//각 국가 전월 장수수 대비 당월 장수수로 단합도 산정
//각 국가 장수수를 구하고 국력 산정
// $query = "select nation,gennum from nation where level>0";
// 국력=
// 자원(국가/장수의 금,쌀)
// 기술력
// 인구수*내정%
// 장수능력
// 접속률
// 숙련도
// 명성,공헌
$nations = Util::convertArrayToDict($db->query('SELECT
A.nation,
A.gennum,
round((
round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100)
+A.tech
+if(A.level=0,0,(
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
) from city where nation=A.nation and supply=1
))
+(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(experience+dedication)/100) from general where nation=A.nation)
+(select round(avg(connect)) from general where nation=A.nation)
)/10)
as power,
(select sum(crew) from general where nation=A.nation) as totalCrew
from nation A
group by A.nation'), 'nation');
$maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power');
foreach ($nations as $nation) {
$nationID = $nation['nation'];
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$genNum[$nationID] = $nation['gennum'];
$powerValues = $maxPowerValues[$nationID]??[];
//약간의 랜덤치 부여 (95% ~ 105%)
$nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000);
$powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']);
$powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew']));
if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) {
$powerValues['maxCities'] = $cityNations[$nationID];
}
$db->update('nation', [
'power' => $nation['power']
], 'nation=%i', $nationID);
$nationStor->max_power = $powerValues;
}
// 전쟁기한 세팅
foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) {
$genCount = $genNum[$dip['me']];
// 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산
// 4000 / 10 * 0.25 = 100
$term = floor($dip['dead'] / 100 / $genCount);
$dip['dead'] -= $term * 100 * $genCount;
$term = Util::valueFit($dip['term'] + $term, 0, 13);
$db->update('diplomacy', [
'term' => $term,
'dead' => $dip['dead'],
], '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){
$nation1 = getNationStaticInfo($dip['me']);
$name1 = $nation1['name'];
$nation2 = getNationStaticInfo($dip['you']);
$name2 = $nation2['name'];
$josaYi = JosaUtil::pick($name2, '이');
$josaWa = JosaUtil::pick($name1, '와');
$globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다.");
}
//휴전국 로그
$stopWarList = [];
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){
$key = "{$me}_{$you}";
}
else{
$key = "{$you}_{$me}";
}
if(!key_exists($key, $stopWarList)){
$stopWarList[$key] = true;
continue;
}
//양측 기간 모두 0이 되는 상황이면 휴전
$nation1 = getNationStaticInfo($me);
$name1 = $nation1['name'];
$nation2 = getNationStaticInfo($you);
$name2 = $nation2['name'];
$josaWa = JosaUtil::pick($name1, '와');
$josaYi = JosaUtil::pick($name2, '이');
$globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다.");
$db->update('diplomacy', [
'state'=>2,
'term'=>0,
], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you);
}
$globalLogger->flush();
//사상자 초기화, 외교 기한-1
$db->update('diplomacy', [
'dead'=>$db->sqleval('if(state!=0, 0, dead)'),
'term'=>$db->sqleval('greatest(0, term-1)'),
], true);
//불가침 끝나면 통상으로
$db->update('diplomacy', [
'state'=>2,
], 'state = 7 AND term = 0');
//선포 끝나면 교전으로
$db->update('diplomacy', [
'state'=>0,
'term'=>6,
], 'state = 1 AND term = 0');
//초반이후 방랑군 자동 해체
if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander();
}
// 작위 업데이트
updateNationState();
updateGeneralNumber();
refreshNationStaticInfo();
// 천통여부 검사
checkEmperior();
//토너먼트 개시
triggerTournament();
// 시스템 거래건 등록
registerAuction();
//전방설정
foreach (getAllNationStaticInfo() as $nation) {
if ($nation['level'] <= 0) {
continue;
}
SetNationFront($nation['nation']);
}
}
function checkWander()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$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');
foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) {
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
if ($wanderCmd->hasFullConditionMet()) {
$logger = $wanderer->getLogger();
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
$wanderCmd->run();
}
}
if ($wanderers) {
refreshNationStaticInfo();
}
}
function updateNationState()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$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[$nationID] = $assemblerCnt;
};
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
if ($citycount == 0) {
$nationlevel = 0; // 방랑군
} elseif ($citycount == 1) {
$nationlevel = 1; // 호족
} elseif ($citycount <= 4) {
$nationlevel = 2; // 군벌
} elseif ($citycount <= 7) {
$nationlevel = 3; // 주자사
} elseif ($citycount <= 10) {
$nationlevel = 4; // 주목
} elseif ($citycount <= 15) {
$nationlevel = 5; // 공
} elseif ($citycount <= 20) {
$nationlevel = 6; // 왕
} else {
$nationlevel = 7; // 황제
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level'];
$oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel
];
switch ($nationlevel) {
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} 자칭하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6:
$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) . "</>에 등극"]);
break;
case 5:
case 4:
case 3:
$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) . "</>에 임명됨"]);
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) . "</>로 나서다"]);
break;
}
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
$turnRows[] = [
'nation_id' => $nation['nation'],
'officer_level' => $chiefLevel,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
}
$db->insertIgnore('nation_turn', $turnRows);
if ($levelDiff) {
//유니크 아이템 하나 돌리자
$targetKillTurn = $admin['killturn'];
$targetKillTurn -= 24 * 60 / $admin['turnterm'];
$nationGenIDList = $db->queryFirstColumn(
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$nation['nation'],
$targetKillTurn
);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong'], 2);
$uniqueLotteryWeightList = [];
foreach ($nationGenList as $nationGen) {
$hasUnique = false;
foreach ($nationGen->getItems() as $item) {
if (!$item->isBuyable()) {
$hasUnique = true;
break;
}
}
if ($hasUnique) {
continue;
}
$score = $nationGen->getVar('belong') + 5;
if ($nationGen->getVar('officer_level') == 12) {
$score += 200; //NOTE: 꼬우면 군주하세요.
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 70;
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 35;
}
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
$winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
giveRandomUniqueItem($winnerObj, '작위보상');
$winnerObj->applyDB($db);
}
}
}
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0;
$maxAssemblerCnt = [
1 => 0,
2 => 1,
3 => 3,
4 => 4,
5 => 6,
6 => 7,
7 => 9
][$nationlevel] ?? 0;
if ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID = $gameStor->assembler_id ?? 0;
while ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1;
$npcObj = new Scenario\NPC(
999,
sprintf('부대장%4d', $lastAssemblerID),
null,
$nation['nation'],
null,
10,
10,
10,
1,
$admin['year'] - 15,
$admin['year'] + 15,
'은둔',
'척사'
);
$npcObj->killturn = 70;
$npcObj->gold = 0;
$npcObj->rice = 0;
$npcObj->npc = 5;
$npcObj->build($admin);
$npcID = $npcObj->generalID;
$db->insert('troop', [
'troop_leader' => $npcID,
'name' => $npcObj->realName,
'nation' => $nation['nation'],
]);
$db->update('general', [
'troop' => $npcID
], 'no=%i', $npcID);
//TODO: 5턴간 집합턴 입력
$assemblerCnt += 1;
$gameStor->assembler_id = $lastAssemblerID;
}
}
}
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
function checkStatistic()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month']);
$nationHists = [];
$specialHists = [];
$personalHists = [];
$specialHists2 = [];
$crewtypeHists = [];
$etc = '';
$auxData = [
'generals' => [],
'nations' => [],
];
$avgGeneral = $db->queryFirstRow(
'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
FROM general'
);
$auxData['generals']['avg'] = $avgGeneral;
$avgGeneral['avggold'] = Util::round($avgGeneral['avggold']);
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']);
$avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']);
$avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
$etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), ";
$avgNation = $db->queryFirstRow(
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech,
min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0'
);
$auxData['nations']['avg'] = $avgNation;
$avgNation['mintech'] = floor($avgNation['mintech']);
$avgNation['maxtech'] = floor($avgNation['maxtech']);
$avgNation['avgtech'] = Util::round($avgNation['avgtech']);
$avgNation['avgpower'] = Util::round($avgNation['avgpower']);
$etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), ";
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), ";
$nationName = '';
$powerHist = '';
$nations = Util::convertArrayToDict(
$db->query(
'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc',
'nation'
),
'nation'
);
$nationCount = count($nations);
$nationGeneralInfos = Util::convertArrayToDict(
$db->query(
'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'
),
'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'
);
foreach ($nations as $nationNo => &$nation) {
$general = $nationGeneralInfos[$nationNo];
$city = $nationCityInfos[$nationNo];
$nation['generalInfo'] = $general;
$nation['cityInfo'] = $city;
$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']}), ";
if (!isset($nationHists[$nation['type']])) {
$nationHists[$nation['type']] = 0;
}
$nationHists[$nation['type']]++;
}
unset($nation);
$auxData['nations']['all'] = $nations;
$nationHist = '';
foreach (GameConst::$availableNationType as $nationType) {
if (!Util::array_get($nationHists[$nationType])) {
$nationHists[$nationType] = '-';
}
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
}
$generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general');
$genCount = 0;
$npcCount = 0;
$generalCount = count($generals);
foreach ($generals as $general) {
if (!isset($personalHists[$general['personal']])) {
$personalHists[$general['personal']] = 0;
}
if (!isset($specialHists[$general['special']])) {
$specialHists[$general['special']] = 0;
}
if (!isset($specialHists2[$general['special2']])) {
$specialHists2[$general['special2']] = 0;
}
if ($general['npc'] < 2) {
$genCount += 1;
} else {
$npcCount += 1;
}
$personalHists[$general['personal']]++;
$specialHists[$general['special']]++;
$specialHists2[$general['special2']]++;
}
foreach ($db->queryAllLists(
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype'
) as [$crewtype, $cnt]) {
$crewtypeHists[$crewtype] = $cnt;
}
$auxData['generals']['hists'] = [
'personal' => $personalHists,
'special' => $specialHists,
'special2' => $specialHists2,
'crewtype' => $crewtypeHists,
'userCnt' => $genCount,
'npcCnt' => $npcCount,
];
$generalCountStr = "{$generalCount}({$genCount}+{$npcCount})";
$personalHistStr = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return getGenChar($histKey) . '(' . $cnt . ')';
}, Util::convertDictToArray($personalHists)));
$specialHistsStr = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')';
}, Util::convertDictToArray($specialHists)));
$specialHists2Str = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')';
}, Util::convertDictToArray($specialHists2)));
$specialHistsAllStr = "$specialHistsStr // $specialHists2Str";
$crewtypeHistsStr = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')';
}, Util::convertDictToArray($crewtypeHists)));
$db->insert('statistic', [
'year' => $admin['year'],
'month' => $admin['month'],
'nation_count' => $nationCount,
'nation_name' => $nationName,
'nation_hist' => $nationHist,
'gen_count' => $generalCountStr,
'personal_hist' => $personalHistStr,
'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,
'general_no' => $general['no'],
'owner' => $general['owner'],
'name' => $general['name'],
'last_yearmonth' => $year * 100 + $month,
'turntime' => $general['turntime'],
'data' => Json::encode($general)
];
}
function storeOldGeneral(int $no, int $year, int $month)
{
$db = DB::db();
$general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
if (!$general) {
return;
}
$data = convForOldGeneral($general, $year, $month);
$db->insertUpdate(
'ng_old_generals',
$data,
$data
);
}
function storeOldGenerals(int $nation, int $year, int $month)
{
$db = DB::db();
foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
$data = convForOldGeneral($general, $year, $month);
$db->insertUpdate(
'ng_old_generals',
$data,
$data
);
}
}
function checkEmperior()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
if ($admin['isunited'] != 0) {
return;
}
$remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2');
if (!$remainNations || count($remainNations) != 1) {
return;
}
$nationID = $remainNations[0];
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID);
if (!$cityCnt) {
return;
}
if ($cityCnt != count(CityConst::all())) {
return;
}
checkStatistic();
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name'];
$josaYi = JosaUtil::pick($nationName, '이');
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
$gameStor->isunited = 2;
$gameStor->conlimit = $gameStor->conlimit * 100;
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
CheckHall($hallGeneralNo);
}
[$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city');
$pop = "{$totalPop} / {$totalMaxPop}";
$poprate = round($totalPop / $totalMaxPop * 100, 2). " %";
$chiefs = Util::convertArrayToDict(
$db->query(
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
$nationID
),
'officer_level'
);
$nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID);
$nation['generals'] = $nationGenerals;
$tigers = $db->query(
'SELECT value, name
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',
$nationID
); // 오호장군
$tigerstr = join(', ', array_map(function ($arr) {
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $tigers));
$eagles = $db->query(
'SELECT value, name
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',
$nationID
); // 건안칠자
$eaglestr = join(', ', array_map(function ($arr) {
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $eagles));
$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']);
$generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH);
$generalLogger->flush();
}
$gen = join(', ', array_column($rawGeneral, 'name'));
$nation['type'] = getNationType($nation['type']);
$stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic');
$genCnt = $db->queryFirstField('SELECT count(*) FROM general');
$statNC = "1 / {$stat['nc']}";
$statGC = "{$genCnt} / {$stat['gc']}";
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
$statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1');
$nation = $nation;
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
$nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->notice;
$nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power;
$nation['history'] = getNationHistoryLogAll($nation['nation']);
storeOldGenerals(0, $admin['year'], $admin['month']);
storeOldGenerals($nation['nation'], $admin['year'], $admin['month']);
$db->insert('ng_old_nations', [
'server_id' => UniqueConst::$serverID,
'nation' => $nation['nation'],
'data' => Json::encode($nation)
]);
$noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0');
$db->insert('ng_old_nations', [
'server_id' => UniqueConst::$serverID,
'nation' => 0,
'data' => Json::encode([
'nation' => 0,
'name' => '재야',
'generals' => $noNationGeneral
])
]);
$nationHistory = getNationHistoryLogAll($nation['nation']);
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
$serverName = UniqueConst::$serverName;
$db->update('ng_games', [
'winner_nation' => $nation['nation']
], 'server_id=%s', UniqueConst::$serverID);
$db->insert('emperior', [
'phase' => $serverName . $serverCnt . '기',
'server_id' => UniqueConst::$serverID,
'nation_count' => $statNC,
'nation_name' => $statNation['nation_name'],
'nation_hist' => $statNation['nation_hist'],
'gen_count' => $statGC,
'personal_hist' => $statGeneral['personal_hist'],
'special_hist' => $statGeneral['special_hist'],
'name' => $nation['name'],
'type' => $nation['type'],
'color' => $nation['color'],
'year' => $admin['year'],
'month' => $admin['month'],
'power' => $nation['power'],
'gennum' => $nation['gennum'],
'citynum' => $cityCnt,
'pop' => $pop,
'poprate' => $poprate,
'gold' => $nation['gold'],
'rice' => $nation['rice'],
'l12name' => $chiefs[12]['name'],
'l12pic' => $chiefs[12]['picture'],
'l11name' => $chiefs[11]['name'],
'l11pic' => $chiefs[11]['picture'],
'l10name' => $chiefs[10]['name'],
'l10pic' => $chiefs[10]['picture'],
'l9name' => $chiefs[9]['name'],
'l9pic' => $chiefs[9]['picture'],
'l8name' => $chiefs[8]['name'],
'l8pic' => $chiefs[8]['picture'],
'l7name' => $chiefs[7]['name'],
'l7pic' => $chiefs[7]['picture'],
'l6name' => $chiefs[6]['name'],
'l6pic' => $chiefs[6]['picture'],
'l5name' => $chiefs[5]['name'],
'l5pic' => $chiefs[5]['picture'],
'tiger' => $tigerstr,
'eagle' => $eaglestr,
'gen' => $gen,
'history' => JSON::encode($nationHistory),
'aux' => $statGeneral['aux']
]);
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
//연감 월결산
LogHistory();
}
<?php
namespace sammo;
use Monolog\Logger;
/**
* 게임 룰에 해당하는 함수 모음
*/
function getNationLevelList(): array
{
$table = [
0 => ['방랑군', 2, 0],
1 => ['호족', 2, 1],
2 => ['군벌', 4, 2],
3 => ['주자사', 4, 5],
4 => ['주목', 6, 8],
5 => ['공', 6, 11],
6 => ['왕', 8, 16],
7 => ['황제', 8, 21],
];
return $table;
}
function getCityLevelList(): array
{
return [
1 => '수',
2 => '진',
3 => '관',
4 => '이',
5 => '소',
6 => '중',
7 => '대',
8 => '특'
];
}
//한국가의 전체 전방 설정
function SetNationFront($nationNo)
{
if (!$nationNo) {
return;
}
// 도시소유 국가와 선포,교전중인 국가
$adj3 = [];
$adj2 = [];
$adj1 = [];
$db = DB::db();
foreach ($db->queryFirstColumn(
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i',
$nationNo
) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj3[$adjKey] = $adjVal;
}
};
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',
$nationNo
) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj1[$adjKey] = $adjVal;
}
}
if (!$adj3 && !$adj1) {
//평시이면 공백지
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj2[$adjKey] = $adjVal;
}
}
}
$db->update('city', [
'front' => 0
], 'nation=%i', $nationNo);
if ($adj1) {
$db->update('city', [
'front' => 1,
], 'nation=%i and city in %li', $nationNo, array_keys($adj1));
}
if ($adj2) {
$db->update('city', [
'front' => 2,
], 'nation=%i and city in %li', $nationNo, array_keys($adj2));
}
if ($adj3) {
$db->update('city', [
'front' => 3,
], 'nation=%i and city in %li', $nationNo, array_keys($adj3));
}
}
function checkSupply()
{
$db = DB::db();
$cities = [];
foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) {
$newCity = new \stdClass();
$newCity->id = Util::toInt($city['city']);
$newCity->nation = Util::toInt($city['nation']);
$newCity->supply = false;
$cities[$newCity->id] = $newCity;
}
$queue = new \SplQueue();
foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) {
if (!key_exists($capitalID, $cities)) {
continue;
}
$city = $cities[$capitalID];
if ($nationID != $city->nation) {
continue;
}
$city->supply = true;
$queue->enqueue($city);
}
while (!$queue->isEmpty()) {
$cityLink = $queue->dequeue();
$city = CityConst::byID($cityLink->id);
foreach (array_keys($city->path) as $connCityID) {
if (!key_exists($connCityID, $cities)) {
continue;
}
$connCity = $cities[$connCityID];
if ($connCity->nation != $cityLink->nation) {
continue;
}
if ($connCity->supply) {
continue;
}
$connCity->supply = true;
$queue->enqueue($connCity);
}
}
$db->update('city', [
'supply' => 1
], 'nation=0');
$db->update('city', [
'supply' => 0
], 'nation!=0');
$supply = [];
foreach ($cities as $city) {
if ($city->supply) {
$supply[] = $city->id;
}
}
if ($supply) {
$db->update('city', [
'supply' => 1
], 'city IN %li', $supply);
}
}
function updateGeneralNumber(){
$db = DB::db();
foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){
if($nationID === 0){
continue;
}
$db->update('nation', [
'gennum'=>$gennum
], 'nation=%i', $nationID);
}
refreshNationStaticInfo();
}
function updateYearly()
{
//통계
checkStatistic();
}
//관직 변경 해제
function updateQuaterly()
{
$db = DB::db();
//천도 제한 해제, 관직 변경 제한 해제
$db->update('nation', [
'chief_set' => 0,
], true);
//관직 변경 제한 해제
$db->update('city', [
'officer_set' => 0,
], true);
}
// 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
function preUpdateMonthly()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
//연감 월결산
$result = LogHistory();
if ($result == false) {
return false;
}
$admin = $gameStor->getValues(['startyear', 'year', 'month']);
$logger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//보급선 체크
checkSupply();
//미보급도시 10% 감소
$db->update('city', [
'pop' => $db->sqleval('pop * 0.9'),
'trust' => $db->sqleval('trust * 0.9'),
'agri' => $db->sqleval('agri * 0.9'),
'comm' => $db->sqleval('comm * 0.9'),
'secu' => $db->sqleval('secu * 0.9'),
'def' => $db->sqleval('def * 0.9'),
'wall' => $db->sqleval('wall * 0.9'),
], 'supply = 0');
//미보급도시 장수 병 훈 사 5%감소
//NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게.
$unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0');
foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) {
$cityIDList = Util::squeezeFromArray($cityList, 'city');
$db->update('general', [
'crew' => $db->sqleval('crew*0.95'),
'atmos' => $db->sqleval('atmos*0.95'),
'train' => $db->sqleval('train*0.95'),
], 'city IN %li AND nation = %i', $cityIDList, $nationID);
}
//민심30이하 공백지 처리
$lostCities = [];
foreach ($unsuppliedCities as $unsuppliedCity) {
if ($unsuppliedCity['trust'] >= 30) {
continue;
}
$lostCities[$unsuppliedCity['city']] = $unsuppliedCity;
}
if ($lostCities) {
foreach ($lostCities as $lostCity) {
$josaYi = JosaUtil::pick($lostCity['name'], '이');
$logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다.");
}
$db->update('general', [
'officer_level' => 1,
'officer_city' => 0
], 'officer_city IN %li', array_keys($lostCities));
$db->update('city', [
'nation' => 0,
'officer_set' => 0,
'conflict' => '{}',
'term' => 0,
'front' => 0
], 'city IN %li', array_keys($lostCities));
}
//접률감소, 건국제한-1
$db->update('general', [
'connect' => $db->sqleval('floor(connect*0.99)'),
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
], true);
//전략제한-1, 외교제한-1, 세율동기화
$db->update('nation', [
'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'),
'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'),
'rate_tmp' => $db->sqleval('rate')
], true);
//도시훈사 180년 60, 220년 87, 240년 100
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
if ($rate > 100) $rate = 100;
// 20 ~ 140원
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
$gameStor->city_rate = $rate;
$gameStor->develcost = $develcost;
//매달 사망자 수입 결산
processWarIncome();
//계략, 전쟁표시 해제
$db->update('city', [
'state' => $db->sqleval(<<<EOD
(CASE
WHEN state=31 THEN 0
WHEN state=32 THEN 31
WHEN state=33 THEN 0
WHEN state=34 THEN 33
WHEN state=41 THEN 0
WHEN state=42 THEN 41
WHEN state=43 THEN 42
ELSE state END)
EOD),
'term' => $db->sqleval('greatest(0, term - 1)'),
'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'),
], true);
//첩보-1
foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) {
$spyInfo = Json::decode($rawSpy);
foreach ($spyInfo as $cityNo => $remainMonth) {
if ($remainMonth <= 1) {
unset($spyInfo[$cityNo]);
} else {
$spyInfo[$cityNo] -= 1;
}
}
$db->update('nation', [
'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
], 'nation=%i', $nationNo);
}
return true;
}
// 외교 로그처리, 외교 상태 처리
function postUpdateMonthly()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']);
$globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//도시 수 측정
$cityNations = [];
foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) {
if (!key_exists($cityNation, $cityNations)) {
$cityNations[$cityNation] = [];
}
$cityNations[$cityNation][] = $cityName;
}
//각 국가 전월 장수수 대비 당월 장수수로 단합도 산정
//각 국가 장수수를 구하고 국력 산정
// $query = "select nation,gennum from nation where level>0";
// 국력=
// 자원(국가/장수의 금,쌀)
// 기술력
// 인구수*내정%
// 장수능력
// 접속률
// 숙련도
// 명성,공헌
$nations = Util::convertArrayToDict($db->query('SELECT
A.nation,
A.gennum,
round((
round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100)
+A.tech
+if(A.level=0,0,(
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
) from city where nation=A.nation and supply=1
))
+(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(experience+dedication)/100) from general where nation=A.nation)
+(select round(avg(connect)) from general where nation=A.nation)
)/10)
as power,
(select sum(crew) from general where nation=A.nation) as totalCrew
from nation A
group by A.nation'), 'nation');
$maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power');
foreach ($nations as $nation) {
$nationID = $nation['nation'];
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$genNum[$nationID] = $nation['gennum'];
$powerValues = $maxPowerValues[$nationID]??[];
//약간의 랜덤치 부여 (95% ~ 105%)
$nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000);
$powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']);
$powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew']));
if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) {
$powerValues['maxCities'] = $cityNations[$nationID];
}
$db->update('nation', [
'power' => $nation['power']
], 'nation=%i', $nationID);
$nationStor->max_power = $powerValues;
}
// 전쟁기한 세팅
foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) {
$genCount = $genNum[$dip['me']];
// 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산
// 4000 / 10 * 0.25 = 100
$term = floor($dip['dead'] / 100 / $genCount);
$dip['dead'] -= $term * 100 * $genCount;
$term = Util::valueFit($dip['term'] + $term, 0, 13);
$db->update('diplomacy', [
'term' => $term,
'dead' => $dip['dead'],
], '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){
$nation1 = getNationStaticInfo($dip['me']);
$name1 = $nation1['name'];
$nation2 = getNationStaticInfo($dip['you']);
$name2 = $nation2['name'];
$josaYi = JosaUtil::pick($name2, '이');
$josaWa = JosaUtil::pick($name1, '와');
$globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다.");
}
//휴전국 로그
$stopWarList = [];
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){
$key = "{$me}_{$you}";
}
else{
$key = "{$you}_{$me}";
}
if(!key_exists($key, $stopWarList)){
$stopWarList[$key] = true;
continue;
}
//양측 기간 모두 0이 되는 상황이면 휴전
$nation1 = getNationStaticInfo($me);
$name1 = $nation1['name'];
$nation2 = getNationStaticInfo($you);
$name2 = $nation2['name'];
$josaWa = JosaUtil::pick($name1, '와');
$josaYi = JosaUtil::pick($name2, '이');
$globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다.");
$db->update('diplomacy', [
'state'=>2,
'term'=>0,
], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you);
}
$globalLogger->flush();
//사상자 초기화, 외교 기한-1
$db->update('diplomacy', [
'dead'=>$db->sqleval('if(state!=0, 0, dead)'),
'term'=>$db->sqleval('greatest(0, term-1)'),
], true);
//불가침 끝나면 통상으로
$db->update('diplomacy', [
'state'=>2,
], 'state = 7 AND term = 0');
//선포 끝나면 교전으로
$db->update('diplomacy', [
'state'=>0,
'term'=>6,
], 'state = 1 AND term = 0');
//초반이후 방랑군 자동 해체
if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander();
}
// 작위 업데이트
updateNationState();
updateGeneralNumber();
refreshNationStaticInfo();
// 천통여부 검사
checkEmperior();
//토너먼트 개시
triggerTournament();
// 시스템 거래건 등록
registerAuction();
//전방설정
foreach (getAllNationStaticInfo() as $nation) {
if ($nation['level'] <= 0) {
continue;
}
SetNationFront($nation['nation']);
}
}
function checkWander()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$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');
foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) {
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
if ($wanderCmd->hasFullConditionMet()) {
$logger = $wanderer->getLogger();
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
$wanderCmd->run();
$wanderCmd->setNextAvailable();
}
}
if ($wanderers) {
refreshNationStaticInfo();
}
}
function updateNationState()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$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[$nationID] = $assemblerCnt;
};
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
if ($citycount == 0) {
$nationlevel = 0; // 방랑군
} elseif ($citycount == 1) {
$nationlevel = 1; // 호족
} elseif ($citycount <= 4) {
$nationlevel = 2; // 군벌
} elseif ($citycount <= 7) {
$nationlevel = 3; // 주자사
} elseif ($citycount <= 10) {
$nationlevel = 4; // 주목
} elseif ($citycount <= 15) {
$nationlevel = 5; // 공
} elseif ($citycount <= 20) {
$nationlevel = 6; // 왕
} else {
$nationlevel = 7; // 황제
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level'];
$oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel,
'gold'=>$db->sqleval('gold + %i', $nationlevel*1000),
'rice'=>$db->sqleval('rice + %i', $nationlevel*1000),
];
switch ($nationlevel) {
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} 자칭하였습니다.";
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$auxVal = Json::decode($nation['aux']);
$auxVal['can_국기변경'] = 1;
$auxVal['can_국호변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal);
break;
case 6:
$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) . "</>에 등극"]);
break;
case 5:
case 4:
case 3:
$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) . "</>에 임명됨"]);
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) . "</>로 나서다"]);
break;
}
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
$turnRows[] = [
'nation_id' => $nation['nation'],
'officer_level' => $chiefLevel,
'turn_idx' => $turnIdx,
'action' => '휴식',
'arg' => null,
'brief' => '휴식'
];
}
}
$db->insertIgnore('nation_turn', $turnRows);
if ($levelDiff) {
//유니크 아이템 하나 돌리자
$targetKillTurn = $admin['killturn'];
$targetKillTurn -= 24 * 60 / $admin['turnterm'];
$nationGenIDList = $db->queryFirstColumn(
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$nation['nation'],
$targetKillTurn
);
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc'], 2);
$chiefObj = null;
$uniqueLotteryWeightList = [];
foreach ($nationGenList as $nationGen) {
if ($nationGen->getVar('officer_level') == 12) {
$chiefObj = $nationGen;
}
$trialCnt = count(GameConst::$allItems);
foreach ($nationGen->getItems() as $item) {
if (!$item->isBuyable()) {
$trialCnt -= 1;
}
}
if ($trialCnt <= 0) {
continue;
}
$score = $nationGen->getVar('belong') + 5;
if ($nationGen->getVar('officer_level') == 12) {
$score += 100; //NOTE: 꼬우면 군주하세요.
} else if ($nationGen->getVar('officer_level') == 11) {
$score += 50;
} else if ($nationGen->getVar('officer_level') > 4) {
$score += 35;
}
$score *= $trialCnt;
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
}
foreach (Util::range($levelDiff) as $idx) {
if (!$uniqueLotteryWeightList) {
break;
}
/** @var General */
$winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
unset($uniqueLotteryWeightList[$winnerObj->getID()]);
giveRandomUniqueItem($winnerObj, '작위보상');
$winnerObj->applyDB($db);
}
if($chiefObj){
$chiefObj->increaseInheritancePoint('unifier', 250 * $levelDiff);
}
}
}
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0;
$maxAssemblerCnt = [
1 => 0,
2 => 1,
3 => 3,
4 => 4,
5 => 6,
6 => 7,
7 => 9
][$nationlevel] ?? 0;
if ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID = $gameStor->assembler_id ?? 0;
while ($assemblerCnt < $maxAssemblerCnt) {
$lastAssemblerID += 1;
$npcObj = new Scenario\GeneralBuilder(
sprintf('부대장%4d', $lastAssemblerID),
false,
null,
$nation['nation']
);
$npcObj->setAffinity(999)->setStat(10, 10, 10)
->setSpecialSingle('척사')->setEgo('che_은둔')
->setKillturn(70)->setGoldRice(0, 0)
->setNPCType(5)->fillRemainSpecAsZero($admin);
$npcObj->build($admin);
$npcID = $npcObj->getGeneralID();
$db->insert('troop', [
'troop_leader' => $npcID,
'name' => $npcObj->getGeneralName(),
'nation' => $nation['nation'],
]);
$db->update('general', [
'troop' => $npcID
], 'no=%i', $npcID);
$cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin);
_setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn)));
$assemblerCnt += 1;
$gameStor->assembler_id = $lastAssemblerID;
}
}
}
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
function checkStatistic()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month']);
$nationHists = [];
$specialHists = [];
$personalHists = [];
$specialHists2 = [];
$crewtypeHists = [];
$etc = '';
$auxData = [
'generals' => [],
'nations' => [],
];
$avgGeneral = $db->queryFirstRow(
'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
FROM general'
);
$auxData['generals']['avg'] = $avgGeneral;
$avgGeneral['avggold'] = Util::round($avgGeneral['avggold']);
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']);
$avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']);
$avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
$etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), ";
$avgNation = $db->queryFirstRow(
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech,
min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0'
);
$auxData['nations']['avg'] = $avgNation;
$avgNation['mintech'] = floor($avgNation['mintech']);
$avgNation['maxtech'] = floor($avgNation['maxtech']);
$avgNation['avgtech'] = Util::round($avgNation['avgtech']);
$avgNation['avgpower'] = Util::round($avgNation['avgpower']);
$etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), ";
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), ";
$nationName = '';
$powerHist = '';
$nations = Util::convertArrayToDict(
$db->query(
'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc',
'nation'
),
'nation'
);
$nationCount = count($nations);
$nationGeneralInfos = Util::convertArrayToDict(
$db->query(
'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'
),
'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'
);
foreach ($nations as $nationNo => &$nation) {
$general = $nationGeneralInfos[$nationNo];
$city = $nationCityInfos[$nationNo];
$nation['generalInfo'] = $general;
$nation['cityInfo'] = $city;
$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']}), ";
if (!isset($nationHists[$nation['type']])) {
$nationHists[$nation['type']] = 0;
}
$nationHists[$nation['type']]++;
}
unset($nation);
$auxData['nations']['all'] = $nations;
$nationHist = '';
foreach (GameConst::$availableNationType as $nationType) {
if (!Util::array_get($nationHists[$nationType])) {
$nationHists[$nationType] = '-';
}
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
}
$generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general');
$genCount = 0;
$npcCount = 0;
$generalCount = count($generals);
foreach ($generals as $general) {
if (!isset($personalHists[$general['personal']])) {
$personalHists[$general['personal']] = 0;
}
if (!isset($specialHists[$general['special']])) {
$specialHists[$general['special']] = 0;
}
if (!isset($specialHists2[$general['special2']])) {
$specialHists2[$general['special2']] = 0;
}
if ($general['npc'] < 2) {
$genCount += 1;
} else {
$npcCount += 1;
}
$personalHists[$general['personal']]++;
$specialHists[$general['special']]++;
$specialHists2[$general['special2']]++;
}
foreach ($db->queryAllLists(
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype'
) as [$crewtype, $cnt]) {
$crewtypeHists[$crewtype] = $cnt;
}
$auxData['generals']['hists'] = [
'personal' => $personalHists,
'special' => $specialHists,
'special2' => $specialHists2,
'crewtype' => $crewtypeHists,
'userCnt' => $genCount,
'npcCnt' => $npcCount,
];
$generalCountStr = "{$generalCount}({$genCount}+{$npcCount})";
$personalHistStr = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return getGenChar($histKey) . '(' . $cnt . ')';
}, Util::convertDictToArray($personalHists)));
$specialHistsStr = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')';
}, Util::convertDictToArray($specialHists)));
$specialHists2Str = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')';
}, Util::convertDictToArray($specialHists2)));
$specialHistsAllStr = "$specialHistsStr // $specialHists2Str";
$crewtypeHistsStr = join(', ', array_map(function ($histPair) {
[$histKey, $cnt] = $histPair;
return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')';
}, Util::convertDictToArray($crewtypeHists)));
$db->insert('statistic', [
'year' => $admin['year'],
'month' => $admin['month'],
'nation_count' => $nationCount,
'nation_name' => $nationName,
'nation_hist' => $nationHist,
'gen_count' => $generalCountStr,
'personal_hist' => $personalHistStr,
'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,
'general_no' => $general['no'],
'owner' => $general['owner'],
'name' => $general['name'],
'last_yearmonth' => $year * 100 + $month,
'turntime' => $general['turntime'],
'data' => Json::encode($general)
];
}
function storeOldGeneral(int $no, int $year, int $month)
{
$db = DB::db();
$general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
if (!$general) {
return;
}
$data = convForOldGeneral($general, $year, $month);
$db->insertUpdate(
'ng_old_generals',
$data,
$data
);
}
function storeOldGenerals(int $nation, int $year, int $month)
{
$db = DB::db();
foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
$data = convForOldGeneral($general, $year, $month);
$db->insertUpdate(
'ng_old_generals',
$data,
$data
);
}
}
function checkEmperior()
{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
if ($admin['isunited'] != 0) {
return;
}
$remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2');
if (!$remainNations || count($remainNations) != 1) {
return;
}
$nationID = $remainNations[0];
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID);
if (!$cityCnt) {
return;
}
if ($cityCnt != count(CityConst::all())) {
return;
}
checkStatistic();
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name'];
$josaYi = JosaUtil::pick($nationName, '이');
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
if($genObj->getNationID() == $nationID){
if($genObj->getVar('officer_level') > 4){
$genObj->increaseInheritancePoint('unifier', 2000);
};
}
$genObj->mergeTotalInheritancePoint();
}
$gameStor->isunited = 2;
$gameStor->conlimit = $gameStor->conlimit * 100;
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
CheckHall($hallGeneralNo);
}
[$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city');
$pop = "{$totalPop} / {$totalMaxPop}";
$poprate = round($totalPop / $totalMaxPop * 100, 2). " %";
$chiefs = Util::convertArrayToDict(
$db->query(
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
$nationID
),
'officer_level'
);
$nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID);
$nation['generals'] = $nationGenerals;
$tigers = $db->query(
'SELECT value, name
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5',
$nationID
); // 오호장군
$tigerstr = join(', ', array_map(function ($arr) {
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $tigers));
$eagles = $db->query(
'SELECT value, name
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',
$nationID
); // 건안칠자
$eaglestr = join(', ', array_map(function ($arr) {
$number = number_format($arr['value']);
return "{$arr['name']}{$number}";
}, $eagles));
$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']);
$generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH);
$generalLogger->flush();
}
$gen = join(', ', array_column($rawGeneralList, 'name'));
$stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic');
$genCnt = $db->queryFirstField('SELECT count(*) FROM general');
$statNC = "1 / {$stat['nc']}";
$statGC = "{$genCnt} / {$stat['gc']}";
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
$statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1');
$nation = $nation;
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
$nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->notice;
$nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power;
$nation['history'] = getNationHistoryLogAll($nation['nation']);
storeOldGenerals(0, $admin['year'], $admin['month']);
storeOldGenerals($nation['nation'], $admin['year'], $admin['month']);
$db->insert('ng_old_nations', [
'server_id' => UniqueConst::$serverID,
'nation' => $nation['nation'],
'data' => Json::encode($nation)
]);
$noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0');
$db->insert('ng_old_nations', [
'server_id' => UniqueConst::$serverID,
'nation' => 0,
'data' => Json::encode([
'nation' => 0,
'name' => '재야',
'generals' => $noNationGeneral
])
]);
$nationHistory = getNationHistoryLogAll($nation['nation']);
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
$serverName = UniqueConst::$serverName;
$db->update('ng_games', [
'winner_nation' => $nation['nation']
], 'server_id=%s', UniqueConst::$serverID);
$db->insert('emperior', [
'phase' => $serverName . $serverCnt . '기',
'server_id' => UniqueConst::$serverID,
'nation_count' => $statNC,
'nation_name' => $statNation['nation_name'],
'nation_hist' => $statNation['nation_hist'],
'gen_count' => $statGC,
'personal_hist' => $statGeneral['personal_hist'],
'special_hist' => $statGeneral['special_hist'],
'name' => $nation['name'],
'type' => $nation['type'],
'color' => $nation['color'],
'year' => $admin['year'],
'month' => $admin['month'],
'power' => $nation['power'],
'gennum' => $nation['gennum'],
'citynum' => $cityCnt,
'pop' => $pop,
'poprate' => $poprate,
'gold' => $nation['gold'],
'rice' => $nation['rice'],
'l12name' => $chiefs[12]['name'],
'l12pic' => $chiefs[12]['picture'],
'l11name' => $chiefs[11]['name'],
'l11pic' => $chiefs[11]['picture'],
'l10name' => $chiefs[10]['name'],
'l10pic' => $chiefs[10]['picture'],
'l9name' => $chiefs[9]['name'],
'l9pic' => $chiefs[9]['picture'],
'l8name' => $chiefs[8]['name'],
'l8pic' => $chiefs[8]['picture'],
'l7name' => $chiefs[7]['name'],
'l7pic' => $chiefs[7]['picture'],
'l6name' => $chiefs[6]['name'],
'l6pic' => $chiefs[6]['picture'],
'l5name' => $chiefs[5]['name'],
'l5pic' => $chiefs[5]['picture'],
'tiger' => $tigerstr,
'eagle' => $eaglestr,
'gen' => $gen,
'history' => JSON::encode($nationHistory),
'aux' => $statGeneral['aux']
]);
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."];
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
//연감 월결산
LogHistory();
}
function resetInheritanceUser(int $userID, bool $isRebirth=false){
$rebirthDegraded = [
'dex'=>0.5,
];
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$totalPoint = 0;
foreach($inheritStor->getAll() as $key=>[$value,]){
if(key_exists($key, $rebirthDegraded)){
$value *= $rebirthDegraded[$key];
}
$totalPoint += $value;
}
$totalPoint = Util::toInt($totalPoint);
$inheritStor->resetValues();
$inheritStor->setValue('previous', [$totalPoint, null]);
}
function updateMaxDomesticCritical(General $general, $score){
$maxDomesticCritical = $general->getAuxVar('max_domestic_critical')??0;
$maxDomesticCritical += $score / 2;
$general->setAuxVar('max_domestic_critical', $maxDomesticCritical);
$oldMaxDomesticCritical = $general->getInheritancePoint('max_domestic_critical');
if($maxDomesticCritical > $oldMaxDomesticCritical){
$general->setInheritancePoint('max_domestic_critical', $maxDomesticCritical);
}
}
+20 -4
View File
@@ -39,10 +39,26 @@ function bar($per, $h=7) {
}
function optionsForCities() {
return join('', array_map(function($city){
return "<option value='{$city->id}'>{$city->name}</option>";
}, CityConst::all()));
function optionsForCities(callable $infoCall=null) {
if(!$infoCall){
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="") {
+274 -270
View File
@@ -1,270 +1,274 @@
<?php
namespace sammo;
/**
* 템플릿 생성과 관련된 함수들을 모아두는 파일
*
* NOTE: 아직 converter와 명확한 구분이 되어있지 않음.
* TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음
* TODO: side effect를 제거
*/
/**
* 관리자 권한이 필요함을 출력.
* @return void
*/
function requireAdminPermissionHTML()
{
ob_start();
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('css/common.css') ?>
</head>
<body>
관리자가 아닙니다.<br>
<?= banner() ?>
</body>
</html>
<?php
return ob_get_clean();
}
function turnTable()
{
$turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) {
$turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
}
$turnText = join("\n", $turnList);
return "
<select id='generalTurnSelector' name=turn[] size=11 multiple>
<option value='-3'>전체</option>
<option value='-1'>홀턴</option>
<option value='-2'>짝턴</option>
{$turnText}
</select>
";
}
function chiefTurnTable()
{
$turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) {
$turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
}
$turnText = join("\n", $turnList);
return "
<select id='chiefTurnSelector' name=turn[] size=6 multiple>
{$turnText}
</select>
";
}
function displayiActionObjInfo(?iAction $action)
{
if ($action === null) {
$info = '';
$text = '-';
} else {
$info = $action->getInfo();
$text = $action->getName();
}
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $text,
'info' => $info,
]);
}
function displayCharInfo(string $type): string
{
$class = buildPersonalityClass($type);
$info = $class->getInfo();
$text = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $text,
'info' => $info,
]);
}
function displaySpecialWarInfo(?string $type): string
{
$class = buildGeneralSpecialWarClass($type);
$info = $class->getInfo();
$name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $name,
'info' => $info,
]);
}
function displaySpecialDomesticInfo(?string $type): string
{
$class = buildGeneralSpecialDomesticClass($type);
$info = $class->getInfo();
$name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $name,
'info' => $info,
]);
}
function allButton(bool $seizeNPCMode)
{
if ($seizeNPCMode) {
$site = "a_npcList.php";
$call = "빙의일람";
} else {
$site = "a_vote.php";
$call = "설문조사";
}
if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) {
$templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates');
} else {
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
}
return $templates->render('allButton', [
'call' => $call,
'site' => $site
]);
}
function commandButton()
{
$session = Session::getInstance();
$userID = Session::getUserID();
if (!$session->isGameLoggedIn()) {
return '';
}
$db = DB::db();
$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' => 0,
'level' => 0,
'secretlimit' => 99,
'color' => '#000000'
];
$bgColor = Util::array_get($nation['color']) ?: '#000000';
$fgColor = newColor($bgColor);
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
$showSecret = false;
$permission = checkSecretPermission($me);
if ($permission >= 1) {
$showSecret = true;
} else if ($me['officer_level'] == 0) {
$showSecret = false;
}
return $templates->render('commandButton', [
'bgColor' => $bgColor,
'fgColor' => $fgColor,
'meLevel' => $me['officer_level'],
'nationLevel' => $nation['level'],
'showSecret' => $showSecret,
'permission' => $permission,
]);
}
function formatWounded(int $value, int $wound): string
{
if ($wound == 0) {
return "$value";
}
$woundedValue = intdiv($value * (100 - $wound), 100);
return "<font color=red>$woundedValue</font>";
}
function formatDefenceTrain(int $value): string
{
if ($value === 999) {
return "×";
} else if ($value >= 80) {
return "";
} else {
return "";
}
}
function formatLeadershipBonus(int $value): string
{
if ($value == 0) {
return '';
}
return "<font color=cyan>+{$value}</font>";
}
function formatName(string $name, int $npc): string
{
if ($npc == 1) {
$name = "<font color='skyblue'>$name</font>";
} else if ($npc > 1) {
$name = "<font color='cyan'>$name</font>";
}
return $name;
}
function getMapHtml(?string $mapTheme = null)
{
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
if ($mapTheme === null) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme ?? 'che';
}
return $templates->render('map', [
'mapTheme' => $mapTheme
]);
}
function getInvitationList(array $nationList)
{
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
foreach ($nationList as &$nation) {
$nation['textColor'] = newColor($nation['color']);
}
return $templates->render('invitationList', [
'nationList' => $nationList
]);
}
<?php
namespace sammo;
/**
* 템플릿 생성과 관련된 함수들을 모아두는 파일
*
* NOTE: 아직 converter와 명확한 구분이 되어있지 않음.
* TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음
* TODO: side effect를 제거
*/
/**
* 관리자 권한이 필요함을 출력.
* @return void
*/
function requireAdminPermissionHTML()
{
ob_start();
?>
<!DOCTYPE html>
<html>
<head>
<title>관리메뉴</title>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('css/common.css') ?>
</head>
<body>
관리자가 아닙니다.<br>
<?= banner() ?>
</body>
</html>
<?php
return ob_get_clean();
}
function turnTable()
{
$turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) {
$turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
}
$turnText = join("\n", $turnList);
return "
<select id='generalTurnSelector' name=turn[] size=11 multiple>
<option value='-3'>전체</option>
<option value='-1'>홀턴</option>
<option value='-2'>짝턴</option>
{$turnText}
</select>
";
}
function chiefTurnTable()
{
$turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) {
$turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
}
$turnText = join("\n", $turnList);
return "
<select id='chiefTurnSelector' name=turn[] size=6 multiple>
{$turnText}
</select>
";
}
function displayiActionObjInfo(?iAction $action)
{
if ($action === null) {
$info = '';
$text = '-';
} else {
$info = $action->getInfo();
$text = $action->getName();
}
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $text,
'info' => $info,
]);
}
function displayCharInfo(string $type): string
{
$class = buildPersonalityClass($type);
$info = $class->getInfo();
$text = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $text,
'info' => $info,
]);
}
function displaySpecialWarInfo(?string $type): string
{
$class = buildGeneralSpecialWarClass($type);
$info = $class->getInfo();
$name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $name,
'info' => $info,
]);
}
function displaySpecialDomesticInfo(?string $type): string
{
$class = buildGeneralSpecialDomesticClass($type);
$info = $class->getInfo();
$name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [
'text' => $name,
'info' => $info,
]);
}
function allButton(bool $seizeNPCMode)
{
if ($seizeNPCMode) {
$site = "a_npcList.php";
$call = "빙의일람";
} else {
$site = "a_vote.php";
$call = "설문조사";
}
if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) {
$templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates');
} else {
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
}
return $templates->render('allButton', [
'call' => $call,
'site' => $site
]);
}
function commandButton()
{
$session = Session::getInstance();
$userID = Session::getUserID();
if (!$session->isGameLoggedIn()) {
return '';
}
$db = DB::db();
$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' => 0,
'level' => 0,
'secretlimit' => 99,
'color' => '#000000'
];
$bgColor = Util::array_get($nation['color']) ?: '#000000';
$fgColor = newColor($bgColor);
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
$showSecret = false;
$permission = checkSecretPermission($me);
if ($permission >= 1) {
$showSecret = true;
} else if ($me['officer_level'] == 0) {
$showSecret = false;
}
return $templates->render('commandButton', [
'bgColor' => $bgColor,
'fgColor' => $fgColor,
'meLevel' => $me['officer_level'],
'nationLevel' => $nation['level'],
'showSecret' => $showSecret,
'permission' => $permission,
]);
}
function formatWounded(int $value, int $wound): string
{
if ($wound == 0) {
return "$value";
}
$woundedValue = intdiv($value * (100 - $wound), 100);
return "<font color=red>$woundedValue</font>";
}
function formatDefenceTrain(int $value): string
{
if ($value === 999) {
return "×";
} else if ($value >= 90){
return "";
} else if ($value >= 80) {
return "";
} else if ($value >= 60) {
return "";
} else{
return "";
}
}
function formatLeadershipBonus(int $value): string
{
if ($value == 0) {
return '';
}
return "<font color=cyan>+{$value}</font>";
}
function formatName(string $name, int $npc): string
{
if ($npc == 1) {
$name = "<font color='skyblue'>$name</font>";
} else if ($npc > 1) {
$name = "<font color='cyan'>$name</font>";
}
return $name;
}
function getMapHtml(?string $mapTheme = null)
{
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
if ($mapTheme === null) {
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme ?? 'che';
}
return $templates->render('map', [
'mapTheme' => $mapTheme
]);
}
function getInvitationList(array $nationList)
{
$templates = new \League\Plates\Engine(__DIR__ . '/templates');
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;
}
$nation['gold'] = Util::valueFit($nation['gold'], GameConst::$basegold);
$adminLog[] = StringUtil::padStringAlignRight((string)$nation['name'],12," ")
." // 세금 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
@@ -87,6 +88,8 @@ function processGoldIncome() {
$incomeText = number_format($income);
$incomeLog = "이번 수입은 금 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_gold = $income;
$db->update('nation', [
'gold'=>$nation['gold']
@@ -353,6 +356,7 @@ function processRiceIncome() {
// 실지급률
$ratio = $realoutcome / $originoutcome;
}
$nation['rice'] = Util::valueFit($nation['rice'], GameConst::$baserice);
$adminLog[] = StringUtil::padStringAlignRight($nation['name'],12," ")
." // 세곡 : ".StringUtil::padStringAlignRight((string)$income,6," ")
." // 세출 : ".StringUtil::padStringAlignRight((string)$originoutcome,6," ")
@@ -362,6 +366,8 @@ function processRiceIncome() {
$incomeText = number_format($income);
$incomeLog = "이번 수입은 쌀 <C>$incomeText</>입니다.";
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->prev_income_rice = $income;
$db->update('nation', [
'rice'=>$nation['rice']
@@ -528,36 +534,36 @@ function disaster() {
$targetCityNames = "<G><b>".join(' ', Util::squeezeFromArray($targetCityList, 'name'))."</b></>";
$disasterTextList = [
1 => [
['재난', 4, '역병이 발생하여 도시가 황폐해지고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 3, '추위가 풀리지 않아 얼어죽는 백성들이 늘어나고 있습니다.'],
['재난', 9, '황건적이 출현해 도시를 습격하고 있습니다.'],
['<M><b>【재난】</b></>', 4, '역병이 발생하여 도시가 황폐해지고 있습니다.'],
['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['<M><b>【재난】</b></>', 3, '추위가 풀리지 않아 얼어죽는 백성들이 늘어나고 있습니다.'],
['<M><b>【재난】</b></>', 9, '황건적이 출현해 도시를 습격하고 있습니다.'],
],
4 => [
['재난', 7, '홍수로 인해 피해가 급증하고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 6, '태풍으로 인해 피해가 속출하고 있습니다.'],
['<M><b>【재난】</b></>', 7, '홍수로 인해 피해가 급증하고 있습니다.'],
['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['<M><b>【재난】</b></>', 6, '태풍으로 인해 피해가 속출하고 있습니다.'],
],
7 => [
['재난', 8, '메뚜기 떼가 발생하여 도시가 황폐해지고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 8, '흉년이 들어 굶어죽는 백성들이 늘어나고 있습니다.'],
['<M><b>【재난】</b></>', 8, '메뚜기 떼가 발생하여 도시가 황폐해지고 있습니다.'],
['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['<M><b>【재난】</b></>', 8, '흉년이 들어 굶어죽는 백성들이 늘어나고 있습니다.'],
],
10 => [
['재난', 3, '혹한으로 도시가 황폐해지고 있습니다.'],
['재난', 5, '지진으로 피해가 속출하고 있습니다.'],
['재난', 3, '눈이 많이 쌓여 도시가 황폐해지고 있습니다.'],
['재난', 9, '황건적이 출현해 도시를 습격하고 있습니다.'],
['<M><b>【재난】</b></>', 3, '혹한으로 도시가 황폐해지고 있습니다.'],
['<M><b>【재난】</b></>', 5, '지진으로 피해가 속출하고 있습니다.'],
['<M><b>【재난】</b></>', 3, '눈이 많이 쌓여 도시가 황폐해지고 있습니다.'],
['<M><b>【재난】</b></>', 9, '황건적이 출현해 도시를 습격하고 있습니다.'],
]
];
$boomingTextList = [
1 => null,
4 => [
['호황', 2, '호황으로 도시가 번창하고 있습니다.'],
['<C><b>【호황】</b></>', 2, '호황으로 도시가 번창하고 있습니다.'],
],
7 => [
['풍작', 1, '풍작으로 도시가 번창하고 있습니다.'],
['<C><b>【풍작】</b></>', 1, '풍작으로 도시가 번창하고 있습니다.'],
],
10 => null
];
@@ -566,7 +572,7 @@ function disaster() {
$logger = new ActionLogger(0, 0, $year, $month, false);
$logger->pushGlobalHistoryLog("<M><b>【{$logTitle}】</b></>{$targetCityNames}{$logBody}");
$logger->pushGlobalHistoryLog("{$logTitle}{$targetCityNames}{$logBody}");
$logger->flush();
if (!$isGood) {
+21 -16
View File
@@ -173,7 +173,7 @@ function printRow($k, $npc, $name, $abil, $tgame, $win, $draw, $lose, $gd, $gl,
if($prmt > 0) { $name = "<font color=orange>".$name."</font>"; }
elseif($npc >= 2) { $name = "<font color=cyan>".$name."</font>"; }
elseif($npc == 1) { $name = "<font color=skyblue>".$name."</font>"; }
echo "<tr align=center><td id=bg2>$k</td><td style='font-size:80%;'>$name</td><td>$abil</td><td>$tgame</td><td>$win</td><td>$draw</td><td>$lose</td><td>$gd</td><td>$gl</td></tr>";
echo "<tr align=center><td class='bg2'>$k</td><td style='font-size:80%;'>$name</td><td>$abil</td><td>$tgame</td><td>$win</td><td>$draw</td><td>$lose</td><td>$gd</td><td>$gl</td></tr>";
}
function printFighting($tournament, $phase) {
@@ -246,7 +246,7 @@ function startTournament($auto, $type) {
}
$admin = $gameStor->getValues(['year', 'month']);
$gameStor->tnmt_auto = $auto;
$gameStor->tnmt_time = (new \DateTimeImmutable())->add(new \DateInterval("PT{$unit}M"))->format('Y-m-d H:i:s');
$gameStor->tournament = 1;
@@ -297,7 +297,7 @@ function startTournament($auto, $type) {
][$type];
$history[] = "<S>◆</>{$admin['year']}{$admin['month']}월:{$openerText}<C>{$typeText}</> 대회가 개최됩니다! 천하의 <span class='ev_highlight'>{$genTypeText}</span>들을 모집하고 있습니다!";
pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
}
@@ -523,7 +523,7 @@ function selection($tnmt_type, $tnmt, $phase) {
if($phase < 31) {
$gameStor->phase+=1;
} else {
$gameStor->tournamemt = 4;
$gameStor->tournament = 4;
$gameStor->phase=0;
}
}
@@ -689,7 +689,8 @@ function setGift($tnmt_type, $tnmt, $phase) {
'grp_no'=>$general['grp_no'],
'reward'=>$cost,
'msg'=>"<span class='ev_highlight'>16강 진출</span>",
'logger'=>$logger
'logger'=>$logger,
'inheritance_point'=>10,
];
}
//8강자 명성 돈
@@ -723,6 +724,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
//포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>";
General::createGeneralObjFromDB($generalID)->increaseInheritancePoint('tournament', 10);
}
//결승자 명성 돈
$cost = $admin['develcost'] * 6;
@@ -739,6 +741,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
//포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>준우승</span>으";
$resultHelper[$generalID]['inheritance_point'] = 50;
if($general['lose'] > 0){
$runnerUp = $general;
}
@@ -761,6 +764,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
//포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>우승</span>으";
$resultHelper[$generalID]['inheritance_point'] = 100;
$winner = $general;
}
@@ -775,9 +779,6 @@ function setGift($tnmt_type, $tnmt, $phase) {
$runnerUpLogger = $resultHelper[$runnerUp['no']]['logger'];
$runnerUpLogger->pushGeneralHistoryLog("<C>{$tp}</> 대회에서 준우승");
$winnerRewardText = number_format($resultHelper[$winner['no']]['reward']);
$runnerUpRewardText = number_format($resultHelper[$runnerUp['no']]['reward']);
@@ -786,12 +787,16 @@ function setGift($tnmt_type, $tnmt, $phase) {
$winnerLogger->pushGlobalHistoryLog("<C>{$tp}</> 대회에서 <Y>{$winner['name']}</>{$josaYiWinner} <C>우승</>, <Y>{$runnerUp['name']}</>{$josaYiRunnerUp} <C>준우승</>을 차지하여 천하에 이름을 떨칩니다!", ActionLogger::EVENT_YEAR_MONTH);
$winnerLogger->pushGlobalHistoryLog("<C>{$tp}</> 대회의 <S>우승자</>에게는 <C>{$winnerRewardText}</>, <S>준우승자</>에겐 <C>{$runnerUpRewardText}</>의 <S>상금</>과 약간의 <S>명성</>이 주어집니다!", ActionLogger::EVENT_YEAR_MONTH);
foreach($resultHelper as $general){
$generalObjList = General::createGeneralObjListFromDB(array_keys($resultHelper));
foreach($resultHelper as $generalID=>$general){
$rewardText = number_format($general['reward']);
/** @var ActionLogger */
$logger = $general['logger'];
$logger->pushGeneralActionLog("<C>{$tp}</> 대회의 {$general['msg']}로 <C>{$rewardText}</>의 <S>상금</>, 약간의 <S>명성</> 획득!", ActionLogger::EVENT_PLAIN);
//TODO: 토너먼트의 다른 값이 모두 sql에 직접 입력하므로 기반을 바꿔야함.
$generalObjList[$generalID]->increaseInheritancePoint('tournament', $general['inheritance_point']);
}
//우승자 번호
@@ -829,7 +834,7 @@ function setRefund() {
$db->update('general', [
'gold'=>$db->sqleval('gold + %i', $cost)
], 'no IN %li', $generalIDList);
//베팅금 환수
$db->update(['general', [
'gold'=>$db->sqleval('gold + (SELECT bet0+bet1+bet2+bet3+bet4+bet5+bet6+bet7+bet8+bet9+bet10+bet11+bet12+bet13+bet14+bet15 FROM betting WHERE general_id = general.no)')
@@ -862,16 +867,16 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type) {
if($type == 0) { $turn = 10; }
else { $turn = 100; }
if($tnmt_type == 1) { $tp = "leadership"; $tp2 = "tl"; }
elseif($tnmt_type == 2) { $tp = "strength"; $tp2 = "ts"; }
elseif($tnmt_type == 3) { $tp = "intel"; $tp2 = "ti"; }
else /*$tnmt_type == 0*/{ $tp = "total"; $tp2 = "tt"; }
else /*$tnmt_type == 0*/{ $tp = "total"; $tp2 = "tt"; }
$e1 = $energy1 = Util::round($gen1[$tp] * getLog($gen1['lvl'], $gen2['lvl']) * 10);
$e2 = $energy2 = Util::round($gen2[$tp] * getLog($gen1['lvl'], $gen2['lvl']) * 10);
foreach([$gen1, $gen2] as $gen){
$horse = buildItemClass($gen['h']);
@@ -883,7 +888,7 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type) {
$itemName = $horse->getName();
$itemRawName = $horse->getRawName();
switch(rand()%4) {
case 0:
case 0:
$josaYi = JosaUtil::pick($itemRawName, '이');
$log[] = "<S>●</> <Y>{$gen['name']}</>의 <S>{$itemName}</>{$josaYi} 포효합니다!"; break;
case 1:
@@ -1085,7 +1090,7 @@ function fight($tnmt_type, $tnmt, $phs, $group, $g1, $g2, $type) {
'lose'=>$db->sqleval('lose+1'),
'gl'=>$db->sqleval('gl-%i', $gl)
], 'grp=%i AND grp_no=%i', $group, $g2);
if($general1['gl'] > $general2['gl']) { $gl1 = 1; $gl2 = 0; }
elseif($general1['gl'] == $general2['gl']) { $gl1 = 2; $gl2 = -1; }
else { $gl1 = 3; $gl2 = -2; }
+11 -17
View File
@@ -61,7 +61,7 @@ $scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID();
if($nationID){
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheValues(['notice', 'online_genenerals']);
$nationStor->cacheAll();
}
$valid = 0;
@@ -79,9 +79,11 @@ if ($gameStor->fiction == 0) {
}
if ($gameStor->npcmode == 0) {
$npcmode = "불가능";
} else {
} else if($gameStor->npcmode == 1){
$npcmode = "가능";
$valid = 1;
} else {
$npcmode = "선택 생성";
}
$color = "cyan";
$mapTheme = $gameStor->map_theme;
@@ -95,18 +97,10 @@ $serverCnt = $gameStor->server_cnt;
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.redirect.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/moment.min.js')?>
<?=WebUtil::printJS('../e_lib/linkify/linkify.min.js')?>
<?=WebUtil::printJS('../e_lib/linkify/linkify-string.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/main.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('d_shared/base_map.js')?>
<?=WebUtil::printJS('js/map.js')?>
<?=WebUtil::printJS('js/msg.js')?>
<?=WebUtil::printJS('dist_js/main.js')?>
<script>
window.serverNick = '<?=DB::prefix()?>';
window.serverID = '<?=UniqueConst::$serverID?>';
@@ -134,7 +128,7 @@ $(function(){
<body class="img_back">
<div id="container">
<div><?=allButton($gameStor->npcmode!=0)?></div>
<div><?=allButton($gameStor->npcmode==1)?></div>
<table class="tb_layout bg0" style="width:1000px;">
<tr height=50>
<td colspan=5 id="server_title" align=center><font size=4>삼국지 모의전투 HiDCHe <?=$serverName.$serverCnt?>기 (<font color=cyan><?=$scenario?></font>)</font></td>
@@ -293,7 +287,7 @@ else if($session->userGrade == 4){
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:70px;font-size:13px;margin-left:1ch;margin-right:2ch;'
><input type=button value='▼미루기' id='pushTurn'
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px;'
><input type=button value='▲당기기' id='pullTurn'
><input type=button value='▲당기기' id='pullTurn'
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:80px;font-size:13px;'
></td>
</tr>
@@ -304,7 +298,7 @@ else if($session->userGrade == 4){
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:110px;font-size:13px;'
><input type=button value='갱 신' id='refreshPage'
style='background-color:<?=GameConst::$basecolor2?>;color:white;width:110px;font-size:13px;'
><input type=button value='로비로' onclick="location.replace('../')"
><input type=button value='로비로' onclick="location.replace('../')"
style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;font-size:13px;
>
</td>
@@ -341,7 +335,7 @@ else if($session->userGrade == 4){
<button id="msg_submit">서신전달&amp;갱신</button><br>
내용 없이 '서신전달&amp;갱신' 누르면 메세지창이 갱신됩니다.
</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 class="board_header bg0" id='public_talk_position'>전체 메시지(최고99자)</div>
<section class="public_message">
@@ -361,7 +355,7 @@ else if($session->userGrade == 4){
<button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="diplomacy">이전 메시지 불러오기</button>
</section>
</div></div>
<div style="clear:left;"><?=allButton($gameStor->npcmode!=0)?><?=banner()?></div>
<div style="clear:left;"><?=allButton($gameStor->npcmode==1)?><?=banner()?></div>
</div>
<?php
if ($con == 1) {
+35 -20
View File
@@ -14,7 +14,7 @@ $serverName = DB::prefix();
$serverAcl = $session->acl[$serverName]??[];
$allowReset = in_array('reset', $serverAcl);
$allowFullReset = in_array('fullReset',$serverAcl);
$allowReset |= $allowFullReset;
$allowReset = $allowReset || $allowFullReset;
if($session->userGrade < 5 && !$allowReset){
die('관리자 아님');
@@ -28,11 +28,9 @@ if($session->userGrade < 5 && !$allowReset){
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.validate.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/install.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/install.js')?>
<?=WebUtil::printCSS('css/normalize.css')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('css/install.css')?>
@@ -47,7 +45,7 @@ if($session->userGrade < 5 && !$allowReset){
<h3 class="card-header">
설치(환경 설정)
<!--턴시간, 시간동기화, 시나리오, 상성, 확장장수, NPC유저, 이미지설정-->
</h3>
</h3>
<div class="card-body">
<form id="game_form" method="post" action="#">
<div class="form-group row">
@@ -82,7 +80,7 @@ if($session->userGrade < 5 && !$allowReset){
</div>
</div>
<div class="form-group row">
<label for="sync" class="col-sm-3 col-form-label">시간 동기화</label>
<div class="col-sm-9" style="display: inline-flex;">
@@ -93,7 +91,7 @@ if($session->userGrade < 5 && !$allowReset){
<label class="btn btn-secondary">
<input type="radio" name="sync" value="0">N
</label>
</div>
<small class="text-muted">
시간 단위에 맞게 /월이 설정됩니다. <br>: 120(오전1시=1), 60(오전/오후 1=1)
@@ -102,11 +100,11 @@ if($session->userGrade < 5 && !$allowReset){
</div>
<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">
<select class="form-control" name="scenario" size="1" id="scenario_sel">
</select>
</div>
</div>
@@ -138,6 +136,20 @@ if($session->userGrade < 5 && !$allowReset){
</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">
<label for="npcmode" class="col-sm-3 col-form-label">NPC 빙의</label>
<div class="col-sm-9">
@@ -148,35 +160,38 @@ if($session->userGrade < 5 && !$allowReset){
<label class="btn btn-secondary active">
<input type="radio" name="npcmode" value="0" checked>불가
</label>
<label class="btn btn-secondary">
<input type="radio" name="npcmode" value="2">선택 생성 가능
</label>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">휴식 장수 </label>
<label class="col-sm-3 col-form-label" id="autorun_set_label">휴식 장수 </label>
<div class="col-sm-9">
<div class="input-group">
<div class="input-group-prepend btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="develop" name="autorun_develop" id="autorun_develop">내정
<input type="checkbox" class="autorun_user_chk" data-key="develop" name="autorun_user[]" value="develop">내정
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="warp" name="autorun_warp" id="autorun_warp">순간이동
<input type="checkbox" class="autorun_user_chk" data-key="warp" name="autorun_user[]" value="warp">순간이동
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="recruit" name="autorun_recruit" id="autorun_recruit">징병
<input type="checkbox" class="autorun_user_chk" data-key="recruit" name="autorun_user[]" value="recruit">징병
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="recruit_high" name="autorun_recruit_high" id="autorun_recruit_high">모병
<input type="checkbox" class="autorun_user_chk" data-key="recruit_high" name="autorun_user[]" value="recruit_high">모병
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="train" name="autorun_train" id="autorun_train">훈사
<input type="checkbox" class="autorun_user_chk" data-key="train" name="autorun_user[]" value="train">훈사
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="battle" name="autorun_battle" id="autorun_battle">출병
<input type="checkbox" class="autorun_user_chk" data-key="battle" name="autorun_user[]" value="battle">출병
</label>
<label class="btn btn-secondary">
<input type="checkbox" class="autorun_user_chk" data-key="chief" name="autorun_chief" id="autorun_chief">기본 사령턴
<input type="checkbox" class="autorun_user_chk" data-key="chief" name="autorun_user[]" value="chief">기본 사령턴
</label>
</div>
<div class="input-group-append">
@@ -351,7 +366,7 @@ if($session->userGrade < 5 && !$allowReset){
</tbody>
<tfoot>
<tr><td colspan="2">
</td></tr>
</tfoot>
</table>
+7 -9
View File
@@ -21,11 +21,9 @@ if($session->userGrade == 5){
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../e_lib/jquery.validate.min.js')?>
<?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printJS('js/install_db.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('dist_js/vendors.js')?>
<?=WebUtil::printJS('dist_js/install_db.js')?>
<?=WebUtil::printCSS('css/normalize.css')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('css/install.css')?>
@@ -39,7 +37,7 @@ if($session->userGrade == 5){
<div class="card" id="db_form_card">
<h3 class="card-header">
설치(DB 설정)
</h3>
</h3>
<div class="card-body">
<form id="db_form" method="post" action="#">
<?php if(class_exists('\\sammo\\DB')): ?>
@@ -53,7 +51,7 @@ if($session->userGrade == 5){
<label class="btn btn-secondary active">
<input type="radio" name="full_reset" value="0" checked>N
</label>
</div>
</div>
</div>
@@ -73,7 +71,7 @@ if($session->userGrade == 5){
<input type="text" class="form-control" name="db_port" id="db_port" placeholder="접속 포트" value="3306" />
</div>
</div>
<div class="form-group row">
<label for="db_id" class="col-sm-3 col-form-label">DB계정</label>
<div class="col-sm-9">
@@ -82,7 +80,7 @@ if($session->userGrade == 5){
</div>
</div>
<div class="form-group row">
<label for="db_pw" class="col-sm-3 col-form-label">DB비밀번호</label>
<div class="col-sm-9">
+101 -100
View File
@@ -1,101 +1,102 @@
<?php
namespace sammo;
include 'lib.php';
include "func.php";
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
Json::die([
'result'=>true,
'affected'=>0,
'status'=>'no_reserved_table'
]);
}
$reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1');
if(!$reserved){
Json::die([
'result'=>true,
'affected'=>0,
'status'=>'no_reserved'
]);
}
$reservedDate = new \DateTime($reserved['date']);
$now = new \DateTime();
$status = 'not_yet';
list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']);
if($isUnited === null || $lastTurn === null){
$isUnited = 2;
$lastTurn = '2000-01-01';
}
if($lastTurn !== null){
$lastTurn = new \DateTime($lastTurn);
}
if($lastTurn === null){
//이미 리셋된 상태임
}
else if(file_exists(__DIR__.'/.htaccess')){
//일단 서버는 닫혀 있음
}
else if(
$isUnited == 2 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp()
){
//정지 상태 & 중간 넘음
AppConf::getList()[DB::prefix()]->closeServer();
$status = 'closed';
}
else if(
$isUnited > 0 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2
){
//천통 & 비정지 상태 & 2/3 넘음
AppConf::getList()[DB::prefix()]->closeServer();
$status = 'closed';
}
else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){
//어쨌든 간에 10분 남았다면.
AppConf::getList()[DB::prefix()]->closeServer();
$status = 'closed';
}
if($now < $reservedDate){
Json::die([
'result'=>true,
'affected'=>0,
'status'=>$status
]);
}
$options = Json::decode($reserved['options']);
$result = ResetHelper::buildScenario(
$options['turnterm'],
$options['sync'],
$options['scenario'],
$options['fiction'],
$options['extend'],
$options['npcmode'],
$options['show_img_level'],
$options['tournament_trig'],
$options['join_mode'],
$options['starttime'],
$options['autorun_user']?:null
);
$result['affected']=1;
$prefix = DB::prefix();
AppConf::getList()[$prefix]->openServer();
<?php
namespace sammo;
include 'lib.php';
include "func.php";
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
Json::die([
'result'=>true,
'affected'=>0,
'status'=>'no_reserved_table'
]);
}
$reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1');
if(!$reserved){
Json::die([
'result'=>true,
'affected'=>0,
'status'=>'no_reserved'
]);
}
$reservedDate = new \DateTime($reserved['date']);
$now = new \DateTime();
$status = 'not_yet';
list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']);
if($isUnited === null || $lastTurn === null){
$isUnited = 2;
$lastTurn = '2000-01-01';
}
if($lastTurn !== null){
$lastTurn = new \DateTime($lastTurn);
}
if($lastTurn === null){
//이미 리셋된 상태임
}
else if(file_exists(__DIR__.'/.htaccess')){
//일단 서버는 닫혀 있음
}
else if(
$isUnited == 2 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp()
){
//정지 상태 & 중간 넘음
ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed';
}
else if(
$isUnited > 0 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2
){
//천통 & 비정지 상태 & 2/3 넘음
ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed';
}
else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){
//어쨌든 간에 10분 남았다면.
ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed';
}
if($now < $reservedDate){
Json::die([
'result'=>true,
'affected'=>0,
'status'=>$status
]);
}
$options = Json::decode($reserved['options']);
$result = ResetHelper::buildScenario(
$options['turnterm'],
$options['sync'],
$options['scenario'],
$options['fiction'],
$options['extend'],
$options['block_general_create'],
$options['npcmode'],
$options['show_img_level'],
$options['tournament_trig'],
$options['join_mode'],
$options['starttime'],
$options['autorun_user']?:null
);
$result['affected']=1;
$prefix = DB::prefix();
ServConfig::getServerList()[$prefix]->openServer();
Json::die($result);
+5 -3
View File
@@ -5,9 +5,11 @@ include('lib.php');
include 'func.php';
$result = [
"generalID"=>null,
"myNationID"=>null,
"isChief"=>false
"generalID"=>0,
"myNationID"=>0,
"isChief"=>false,
"officerLevel"=>0,
"permission"=>0,
];
$session = Session::requireGameLogin([])->setReadOnly();
$userID = Session::getUserID();
@@ -4,6 +4,9 @@ namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$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);
if(!$general){
header('location:b_myPage.php');
die();
Json::die([
'result'=>false,
'reason'=>'장수가 없습니다.'
]);
}
increaseRefresh("장수 삭제", 1);
$gameStor->cacheValues(['turnterm', 'opentime', 'turntime', 'year', 'month']);
if($gameStor->turntime <= $gameStor->opentime){
//서버 가오픈시 할 수 있는 행동
if(addTurn($general['lastrefresh'], $gameStor->turnterm, 2) <= TimeUtil::now()){
$availableDieImmediately = true;
}
if($gameStor->turntime > $gameStor->opentime){
Json::die([
'result'=>false,
'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']);
@@ -46,4 +55,7 @@ $josaYi = JosaUtil::pick($generalName, '이');
$generalObj->kill($db, true, "<Y>{$generalName}</>{$josaYi} 이 홀연히 모습을 <R>감추었습니다</>");
$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
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("사령부", 1);
$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']);
$nationID = $me['nation'];
$con = checkLimit($me['con']);
if($con >= 2) {
Json::die([
'result'=>false,
'reason'=>"접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : {$me['turntime']})"
]);
}
$permission = checkSecretPermission($me);
if($permission < 0){
Json::die([
'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.'
]);
echo '국가에 소속되어있지 않습니다.';
die();
}
else if ($permission < 1) {
Json::die([
'result'=>false,
'reason'=>'수뇌부가 아니거나 사관년도가 부족합니다.'
]);
die();
}
$date = TimeUtil::now();
// 명령 목록
[$year, $month, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'turnterm']);
$lv = getNationChiefLevel($nationLevel);
$turn = [];
$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){
$generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, $year, $month, false);
}
$nationTurnList = [];
foreach(
$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',
$me['nation']
) as [$officer_level, $turn_idx, $action, $arg, $brief]
){
if(!key_exists($officer_level, $nationTurnList)){
$nationTurnList[$officer_level] = [];
}
$nationTurnList[$officer_level][$turn_idx] = $brief;
}
$nationTurnBrief = [];
foreach($nationTurnList as $officer_level=>$turnBrief){
if(!key_exists($officer_level, $generals)){
continue;
}
$general = $generals[$officer_level];
$nationTurnBrief[$officer_level] = [
'name'=>$general->getName(),
'turnTime'=>$general->getTurnTime($general::TURNTIME_FULL),
'officerLevelText'=>getOfficerLevelText($general->getVar('officer_level'), $nationLevel),
'npcType'=>$general->getNPCType(),
'turn'=>$turnBrief
];
}
$date = substr(TimeUtil::now(), 14);
Json::die([
'result'=>true,
'reason'=>'success',
'date'=>$date,
'nationTurnBrief'=>$nationTurnBrief,
'isChief'=>($me['officer_level'] > 4),
'turnTerm'=>$turnterm
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("사령부", 1);
$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']);
$nationID = $me['nation'];
$con = checkLimit($me['con']);
if($con >= 2) {
Json::die([
'result'=>false,
'reason'=>"접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다. (다음 접속 가능 시각 : {$me['turntime']})"
]);
}
$permission = checkSecretPermission($me);
if($permission < 0){
Json::die([
'result'=>false,
'reason'=>'국가에 소속되어있지 않습니다.'
]);
echo '국가에 소속되어있지 않습니다.';
die();
}
else if ($permission < 1) {
Json::die([
'result'=>false,
'reason'=>'수뇌부가 아니거나 사관년도가 부족합니다.'
]);
die();
}
$date = TimeUtil::now();
// 명령 목록
[$year, $month, $turnterm] = $gameStor->getValuesAsArray(['year', 'month', 'turnterm']);
$lv = getNationChiefLevel($nationLevel);
$turn = [];
$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){
$generals[$rawGeneral['officer_level']] = new General($rawGeneral, null, null, null, $year, $month, false);
}
$nationTurnList = [];
foreach(
$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',
$me['nation']
) as [$officer_level, $turn_idx, $action, $arg, $brief]
){
if(!key_exists($officer_level, $nationTurnList)){
$nationTurnList[$officer_level] = [];
}
$nationTurnList[$officer_level][$turn_idx] = $brief;
}
$nationTurnBrief = [];
foreach($nationTurnList as $officer_level=>$turnBrief){
if(!key_exists($officer_level, $generals)){
$nationTurnBrief[$officer_level] = [
'name'=>null,
'turnTime'=>null,
'officerLevelText'=>getOfficerLevelText($officer_level, $nationLevel),
'npcType'=>null,
'turn'=>$turnBrief
];
continue;
}
$general = $generals[$officer_level];
$nationTurnBrief[$officer_level] = [
'name'=>$general->getName(),
'turnTime'=>$general->getTurnTime($general::TURNTIME_FULL),
'officerLevelText'=>getOfficerLevelText($general->getVar('officer_level'), $nationLevel),
'npcType'=>$general->getNPCType(),
'turn'=>$turnBrief
];
}
$date = substr(TimeUtil::now(), 14);
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
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireLogin();
$userID = Session::getUserID();
$db = DB::db();
$withToken = Util::getPost('with_token', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env');
if($session->isGameLoggedIn()){
increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]);
}
}
else{
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
$now = new \DateTimeImmutable();
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
Json::die([
'result'=>false,
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
]);
}
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
$session->availableNextCallGetGeneralList = $availableNextCall;
}
$session->setReadOnly();
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
$ownerNameList = [];
if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName;
}
}
$generalList = [];
foreach($rawGeneralList as $rawGeneral){
[$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral;
if(key_exists($owner, $ownerNameList)){
$ownerName = $ownerNameList[$owner];
}
$nationArr = getNationStaticInfo($nation);
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
$generalList[] = [
$no,
$picture,
$imgsvr,
$npc,
$age,
$nationArr['name'],
getGeneralSpecialDomesticName($special),
getGeneralSpecialWarName($special2),
getGenChar($personal),
$name,
$npc==1?$ownerName:null,
$injury,
$leadership,
$lbonus,
$strength,
$intel,
getExpLevel($experience),
getHonor($experience),
getDed($dedication),
getOfficerLevelText($officerLevel, $nationArr['level']),
$killturn,
$connectCnt
];
}
$result = [
'result'=>'true',
'list'=>$generalList,
];
if($withToken){
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
$tokens = [];
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
$validUntil = $token['valid_until'];
foreach(Json::decode($token['pick_result']) as $pickResult){
$tokens[$pickResult['no']]=$pickResult['keepCnt'];
}
}
$result['token'] = $tokens;
}
Json::die($result);
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireLogin([]);
$userID = Session::getUserID();
$db = DB::db();
$withToken = Util::getPost('with_token', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env');
if($session->isGameLoggedIn()){
increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']);
if ($con >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]);
}
}
else{
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
$now = new \DateTimeImmutable();
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
Json::die([
'result'=>false,
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
]);
}
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
$session->availableNextCallGetGeneralList = $availableNextCall;
}
$session->setReadOnly();
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
$ownerNameList = [];
if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName;
}
}
$generalList = [];
foreach($rawGeneralList as $rawGeneral){
[$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral;
if(key_exists($owner, $ownerNameList)){
$ownerName = $ownerNameList[$owner];
}
$nationArr = getNationStaticInfo($nation);
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
$generalList[] = [
$no,
$picture,
$imgsvr,
$npc,
$age,
$nationArr['name'],
getGeneralSpecialDomesticName($special),
getGeneralSpecialWarName($special2),
getGenChar($personal),
$name,
$npc==1?$ownerName:null,
$injury,
$leadership,
$lbonus,
$strength,
$intel,
getExpLevel($experience),
getHonor($experience),
getDed($dedication),
getOfficerLevelText($officerLevel, $nationArr['level']),
$killturn,
$connectCnt
];
}
$result = [
'result'=>'true',
'list'=>$generalList,
];
if($withToken){
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
$tokens = [];
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
$validUntil = $token['valid_until'];
foreach(Json::decode($token['pick_result']) as $pickResult){
$tokens[$pickResult['no']]=$pickResult['keepCnt'];
}
}
$result['token'] = $tokens;
}
Json::die($result);
+96 -77
View File
@@ -1,4 +1,5 @@
<?php
namespace sammo;
//통합 세력장수&암행부 viewer
@@ -11,145 +12,163 @@ $session = Session::requireGameLogin([])->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$reqType = Util::getPost('req', 'int', 1);
$reqForce = Util::getPost('force', 'bool', false);
$reqType = Util::getReq('req', 'int', 1);
$reqForce = Util::getReq('force', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("세력장수", 1);
$me = $db->queryFirstRow('SELECT con, turntime, 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']);
if ($con >= 2) {
Json::die([
'result'=>false,
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
'result' => false,
'reason' => '접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]);
}
$nationID = $me['nation'];
$permission = checkSecretPermission($me, true);
if($reqForce && $reqType > $permission){
if ($reqForce && $reqType > $permission) {
Json::die([
'result'=>false,
'reason'=>'권한이 부족합니다.'
'result' => false,
'reason' => '권한이 부족합니다.'
]);
}
$permission = min($reqType, $permission);
$nationArr = getNationStaticInfo($nationID);
$viewColumns = [
'no'=>1,
'name'=>1,
'owner_name'=>9,
'nation'=>1,
'city'=>1,
'officer_level'=>9,
'npc'=>1,
'defence_train'=>2,
'troop'=>2,
'injury'=>1,
'leadership'=>1,
'strength'=>1,
'intel'=>1,
'experience'=>1,
'explevel'=>1,
'dedication'=>1,
'dedlevel'=>1,
'gold'=>1,
'rice'=>1,
'crewtype'=>2,
'crew'=>2,
'train'=>2,
'atmos'=>2,
'killturn'=>1,
'turntime'=>2,
'picture'=>1,
'imgsvr'=>1,
'age'=>1,
'special'=>1,
'special2'=>1,
'personal'=>1,
'horse'=>3,
'weapon'=>3,
'book'=>3,
'item'=>3,
'connect'=>1
'no' => 0,
'name' => 0,
'owner_name' => 9,
'nation' => 0,
'city' => 1,
'officer_level' => 2,
'officer_city' => 2,
'npc' => 0,
'defence_train' => 2,
'troop' => 2,
'injury' => 0,
'leadership' => 0,
'strength' => 0,
'intel' => 0,
'experience' => 1,
'explevel' => 0,
'dedication' => 1,
'dedlevel' => 0,
'gold' => 0,
'rice' => 0,
'crewtype' => 2,
'crew' => 2,
'train' => 2,
'atmos' => 2,
'killturn' => 0,
'turntime' => 2,
'picture' => 0,
'imgsvr' => 0,
'age' => 0,
'special' => 0,
'special2' => 0,
'personal' => 0,
'belong' => 0,
'horse' => 2,
'weapon' => 2,
'book' => 2,
'item' => 2,
'connect' => 0
];
$customViewColumns = [
'officerLevel'=>1,
'officerLevelText'=>1,
'lbonus'=>1,
'ownerName'=>1,
'honorText'=>1,
'expLevelText'=>1,
'officerLevel' => 0,
'officerLevelText' => 0,
'lbonus' => 0,
'ownerName' => 0,
'honorText' => 0
];
function getOfficerLevel($rawGeneral)
{
global $permission;
$level = $rawGeneral['officer_level'];
if ($level >= 5) {
return $level;
}
if ($permission > 1) {
return $level;
}
return 1;
}
$specialViewFilter = [
'officerLevel'=>function($rawGeneral){
return $rawGeneral['officer_level'];
'officerLevel' => function ($rawGeneral){
return getOfficerLevel($rawGeneral);
},
'special'=>function($rawGeneral){
'special' => function ($rawGeneral) {
return getGeneralSpecialDomesticName($rawGeneral['special']);
},
'special2'=>function($rawGeneral){
'special2' => function ($rawGeneral) {
return getGeneralSpecialWarName($rawGeneral['special2']);
},
'personal'=>function($rawGeneral){
'personal' => function ($rawGeneral) {
return getGenChar($rawGeneral['personal']);
},
'lbonus'=>function($rawGeneral)use($nationArr){
'lbonus' => function ($rawGeneral) use ($nationArr) {
return calcLeadershipBonus($rawGeneral['officer_level'], $nationArr['level']);
},
'ownerName'=>function($rawGeneral){
if($rawGeneral['npc']!=1){
'ownerName' => function ($rawGeneral) {
if ($rawGeneral['npc'] != 1) {
return null;
}
return $rawGeneral['owner_name'];
},
'officerLevelText'=>function($rawGeneral)use($nationArr){
return getOfficerLevelText($rawGeneral['officer_level'], $nationArr['level']);
'officerLevelText' => function ($rawGeneral) use ($nationArr) {
$level = getOfficerLevel($rawGeneral);
return getOfficerLevelText($level, $nationArr['level']);
},
'honorText'=>function($rawGeneral){
'honorText' => function ($rawGeneral) {
return getHonor($rawGeneral['experience']);
},
'dedLevelText'=>function($rawGeneral){
'dedLevelText' => function ($rawGeneral) {
return getDedLevelText($rawGeneral['dedLevel']);
},
'turntime'=>function($rawGeneral){
'turntime' => function ($rawGeneral) {
//'0000-00-00 11:23';
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 = [];
foreach($viewColumns as $column=>$reqPermission){
if($reqPermission > $permission){
foreach ($viewColumns as $column => $reqPermission) {
if ($reqPermission > $permission) {
continue;
}
$resultColumns[] = $column;
}
foreach($customViewColumns as $column=>$reqPermission){
if($reqPermission > $permission){
foreach ($customViewColumns as $column => $reqPermission) {
if ($reqPermission > $permission) {
continue;
}
$resultColumns[] = $column;
}
foreach($rawGeneralList as $rawGeneral){
$generalList = [];
foreach ($rawGeneralList as $rawGeneral) {
//General 생성?
$item = [];
foreach($resultColumns as $column){
$value = $rawGeneral[$column];
if(key_exists($column, $specialViewFilter)){
foreach ($resultColumns as $column) {
if (key_exists($column, $specialViewFilter)) {
$value = $specialViewFilter[$column]($rawGeneral);
}
else{
$value = $rawGeneral[$column];
}
$item[] = $value;
}
@@ -157,9 +176,9 @@ foreach($rawGeneralList as $rawGeneral){
}
$result = [
'result'=>true,
'column'=>$resultColumns,
'list'=>$generalList,
'result' => true,
'column' => $resultColumns,
'list' => $generalList,
];
Json::die($result);
+1 -1
View File
@@ -37,7 +37,7 @@ list(
$npcmode
) = $gameStor->getValuesAsArray(['maxgeneral', 'turnterm', 'npcmode']);
if(!$npcmode){
if($npcmode!=1){
Json::die([
'result'=>false,
'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
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly();
if(!class_exists('\\sammo\\DB')){
Json::die([
'result'=>false,
'reason'=>'DB리셋 필요'
]);
}
$serverName = DB::prefix();
$serverAcl = $session->acl[$serverName]??[];
$allowReset = in_array('reset', $serverAcl);
$allowFullReset = in_array('fullReset',$serverAcl);
$allowReset |= $allowFullReset;
$reserve_open = Util::getPost('reserve_open');
if($reserve_open && $reserve_open < date('Y-m-d H:i')){
Json::die([
'result'=>false,
'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.'
]);
}
$pre_reserve_open = Util::getPost('pre_reserve_open');
if($pre_reserve_open && !$reserve_open){
Json::die([
'result'=>false,
'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.'
]);
}
if($pre_reserve_open && $pre_reserve_open >= $reserve_open){
Json::die([
'result'=>false,
'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.'
]);
}
if($session->userGrade < 5 && !$allowReset){
Json::die([
'result'=>false,
'reason'=>'관리자 아님'
]);
}
$v = new Validator($_POST);
$v->rule('required', [
'turnterm',
'sync',
'scenario',
'fiction',
'extend',
'join_mode',
'npcmode',
'show_img_level',
'autorun_user_minutes'
])->rule('integer', [
'turnterm',
'sync',
'scenario',
'fiction',
'extend',
'npcmode',
'show_img_level',
'tournament_trig',
'autorun_user_minutes'
])->rule('in', 'join_mode', ['onlyRandom', 'full']);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>$v->errorStr()
]);
}
$allowReset = true;
if($session->userGrade < 5 && !$allowFullReset){
//리셋 가능한 조건인지 테스트
$allowReset = false;
if(file_exists(__DIR__.'/.htaccess')){
$allowReset = true;
}
else{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if($gameStor->isunited){
$allowReset = true;
}
}
}
if(!$allowReset){
Json::die([
'result'=>false,
'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.'
]);
}
$turnterm = (int)$_POST['turnterm'];
$sync = (int)$_POST['sync'];
$scenario = (int)$_POST['scenario'];
$fiction = (int)$_POST['fiction'];
$extend = (int)$_POST['extend'];
$npcmode = (int)$_POST['npcmode'];
$show_img_level = (int)$_POST['show_img_level'];
$tournament_trig = (int)$_POST['tournament_trig'];
$join_mode = $_POST['join_mode'];
$autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
$autorun_user_options = [];
foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){
$autorun_user_options[$autorun_option] = 1;
}
if($autorun_user_minutes > 0 && !$autorun_user_options){
Json::die([
'result'=>false,
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
]);
}
if($autorun_user_minutes < 0){
Json::die([
'result'=>false,
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
]);
}
$autorun_user = $autorun_user_minutes?[
'limit_minutes'=>$autorun_user_minutes,
'options'=>$autorun_user_options
]:null;
if($reserve_open){
$reserve_open = new \DateTime($reserve_open);
$db = DB::db();
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
$clearResult = ResetHelper::clearDB();
if(!$clearResult['result']){
Json::die($clearResult);
}
}
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
Json::die([
'result'=>false,
'reason'=>'예약 테이블이 없음!'
]);
}
$scenarioObj = new Scenario($scenario, true);
$open_date = $reserve_open->format('Y-m-d H:i:s');
$reserveInfo = [
'turnterm'=>$turnterm,
'sync'=>$sync,
'scenario'=>$scenario,
'scenarioName'=>$scenarioObj->getTitle(),
'fiction'=>$fiction,
'extend'=>$extend,
'npcmode'=>$npcmode,
'show_img_level'=>$show_img_level,
'tournament_trig'=>$tournament_trig,
'gameConf'=>$scenarioObj->getGameConf(),
'join_mode'=>$join_mode,
'starttime'=>$open_date,
'autorun_user'=>$autorun_user
];
if($pre_reserve_open){
$pre_reserve_open = new \DateTime($pre_reserve_open);
$open_date = $pre_reserve_open->format('Y-m-d H:i:s');
}
$db->delete('reserved_open', true);
$db->insert('reserved_open', [
'options'=>Json::encode($reserveInfo),
'date'=>$open_date
]);
AppConf::getList()[DB::prefix()]->closeServer();
Json::die([
'result'=>true,
'reason'=>'예약'
]);
}
Json::die(ResetHelper::buildScenario(
$turnterm,
$sync,
$scenario,
$fiction,
$extend,
$npcmode,
$show_img_level,
$tournament_trig,
$join_mode,
TimeUtil::now(),
$autorun_user
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly();
if(!class_exists('\\sammo\\DB')){
Json::die([
'result'=>false,
'reason'=>'DB리셋 필요'
]);
}
$serverName = DB::prefix();
$serverAcl = $session->acl[$serverName]??[];
$allowReset = in_array('reset', $serverAcl);
$allowFullReset = in_array('fullReset',$serverAcl);
$allowReset = $allowReset || $allowFullReset;
$reserve_open = Util::getPost('reserve_open');
if($reserve_open && $reserve_open < date('Y-m-d H:i')){
Json::die([
'result'=>false,
'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.'
]);
}
$pre_reserve_open = Util::getPost('pre_reserve_open');
if($pre_reserve_open && !$reserve_open){
Json::die([
'result'=>false,
'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.'
]);
}
if($pre_reserve_open && $pre_reserve_open >= $reserve_open){
Json::die([
'result'=>false,
'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.'
]);
}
if($session->userGrade < 5 && !$allowReset){
Json::die([
'result'=>false,
'reason'=>'관리자 아님'
]);
}
$v = new Validator($_POST);
$v->rule('required', [
'turnterm',
'sync',
'scenario',
'fiction',
'extend',
'block_general_create',
'join_mode',
'npcmode',
'show_img_level',
'autorun_user_minutes'
])->rule('integer', [
'turnterm',
'sync',
'scenario',
'fiction',
'extend',
'block_general_create',
'npcmode',
'show_img_level',
'tournament_trig',
'autorun_user_minutes'
])->rule('in', 'join_mode', ['onlyRandom', 'full']);
if(!$v->validate()){
Json::die([
'result'=>false,
'reason'=>$v->errorStr()
]);
}
$allowReset = true;
if($session->userGrade < 5 && !$allowFullReset){
//리셋 가능한 조건인지 테스트
$allowReset = false;
if(file_exists(__DIR__.'/.htaccess')){
$allowReset = true;
}
else{
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
if($gameStor->isunited){
$allowReset = true;
}
}
}
if(!$allowReset){
Json::die([
'result'=>false,
'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.'
]);
}
$turnterm = (int)$_POST['turnterm'];
$sync = (int)$_POST['sync'];
$scenario = (int)$_POST['scenario'];
$fiction = (int)$_POST['fiction'];
$extend = (int)$_POST['extend'];
$npcmode = (int)$_POST['npcmode'];
$block_general_create = (bool)$_POST['block_general_create'];
$show_img_level = (int)$_POST['show_img_level'];
$tournament_trig = (int)$_POST['tournament_trig'];
$join_mode = $_POST['join_mode'];
$autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
$autorun_user_options = [];
foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){
$autorun_user_options[$autorun_option] = 1;
}
if($autorun_user_minutes > 0 && !$autorun_user_options){
Json::die([
'result'=>false,
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
]);
}
if($autorun_user_minutes < 0){
Json::die([
'result'=>false,
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
]);
}
$autorun_user = $autorun_user_minutes?[
'limit_minutes'=>$autorun_user_minutes,
'options'=>$autorun_user_options
]:null;
if($reserve_open){
$reserve_open = new \DateTime($reserve_open);
$db = DB::db();
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
$clearResult = ResetHelper::clearDB();
if(!$clearResult['result']){
Json::die($clearResult);
}
}
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
Json::die([
'result'=>false,
'reason'=>'예약 테이블이 없음!'
]);
}
$scenarioObj = new Scenario($scenario, true);
$open_date = $reserve_open->format('Y-m-d H:i:s');
$reserveInfo = [
'turnterm'=>$turnterm,
'sync'=>$sync,
'scenario'=>$scenario,
'scenarioName'=>$scenarioObj->getTitle(),
'fiction'=>$fiction,
'extend'=>$extend,
'block_general_create'=>$block_general_create,
'npcmode'=>$npcmode,
'show_img_level'=>$show_img_level,
'tournament_trig'=>$tournament_trig,
'gameConf'=>$scenarioObj->getGameConf(),
'join_mode'=>$join_mode,
'starttime'=>$open_date,
'autorun_user'=>$autorun_user
];
if($pre_reserve_open){
$pre_reserve_open = new \DateTime($pre_reserve_open);
$open_date = $pre_reserve_open->format('Y-m-d H:i:s');
}
$db->delete('reserved_open', true);
$db->insert('reserved_open', [
'options'=>Json::encode($reserveInfo),
'date'=>$open_date
]);
ServConfig::getServerList()[DB::prefix()]->closeServer();
Json::die([
'result'=>true,
'reason'=>'예약'
]);
}
Json::die(ResetHelper::buildScenario(
$turnterm,
$sync,
$scenario,
$fiction,
$extend,
$block_general_create,
$npcmode,
$show_img_level,
$tournament_trig,
$join_mode,
TimeUtil::now(),
$autorun_user
));
+102 -102
View File
@@ -1,103 +1,103 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly();
if($session->userGrade < 6){
Json::die([
'result'=>false,
'reason'=>'관리자 아님'
]);
}
$fullReset = Util::getPost('full_reset', 'bool', false);
$host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id');
$password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name');
if(!$host || !$port || !$username || !$password || !$dbName){
Json::die([
'result'=>false,
'reason'=>'입력 값이 올바르지 않습니다'
]);
}
if($fullReset && class_exists('\\sammo\\DB')){
$mysqli_obj = DB::db()->get();
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){
while(true){
if (!$mysqli_obj->more_results()) {
break;
}
if(!$mysqli_obj->next_result()){
break;
}
}
}
}
if($fullReset){
FileUtil::delInDir(__DIR__."/logs");
FileUtil::delInDir(__DIR__."/data");
if(file_exists(__DIR__.'/d_setting/DB.php')){
@unlink(__DIR__.'/d_setting/DB.php');
}
if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){
@unlink(__DIR__.'/d_setting/UniqueConst.php');
}
}
function dbConnFail($params){
Json::die([
'result'=>false,
'reason'=>'DB 접속에 실패했습니다.'
]);
}
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4');
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->throw_exception_on_nonsql_error = false;
$db->nonsql_error_handler = 'dbConnFail';
$mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
$prefix = basename(__DIR__);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__.'/d_setting/DB.orig.php',
__DIR__.'/d_setting/DB.php',[
'host'=>$host,
'user'=>$username,
'password'=>$password,
'dbName'=>$dbName,
'port'=>$port,
'prefix'=>$prefix
], true
);
if($result !== true){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
ResetHelper::clearDB();
AppConf::getList()[$prefix]->closeServer();
Json::die([
'result'=>true,
'reason'=>'success'
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly();
if($session->userGrade < 6){
Json::die([
'result'=>false,
'reason'=>'관리자 아님'
]);
}
$fullReset = Util::getPost('full_reset', 'bool', false);
$host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id');
$password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name');
if(!$host || !$port || !$username || !$password || !$dbName){
Json::die([
'result'=>false,
'reason'=>'입력 값이 올바르지 않습니다'
]);
}
if($fullReset && class_exists('\\sammo\\DB')){
$mysqli_obj = DB::db()->get();
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){
while(true){
if (!$mysqli_obj->more_results()) {
break;
}
if(!$mysqli_obj->next_result()){
break;
}
}
}
}
if($fullReset){
FileUtil::delInDir(__DIR__."/logs");
FileUtil::delInDir(__DIR__."/data");
if(file_exists(__DIR__.'/d_setting/DB.php')){
@unlink(__DIR__.'/d_setting/DB.php');
}
if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){
@unlink(__DIR__.'/d_setting/UniqueConst.php');
}
}
function dbConnFail($params){
Json::die([
'result'=>false,
'reason'=>'DB 접속에 실패했습니다.'
]);
}
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4');
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->throw_exception_on_nonsql_error = false;
$db->nonsql_error_handler = 'dbConnFail';
$mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
$prefix = basename(__DIR__);
$result = Util::generateFileUsingSimpleTemplate(
__DIR__.'/d_setting/DB.orig.php',
__DIR__.'/d_setting/DB.php',[
'host'=>$host,
'user'=>$username,
'password'=>$password,
'dbName'=>$dbName,
'port'=>$port,
'prefix'=>$prefix
], true
);
if($result !== true){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
ResetHelper::clearDB();
ServConfig::getServerList()[$prefix]->closeServer();
Json::die([
'result'=>true,
'reason'=>'success'
]);
+1 -1
View File
@@ -9,7 +9,7 @@ $serverName = DB::prefix();
$serverAcl = $session->acl[$serverName]??[];
$allowReset = in_array('reset', $serverAcl);
$allowFullReset = in_array('fullReset',$serverAcl);
$allowReset |= $allowFullReset;
$allowReset = $allowReset || $allowFullReset;
if($session->userGrade < 5 && !$allowReset){
Json::die([
+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);
+1 -1
View File
@@ -56,6 +56,6 @@ else{
Json::die([
'result' => $result===DiplomaticMessage::ACCEPTED,
'result' => $result!==DiplomaticMessage::INVALID,
'reason' => $reason
]);
+1 -1
View File
@@ -32,7 +32,7 @@ $lastMsgGet[] = TimeUtil::now();
$session->lastMsgGet = Json::encode($lastMsgGet);
if($delayTime){
sleep(0.2);
usleep(200);
}
$session->setReadOnly();
+360 -359
View File
@@ -1,360 +1,361 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$action = Util::getPost('action');
$officerLevel = Util::getPost('officerLevel', 'int');
$destGeneralID = Util::getPost('destGeneralID', 'int');
$destCityID = Util::getPost('destCityID', 'int');
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['startyear','year','month','scenario']);
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$myOfficerLevel = $me['officer_level'];
$nationID = $me['nation'];
//수뇌가 아니면 아무것도 할 수 없음
if($myOfficerLevel < 5){
Json::die([
'result'=>false,
'reason'=>'수뇌가 아닙니다.'
]);
}
if($action === '추방' && $destGeneralID==0){
Json::die([
'result'=>false,
'reason'=>'장수가 지정되지 않았습니다.'
]);
}
if($destGeneralID==0){
$general = new DummyGeneral(true);
}
else{
$general = General::createGeneralObjFromDB($destGeneralID, [
'name', 'leadership', 'strength', 'intel', 'gold','rice',
'troop','officer_level','npc','picture','imgsvr',
'permission','penalty','belong', 'crewtype',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit',
], 1);
if($general instanceof DummyGeneral){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 장수입니다.'
]);
}
if($nationID != $general->getNationID()){
Json::die([
'result'=>false,
'reason'=>'아국 장수가 아닙니다'
]);
}
}
if($officerLevel == 12){
Json::die([
'result'=>false,
'reason'=>'군주를 대상으로 할 수 없습니다.'
]);
}
function do수뇌임명(General $general, int $targetOfficerLevel):?string{
$generalID = $general->getID();
$nationID = $general->getNationID();
$db = DB::db();
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
// 임명가능 레벨
$lv = getNationChiefLevel($nationLevel);
if($targetOfficerLevel < $lv){
return '임명불가능한 관직입니다.';
}
if(isOfficerSet($chiefSet, $targetOfficerLevel)){
return '지금은 임명할 수 없습니다.';
}
//기존 장수 일반으로
$db->update('general', [
'officer_level'=>1,
'officer_city'=>0,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
if($targetOfficerLevel === 11){
}
else if($targetOfficerLevel % 2 == 0){
if($general->getVar('strength') < GameConst::$chiefStatMin){
return '무력이 부족합니다.';
}
}
else{
if($general->getVar('intel') < GameConst::$chiefStatMin){
return '지력이 부족합니다.';
}
}
//신임 장수
$general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', 0);
$db->update('nation', [
'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
], 'nation=%i', $nationID);
$general->applyDB($db);
return null;
}
function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
$nationID = $general->getNationID();
$db = DB::db();
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){
return '아국 도시가 아닙니다';
}
if(isOfficerSet($officerSet, $targetOfficerLevel)){
return '이미 다른 장수가 임명되어있습니다';
}
//기존 장수 일반으로
$db->update('general', [
'officer_level'=>1,
'officer_city'=>0,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
if($general instanceof DummyGeneral){
return null;
}
if($targetOfficerLevel === 4 && $general->getVar('strength') < 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)),
], 'city=%i AND nation=%i', $cityID, $nationID);
$general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', $cityID);
$general->applyDB($db);
return null;
}
function do추방(General $general, int $myOfficerLevel):?string{
$generalID = $general->getID();
$generalName = $general->getVar('name');
$nationID = $general->getNationID();
//추방할사람이 외교권자이면 불가
$permission = checkSecretPermission($general->getRaw());
if($permission == 4){
return '외교권자는 추방할 수 없습니다.';
}
$db = DB::db();
$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'];
$logger = $general->getLogger();
//이미 지정했다면 무시
if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
return '이미 추방 권한을 사용했습니다.';
}
$gold = 0;
$rice = 0;
// 금쌀1000이상은 남김
if($general->getVar('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;
$general->setVar('rice', GameConst::$defaultRice);
}
$general->setVar('nation', 0);
$general->setVar('officer_level', 0);
$general->setVar('officer_city', 0);
$general->setVar('belong', 0);
$oldMakeLimit = $general->getVar('makelimit');
$general->setVar('makelimit', 12);
$general->setVar('permission', 'normal');
$josaYi = JosaUtil::pick($generalName, '이');
$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){
$general->setVar('makelimit', $oldMakeLimit);
}
else{
$betrayCnt = $general->getVar('betray');
$general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
$general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
}
//부대장일 경우
if($general->getVar('troop') == $generalID){
// 모두 탈퇴
$db->update('general', [
'troop'=>0,
], 'troop = %i', $generalID);
$db->delete('troop', 'troop_leader=%i', $generalID);
}
$general->setVar('troop', 0);
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
$str = Util::choiceRandom([
'날 버리다니... 곧 전장에서 복수해주겠다...',
'추방이라... 내가 무얼 잘못했단 말인가...',
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
]);
$src = new MessageTarget(
$generalID,
$generalName,
$nationID,
$nation['name'],
$nation['color'],
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
);
$msg = new Message(
Message::MSGTYPE_PUBLIC,
$src,
$src,
$str,
new \DateTime(),
new \DateTime('9999-12-31'),
[]
);
$msg->send();
}
if($env['year'] < $env['startyear']+3) {
//초반엔 군주 부상 증가(엔장 임관지양)
$db->update('general', [
'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),
'gold'=>$db->sqleval('gold + %i', $gold),
'rice'=>$db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID);
} else {
//이번분기는 추방불가(초반 제외)
$db->update('nation', [
'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'gold'=>$db->sqleval('gold + %i', $gold),
'rice'=>$db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID);
}
$logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
$general->applyDB($db);
return null;
}
if($action == "임명") {
if(2 <= $officerLevel && $officerLevel <= 4){
if(!$destCityID){
Json::die([
'result'=>false,
'reason'=>'도시가 지정되지 않았습니다.'
]);
}
$result = do도시임명($general, $destCityID, $officerLevel);
if($result !== null){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if(5 <= $officerLevel && $officerLevel < 12){
$result = do수뇌임명($general, $officerLevel);
if($result !== null){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 지정입니다.'
]);
}
if($action == "추방") {
$result = do추방($general, $myOfficerLevel);
if($result !== null){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 명령입니다.'
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$action = Util::getPost('action');
$officerLevel = Util::getPost('officerLevel', 'int');
$destGeneralID = Util::getPost('destGeneralID', 'int');
$destCityID = Util::getPost('destCityID', 'int');
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['startyear','year','month','scenario']);
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$myOfficerLevel = $me['officer_level'];
$nationID = $me['nation'];
//수뇌가 아니면 아무것도 할 수 없음
if($myOfficerLevel < 5){
Json::die([
'result'=>false,
'reason'=>'수뇌가 아닙니다.'
]);
}
if($action === '추방' && $destGeneralID==0){
Json::die([
'result'=>false,
'reason'=>'장수가 지정되지 않았습니다.'
]);
}
if($destGeneralID==0){
$general = new DummyGeneral(true);
$general->setVar('nation', $nationID);
}
else{
$general = General::createGeneralObjFromDB($destGeneralID, [
'name', 'leadership', 'strength', 'intel', 'gold','rice',
'troop','officer_level','npc','picture','imgsvr',
'permission','penalty','belong', 'crewtype',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit',
], 1);
if($general instanceof DummyGeneral){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 장수입니다.'
]);
}
if($nationID != $general->getNationID()){
Json::die([
'result'=>false,
'reason'=>'아국 장수가 아닙니다'
]);
}
}
if($officerLevel == 12){
Json::die([
'result'=>false,
'reason'=>'군주를 대상으로 할 수 없습니다.'
]);
}
function do수뇌임명(General $general, int $targetOfficerLevel):?string{
$generalID = $general->getID();
$nationID = $general->getNationID();
$db = DB::db();
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
// 임명가능 레벨
$lv = getNationChiefLevel($nationLevel);
if($targetOfficerLevel < $lv){
return '임명불가능한 관직입니다.';
}
if(isOfficerSet($chiefSet, $targetOfficerLevel)){
return '지금은 임명할 수 없습니다.';
}
//기존 장수 일반으로
$db->update('general', [
'officer_level'=>1,
'officer_city'=>0,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
if($targetOfficerLevel === 11){
}
else if($targetOfficerLevel % 2 == 0){
if($general->getVar('strength') < GameConst::$chiefStatMin){
return '무력이 부족합니다.';
}
}
else{
if($general->getVar('intel') < GameConst::$chiefStatMin){
return '지력이 부족합니다.';
}
}
//신임 장수
$general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', 0);
$db->update('nation', [
'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
], 'nation=%i', $nationID);
$general->applyDB($db);
return null;
}
function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
$nationID = $general->getNationID();
$db = DB::db();
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){
return '아국 도시가 아닙니다';
}
if(isOfficerSet($officerSet, $targetOfficerLevel)){
return '이미 다른 장수가 임명되어있습니다';
}
//기존 장수 일반으로
$db->update('general', [
'officer_level'=>1,
'officer_city'=>0,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
if($general instanceof DummyGeneral){
return null;
}
if($targetOfficerLevel === 4 && $general->getVar('strength') < 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)),
], 'city=%i AND nation=%i', $cityID, $nationID);
$general->setVar('officer_level', $targetOfficerLevel);
$general->setVar('officer_city', $cityID);
$general->applyDB($db);
return null;
}
function do추방(General $general, int $myOfficerLevel):?string{
$generalID = $general->getID();
$generalName = $general->getVar('name');
$nationID = $general->getNationID();
//추방할사람이 외교권자이면 불가
$permission = checkSecretPermission($general->getRaw());
if($permission == 4){
return '외교권자는 추방할 수 없습니다.';
}
$db = DB::db();
$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'];
$logger = $general->getLogger();
//이미 지정했다면 무시
if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
return '이미 추방 권한을 사용했습니다.';
}
$gold = 0;
$rice = 0;
// 금쌀1000이상은 남김
if($general->getVar('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;
$general->setVar('rice', GameConst::$defaultRice);
}
$general->setVar('nation', 0);
$general->setVar('officer_level', 0);
$general->setVar('officer_city', 0);
$general->setVar('belong', 0);
$oldMakeLimit = $general->getVar('makelimit');
$general->setVar('makelimit', 12);
$general->setVar('permission', 'normal');
$josaYi = JosaUtil::pick($generalName, '이');
$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){
$general->setVar('makelimit', $oldMakeLimit);
}
else{
$betrayCnt = $general->getVar('betray');
$general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
$general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
}
//부대장일 경우
if($general->getVar('troop') == $generalID){
// 모두 탈퇴
$db->update('general', [
'troop'=>0,
], 'troop = %i', $generalID);
$db->delete('troop', 'troop_leader=%i', $generalID);
}
$general->setVar('troop', 0);
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
$str = Util::choiceRandom([
'날 버리다니... 곧 전장에서 복수해주겠다...',
'추방이라... 내가 무얼 잘못했단 말인가...',
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
]);
$src = new MessageTarget(
$generalID,
$generalName,
$nationID,
$nation['name'],
$nation['color'],
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
);
$msg = new Message(
Message::MSGTYPE_PUBLIC,
$src,
$src,
$str,
new \DateTime(),
new \DateTime('9999-12-31'),
[]
);
$msg->send();
}
if($env['year'] < $env['startyear']+3) {
//초반엔 군주 부상 증가(엔장 임관지양)
$db->update('general', [
'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),
'gold'=>$db->sqleval('gold + %i', $gold),
'rice'=>$db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID);
} else {
//이번분기는 추방불가(초반 제외)
$db->update('nation', [
'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'gold'=>$db->sqleval('gold + %i', $gold),
'rice'=>$db->sqleval('rice + %i', $rice),
], 'nation = %i', $nationID);
}
$logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
$general->applyDB($db);
return null;
}
if($action == "임명") {
if(2 <= $officerLevel && $officerLevel <= 4){
if(!$destCityID){
Json::die([
'result'=>false,
'reason'=>'도시가 지정되지 않았습니다.'
]);
}
$result = do도시임명($general, $destCityID, $officerLevel);
if($result !== null){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
if(5 <= $officerLevel && $officerLevel < 12){
$result = do수뇌임명($general, $officerLevel);
if($result !== null){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 지정입니다.'
]);
}
if($action == "추방") {
$result = do추방($general, $myOfficerLevel);
if($result !== null){
Json::die([
'result'=>false,
'reason'=>$result
]);
}
Json::die([
'result'=>true,
'reason'=>'success'
]);
}
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 명령입니다.'
]);
+1 -1
View File
@@ -59,7 +59,7 @@ list(
$npcmode
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode']);
if(!$npcmode){
if($npcmode!=1){
Json::die([
'result'=>false,
'reason'=>'빙의 가능한 서버가 아닙니다'

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