Compare commits

...
132 Commits
Author SHA1 Message Date
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
1379 changed files with 128604 additions and 52563 deletions
+18
View File
@@ -0,0 +1,18 @@
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": [
"last 2 versions"
]
},
"modules":false
}
]
],
"plugins": [
"lodash"
]
}
+22
View File
@@ -0,0 +1,22 @@
module.exports = {
root: true,
parser: "@typescript-eslint/parser",
parserOptions: {
"project": "./tsconfig.json"
},
ignorePatterns: ['*.test.ts', '.eslintrc.js', 'webpack.config.js', '*.js'],
overrides: [{
files: ['*.ts', '*.tsx'],
}],
plugins: [
"@typescript-eslint",
],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
rules: {
'@typescript-eslint/no-floating-promises': 'error',
}
}
+54 -50
View File
@@ -1,50 +1,54 @@
.vscode/* .vscode/*
!.vscode/settings.json !.vscode/settings.json
!.vscode/tasks.json !.vscode/tasks.json
!.vscode/launch.json !.vscode/launch.json
!.vscode/extensions.json !.vscode/extensions.json
/node_modules
package-lock.json
# 체섭 ignore
*.log # 체섭 ignore
*.log
logs/*.txt
d_log/*.txt logs/*.txt
d_log/*.zip d_log/*.txt
sess_* d_log/*.zip
*/logs/*.txt sess_*
*/logs/*/*.txt */logs/*.txt
*/logs/preserved */logs/*/*.txt
err.txt */logs/preserved
che/.htaccess err.txt
kwe/.htaccess che/.htaccess
pwe/.htaccess kwe/.htaccess
twe/.htaccess pwe/.htaccess
hwe/.htaccess twe/.htaccess
hwe/.htaccess
d_shared
d_shared
d_pic/*.jpg
d_pic/*.gif d_pic/*.jpg
d_pic/*.png d_pic/*.gif
d_pic/uploaded_image d_pic/*.png
d_pic/*.webp
d_setting/*.php d_pic/uploaded_image
*/d_setting/*.php
*/d_setting/templates/*.php d_setting/*.php
*/d_setting/*.php
**/old/* */d_setting/templates/*.php
test.php
*/data/file_cache
/che
/kwe **/old/*
/pwe test.php
/nya
/pya /che
/twe /kwe
/pwe
phpinfo.php /nya
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/* /pya
*.sqlite3 /twe
phpinfo.php
vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/*
*.sqlite3
-1
View File
@@ -23,7 +23,6 @@ return [
'f_config/config.php', 'f_config/config.php',
'hwe/a_bestGeneral.php', 'hwe/a_bestGeneral.php',
'hwe/a_emperior.php', 'hwe/a_emperior.php',
'hwe/a_emperior2.php',
'hwe/a_emperior_detail.php', 'hwe/a_emperior_detail.php',
'hwe/a_genList.php', 'hwe/a_genList.php',
'hwe/a_hallOfFame.php', 'hwe/a_hallOfFame.php',
+5 -5
View File
@@ -9,18 +9,18 @@
* <code>mpm_event</code> 권장 * <code>mpm_event</code> 권장
* PHP 7.3 이상 * PHP 7.3 이상
* <code>php-fpm</code> 권장 * <code>php-fpm</code> 권장
* php에서 curl, pdo-sqlite을 실행가능해야 합니다. (기본값: 지원) * php에서 curl, pdo-sqlite을 실행가능해야 합니다.
* mysqlnd가 지원되어야합니다. (기본값: 지원) * mysqli, mysqlnd
* mysqli
* gd * gd
* mbstring
* MariaDB 10.2.1 이상 * MariaDB 10.2.1 이상
* 현재 MySQL은 지원하지 않습니다. * 현재 MySQL은 지원하지 않습니다.
* <code>git</code> * <code>git</code>
* <code>curl</code> * <code>curl</code>
Linux는 Ubuntu 16.04, 18.04, Windows는 Windows 10에서 XAMPP를 사용한 환경에서 테스트되었습니다. Linux는 Ubuntu 18.04, 20.04, Windows는 Windows 10에서 XAMPP, WSL2를 사용한 환경에서 테스트되었습니다.
Docker를 이용한 설치는 계획중입니다. Docker를 이용한 설치는 테스트버전만 제공됩니다.
## Docker를 이용한 설치 ## Docker를 이용한 설치
+3 -2
View File
@@ -26,8 +26,9 @@
"ezyang/htmlpurifier": "^4.10", "ezyang/htmlpurifier": "^4.10",
"xemlock/htmlpurifier-html5": "^0.1.7", "xemlock/htmlpurifier-html5": "^0.1.7",
"catfan/medoo": "^1.5", "catfan/medoo": "^1.5",
"phan/phan": "^2.7", "phan/phan": "*",
"erusev/parsedown-extra": "^0.8.1" "erusev/parsedown-extra": "^0.8.1",
"nette/caching": "^3.0"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
Generated
+1364 -271
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "1c2e0182ebdf9bfe795e52a5d7fc6abd", "content-hash": "2aeb036fc53a6fdc343bd2707d4697ee",
"packages": [ "packages": [
{ {
"name": "brandonwamboldt/utilphp", "name": "brandonwamboldt/utilphp",
@@ -50,20 +50,24 @@
"php", "php",
"utility" "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" "time": "2015-02-02T17:56:14+00:00"
}, },
{ {
"name": "catfan/medoo", "name": "catfan/medoo",
"version": "v1.7.8", "version": "v1.7.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/catfan/Medoo.git", "url": "https://github.com/catfan/Medoo.git",
"reference": "dd9d570584cfb1e09ec470608479b86e41d5b60d" "reference": "2d675f73e23f63bbaeb9a8aa33318659a3d3c32f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/catfan/Medoo/zipball/dd9d570584cfb1e09ec470608479b86e41d5b60d", "url": "https://api.github.com/repos/catfan/Medoo/zipball/2d675f73e23f63bbaeb9a8aa33318659a3d3c32f",
"reference": "dd9d570584cfb1e09ec470608479b86e41d5b60d", "reference": "2d675f73e23f63bbaeb9a8aa33318659a3d3c32f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -110,32 +114,37 @@
"sql", "sql",
"sqlite" "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", "name": "composer/semver",
"version": "1.5.1", "version": "3.2.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/semver.git", "url": "https://github.com/composer/semver.git",
"reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de" "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/c6bea70230ef4dd483e6bbcab6005f682ed3a8de", "url": "https://api.github.com/repos/composer/semver/zipball/31f3ea725711245195f62e54ffa402d8ef2fdba9",
"reference": "c6bea70230ef4dd483e6bbcab6005f682ed3a8de", "reference": "31f3ea725711245195f62e54ffa402d8ef2fdba9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^5.3.2 || ^7.0" "php": "^5.3.2 || ^7.0 || ^8.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.5 || ^5.0.5" "phpstan/phpstan": "^0.12.54",
"symfony/phpunit-bridge": "^4.2 || ^5"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.x-dev" "dev-main": "3.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -171,28 +180,48 @@
"validation", "validation",
"versioning" "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", "name": "composer/xdebug-handler",
"version": "1.4.1", "version": "2.0.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/xdebug-handler.git", "url": "https://github.com/composer/xdebug-handler.git",
"reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7" "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/1ab9842d69e64fb3a01be6b656501032d1b78cb7", "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339",
"reference": "1ab9842d69e64fb3a01be6b656501032d1b78cb7", "reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^5.3.2 || ^7.0 || ^8.0", "php": "^5.3.2 || ^7.0 || ^8.0",
"psr/log": "^1.0" "psr/log": "^1 || ^2 || ^3"
}, },
"require-dev": { "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", "type": "library",
"autoload": { "autoload": {
@@ -215,7 +244,26 @@
"Xdebug", "Xdebug",
"performance" "performance"
], ],
"time": "2020-03-01T12:26:26+00:00" "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": "2021-07-31T17:03:58+00:00"
}, },
{ {
"name": "erusev/parsedown", "name": "erusev/parsedown",
@@ -261,6 +309,10 @@
"markdown", "markdown",
"parser" "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" "time": "2019-12-30T22:54:17+00:00"
}, },
{ {
@@ -308,20 +360,24 @@
"parsedown", "parsedown",
"parser" "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" "time": "2019-12-30T23:20:37+00:00"
}, },
{ {
"name": "ezyang/htmlpurifier", "name": "ezyang/htmlpurifier",
"version": "v4.12.0", "version": "v4.13.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git", "url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "a617e55bc62a87eec73bd456d146d134ad716f03" "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/a617e55bc62a87eec73bd456d146d134ad716f03", "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
"reference": "a617e55bc62a87eec73bd456d146d134ad716f03", "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -337,6 +393,9 @@
}, },
"files": [ "files": [
"library/HTMLPurifier.composer.php" "library/HTMLPurifier.composer.php"
],
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
] ]
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@@ -355,29 +414,33 @@
"keywords": [ "keywords": [
"html" "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", "name": "felixfbecker/advanced-json-rpc",
"version": "v3.1.1", "version": "v3.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git",
"reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40" "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/0ed363f8de17d284d479ec813c9ad3f6834b5c40", "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40", "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"netresearch/jsonmapper": "^1.0 || ^2.0", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0",
"php": ">=7.0", "php": "^7.1 || ^8.0",
"phpdocumentor/reflection-docblock": "^4.0.0 || ^5.0.0" "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.0.0" "phpunit/phpunit": "^7.0 || ^8.0"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@@ -396,7 +459,11 @@
} }
], ],
"description": "A more advanced JSONRPC implementation", "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", "name": "firephp/firephp-core",
@@ -432,27 +499,33 @@
], ],
"description": "Traditional FirePHPCore library for sending PHP variables to the browser.", "description": "Traditional FirePHPCore library for sending PHP variables to the browser.",
"homepage": "https://github.com/firephp/firephp-core", "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" "time": "2013-04-23T15:28:20+00:00"
}, },
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "6.5.2", "version": "6.5.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/guzzle.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82" "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82", "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"guzzlehttp/promises": "^1.0", "guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1", "guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5" "php": ">=5.5",
"symfony/polyfill-intl-idn": "^1.17.0"
}, },
"require-dev": { "require-dev": {
"ext-curl": "*", "ext-curl": "*",
@@ -460,7 +533,6 @@
"psr/log": "^1.1" "psr/log": "^1.1"
}, },
"suggest": { "suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware" "psr/log": "Required for using the Log middleware"
}, },
"type": "library", "type": "library",
@@ -499,27 +571,31 @@
"rest", "rest",
"web service" "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", "name": "guzzlehttp/promises",
"version": "v1.3.1", "version": "1.4.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/promises.git", "url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.5.0" "php": ">=5.5"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.0" "symfony/phpunit-bridge": "^4.4 || ^5.1"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@@ -550,20 +626,24 @@
"keywords": [ "keywords": [
"promise" "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", "name": "guzzlehttp/psr7",
"version": "1.6.1", "version": "1.8.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/psr7.git", "url": "https://github.com/guzzle/psr7.git",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a" "reference": "dc960a912984efb74d0a90222870c72c87f10c91"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a", "reference": "dc960a912984efb74d0a90222870c72c87f10c91",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -576,15 +656,15 @@
}, },
"require-dev": { "require-dev": {
"ext-zlib": "*", "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": { "suggest": {
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.6-dev" "dev-master": "1.7-dev"
} }
}, },
"autoload": { "autoload": {
@@ -621,29 +701,33 @@
"uri", "uri",
"url" "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", "name": "league/plates",
"version": "3.3.0", "version": "v3.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/plates.git", "url": "https://github.com/thephpleague/plates.git",
"reference": "b1684b6f127714497a0ef927ce42c0b44b45a8af" "reference": "6d3ee31199b536a4e003b34a356ca20f6f75496a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/plates/zipball/b1684b6f127714497a0ef927ce42c0b44b45a8af", "url": "https://api.github.com/repos/thephpleague/plates/zipball/6d3ee31199b536a4e003b34a356ca20f6f75496a",
"reference": "b1684b6f127714497a0ef927ce42c0b44b45a8af", "reference": "6d3ee31199b536a4e003b34a356ca20f6f75496a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^5.3 | ^7.0" "php": "^7.0|^8.0"
}, },
"require-dev": { "require-dev": {
"mikey179/vfsstream": "^1.4", "mikey179/vfsstream": "^1.6",
"phpunit/phpunit": "~4.0", "phpunit/phpunit": "^9.5",
"squizlabs/php_codesniffer": "~1.5" "squizlabs/php_codesniffer": "^3.5"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@@ -665,10 +749,15 @@
"name": "Jonathan Reinink", "name": "Jonathan Reinink",
"email": "jonathan@reinink.ca", "email": "jonathan@reinink.ca",
"role": "Developer" "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.", "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": [ "keywords": [
"league", "league",
"package", "package",
@@ -676,27 +765,31 @@
"templating", "templating",
"views" "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", "name": "microsoft/tolerant-php-parser",
"version": "v0.0.20", "version": "v0.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/microsoft/tolerant-php-parser.git", "url": "https://github.com/microsoft/tolerant-php-parser.git",
"reference": "c5e2bf5d8c9f4f27eef1370bd39ea2d1f374eeb4" "reference": "6a965617cf484355048ac6d2d3de7b6ec93abb16"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/microsoft/tolerant-php-parser/zipball/c5e2bf5d8c9f4f27eef1370bd39ea2d1f374eeb4", "url": "https://api.github.com/repos/microsoft/tolerant-php-parser/zipball/6a965617cf484355048ac6d2d3de7b6ec93abb16",
"reference": "c5e2bf5d8c9f4f27eef1370bd39ea2d1f374eeb4", "reference": "6a965617cf484355048ac6d2d3de7b6ec93abb16",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.0" "php": ">=7.2"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.4" "phpunit/phpunit": "^8.5.15"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@@ -717,20 +810,24 @@
} }
], ],
"description": "Tolerant PHP-to-AST parser designed for IDE usage scenarios", "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", "name": "monolog/monolog",
"version": "1.25.3", "version": "1.26.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Seldaek/monolog.git", "url": "https://github.com/Seldaek/monolog.git",
"reference": "fa82921994db851a8becaf3787a9e73c5976b6f1" "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/fa82921994db851a8becaf3787a9e73c5976b6f1", "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c6b00f05152ae2c9b04a448f99c7590beb6042f5",
"reference": "fa82921994db851a8becaf3787a9e73c5976b6f1", "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -744,11 +841,10 @@
"aws/aws-sdk-php": "^2.4.9 || ^3.0", "aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev", "doctrine/couchdb": "~1.0@dev",
"graylog2/gelf-php": "~1.0", "graylog2/gelf-php": "~1.0",
"jakub-onderka/php-parallel-lint": "0.9",
"php-amqplib/php-amqplib": "~2.4", "php-amqplib/php-amqplib": "~2.4",
"php-console/php-console": "^3.1.3", "php-console/php-console": "^3.1.3",
"phpstan/phpstan": "^0.12.59",
"phpunit/phpunit": "~4.5", "phpunit/phpunit": "~4.5",
"phpunit/phpunit-mock-objects": "2.3.0",
"ruflin/elastica": ">=0.90 <3.0", "ruflin/elastica": ">=0.90 <3.0",
"sentry/sentry": "^0.13", "sentry/sentry": "^0.13",
"swiftmailer/swiftmailer": "^5.3|^6.0" "swiftmailer/swiftmailer": "^5.3|^6.0"
@@ -767,11 +863,6 @@
"sentry/sentry": "Allow sending log messages to a Sentry server" "sentry/sentry": "Allow sending log messages to a Sentry server"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Monolog\\": "src/Monolog" "Monolog\\": "src/Monolog"
@@ -795,20 +886,34 @@
"logging", "logging",
"psr-3" "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", "name": "netresearch/jsonmapper",
"version": "v2.1.0", "version": "v4.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/cweiske/jsonmapper.git", "url": "https://github.com/cweiske/jsonmapper.git",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e" "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/e0f1e33a71587aca81be5cffbb9746510e1fe04e", "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e", "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -816,10 +921,10 @@
"ext-pcre": "*", "ext-pcre": "*",
"ext-reflection": "*", "ext-reflection": "*",
"ext-spl": "*", "ext-spl": "*",
"php": ">=5.6" "php": ">=7.1"
}, },
"require-dev": { "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" "squizlabs/php_codesniffer": "~3.5"
}, },
"type": "library", "type": "library",
@@ -841,7 +946,235 @@
} }
], ],
"description": "Map nested JSON structures onto PHP classes", "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", "name": "pguardiario/phpuri",
@@ -865,47 +1198,52 @@
}, },
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
"description": "A php library for converting relative urls to absolute.", "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" "time": "2015-05-24T09:13:17+00:00"
}, },
{ {
"name": "phan/phan", "name": "phan/phan",
"version": "2.7.1", "version": "5.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phan/phan.git", "url": "https://github.com/phan/phan.git",
"reference": "67c51bb1593e5c30271fc16d691b82e318b90b77" "reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phan/phan/zipball/67c51bb1593e5c30271fc16d691b82e318b90b77", "url": "https://api.github.com/repos/phan/phan/zipball/f36b6b9a2f4143a25f35ce94d712ceb0527e9d90",
"reference": "67c51bb1593e5c30271fc16d691b82e318b90b77", "reference": "f36b6b9a2f4143a25f35ce94d712ceb0527e9d90",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"composer/semver": "^1.4", "composer/semver": "^1.4|^2.0|^3.0",
"composer/xdebug-handler": "^1.3.2", "composer/xdebug-handler": "^1.3.2|^2.0.0",
"ext-filter": "*", "ext-filter": "*",
"ext-json": "*", "ext-json": "*",
"ext-tokenizer": "*", "ext-tokenizer": "*",
"felixfbecker/advanced-json-rpc": "^3.0.4", "felixfbecker/advanced-json-rpc": "^3.0.4",
"microsoft/tolerant-php-parser": "0.0.20", "microsoft/tolerant-php-parser": "^0.1.0",
"netresearch/jsonmapper": "^1.6.0|^2.0", "netresearch/jsonmapper": "^1.6.0|^2.0|^3.0|^4.0",
"php": "^7.1.0", "php": "^7.2.0|^8.0.0",
"sabre/event": "^5.0", "sabre/event": "^5.0.3",
"symfony/console": "^2.3|^3.0|^4.0|^5.0", "symfony/console": "^3.2|^4.0|^5.0",
"symfony/polyfill-mbstring": "^1.11.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": { "require-dev": {
"brianium/paratest": "^4.0.0", "phpunit/phpunit": "^8.5.0"
"phpunit/phpunit": "^7.5.0"
}, },
"suggest": { "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-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-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-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": [ "bin": [
"phan", "phan",
@@ -939,7 +1277,11 @@
"php", "php",
"static" "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", "name": "php-extended/php-system",
@@ -979,6 +1321,10 @@
"php", "php",
"system" "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" "time": "2018-06-07T06:03:27+00:00"
}, },
{ {
@@ -1023,29 +1369,33 @@
"php", "php",
"tail" "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" "time": "2018-06-07T06:04:58+00:00"
}, },
{ {
"name": "phpdocumentor/reflection-common", "name": "phpdocumentor/reflection-common",
"version": "2.1.0", "version": "2.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": "^7.2 || ^8.0"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.x-dev" "dev-2.x": "2.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -1072,32 +1422,35 @@
"reflection", "reflection",
"static analysis" "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", "name": "phpdocumentor/reflection-docblock",
"version": "5.1.0", "version": "5.2.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-filter": "^7.1", "ext-filter": "*",
"php": "^7.2", "php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.0", "phpdocumentor/reflection-common": "^2.2",
"phpdocumentor/type-resolver": "^1.0", "phpdocumentor/type-resolver": "^1.3",
"webmozart/assert": "^1" "webmozart/assert": "^1.9.1"
}, },
"require-dev": { "require-dev": {
"doctrine/instantiator": "^1", "mockery/mockery": "~1.3.2"
"mockery/mockery": "^1"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
@@ -1125,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.", "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", "name": "phpdocumentor/type-resolver",
"version": "1.1.0", "version": "1.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git", "url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "7462d5f123dfc080dfdf26897032a6513644fc95" "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
"reference": "7462d5f123dfc080dfdf26897032a6513644fc95", "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2", "php": "^7.2 || ^8.0",
"phpdocumentor/reflection-common": "^2.0" "phpdocumentor/reflection-common": "^2.0"
}, },
"require-dev": { "require-dev": {
"ext-tokenizer": "^7.2", "ext-tokenizer": "*"
"mockery/mockery": "~1"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.x-dev" "dev-1.x": "1.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -1171,31 +1527,30 @@
} }
], ],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "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", "name": "psr/container",
"version": "1.0.0", "version": "1.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-fig/container.git", "url": "https://github.com/php-fig/container.git",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.0" "php": ">=7.2.0"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Psr\\Container\\": "src/" "Psr\\Container\\": "src/"
@@ -1208,7 +1563,7 @@
"authors": [ "authors": [
{ {
"name": "PHP-FIG", "name": "PHP-FIG",
"homepage": "http://www.php-fig.org/" "homepage": "https://www.php-fig.org/"
} }
], ],
"description": "Common Container Interface (PHP FIG PSR-11)", "description": "Common Container Interface (PHP FIG PSR-11)",
@@ -1220,7 +1575,11 @@
"container-interop", "container-interop",
"psr" "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", "name": "psr/http-message",
@@ -1270,20 +1629,23 @@
"request", "request",
"response" "response"
], ],
"support": {
"source": "https://github.com/php-fig/http-message/tree/master"
},
"time": "2016-08-06T14:39:51+00:00" "time": "2016-08-06T14:39:51+00:00"
}, },
{ {
"name": "psr/log", "name": "psr/log",
"version": "1.1.2", "version": "1.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-fig/log.git", "url": "https://github.com/php-fig/log.git",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801" "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/446d54b4cb6bf489fc9d75f55843658e6f25d801", "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
"reference": "446d54b4cb6bf489fc9d75f55843658e6f25d801", "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1307,7 +1669,7 @@
"authors": [ "authors": [
{ {
"name": "PHP-FIG", "name": "PHP-FIG",
"homepage": "http://www.php-fig.org/" "homepage": "https://www.php-fig.org/"
} }
], ],
"description": "Common interface for logging libraries", "description": "Common interface for logging libraries",
@@ -1317,7 +1679,10 @@
"psr", "psr",
"psr-3" "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", "name": "ralouphie/getallheaders",
@@ -1357,28 +1722,33 @@
} }
], ],
"description": "A polyfill for getallheaders.", "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" "time": "2019-03-08T08:55:37+00:00"
}, },
{ {
"name": "sabre/event", "name": "sabre/event",
"version": "5.1.0", "version": "5.1.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sabre-io/event.git", "url": "https://github.com/sabre-io/event.git",
"reference": "d00a17507af0e7544cfe17096372f5d733e3b276" "reference": "c120bec57c17b6251a496efc82b732418b49d50a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sabre-io/event/zipball/d00a17507af0e7544cfe17096372f5d733e3b276", "url": "https://api.github.com/repos/sabre-io/event/zipball/c120bec57c17b6251a496efc82b732418b49d50a",
"reference": "d00a17507af0e7544cfe17096372f5d733e3b276", "reference": "c120bec57c17b6251a496efc82b732418b49d50a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.1" "php": "^7.1 || ^8.0"
}, },
"require-dev": { "require-dev": {
"friendsofphp/php-cs-fixer": "~2.16.1", "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", "type": "library",
"autoload": { "autoload": {
@@ -1417,20 +1787,25 @@
"reactor", "reactor",
"signal" "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", "name": "scssphp/scssphp",
"version": "1.0.6", "version": "v1.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/scssphp/scssphp.git", "url": "https://github.com/scssphp/scssphp.git",
"reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c" "reference": "b83594e2323c5d6e80785df3f91b9d1d32aad530"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/scssphp/scssphp/zipball/5b3c9d704950d8f9637f5110c36c281ec47dc13c", "url": "https://api.github.com/repos/scssphp/scssphp/zipball/b83594e2323c5d6e80785df3f91b9d1d32aad530",
"reference": "5b3c9d704950d8f9637f5110c36c281ec47dc13c", "reference": "b83594e2323c5d6e80785df3f91b9d1d32aad530",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1439,11 +1814,19 @@
"php": ">=5.6.0" "php": ">=5.6.0"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3", "bamarni/composer-bin-plugin": "^1.4",
"squizlabs/php_codesniffer": "~2.5", "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4",
"twbs/bootstrap": "~4.3", "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" "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": [
"bin/pscss" "bin/pscss"
], ],
@@ -1478,24 +1861,28 @@
"scss", "scss",
"stylesheet" "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", "name": "sergeytsalkov/meekrodb",
"version": "v2.3", "version": "v2.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/SergeyTsalkov/meekrodb.git", "url": "https://github.com/SergeyTsalkov/meekrodb.git",
"reference": "eb36858f1aff94ae1665900e681a1cfb78563ee1" "reference": "e30c240d54bc81f58c58507a9ed768032eb494a5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/SergeyTsalkov/meekrodb/zipball/eb36858f1aff94ae1665900e681a1cfb78563ee1", "url": "https://api.github.com/repos/SergeyTsalkov/meekrodb/zipball/e30c240d54bc81f58c58507a9ed768032eb494a5",
"reference": "eb36858f1aff94ae1665900e681a1cfb78563ee1", "reference": "e30c240d54bc81f58c58507a9ed768032eb494a5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.2.0" "php": ">=5.3.0"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@@ -1521,39 +1908,49 @@
"mysqli", "mysqli",
"pdo" "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", "name": "symfony/console",
"version": "v5.0.8", "version": "v5.3.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935" "reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", "url": "https://api.github.com/repos/symfony/console/zipball/51b71afd6d2dc8f5063199357b9880cea8d8bfe2",
"reference": "5fa1caadc8cdaa17bcfb25219f3b53fe294a9935", "reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2.5", "php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php73": "^1.8", "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": { "conflict": {
"psr/log": ">=3",
"symfony/dependency-injection": "<4.4", "symfony/dependency-injection": "<4.4",
"symfony/dotenv": "<5.1",
"symfony/event-dispatcher": "<4.4", "symfony/event-dispatcher": "<4.4",
"symfony/lock": "<4.4", "symfony/lock": "<4.4",
"symfony/process": "<4.4" "symfony/process": "<4.4"
}, },
"provide": { "provide": {
"psr/log-implementation": "1.0" "psr/log-implementation": "1.0|2.0"
}, },
"require-dev": { "require-dev": {
"psr/log": "~1.0", "psr/log": "^1|^2",
"symfony/config": "^4.4|^5.0", "symfony/config": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0", "symfony/dependency-injection": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.4|^5.0", "symfony/event-dispatcher": "^4.4|^5.0",
@@ -1568,11 +1965,6 @@
"symfony/process": "" "symfony/process": ""
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0-dev"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Symfony\\Component\\Console\\": "" "Symfony\\Component\\Console\\": ""
@@ -1595,42 +1987,127 @@
"homepage": "https://symfony.com/contributors" "homepage": "https://symfony.com/contributors"
} }
], ],
"description": "Symfony Console Component", "description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"time": "2020-03-30T11:42:42+00:00" "keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.3.6"
},
"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-27T19:10:22+00:00"
}, },
{ {
"name": "symfony/lock", "name": "symfony/deprecation-contracts",
"version": "v4.4.3", "version": "v2.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/lock.git", "url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "6c4f5b620871cfef5b004fc57f2ca74572ae03b3" "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/lock/zipball/6c4f5b620871cfef5b004fc57f2ca74572ae03b3", "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"reference": "6c4f5b620871cfef5b004fc57f2ca74572ae03b3", "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.1.3", "php": ">=7.1"
"psr/log": "~1.0"
},
"conflict": {
"doctrine/dbal": "<2.5"
},
"require-dev": {
"doctrine/dbal": "~2.5",
"mongodb/mongodb": "~1.1",
"predis/predis": "~1.0"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "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": { "autoload": {
"psr-4": { "psr-4": {
"Symfony\\Component\\Lock\\": "" "Symfony\\Component\\Lock\\": ""
@@ -1653,7 +2130,7 @@
"homepage": "https://symfony.com/contributors" "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", "homepage": "https://symfony.com",
"keywords": [ "keywords": [
"cas", "cas",
@@ -1663,24 +2140,41 @@
"redlock", "redlock",
"semaphore" "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", "name": "symfony/polyfill-ctype",
"version": "v1.15.0", "version": "v1.23.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.3" "php": ">=7.1"
}, },
"suggest": { "suggest": {
"ext-ctype": "For best performance" "ext-ctype": "For best performance"
@@ -1688,7 +2182,11 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.15-dev" "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
} }
}, },
"autoload": { "autoload": {
@@ -1721,24 +2219,293 @@
"polyfill", "polyfill",
"portable" "portable"
], ],
"time": "2020-02-27T09:26:54+00:00" "support": {
"source": "https://github.com/symfony/polyfill-ctype/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", "name": "symfony/polyfill-intl-grapheme",
"version": "v1.15.0", "version": "v1.23.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" "reference": "16880ba9c5ebe3642d1995ab866db29270b36535"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", "reference": "16880ba9c5ebe3642d1995ab866db29270b36535",
"shasum": "" "shasum": ""
}, },
"require": { "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": { "suggest": {
"ext-mbstring": "For best performance" "ext-mbstring": "For best performance"
@@ -1746,7 +2513,11 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.15-dev" "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
} }
}, },
"autoload": { "autoload": {
@@ -1780,29 +2551,50 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-03-09T19:04:49+00:00" "support": {
"source": "https://github.com/symfony/polyfill-mbstring/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-php72", "name": "symfony/polyfill-php72",
"version": "v1.15.0", "version": "v1.23.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php72.git", "url": "https://github.com/symfony/polyfill-php72.git",
"reference": "37b0976c78b94856543260ce09b460a7bc852747" "reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
"reference": "37b0976c78b94856543260ce09b460a7bc852747", "reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.3" "php": ">=7.1"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.15-dev" "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
} }
}, },
"autoload": { "autoload": {
@@ -1835,29 +2627,50 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-02-27T09:26:54+00:00" "support": {
"source": "https://github.com/symfony/polyfill-php72/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:17:38+00:00"
}, },
{ {
"name": "symfony/polyfill-php73", "name": "symfony/polyfill-php73",
"version": "v1.15.0", "version": "v1.23.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php73.git", "url": "https://github.com/symfony/polyfill-php73.git",
"reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7" "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010",
"reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.3" "php": ">=7.1"
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.15-dev" "dev-main": "1.23-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
} }
}, },
"autoload": { "autoload": {
@@ -1893,25 +2706,125 @@
"portable", "portable",
"shim" "shim"
], ],
"time": "2020-02-27T09:26:54+00:00" "support": {
"source": "https://github.com/symfony/polyfill-php73/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/service-contracts", "name": "symfony/polyfill-php80",
"version": "v2.0.1", "version": "v1.23.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/service-contracts.git", "url": "https://github.com/symfony/polyfill-php80.git",
"reference": "144c5e51266b281231e947b51223ba14acf1a749" "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
"reference": "144c5e51266b281231e947b51223ba14acf1a749", "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2.5", "php": ">=7.1"
"psr/container": "^1.0" },
"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": { "suggest": {
"symfony/service-implementation": "" "symfony/service-implementation": ""
@@ -1919,7 +2832,11 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "2.0-dev" "dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
} }
}, },
"autoload": { "autoload": {
@@ -1951,27 +2868,178 @@
"interoperability", "interoperability",
"standards" "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", "name": "symfony/string",
"version": "v1.4.7", "version": "v5.3.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/vlucas/valitron.git", "url": "https://github.com/symfony/string.git",
"reference": "a03072bed1679660200766d134507a30193eaf6d" "reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/vlucas/valitron/zipball/a03072bed1679660200766d134507a30193eaf6d", "url": "https://api.github.com/repos/symfony/string/zipball/bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1",
"reference": "a03072bed1679660200766d134507a30193eaf6d", "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": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=5.3.2" "php": ">=5.3.2"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.5 || ^6.5" "phpunit/phpunit": ">=4.8.35"
}, },
"suggest": { "suggest": {
"ext-mbstring": "It can support the multiple bytes string length." "ext-mbstring": "It can support the multiple bytes string length."
@@ -1990,43 +3058,59 @@
{ {
"name": "Vance Lucas", "name": "Vance Lucas",
"email": "vance@vancelucas.com", "email": "vance@vancelucas.com",
"homepage": "http://www.vancelucas.com" "homepage": "https://www.vancelucas.com"
} }
], ],
"description": "Simple, elegant, stand-alone validation library with NO dependencies", "description": "Simple, elegant, stand-alone validation library with NO dependencies",
"homepage": "http://github.com/vlucas/valitron", "homepage": "https://github.com/vlucas/valitron",
"keywords": [ "keywords": [
"valid", "valid",
"validation", "validation",
"validator" "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", "name": "webmozart/assert",
"version": "1.8.0", "version": "1.10.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozart/assert.git", "url": "https://github.com/webmozarts/assert.git",
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6" "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6", "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6", "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^5.3.3 || ^7.0", "php": "^7.2 || ^8.0",
"symfony/polyfill-ctype": "^1.8" "symfony/polyfill-ctype": "^1.8"
}, },
"conflict": { "conflict": {
"vimeo/psalm": "<3.9.1" "phpstan/phpstan": "<0.12.20",
"vimeo/psalm": "<4.6.1 || 4.6.2"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13" "phpunit/phpunit": "^8.5.13"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.10-dev"
}
},
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Webmozart\\Assert\\": "src/" "Webmozart\\Assert\\": "src/"
@@ -2048,7 +3132,11 @@
"check", "check",
"validate" "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", "name": "xemlock/htmlpurifier-html5",
@@ -2099,6 +3187,10 @@
"validator", "validator",
"xss" "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" "time": "2019-08-07T17:19:21+00:00"
} }
], ],
@@ -2112,5 +3204,6 @@
"platform-dev": [], "platform-dev": [],
"platform-overrides": { "platform-overrides": {
"php": "7.3" "php": "7.3"
} },
"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"; @charset "utf-8";
body {
body { color: white;
color:white; background-color:black; font-family: '맑은 고딕'; background-color: black;
} font-family: '맑은 고딕';
}
table {
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black; table {
padding: 0px; border: solid 1px;
font-size: 13px; border-spacing: 0px;
word-break: break-all; border-collapse: separate;
text-align: center; border-top-color: gray;
font-family: '맑은 고딕'; border-left-color: gray;
} border-right-color: black;
th, td { border-bottom-color: black;
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black; padding: 0px;
padding: 0px; font-size: 13px;
font-size: 13px; word-break: break-all;
word-break: break-all; text-align: center;
text-align: center; font-family: '맑은 고딕';
font-family: '맑은 고딕'; }
}
th,
a.just_link { td {
text-decoration: none; border: solid 1px;
} border-spacing: 0px;
border-collapse: separate;
.with_border{ border-top-color: gray;
margin:0; border-left-color: gray;
border: solid 1px; border-right-color: black;
border-spacing: 0px; border-bottom-color: black;
border-collapse: separate; padding: 0px;
border-top-color: gray; font-size: 13px;
border-left-color: gray; word-break: break-all;
border-right-color: black; text-align: center;
border-bottom-color: black; font-family: '맑은 고딕';
} }
.section_title { a.just_link {
height:50px; text-decoration: none;
line-height:50px; }
font-size: 30px; font-weight: bold;
text-align: center; .with_border {
color:white; margin: 0;
padding:0; border: solid 1px;
} border-spacing: 0px;
border-collapse: separate;
.legacy_layout div { border-top-color: gray;
border: solid 1px; border-spacing: 0px; border-collapse: separate; border-top-color: gray; border-left-color: gray; border-right-color: black; border-bottom-color: black; border-left-color: gray;
padding: 0px; border-right-color: black;
font-size: 13px; border-bottom-color: black;
word-break: break-all; }
text-align: center;
font-family: '맑은 고딕';; .section_title {
} height: 50px;
line-height: 50px;
.obj_fill{ font-size: 30px;
display:block; font-weight: bold;
width:100%; text-align: center;
height:100%; color: white;
} padding: 0;
}
button.with_skin {
padding:0 4px; .legacy_layout div {
background-color: black; color: white; border: solid 1px;
font-family: '맑은 고딕'; border-spacing: 0px;
font-size: 13px; border-collapse: separate;
} border-top-color: gray;
border-left-color: gray;
button.with_skin:disabled { border-right-color: black;
background-color:#333333; border-bottom-color: black;
} padding: 0px;
font-size: 13px;
input.with_skin { word-break: break-all;
background-color: black; color: white; text-align: center;
font-family: '맑은 고딕'; font-family: '맑은 고딕';
font-size: 13px; ;
} }
input.with_skin:disabled { .obj_fill {
background-color: #333333; display: block;
} width: 100%;
height: 100%;
.font0 { font-size: 10px; } }
.font1 { font-size: 13px; }
.font2 { font-size: 15px; } button.with_skin {
.font3 { font-size: 20px; } padding: 0 4px;
.font4 { font-size: 30px; } background-color: black;
.font5 { font-size: 50px; } color: white;
font-family: '맑은 고딕';
caption.section_title { font-size: 13px;
caption-side:top; }
}
button.with_skin:disabled {
background-color: #333333;
.samButton{ }
float:left;
display:block; input.with_skin {
padding:0; background-color: black;
margin:0; color: white;
text-decoration: none; font-family: '맑은 고딕';
position:relative; font-size: 13px;
} }
a.samButton.disabled { input.with_skin:disabled {
pointer-events: none; background-color: #333333;
cursor: default; }
}
.font0 {
.samButtonOuter{ font-size: 10px;
display: table; }
border: outset 2px white;
box-sizing: border-box; .font1 {
font-weight:bold; font-size: 13px;
padding: 1px 6px; }
width:125px;
height:30px; .font2 {
background-color:#000000; font-size: 15px;
color:#ffffff; }
}
.font3 {
.samButtonOuter:active{ font-size: 20px;
border: inset 2px white; }
}
.font4 {
font-size: 30px;
.samButtonInner{ }
display: table-cell;
vertical-align: middle; .font5 {
width: 100%; font-size: 50px;
margin: 0 auto; }
text-align: center;
user-select: none; caption.section_title {
} caption-side: top;
}
.samToolbarButton > .samButtonOuter{
width:125px; .samButton {
height:30px; float: left;
background-color:#225500; display: block;
color:white; padding: 0;
} margin: 0;
text-decoration: none;
.samToolbarButton2 > .samButtonOuter{ position: relative;
width:125px; }
height:30px;
background-color:#225500; a.samButton.disabled {
color:magenta; pointer-events: none;
} cursor: default;
}
.samCommandButton > .samButtonOuter{
width:111px; .samButtonOuter {
height:30px; display: table;
} border: outset 2px white;
box-sizing: border-box;
.samCommandButton.disabled > .samButtonOuter{ font-weight: bold;
background-color:transparent !important; padding: 1px 6px;
color:gray !important; width: 125px;
border-color:transparent !important; height: 30px;
} background-color: #000000;
color: #ffffff;
.samCommandButton.disabled > .samButtonOuter > .samButtonInner::before{ }
content:'【'
} .samButtonOuter:active {
border: inset 2px white;
.samCommandButton.disabled > .samButtonOuter > .samButtonInner::after{ }
content:'】'
} .samButtonInner {
display: table-cell;
.tooltip_copyable_info .tooltiptext{ vertical-align: middle;
display: inline; width: 100%;
color: rgba(0,0,0,0); margin: 0 auto;
font-size: 0; text-align: center;
} user-select: none;
}
.tooltiptext {
display: none; .samToolbarButton>.samButtonOuter {
} width: 125px;
height: 30px;
.hidden_but_copyable{ background-color: #225500;
color: rgba(0,0,0,0); color: white;
font-size: 0; }
.samToolbarButton2>.samButtonOuter {
width: 125px;
height: 30px;
background-color: #225500;
color: magenta;
}
.samCommandButton>.samButtonOuter {
width: 111px;
height: 30px;
}
.samCommandButton.disabled>.samButtonOuter {
background-color: transparent !important;
color: gray !important;
border-color: transparent !important;
}
.samCommandButton.disabled>.samButtonOuter>.samButtonInner::before {
content: '【'
}
.samCommandButton.disabled>.samButtonOuter>.samButtonInner::after {
content: '】'
}
.tooltip_copyable_info .tooltiptext {
display: inline;
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.tooltiptext {
display: none;
}
.hidden_but_copyable {
color: rgba(0, 0, 0, 0);
font-size: 0;
}
.vertical_flex {
height: 100%;
display: flex;
align-content: center;
flex-direction: column;
align-items: stretch;
}
.vertical_flex .item {
display: block;
flex-grow: 1;
}
.fill_box {
display: block;
width: 100%;
height: 100%;
} }
+155 -140
View File
@@ -1,141 +1,156 @@
@charset "utf-8"; @charset "utf-8";
body {
body{ line-height: 1.3;
line-height: 1.3; }
}
#server_notice {
#server_notice { margin: 10px 0;
margin:10px 0; border: none;
border: none; text-align: center;
text-align:center; }
}
#server_list_container {
#server_list_container{ width: 800px;
width:800px; position: absolute;
position:absolute; left: 50%;
left:50%; margin-left: -400px;
margin-left:-400px; }
}
#server_list_table {
#server_list_table{ width: 100%;
width:100%; }
}
#server_list tr {
#server_list tr{ height: 66px;
height:66px; }
}
.ignore_border {
#server_list .server_create_and_select .general_create, border: 0;
#server_list .server_create_and_select .general_select { margin: 0;
width: 120px; height: 33px; padding: 0;
float: left; }
}
#user_info {
#server_list .general_create, margin-top: 20px;
#server_list .general_login { width: 800px;
width: 120px; height: 66px; height: 130px;
float: left; }
}
#user_info button {
.ignore_border{ width: 200px;
border:0; height: 50px;
margin:0; margin: 10px 50px;
padding:0; }
}
.center_ordered_items {
#user_info { text-align: center;
margin-top:20px; }
width: 800px; height: 130px;
} .Entrance_ServerList {
width: 800px;
height: 64px;
#user_info button{ border: none;
width: 200px; float: left;
height: 50px; }
margin: 10px 50px;
} .Entrance_ServerListServer {
width: 98px;
.center_ordered_items{ height: 64px;
text-align:center; float: left;
} }
.Entrance_ServerList { .Entrance_ServerListDown {
width: 800px; height: 64px; width: 698px;
border: none; height: 64px;
float: left; float: left;
} }
.Entrance_ServerListServer { .Entrance_ServerListInfo {
width: 98px; height: 64px; width: 398px;
float: left; height: 64px;
} float: left;
}
.Entrance_ServerListDown {
width: 698px; height: 64px; .Entrance_ServerListBlock {
float: left; width: 298px;
} height: 64px;
float: left;
.Entrance_ServerListInfo { line-height: 64px;
width: 398px; height: 64px; }
float: left;
} .Entrance_ServerListCharacter {
width: 64px;
.Entrance_ServerListBlock { height: 64px;
width: 298px; height: 64px; float: left;
float: left; }
line-height: 64px;
} .Entrance_ServerListName {
width: 112px;
.Entrance_ServerListCharacter { height: 64px;
width: 64px; height: 64px; float: left;
float: left; line-height: 64px;
} }
.Entrance_ServerListName { .Entrance_ServerListSelect {
width: 112px; height: 64px; width: 120px;
float: left; height: 32px;
line-height: 64px; float: left;
} }
#Entrance_000003 {
.Entrance_ServerListSelect { width: 798px;
width: 120px; height: 32px; height: 155px;
float: left; text-align: left;
} }
#Entrance_000003 { .Entrance_Alert {
width: 798px; height: 155px; color: red;
text-align: left; font-size: 15px;
} font-weight: bold;
}
.Entrance_Alert {
color: red; font-size: 15px; font-weight: bold; .Entrance_Che {
} color: white;
font-size: 15px;
.Entrance_Che { font-weight: bold;
color: white; font-size: 15px; font-weight: bold; }
}
.Entrance_Kwe {
.Entrance_Kwe { color: yellow;
color: yellow; font-size: 15px; font-weight: bold; font-size: 15px;
} font-weight: bold;
}
.Entrance_Pwe {
color: orange; font-size: 15px; font-weight: bold; .Entrance_Pwe {
} color: orange;
font-size: 15px;
.Entrance_Twe { font-weight: bold;
color: magenta; font-size: 15px; font-weight: bold; }
}
.Entrance_Twe {
.Entrance_Nya { color: magenta;
color: #e67e22; font-size: 15px; font-weight: bold; font-size: 15px;
} font-weight: bold;
}
.Entrance_Pya {
color: #9b59b6; font-size: 15px; font-weight: bold; .Entrance_Nya {
} color: #e67e22;
font-size: 15px;
.Entrance_Hwe { font-weight: bold;
color: red; font-size: 15px; font-weight: bold; }
.Entrance_Pya {
color: #9b59b6;
font-size: 15px;
font-weight: bold;
}
.Entrance_Hwe {
color: red;
font-size: 15px;
font-weight: bold;
}
.BtnPlate {
height: inherit;
} }
+131 -130
View File
@@ -1,131 +1,132 @@
body, html{ body,
height: 100%; html {
background-repeat: no-repeat; height: 100%;
} background-repeat: no-repeat;
}
.main{
margin-top: 70px; .main {
} margin-top: 70px;
}
h1.title {
font-size: 50px; h1.title {
font-family: 'Passion One', cursive; font-size: 50px;
font-weight: 400; font-family: 'Passion One', cursive;
} font-weight: 400;
}
hr{
width: 10%; hr {
/*color: #fff;*/ width: 10%;
} /*color: #fff;*/
}
.form-group{
margin-bottom: 15px; .form-group {
} margin-bottom: 15px;
}
label{
margin-bottom: 15px; label {
} margin-bottom: 15px;
}
input,
input::-webkit-input-placeholder { input,
font-size: 11px; input::-webkit-input-placeholder {
padding-top: 3px; font-size: 11px;
} padding-top: 3px;
}
.main-login{
/*background-color: #fff;*/ .main-login {
/* shadows and rounded borders */ /*background-color: #fff;*/
-moz-border-radius: 2px; /* shadows and rounded borders */
-webkit-border-radius: 2px; -moz-border-radius: 2px;
border-radius: 2px; -webkit-border-radius: 2px;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); border-radius: 2px;
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
} }
.main-center{ .main-center {
margin-top: 30px; margin-top: 30px;
margin: 0 auto; margin: 0 auto;
max-width: 330px; max-width: 330px;
padding: 40px 40px; padding: 40px 40px;
}
}
.login_btn_group {
.login_btn_group{ margin-top: 5px;
margin-top: 5px; }
}
.login-register {
.login-register{ font-size: 11px;
font-size: 11px; text-align: center;
text-align: center; }
}
.col-form-label {
text-align: center;
.col-form-label{ }
text-align:center;
} .terms {
max-height: 200px;
.terms{ overflow-y: auto;
max-height: 200px; overflow-y: auto; }
}
.terms pre {
.terms pre{ width: 100%;
width:100%; white-space: pre-wrap;
white-space: pre-wrap; /* Since CSS 2.1 */ /* Since CSS 2.1 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -moz-pre-wrap;
white-space: -pre-wrap; /* Opera 4-6 */ /* Mozilla, since 1999 */
white-space: -o-pre-wrap; /* Opera 7 */ white-space: -pre-wrap;
word-wrap: break-word; /* Internet Explorer 5.5+ */ /* Opera 4-6 */
} white-space: -o-pre-wrap;
/* Opera 7 */
.vertical-center { word-wrap: break-word;
min-height: 100%; /* Fallback for browsers do NOT support vh unit */ /* Internet Explorer 5.5+ */
min-height: 100vh; /* These two lines are counted as one :-) */ }
display: flex; .vertical-center {
align-items: center; min-height: 100%;
} /* Fallback for browsers do NOT support vh unit */
min-height: 100vh;
.full-content { /* These two lines are counted as one :-) */
position:fixed; display: flex;
left:0; align-items: center;
top:0; }
width:100%;
height:100%; #login_card {
margin:0; z-index: 801;
padding:0; }
z-index:800;
} #btn_kakao_login {
cursor: pointer;
#login_card{ height: 46px;
z-index:801; width: 116px;
} background-color: transparent;
color: transparent;
#btn_kakao_login{ border: 0;
cursor: pointer; background-size: 100%;
height:46px; /* To fill the dimensions of container (button), or */
width:116px; background-repeat: no-repeat;
background-color: transparent; background-position: bottom center;
color:transparent; margin-top: 5px;
border:0; background-image: url('../oauth_kakao/kakao_login_join.png');
background-size: 100%; /* To fill the dimensions of container (button), or */ }
background-repeat: no-repeat;
background-position: bottom center; #btn_kakao_login:hover {
margin-top:5px; background-image: url('../oauth_kakao/kakao_login_join_ov.png');
background-image:url('../oauth_kakao/kakao_login_join.png'); }
}
#bottom_box .container {
#btn_kakao_login:hover { text-align: center;
background-image:url('../oauth_kakao/kakao_login_join_ov.png'); }
}
.btn-group-xs>.btn,
#bottom_box{ .btn-xs {
position:fixed; padding: .25rem .4rem;
bottom:0; font-size: .875rem;
width:100%; line-height: .5;
left:0; border-radius: .2rem;
} }
#bottom_box .container{
text-align:center; #running_map {
margin-top: 20px;
} }
+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)) { if (!(error_reporting() & $errno)) {
// This error code is not included in error_reporting, so let it fall // This error code is not included in error_reporting, so let it fall
+313 -305
View File
@@ -1,305 +1,313 @@
<?php <?php
namespace sammo; namespace sammo;
require(__DIR__ . '/../vendor/autoload.php'); require(__DIR__ . '/../vendor/autoload.php');
$host = Util::getPost('db_host'); $host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int'); $port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id'); $username = Util::getPost('db_id');
$password = Util::getPost('db_pw'); $password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name'); $dbName = Util::getPost('db_name');
$servHost = Util::getPost('serv_host'); $servHost = Util::getPost('serv_host');
$sharedIconPath = Util::getPost('shared_icon_path'); $sharedIconPath = Util::getPost('shared_icon_path');
$gameImagePath = Util::getPost('game_image_path'); $gameImagePath = Util::getPost('game_image_path');
$imageRequestKey = Util::getPost('image_request_key'); $imageRequestKey = Util::getPost('image_request_key');
$kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', ''); $kakaoRESTKey = Util::getPost('kakao_rest_key', 'string', '');
$kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', ''); $kakaoAdminKey = Util::getPost('kakao_admin_key', 'string', '');
if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) { if (!$host || !$port || !$username || !$password || !$dbName || !$servHost || !$sharedIconPath || !$gameImagePath) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '입력 값이 올바르지 않습니다' 'reason' => '입력 값이 올바르지 않습니다'
]); ]);
} }
if (!filter_var($servHost, FILTER_VALIDATE_URL)) { if (!filter_var($servHost, FILTER_VALIDATE_URL)) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '접속 경로가 올바르지 않습니다.' 'reason' => '접속 경로가 올바르지 않습니다.'
]); ]);
} }
if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) { if (file_exists(ROOT . '/d_setting/RootDB.php') && is_dir(ROOT . '/d_setting/RootDB.php')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_setting/RootDB.php 가 디렉토리입니다' 'reason' => 'd_setting/RootDB.php 가 디렉토리입니다'
]); ]);
} }
if (class_exists('\\sammo\\RootDB')) { if (class_exists('\\sammo\\RootDB')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '이미 RootDB.php 파일이 있습니다' 'reason' => '이미 RootDB.php 파일이 있습니다'
]); ]);
} }
//파일 권한 검사 //파일 권한 검사
if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) { if (file_exists(AppConf::getUserIconPathFS()) && !is_dir(AppConf::getUserIconPathFS())) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다' 'reason' => AppConf::$userIconPath . ' 이 디렉토리가 아닙니다'
]); ]);
} }
if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) { if (file_exists(ROOT . '/d_log') && !is_dir(ROOT . '/d_log')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_log 가 디렉토리가 아닙니다' 'reason' => 'd_log 가 디렉토리가 아닙니다'
]); ]);
} }
if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) { if (file_exists(ROOT . '/d_shared') && !is_dir(ROOT . '/d_shared')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다' 'reason' => 'd_shared 가 디렉토리가 아닙니다'
]); ]);
} }
if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) { if (file_exists(ROOT . '/d_setting') && !is_dir(ROOT . '/d_setting')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_shared 가 디렉토리가 아닙니다' 'reason' => 'd_shared 가 디렉토리가 아닙니다'
]); ]);
} }
if ( if (
!file_exists(ROOT . '/d_log') !file_exists(ROOT . '/d_log')
|| !file_exists(ROOT . '/d_shared') || !file_exists(ROOT . '/d_shared')
|| !file_exists(ROOT . '/d_setting') || !file_exists(ROOT . '/d_setting')
|| !file_exists(AppConf::getUserIconPathFS()) || !file_exists(AppConf::getUserIconPathFS())
) { ) {
if (!is_writable(ROOT)) { if (!is_writable(ROOT)) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => '하위 디렉토리 생성 권한이 없습니다' 'reason' => '하위 디렉토리 생성 권한이 없습니다'
]); ]);
} }
//기본 파일 생성 //기본 파일 생성
if (!file_exists(AppConf::getUserIconPathFS())) { if (!file_exists(AppConf::getUserIconPathFS())) {
mkdir(AppConf::getUserIconPathFS()); mkdir(AppConf::getUserIconPathFS());
} }
if (!file_exists(ROOT . '/d_log')) { if (!file_exists(ROOT . '/d_log')) {
mkdir(ROOT . '/d_log'); mkdir(ROOT . '/d_log');
} }
if (!file_exists(ROOT . '/d_setting')) { if (!file_exists(ROOT . '/d_setting')) {
mkdir(ROOT . '/d_setting'); mkdir(ROOT . '/d_setting');
} }
if (!file_exists(ROOT . '/d_shared')) { if (!file_exists(ROOT . '/d_shared')) {
mkdir(ROOT . '/d_shared'); mkdir(ROOT . '/d_shared');
} }
} }
if (!is_writable(AppConf::getUserIconPathFS())) { if (!is_writable(AppConf::getUserIconPathFS())) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다' 'reason' => AppConf::$userIconPath . ' 디렉토리의 쓰기 권한이 없습니다'
]); ]);
} }
if (!is_writable(ROOT . '/d_log')) { if (!is_writable(ROOT . '/d_log')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다' 'reason' => 'd_log 디렉토리의 쓰기 권한이 없습니다'
]); ]);
} }
if (!is_writable(ROOT . '/d_shared')) { if (!is_writable(ROOT . '/d_shared')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다' 'reason' => 'd_shared 디렉토리의 쓰기 권한이 없습니다'
]); ]);
} }
if (!is_writable(ROOT . '/d_setting')) { if (!is_writable(ROOT . '/d_setting')) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.' 'reason' => 'd_setting 디렉토리의 쓰기 권한이 없습니다.'
]); ]);
} }
if (!file_exists(ROOT . '/d_log/.htaccess')) { if (!file_exists(ROOT . '/d_log/.htaccess')) {
@file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all'); @file_put_contents(ROOT . '/d_log/.htaccess', 'Deny from all');
} }
if (!file_exists(ROOT . '/d_setting/.htaccess')) { if (!file_exists(ROOT . '/d_setting/.htaccess')) {
@file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all'); @file_put_contents(ROOT . '/d_setting/.htaccess', 'Deny from all');
} }
//DB 접근 권한 검사 //DB 접근 권한 검사
$rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4'); $rootDB = new \MeekroDB($host, $username, $password, $dbName, $port, 'utf8mb4');
$rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; $rootDB->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$rootDB->throw_exception_on_nonsql_error = false; $rootDB->throw_exception_on_nonsql_error = false;
$rootDB->nonsql_error_handler = function ($params) { $rootDB->nonsql_error_handler = function ($params) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'DB 접속에 실패했습니다.' 'reason' => 'DB 접속에 실패했습니다.'
]); ]);
}; };
$rootDB->error_handler = function ($params) { $rootDB->error_handler = function ($params) {
Json::die([ Json::die([
'result' => false, 'result' => false,
'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.' 'reason' => 'SQL을 제대로 실행하지 못했습니다. DB상태를 확인해 주세요.'
]); ]);
}; };
$mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨. $mysqli_obj = $rootDB->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) { if ($mysqli_obj->multi_query(file_get_contents(__DIR__ . '/sql/common_schema.sql'))) {
while (true) { while (true) {
if (!$mysqli_obj->more_results()) { if (!$mysqli_obj->more_results()) {
break; break;
} }
if (!$mysqli_obj->next_result()) { if (!$mysqli_obj->next_result()) {
break; break;
} }
} }
} }
$rootDB->insert('system', array( $rootDB->insert('system', array(
'REG' => 'N', 'REG' => 'N',
'LOGIN' => 'N', 'LOGIN' => 'N',
'CRT_DATE' => TimeUtil::now(), 'CRT_DATE' => TimeUtil::now(),
'MDF_DATE' => TimeUtil::now() 'MDF_DATE' => TimeUtil::now()
)); ));
$globalSalt = bin2hex(random_bytes(16)); $globalSalt = bin2hex(random_bytes(16));
'@phan-var-force string $servHost'; '@phan-var-force string $servHost';
'@phan-var-force string $sharedIconPath'; '@phan-var-force string $sharedIconPath';
'@phan-var-force string $gameImagePath'; '@phan-var-force string $gameImagePath';
$sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost); $sharedIconPath = WebUtil::resolveRelativePath($sharedIconPath, $servHost);
$gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost); $gameImagePath = WebUtil::resolveRelativePath($gameImagePath, $servHost);
$imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost); $imageRequestPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/git_pull.php', $servHost);
$imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost); $imageKeyInstallPath = WebUtil::resolveRelativePath($gameImagePath . '/../hook/InstallKey.php', $servHost);
$result = Util::generateFileUsingSimpleTemplate( $result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/ServConfig.orig.php', __DIR__ . '/templates/ServConfig.orig.php',
ROOT . '/d_setting/ServConfig.php', ROOT . '/d_setting/ServConfig.php',
[ [
'serverBasePath' => $servHost, 'serverBasePath' => $servHost,
'sharedIconPath' => $sharedIconPath, 'sharedIconPath' => $sharedIconPath,
'gameImagePath' => $gameImagePath, 'gameImagePath' => $gameImagePath,
'imageRequestPath' => $imageRequestPath, 'imageRequestPath' => $imageRequestPath,
'imageRequestKey' => $imageRequestKey 'imageRequestKey' => $imageRequestKey,
], 'serverList' => [
true ['che', '체', 'white'],
); ['kwe', '퀘', 'yellow'],
['pwe', '풰', 'orange'],
if ($imageRequestKey) { ['twe', '퉤', 'magenta'],
@file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey); ['nya', '냐', '#e67e22'],
} ['pya', '퍄', '#9b59b6']
]
if ($result !== true) { ],
Json::die([ true
'result' => false, );
'reason' => $result
]); if ($imageRequestKey) {
} @file_get_contents($imageKeyInstallPath . '?key=' . $imageRequestKey);
}
$result = Util::generateFileUsingSimpleTemplate(
__DIR__ . '/templates/common_path.orig.js', if ($result !== true) {
ROOT . '/d_shared/common_path.js', Json::die([
[ 'result' => false,
'serverBasePath' => $servHost, 'reason' => $result
'sharedIconPath' => $sharedIconPath, ]);
'gameImagePath' => $gameImagePath }
],
true $result = Util::generateFileUsingSimpleTemplate(
); __DIR__ . '/templates/common_path.orig.js',
ROOT . '/d_shared/common_path.js',
$result = Util::generateFileUsingSimpleTemplate( [
__DIR__ . '/templates/menu.orig.json', 'serverBasePath' => $servHost,
ROOT . '/d_shared/menu.json', 'sharedIconPath' => $sharedIconPath,
[], 'gameImagePath' => $gameImagePath
true ],
); true
);
if ($result !== true) {
Json::die([ $result = Util::generateFileUsingSimpleTemplate(
'result' => false, __DIR__ . '/templates/menu.orig.json',
'reason' => $result ROOT . '/d_shared/menu.json',
]); [],
} true
);
$result = Util::generateFileUsingSimpleTemplate( if ($result !== true) {
__DIR__ . '/templates/common.orig.css', Json::die([
ROOT . '/d_shared/common.css', 'result' => false,
[ 'reason' => $result
'serverBasePath' => $servHost, ]);
'sharedIconPath' => $sharedIconPath, }
'gameImagePath' => $gameImagePath
],
true $result = Util::generateFileUsingSimpleTemplate(
); __DIR__ . '/templates/common.orig.css',
ROOT . '/d_shared/common.css',
if ($result !== true) { [
Json::die([ 'serverBasePath' => $servHost,
'result' => false, 'sharedIconPath' => $sharedIconPath,
'reason' => $result 'gameImagePath' => $gameImagePath
]); ],
} true
);
$result = Util::generateFileUsingSimpleTemplate( if ($result !== true) {
__DIR__ . '/templates/RootDB.orig.php', Json::die([
ROOT . '/d_setting/RootDB.php', 'result' => false,
[ 'reason' => $result
'host' => $host, ]);
'user' => $username, }
'password' => $password,
'dbName' => $dbName,
'port' => $port, $result = Util::generateFileUsingSimpleTemplate(
'globalSalt' => $globalSalt, __DIR__ . '/templates/RootDB.orig.php',
] ROOT . '/d_setting/RootDB.php',
); [
'host' => $host,
$kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/'); 'user' => $username,
'password' => $password,
Util::generateFileUsingSimpleTemplate( 'dbName' => $dbName,
__DIR__ . '/templates/KakaoKey.orig.php', 'port' => $port,
ROOT . '/d_setting/KakaoKey.php', 'globalSalt' => $globalSalt,
[ ]
'REST_API_KEY' => $kakaoRESTKey, );
'ADMIN_KEY' => $kakaoAdminKey,
'REDIRECT_URI' => $kakaoRedirectURI $kakaoRedirectURI = WebUtil::resolveRelativePath('oauth_kakao/oauth.php', $servHost . '/');
],
true Util::generateFileUsingSimpleTemplate(
); __DIR__ . '/templates/KakaoKey.orig.php',
ROOT . '/d_setting/KakaoKey.php',
if ($result !== true) { [
Json::die([ 'REST_API_KEY' => $kakaoRESTKey,
'result' => false, 'ADMIN_KEY' => $kakaoAdminKey,
'reason' => $result 'REDIRECT_URI' => $kakaoRedirectURI
]); ],
} true
);
Json::die([
'result' => true, if ($result !== true) {
'reason' => 'success', Json::die([
'globalSalt' => $globalSalt 'result' => false,
]); 'reason' => $result
]);
}
Json::die([
'result' => true,
'reason' => 'success',
'globalSalt' => $globalSalt
]);
+74 -55
View File
@@ -1,55 +1,74 @@
<?php <?php
namespace sammo; namespace sammo;
class ServConfig class ServConfig
{ {
private function __construct() private function __construct()
{ {
} }
public static $serverWebPath = '_tK_serverBasePath_'; public static $serverWebPath = '_tK_serverBasePath_';
public static $sharedIconPath = '_tK_sharedIconPath_'; public static $sharedIconPath = '_tK_sharedIconPath_';
public static $gameImagePath = "_tK_gameImagePath_"; public static $gameImagePath = "_tK_gameImagePath_";
public static $imageRequestPath = "_tK_imageRequestPath_"; public static $imageRequestPath = "_tK_imageRequestPath_";
public static $imageRequestKey = '_tK_imageRequestKey_'; public static $imageRequestKey = '_tK_imageRequestKey_';
private static $serverList = null;
public static function getSharedIconPath(string $filepath = ''): string
{ public static function getSharedIconPath(string $filepath = ''): string
if ($filepath) { {
return static::$sharedIconPath . "/{$filepath}"; if ($filepath) {
} return static::$sharedIconPath . "/{$filepath}";
return static::$sharedIconPath; }
} return static::$sharedIconPath;
}
public static function getUserIconPath(string $filepath = ''): string
{ public static function getUserIconPath(string $filepath = ''): string
return AppConf::getUserIconPathWeb($filepath); {
} return AppConf::getUserIconPathWeb($filepath);
}
public static function getGameImagePath(string $filepath = ''): string
{ public static function getGameImagePath(string $filepath = ''): string
if ($filepath) { {
return static::$gameImagePath . "/{$filepath}"; if ($filepath) {
} return static::$gameImagePath . "/{$filepath}";
return static::$gameImagePath; }
} return static::$gameImagePath;
}
public static function getImagePullURI(): string
{ public static function getImagePullURI(): string
$now = time(); {
$req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey); $now = time();
return static::$imageRequestPath . "?req={$req_hash}&time={$now}"; $req_hash = Util::hashPassword(sprintf("%016x", $now), static::$imageRequestKey);
} return static::$imageRequestPath . "?req={$req_hash}&time={$now}";
}
/** /**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함 * 서버 설정 반환
* *
* @return string * @return \sammo\Setting[]
*/ */
public static function getServerBasepath(): string public static function getServerList(): array{
{ $servKeyList = [/*_tK_serverList_*/];
return self::$serverWebPath; $servKeyList[] = ['hwe', '훼', 'red'];
}
} if (self::$serverList === null) {
self::$serverList = [];
foreach($servKeyList as [$servKey, $servNick, $servColor]){
self::$serverList[$servKey] = new Setting(ROOT.'/'.$servKey, $servNick, $servColor);
}
}
return self::$serverList;
}
/**
* 서버 주소 반환. 서버의 경로가 하부 디렉토리인 경우에 하부 디렉토리까지 포함
*
* @return string
*/
public static function getServerBasepath(): string
{
return self::$serverWebPath;
}
}
+4
View File
@@ -24,3 +24,7 @@ foreach ($db->queryFirstColumn(
) as $generalNo) { ) as $generalNo) {
CheckHall($generalNo); CheckHall($generalNo);
} }
foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
$genObj->mergeTotalInheritancePoint();
}
+215 -215
View File
@@ -1,215 +1,215 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
$type = Util::getReq('type', 'int', 9); $type = Util::getReq('type', 'int', 9);
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
increaseRefresh("장수일람", 2); increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID); $me = $db->queryFirstRow('SELECT con,turntime FROM general WHERE owner = %i', $userID);
$con = checkLimit($me['con']); $con = checkLimit($me['con']);
if ($con >= 2) { if ($con >= 2) {
printLimitMsg($me['turntime']); printLimitMsg($me['turntime']);
exit(); exit();
} }
if ($type <= 0 || $type > 15) { if ($type <= 0 || $type > 15) {
$type = 9; $type = 9;
} }
$ownerNameList = []; $ownerNameList = [];
if($gameStor->isunited){ if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){ foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName; $ownerNameList[$ownerID] = $ownerName;
} }
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<title><?=UniqueConst::$serverName?>: 장수일람</title> <title><?=UniqueConst::$serverName?>: 장수일람</title>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
<?=WebUtil::printCSS('css/common.css')?> <?=WebUtil::printCSS('css/common.css')?>
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> <?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('../d_shared/common_path.js')?> <?=WebUtil::printJS('../d_shared/common_path.js')?>
<?=WebUtil::printJS('js/common.js')?> <?=WebUtil::printJS('js/common.js')?>
</head> </head>
<body> <body>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td>장 수 일 람<br><?=closeButton()?></td></tr> <tr><td>장 수 일 람<br><?=closeButton()?></td></tr>
<tr><td><form name=form1 method=post>정렬순서 : <tr><td><form name=form1 method=post>정렬순서 :
<select id='viewType' name='type' size=1> <select id='viewType' name='type' size=1>
<option value=1>국가</option> <option value=1>국가</option>
<option value=2>통솔</option> <option value=2>통솔</option>
<option value=3>무력</option> <option value=3>무력</option>
<option value=4>지력</option> <option value=4>지력</option>
<option value=5>명성</option> <option value=5>명성</option>
<option value=6>계급</option> <option value=6>계급</option>
<option value=7>관직</option> <option value=7>관직</option>
<option value=8>삭턴</option> <option value=8>삭턴</option>
<option value=9>벌점</option> <option value=9>벌점</option>
<option value=10>Lv</option> <option value=10>Lv</option>
<option value=11>성격</option> <option value=11>성격</option>
<option value=12>내특</option> <option value=12>내특</option>
<option value=13>전특</option> <option value=13>전특</option>
<option value=14>연령</option> <option value=14>연령</option>
<option value=15>NPC</option> <option value=15>NPC</option>
</select> </select>
<input type=submit value='정렬하기'></form> <input type=submit value='정렬하기'></form>
</td></tr> </td></tr>
</table> </table>
<?php <?php
$nationname = []; $nationname = [];
$nationlevel = []; $nationlevel = [];
$nationname[0] = "-"; $nationname[0] = "-";
foreach (getAllNationStaticInfo() as $nation) { foreach (getAllNationStaticInfo() as $nation) {
$nationname[$nation['nation']] = $nation['name']; $nationname[$nation['nation']] = $nation['name'];
$nationlevel[$nation['nation']] = $nation['level']; $nationlevel[$nation['nation']] = $nation['level'];
} }
[$orderKey, $orderDesc] = [ [$orderKey, $orderDesc] = [
1=>['nation', false], 1=>['nation', false],
2=>['leadership', true], 2=>['leadership', true],
3=>['strength', true], 3=>['strength', true],
4=>['intel', true], 4=>['intel', true],
5=>['experience', true], 5=>['experience', true],
6=>['dedication', true], 6=>['dedication', true],
7=>['officer_level', true], 7=>['officer_level', true],
8=>['killturn', false], 8=>['killturn', false],
9=>['connect', true], 9=>['connect', true],
10=>['experience', true], 10=>['experience', true],
11=>['personal', true], 11=>['personal', true],
12=>['special', true], 12=>['special', true],
13=>['special2', true], 13=>['special2', true],
14=>['age', true], 14=>['age', true],
15=>['npc', true], 15=>['npc', true],
][$type]; ][$type];
$generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc?'desc':''); $generalList = $db->query('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general order by %b %l', $orderKey, $orderDesc?'desc':'');
echo" echo"
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr> <tr>
<td width=64 align=center id=bg1>얼 굴</td> <td width=64 align=center id=bg1>얼 굴</td>
<td width=140 align=center id=bg1>이 름</td> <td width=140 align=center id=bg1>이 름</td>
<td width=45 align=center id=bg1>연령</td> <td width=45 align=center id=bg1>연령</td>
<td width=45 align=center id=bg1>성격</td> <td width=45 align=center id=bg1>성격</td>
<td width=80 align=center id=bg1>특기</td> <td width=80 align=center id=bg1>특기</td>
<td width=45 align=center id=bg1>레 벨</td> <td width=45 align=center id=bg1>레 벨</td>
<td width=140 align=center id=bg1>국 가</td> <td width=140 align=center id=bg1>국 가</td>
<td width=55 align=center id=bg1>명 성</td> <td width=55 align=center id=bg1>명 성</td>
<td width=55 align=center id=bg1>계 급</td> <td width=55 align=center id=bg1>계 급</td>
<td width=75 align=center id=bg1>관 직</td> <td width=75 align=center id=bg1>관 직</td>
<td width=45 align=center id=bg1>통솔</td> <td width=45 align=center id=bg1>통솔</td>
<td width=45 align=center id=bg1>무력</td> <td width=45 align=center id=bg1>무력</td>
<td width=45 align=center id=bg1>지력</td> <td width=45 align=center id=bg1>지력</td>
<td width=45 align=center id=bg1>삭턴</td> <td width=45 align=center id=bg1>삭턴</td>
<td width=70 align=center id=bg1>벌점</td> <td width=70 align=center id=bg1>벌점</td>
</tr>"; </tr>";
foreach($generalList as $general){ foreach($generalList as $general){
$nation = $nationname[$general['nation']]; $nation = $nationname[$general['nation']];
$lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0); $lbonus = calcLeadershipBonus($general['officer_level'], $nationlevel[$general['nation']]??0);
if ($lbonus > 0) { if ($lbonus > 0) {
$lbonusText = "<font color=cyan>+{$lbonus}</font>"; $lbonusText = "<font color=cyan>+{$lbonus}</font>";
} else { } else {
$lbonusText = ""; $lbonusText = "";
} }
if ($general['injury'] > 0) { if ($general['injury'] > 0) {
$leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100); $leadership = intdiv($general['leadership'] * (100 - $general['injury']), 100);
$strength = intdiv($general['strength'] * (100 - $general['injury']), 100); $strength = intdiv($general['strength'] * (100 - $general['injury']), 100);
$intel = intdiv($general['intel'] * (100 - $general['injury']), 100); $intel = intdiv($general['intel'] * (100 - $general['injury']), 100);
$leadership = "<font color=red>{$leadership}</font>{$lbonusText}"; $leadership = "<font color=red>{$leadership}</font>{$lbonusText}";
$strength = "<font color=red>{$strength}</font>"; $strength = "<font color=red>{$strength}</font>";
$intel = "<font color=red>{$intel}</font>"; $intel = "<font color=red>{$intel}</font>";
} else { } else {
$leadership = "{$general['leadership']}{$lbonusText}"; $leadership = "{$general['leadership']}{$lbonusText}";
$strength = "{$general['strength']}"; $strength = "{$general['strength']}";
$intel = "{$general['intel']}"; $intel = "{$general['intel']}";
} }
if ($general['npc'] >= 2) { if ($general['npc'] >= 2) {
$name = "<font color=cyan>{$general['name']}</font>"; $name = "<font color=cyan>{$general['name']}</font>";
} elseif ($general['npc'] == 1) { } elseif ($general['npc'] == 1) {
$name = "<font color=skyblue>{$general['name']}</font>"; $name = "<font color=skyblue>{$general['name']}</font>";
} else { } else {
$name = "{$general['name']}"; $name = "{$general['name']}";
} }
if(key_exists($general['owner'], $ownerNameList)){ if(key_exists($general['owner'], $ownerNameList)){
$name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>'; $name = $name.'<br><small>('.$ownerNameList[$general['owner']].')</small>';
} }
$general['connect'] = Util::round($general['connect'], -1); $general['connect'] = Util::round($general['connect'], -1);
$imageTemp = GetImageURL($general['imgsvr']); $imageTemp = GetImageURL($general['imgsvr']);
echo " echo "
<tr data-general-id='{$general['no']}' <tr data-general-id='{$general['no']}'
data-general-wounded='{$general['injury']}' data-general-wounded='{$general['injury']}'
data-general-leadership='{$general['leadership']}' data-general-leadership='{$general['leadership']}'
data-general-leadership-bonus='{$lbonus}' data-general-leadership-bonus='{$lbonus}'
data-general-strength='{$general['strength']}' data-general-strength='{$general['strength']}'
data-general-intel='{$general['intel']}' data-general-intel='{$general['intel']}'
data-is-npc='".($general['npc']>=2?'true':'false')."' data-is-npc='".($general['npc']>=2?'true':'false')."'
> >
<td align=center><img class='generalIcon' width='64' height='64' src='{$imageTemp}/{$general['picture']}'></img></td> <td align=center><img class='generalIcon' width='64' height='64' src='{$imageTemp}/{$general['picture']}'></img></td>
<td align=center>$name</td> <td align=center>$name</td>
<td align=center>{$general['age']}세</td> <td align=center>{$general['age']}세</td>
<td align=center>".displayCharInfo($general['personal'])."</td> <td align=center>".displayCharInfo($general['personal'])."</td>
<td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td> <td align=center>".displaySpecialDomesticInfo($general['special'])." / ".displaySpecialWarInfo($general['special2'])."</td>
<td align=center>Lv ".getExpLevel($general['experience'])."</td> <td align=center>Lv ".getExpLevel($general['experience'])."</td>
<td align=center>{$nation}</td> <td align=center>{$nation}</td>
<td align=center>".getHonor($general['experience'])."</td> <td align=center>".getHonor($general['experience'])."</td>
<td align=center>".getDed($general['dedication'])."</td> <td align=center>".getDed($general['dedication'])."</td>
<td align=center>"; <td align=center>";
echo getOfficerLevelText($general['officer_level']); echo getOfficerLevelText($general['officer_level']);
echo "</td> echo "</td>
<td align=center>$leadership</td> <td align=center>$leadership</td>
<td align=center>$strength</td> <td align=center>$strength</td>
<td align=center>$intel</td> <td align=center>$intel</td>
<td align=center>{$general['killturn']}</td> <td align=center>{$general['killturn']}</td>
<td align=center>{$general['connect']}"; <td align=center>{$general['connect']}";
echo "<br>【".getConnect($general['connect'])."】</td> echo "<br>【".getConnect($general['connect'])."】</td>
</tr>"; </tr>";
} }
echo " echo "
</table> </table>
"; ";
?> ?>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=closeButton()?></td></tr> <tr><td><?=closeButton()?></td></tr>
<tr><td><?=banner()?></td></tr> <tr><td><?=banner()?></td></tr>
</table> </table>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
$("#viewType").val("<?=$type?>").attr("selected", "selected"); $("#viewType").val("<?=$type?>").attr("selected", "selected");
}); });
</script> </script>
</body> </body>
</html> </html>
+6 -1
View File
@@ -59,8 +59,13 @@ foreach (getAllNationStaticInfo() as $nation) {
$nationName[$nation['nation']] = $nation['name']; $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'); $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 = [ $sortType = [
1 => ['name', true], 1 => ['name', true],
2 => ['nation', true], 2 => ['nation', true],
+65 -11
View File
@@ -148,8 +148,31 @@ echo "
unset($city); unset($city);
// 첩보된 도시까지만 허용 // 첩보된 도시까지만 허용
if($valid == 0 && $userGrade < 5) {
$showDetailedInfo = false;
if($valid){
$showDetailedInfo = true;
}
if(!key_exists($citylist, CityConst::all())){
$citylist = $me['city']; $citylist = $me['city'];
$showDetailedInfo = true;
$valid = 1;
}
if($userGrade >= 5){
$valid = true;
$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,11 +195,35 @@ if($city['trade'] === null) {
} }
$dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'], 2)[0]; $dbColumns = General::mergeQueryColumn(['npc', 'defence_train', 'no', 'picture', 'imgsvr', 'name', 'injury', 'leadership', 'strength', 'intel', 'officer_level', 'nation', 'crewtype', 'crew', 'train', 'atmos'], 2)[0];
$generals = $db->query( if($showDetailedInfo){
'SELECT %l from general where city=%i order by name', $generals = $db->query(
Util::formatListOfBackticks($dbColumns), 'SELECT %l from general where city=%i order by turntime',
$city['city'] Util::formatListOfBackticks($dbColumns),
); $city['city']
);
}
else{
$generals = [];
}
if($valid){
$city['trustText'] = round($city['trust'], 1);
$city['popRateText'] = round($city['pop']/$city['pop_max']*100, 2);
}
else{
$city['agri'] = '?';
$city['comm'] = '?';
$city['pop'] = '?';
$city['secu'] = '?';
$city['trustText'] = '?';
$city['popRateText'] = '?';
if($city['nation'] != 0){
$city['def'] = '?';
$city['wall'] = '?';
}
}
$generalTurnList = []; $generalTurnList = [];
@@ -257,6 +304,10 @@ foreach($generals as $general){
$crew = $general['crew']; $crew = $general['crew'];
$train = -1; $train = -1;
$atmos = -1; $atmos = -1;
if(!$valid){
$crew = -1;
}
} }
$nation = $general['nation']; $nation = $general['nation'];
@@ -331,7 +382,9 @@ foreach($generalsFormat as $general){
} }
if($general['nation'] != $myNation['nation']){ if($general['nation'] != $myNation['nation']){
$enemyCnt += 1; $enemyCnt += 1;
$enemyCrew += $general['crew']; if($general['crew'] >= 0){
$enemyCrew += $general['crew'];
}
if($general['crew'] > 0){ if($general['crew'] > 0){
$enemyArmedCnt += 1; $enemyArmedCnt += 1;
} }
@@ -402,11 +455,11 @@ foreach($generalsFormat as $general){
</tr> </tr>
<tr> <tr>
<td align=center class=bg1>민심</td> <td align=center class=bg1>민심</td>
<td align=center><?=round($city['trust'], 1)?></td> <td align=center><?=$city['trustText']?></td>
<td align=center class=bg1>시세</td> <td align=center class=bg1>시세</td>
<td align=center><?=$city['trade']?>%</td> <td align=center><?=$city['trade']?>%</td>
<td align=center class=bg1>인구</td> <td align=center class=bg1>인구</td>
<td align=center><?=round($city['pop']/$city['pop_max']*100, 2)?>%</td> <td align=center><?=$city['popRateText']?>%</td>
<td align=center class=bg1>태수</td> <td align=center class=bg1>태수</td>
<td align=center><?=$officer[4]['name']?></td> <td align=center><?=$officer[4]['name']?></td>
<td align=center class=bg1>군사</td> <td align=center class=bg1>군사</td>
@@ -430,11 +483,12 @@ foreach($generalsFormat as $general){
</tr> </tr>
<tr> <tr>
<td align=center class=bg1>장수</td> <td align=center class=bg1>장수</td>
<td colspan=11><?=join(', ', $generalsName)?></td> <td colspan=11><?=$showDetailedInfo?join(', ', $generalsName):'<span style="color:gray">알 수 없음</span>'?></td>
</tr> </tr>
</table> </table>
<br> <br>
<?php if($showDetailedInfo): ?>
<table align=center class='tb_layout bg0'> <table align=center class='tb_layout bg0'>
<thead> <thead>
<tr> <tr>
@@ -459,7 +513,7 @@ foreach($generalsFormat as $general){
?> ?>
</tbody> </tbody>
</table> </table>
<?php endif; ?>
<table align=center width=1000 class='tb_layout bg0'> <table align=center width=1000 class='tb_layout bg0'>
<tr><td><?=backButton()?></td></tr> <tr><td><?=backButton()?></td></tr>
<tr><td><?=banner()?> </td></tr> <tr><td><?=banner()?> </td></tr>
+131
View File
@@ -0,0 +1,131 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID();
$generalID = $session->generalID;
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$me = General::createGeneralObjFromDB($generalID);
$pointHelpText = [
'sum' => '다음 플레이에서 사용할 수 있는 총 포인트입니다.',
'new' => '이번 플레이에서 얻은 총 포인트입니다.',
'previous' => '이전에 물려받은 포인트입니다.',
'lived_month' => '살아남은 기간입니다. (1개월 단위)',
'max_belong' => '가장 오래 임관했던 국가의 연도입니다.',
'max_domestic_critical' => '성공한 내정 중 최대 연속값입니다.',
'snipe_combat' => '유리한 상성을 가지고 전투했습니다.',
'combat' => '전투 횟수입니다.',
'sabotage' => '계략 성공 횟수입니다.',
'unifier' => '천통에 기여한 포인트입니다. <br>각 국의 군주, 천통 수뇌, 천통 군주가 받습니다.',
'dex' => '총 숙련도합입니다.',
'tournament' => '토너먼트 입상 포인트입니다.',
'betting' => '성공적인 베팅을 했습니다. <br>수익율과 베팅 성공 횟수를 따릅니다.',
];
$items = [];
foreach(array_keys(General::INHERITANCE_KEY) as $key){
$items[$key] = $me->getInheritancePoint($key)??0;
}
?>
<!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=1024" />
<?= WebUtil::printCSS('../e_lib/bootstrap.min.css') ?>
<?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('../css/config.css') ?>
<?= WebUtil::printCSS('css/common.css') ?>
<?= WebUtil::printCSS('css/inheritPoint.css') ?>
<?= WebUtil::printJS('../d_shared/common_path.js') ?>
<?= 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/inheritPoint.js') ?>
<script>
var items = <?=Json::encode($items)?>;
var helpText = <?=Json::encode($pointHelpText)?>;
</script>
</head>
<body onload="formStart()">
<table style='width:1000px;margin:auto;' class='tb_layout bg0'>
<tr>
<td style='text-align:left;'>유산 관리<br><?= backButton() ?></td>
</tr>
</table>
<div id="container" class="tb_layout bg0" style="width:1000px;margin:auto;border:solid 1px #888888;">
<div id='inheritance_list'>
<div id="inherit_sum" class='inherit_item'>
<div class="row">
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>총 포인트</label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_sum_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<div id="inherit_previous" class='inherit_item'>
<div class="row">
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>기존 포인트</label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_previous_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<div id="inherit_new" class='inherit_item'>
<div class="row">
<label id="inherit_sum_head" class='inherit_head col-sm-6 col-form-label'>신규 포인트</label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_new_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<div style="width:100%; padding:0 10px"><hr style="border-top:1px solid #888888;"></div>
<?php foreach (General::INHERITANCE_KEY as $key => [$type, $multiplier, $name]) : ?>
<?php if ($key == 'previous') {
continue;
} ?>
<div id="inherit_<?= $key ?>" class='inherit_item inherit_template_item'>
<div class="row">
<label id="inherit_<?= $key ?>_head" class='inherit_head col-sm-6 col-form-label'><?= $name ?></label>
<div class="col-sm-6">
<input type="text" class="form-control inherit_value" readonly id="inherit_<?= $key ?>_value" value="">
</div>
</div>
<div style="text-align:right">
<small class="form-text text-muted"></small>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
</body>
</html>
+165 -154
View File
@@ -1,154 +1,165 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
$showDieImmediatelyBtn = false; $showDieImmediatelyBtn = false;
$availableDieImmediately = false; $availableDieImmediately = false;
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$generalID = $session->generalID; $generalID = $session->generalID;
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['turntime', 'opentime', 'autorun_user', 'npcmode']);
increaseRefresh("내정보", 1);
increaseRefresh("내정보", 1);
$me = General::createGeneralObjFromDB($generalID);
$me = General::createGeneralObjFromDB($generalID);
$myset = $me->getVar('myset');
if ($myset > 0) { $myset = $me->getVar('myset');
$submit = 'button'; if ($myset > 0) {
} else { $submit = 'button';
$submit = 'hidden'; } else {
} $submit = 'hidden';
}
$targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
if($gameStor->turntime <= $gameStor->opentime){ $targetTime = addTurn($me->getVar('lastrefresh'), $gameStor->turnterm, 2);
//서버 가오픈시 할 수 있는 행동 if($gameStor->turntime <= $gameStor->opentime){
if($me->getNPCType() == 0){ //서버 가오픈시 할 수 있는 행동
$showDieImmediatelyBtn = true; if($me->getNPCType() == 0){
if($targetTime <= TimeUtil::now()){ $showDieImmediatelyBtn = true;
$availableDieImmediately = true; if($targetTime <= TimeUtil::now()){
} $availableDieImmediately = true;
} }
} }
}
$use_treatment = $me->getAuxVar('use_treatment')??10;
$use_treatment = $me->getAuxVar('use_treatment')??10;
?> $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn')??1;
<!DOCTYPE html> ?>
<html> <!DOCTYPE html>
<head> <html>
<meta charset="UTF-8"> <head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta charset="UTF-8">
<meta name="viewport" content="width=1024" /> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<title><?=UniqueConst::$serverName?>: 내정보</title> <meta name="viewport" content="width=1024" />
<script> <title><?=UniqueConst::$serverName?>: 내정보</title>
var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>; <script>
</script> var availableDieImmediately = <?=$availableDieImmediately?'true':'false'?>;
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> </script>
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<?=WebUtil::printJS('js/common.js')?> <?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<?=WebUtil::printJS('js/myPage.js')?> <?=WebUtil::printJS('js/common.js')?>
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> <?=WebUtil::printJS('js/myPage.js')?>
<?=WebUtil::printCSS('../d_shared/common.css')?> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
<?=WebUtil::printCSS('css/common.css')?> <?=WebUtil::printCSS('../d_shared/common.css')?>
</head> <?=WebUtil::printCSS('css/common.css')?>
</head>
<body>
<table align=center width=1000 class='tb_layout bg0'> <body>
<tr><td>내 정 보<br><?=backButton()?></td></tr> <table align=center width=1000 class='tb_layout bg0'>
</table> <tr><td>내 정 보<br><?=backButton()?></td></tr>
<table align=center width=1000 class='tb_layout bg0'> </table>
<tr> <table align=center width=1000 class='tb_layout bg0'>
<td width=50%> <tr>
<?php generalInfo($me); ?> <td width=50%>
<?php generalInfo2($me); ?> <?php generalInfo($me); ?>
</td> <?php generalInfo2($me); ?>
<td width=50% valign=top style="padding-left:4ch;"> </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":""; ?>>동참여 <input type=radio class='tnmt' name=tnmt value=0 <?=$me->getVar('tnmt')==0?"checked":""; ?>>동참여
】<br> <input type=radio class='tnmt' name=tnmt value=1 <?=$me->getVar('tnmt')==1?"checked":""; ?>>자동참여
∞<span style='color:orange'>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</span><br><br> <br>
∞<span style='color:orange'>개막직전 남는자리가 있을경우 랜덤하게 참여합니다.</span><br><br>
환약 사용 【<select id='use_treatment' name='use_treatment'>
<option value=10 <?=$use_treatment==10?"selected":""; ?>>경상</option> 환약 사용 【<select id='use_treatment' name='use_treatment'>
<option value=20 <?=$use_treatment==21?"selected":""; ?>>상</option> <option value=10 <?=($use_treatment==10)?"selected":""; ?>>상</option>
<option value=40 <?=$use_treatment==41?"selected":""; ?>>심각</option> <option value=21 <?=($use_treatment==21)?"selected":""; ?>>중상</option>
<option value=60 <?=$use_treatment==61?"selected":""; ?>>위독</option> <option value=41 <?=($use_treatment==41)?"selected":""; ?>>심각</option>
<option value=100 <?=$use_treatment==100?"selected":""; ?>>사용안함</option> <option value=61 <?=($use_treatment==61)?"selected":""; ?>>위독</option>
</select>】<br> <option value=100 <?=($use_treatment==100)?"selected":""; ?>>사용안함</option>
∞<span style='color:orange'>부상을 입었을 때 환약을 사용하는 기준입니다.</span><br><br> </select>】<br>
∞<span style='color:orange'>부상을 입었을 때 환약을 사용하는 기준입니다.</span><br><br>
수비 【<select id='defence_train' name='defence_train'> <?php if(($gameStor->autorun_user['options']['chief'])??false) : ?>
<option value=90 <?=$me->getVar('defence_train')==90?"selected":""; ?>>☆(훈사90)</option> 자동 사령턴 허용 【<select id='use_auto_nation_turn' name='use_auto_nation_turn'>
<option value=80 <?=$me->getVar('defence_train')==80?"selected":""; ?>>◎(훈사80)</option> <option value=1 <?=$use_auto_nation_turn?"selected":""; ?>>허용</option>
<option value=60 <?=$me->getVar('defence_train')==60?"selected":""; ?>>○(훈사60)</option> <option value=0 <?=(!$use_auto_nation_turn)?"selected":""; ?>>허용 안함</option>
<option value=40 <?=$me->getVar('defence_train')==40?"selected":""; ?>>△(훈사40)</option> </select>】<br>
<option value=999 <?=$me->getVar('defence_train')==999?"selected":""; ?>>×[훈련, 사기 -3]</option> ∞<span style='color:orange'>수뇌가 되었을 때 휴식 턴이어도 적당한 턴을 알아서 넣는 것을 허용합니다.</span><br><br>
</select> <?php endif; ?>
】<br><br> 수비 【<select id='defence_train' name='defence_train'>
<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> <?php foreach([90, 80, 60, 40] as $targetDefenceTrain): ?>
∞<span style='color:orange'>설정저장은 이달중 <?=$myset?>회 남았습니다.</span><br><br> <option value='<?=$targetDefenceTrain?>' <?=$me->getVar('defence_train')==$targetDefenceTrain?"selected":""; ?>><?=formatDefenceTrain($targetDefenceTrain)?>(훈사<?=$targetDefenceTrain?>)</option>
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?> <?php endforeach; ?>
휴 가 신 청<br> <option value=999 <?=$me->getVar('defence_train')==999?"selected":""; ?>><?=formatDefenceTrain(999)?>[훈련, 사기 -3]</option>
<button type="button" id='vacation' style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button><br><br> </select>
<?php endif; ?> 】<br><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>
<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>--> ∞<span style='color:orange'>설정저장은 이달중 <?=$myset?>회 남았습니다.</span><br><br>
<?php if(!($gameStor->autorun_user['limit_minutes']??false)): ?>
<?php if($showDieImmediatelyBtn): ?> 휴 가 신 청<br>
가오픈 기간 내 장수 삭제 (<?=substr($targetTime, 0, 19)?> 부터)<br> <button type="button" id='vacation' style=background-color:<?=GameConst::$basecolor2?>;color:white;width:160px;height:30px;font-size:13px;>휴가 신청</button><br><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 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>-->
개인용 CSS<br>
<textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea> <?php if($showDieImmediatelyBtn): ?>
</td> 가오픈 기간 내 장수 삭제 (<?=substr($targetTime, 0, 19)?> 부터)<br>
</tr> <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>
<tr> <?php endif; ?>
<td align=center id=bg1><font color=skyblue size=3>개인 기록</font></td>
<td align=center id=bg1><font color=orange size=3>전투 기록</font></td> <?php if($gameStor->npcmode==2 && $me->getNPCType()==0): ?>
</tr> 다른 장수 선택 (<?=substr($me->getAuxVar('next_change')??TimeUtil::now(), 0, 19)?> 부터)<br>
<tr> <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>
<td valign=top> <?php endif; ?>
<div id='generalActionPlate'>
<?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?> 개인용 CSS<br>
</div> <textarea id='custom_css' style='color:white;background-color:black;width:420px;height:150px;'></textarea>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button> </td>
</td> </tr>
<td valign=top> <tr>
<div id='battleDetailPlate'> <td align=center id=bg1><font color=skyblue size=3>개인 기록</font></td>
<?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?> <td align=center id=bg1><font color=orange size=3>전투 기록</font></td>
</div> </tr>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button> <tr>
</td> <td valign=top>
</tr> <div id='generalActionPlate'>
<tr> <?=formatHistoryToHTML(getGeneralActionLogRecent($generalID, 24), 'generalAction')?>
<td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td> </div>
<td align=center id=bg1><font color=orange size=3>전투 결과</font></td> <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="generalAction">이전 로그 불러오기</button>
</tr> </td>
<tr> <td valign=top>
<td valign=top> <div id='battleDetailPlate'>
<?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?> <?=formatHistoryToHTML(getBattleDetailLogRecent($generalID, 24), 'battleDetail')?>
</td> </div>
<td valign=top> <button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleDetail">이전 로그 불러오기</button>
<div id='battleResultPlate'> </td>
<?=formatHistoryToHTML(getBattleResultRecent($generalID, 24), 'battleResult')?> </tr>
</div> <tr>
<button type="button" class="load_old_log btn btn-secondary btn-block" data-log_type="battleResult">이전 로그 불러오기</button> <td align=center id=bg1><font color=skyblue size=3>장수 열전</font></td>
</td> <td align=center id=bg1><font color=orange size=3>전투 결과</font></td>
</tr> </tr>
</table> <tr>
<table align=center width=1000 class='tb_layout bg0'> <td valign=top>
<tr><td><?=backButton()?></td></tr> <?=formatHistoryToHTML(getGeneralHistoryLogAll($generalID))?>
<tr><td><?=banner()?></td></tr> </td>
</table> <td valign=top>
</body> <div id='battleResultPlate'>
</html> <?=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>
+1
View File
@@ -91,6 +91,7 @@ $zeroPolicy = new AutorunNationPolicy($general, ($gameStor->autorun_user)['optio
var availableGeneralActionPriorityItems = <?= Json::encode(AutorunGeneralPolicy::$default_priority) ?>; var availableGeneralActionPriorityItems = <?= Json::encode(AutorunGeneralPolicy::$default_priority) ?>;
var btnHelpMessage = { var btnHelpMessage = {
'불가침제의': '군주가 NPC이고, 타국에서 원조를 받았을 때,<br>세입(금/쌀) 대비 원조량에 따라 불가침제의를 합니다.',
'선전포고': '군주가 NPC이고, 전쟁중이 아닐 때,<br>주변국중 하나를 골라 선포합니다.<br><br>선포 시점은 다음을 참고합니다.<br>- 인구율<br>- 도시내정률<br>- NPC전투장권장 금 충족률<br>- NPC전투장권장 쌀 충족률<br><br>국력이 낮은 국가를 조금 더 선호합니다.', '선전포고': '군주가 NPC이고, 전쟁중이 아닐 때,<br>주변국중 하나를 골라 선포합니다.<br><br>선포 시점은 다음을 참고합니다.<br>- 인구율<br>- 도시내정률<br>- NPC전투장권장 금 충족률<br>- NPC전투장권장 쌀 충족률<br><br>국력이 낮은 국가를 조금 더 선호합니다.',
'천도': '인구가 많은 곳을 찾아 천도를 시도합니다.<br>영토의 가운데를 선호합니다.<br><br>도시 인구가 충분하다면, 굳이 천도하지는 않습니다.', '천도': '인구가 많은 곳을 찾아 천도를 시도합니다.<br>영토의 가운데를 선호합니다.<br><br>도시 인구가 충분하다면, 굳이 천도하지는 않습니다.',
'유저장긴급포상': '금/쌀이 부족한 유저전투장에게 긴급하게 포상합니다.<br>국고가 권장량보다 적어지더라도 시도합니다.', '유저장긴급포상': '금/쌀이 부족한 유저전투장에게 긴급하게 포상합니다.<br>국고가 권장량보다 적어지더라도 시도합니다.',
+551 -480
View File
@@ -1,481 +1,552 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
$session = Session::requireLogin()->setReadOnly(); $session = Session::requireLogin()->setReadOnly();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->getValue('startyear'); $gameStor->cacheValues(['startyear', 'year']);
$startYear = $gameStor->startyear;
?> $year = $gameStor->year;
<!DOCTYPE html>
<html> $me = $db->queryFirstRow('SELECT no, nation, city FROM general WHERE owner =%i', Session::getUserID());
<head>
<title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title> if($me){
<meta charset="UTF-8"> $generalID = $me['no'];
<meta http-equiv="X-UA-Compatible" content="IE=edge"> $nationID = $me['nation'];
<meta name="viewport" content="width=1100" /> $city = $db->queryFirstRow('SELECT city, level, def, wall FROM city WHERE city = %i', $me['city']);
<?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?> }
<?=WebUtil::printCSS('../d_shared/common.css')?> else{
<?=WebUtil::printCSS('css/common.css')?> $generalID = 0;
<?=WebUtil::printCSS('css/battle_simulator.css')?> $nationID = 0;
<?=WebUtil::printJS('../d_shared/common_path.js')?> $city = [
<?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?> 'city'=>0,
<?=WebUtil::printJS('../e_lib/moment.min.js')?> 'level'=>5,
<?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?> 'def'=>1000,
<?=WebUtil::printJS('../e_lib/download2.js')?> 'wall'=>1000,
<?=WebUtil::printJS('js/common.js')?> ];
<script> }
var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
</script> if($nationID){
<?=WebUtil::printJS('js/battle_simulator.js')?> $nation = $db->queryFirstRow('SELECT level, type, tech, capital FROM nation WHERE nation = %i', $nationID);
</head> }
<body> else{
<div id="container"> $nation = null;
<div class="card mb-3"> }
<div class="card-header">
전역 설정 ?>
</div> <!DOCTYPE html>
<div class="card-body dragpad_battle"> <html>
<div class="row"> <head>
<div class="col-sm-6"> <title><?=UniqueConst::$serverName?>: 전투 시뮬레이터</title>
<div class="input-group"> <meta charset="UTF-8">
<input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<div class="input-group-append"> <meta name="viewport" content="width=1100" />
<span class="input-group-text">년 시작</span> <?=WebUtil::printCSS('../e_lib/bootstrap.min.css')?>
</div> <?=WebUtil::printCSS('../d_shared/common.css')?>
<input type="number" class="form-control" id="year" value="<?=$startYear+3?>" min="<?=$startYear?>"> <?=WebUtil::printCSS('css/common.css')?>
<div class="input-group-append"> <?=WebUtil::printCSS('css/battle_simulator.css')?>
<span class="input-group-text">년</span> <?=WebUtil::printJS('../d_shared/common_path.js')?>
</div> <?=WebUtil::printJS('../e_lib/jquery-3.3.1.min.js')?>
<input type="number" class="form-control" id="month" value="1" min="1" max="12"> <?=WebUtil::printJS('../e_lib/moment.min.js')?>
<div class="input-group-append"> <?=WebUtil::printJS('../e_lib/bootstrap.bundle.min.js')?>
<span class="input-group-text">월</span> <?=WebUtil::printJS('../e_lib/download2.js')?>
</div> <?=WebUtil::printJS('js/common.js')?>
</div> <script>
</div> var defaultSpecialDomestic = '<?=GameConst::$defaultSpecialDomestic?>';
<div class="col-sm-6"> var city = <?=Json::encode($city)?>;
<div class="btn-toolbar" role="toolbar"> var nation = <?=Json::encode($nation)?>;
<div class="input-group mr-2" role="group"> </script>
<div class="input-group-prepend"> <?=WebUtil::printJS('js/battle_simulator.js')?>
<span class="input-group-text">반복 횟수</span> </head>
</div> <body>
<select class="custom-select" id="repeat_cnt"> <div id="container">
<option value="1">1회 (로그 표기)</option> <div class="card mb-3">
<option value="1000">1000회 (요약 표기)</option> <div class="card-header">
</select> 전역 설정
</div> </div>
<div class="btn-group mr-2" role="group"> <div class="card-body dragpad_battle">
<button type="button" class="btn btn-danger btn-begin_battle">전투</button> <div class="row">
</div> <div class="col-sm-6">
<div class="btn-group mr-2" role="group"> <div class="input-group">
<button type="button" class="btn btn-info btn-battle-save">모두 저장</button> <input type="number" class="form-control" aria-describedby="text_year" value="<?=$startYear?>" disabled>
<input type="file" class="form_load_battle_file" accept=".json" style="display: none;" /> <div class="input-group-append">
<button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button> <span class="input-group-text">년 시작</span>
</div> </div>
</div> <input type="number" class="form-control" id="year" value="<?=$year?>" min="<?=$startYear?>">
</div> <div class="input-group-append">
</div> <span class="input-group-text">년</span>
</div> </div>
</div> <input type="number" class="form-control" id="month" value="1" min="1" max="12">
<div class="row"> <div class="input-group-append">
<div class="col-sm"> <span class="input-group-text">월</span>
<div class="card mb-2 attacker_nation"> </div>
<div class="card-header"> </div>
출병국 설정 </div>
</div> <div class="col-sm-6">
<div class="card-body nation_detail dragpad_battle"> <div class="btn-toolbar" role="toolbar">
<div class="input-group mb-1"> <div class="input-group mr-2" role="group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text">국가 성향</span> <span class="input-group-text">반복 횟수</span>
</div> </div>
<select class="custom-select form_nation_type" style="width:25ch;"> <select class="custom-select" id="repeat_cnt">
<?php foreach(GameConst::$availableNationType as $typeID): ?> <option value="1">1회 (로그 표기)</option>
<?php $nationTypeClass = buildNationTypeClass($typeID) ?> <option value="1000">1000회 (요약 표기)</option>
<option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option> </select>
<?php endforeach; ?> </div>
</select> <div class="btn-group mr-2" role="group">
<div class="input-group-prepend"> <button type="button" class="btn btn-danger btn-begin_battle">전투</button>
<span class="input-group-text">기술</span> </div>
</div> <div class="btn-group mr-2" role="group">
<input type="number" class="form-control form_tech" value="1" min="0" max="12"> <button type="button" class="btn btn-info btn-battle-save">모두 저장</button>
<div class="input-group-append"> <input type="file" class="form_load_battle_file" accept=".json" style="display: none;" />
<span class="input-group-text">등급</span> <button type="button" class="btn btn-primary btn-battle-load">모두 불러오기</button>
</div> </div>
</div> </div>
<div class="input-group mb-3"> </div>
<div class="input-group-prepend"> </div>
<span class="input-group-text">국가 규모</span> </div>
</div> </div>
<select class="custom-select form_nation_level"> <div class="row">
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?> <div class="col-sm">
<option value="<?=$nationLevel?>"><?=$name?></option> <div class="card mb-2 attacker_nation">
<?php endforeach; ?> <div class="card-header">
</select> 출병국 설정
<div class="input-group-prepend"> </div>
<span class="input-group-text">도시 규모</span> <div class="card-body nation_detail dragpad_battle">
</div> <div class="input-group mb-1">
<select class="custom-select form_city_level"> <div class="input-group-prepend">
<?php foreach(getCityLevelList() as $levelID => $name): ?> <span class="input-group-text">국가 성향</span>
<option value="<?=$levelID?>"><?=$name?></option> </div>
<?php endforeach; ?> <select class="custom-select form_nation_type" style="width:25ch;">
</select> <?php foreach(GameConst::$availableNationType as $typeID): ?>
<div class="input-group-prepend"> <?php $nationTypeClass = buildNationTypeClass($typeID) ?>
<span class="input-group-text">수도</span> <option value="<?=$typeID?>"><?=$nationTypeClass->getName()?> (<?=$nationTypeClass::$pros?>, <?=$nationTypeClass::$cons?>)</option>
</div> <?php endforeach; ?>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons"> </select>
<label class="btn btn-secondary"> <div class="input-group-prepend">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y <span class="input-group-text">기술</span>
</label> </div>
<label class="btn btn-secondary active"> <input type="number" class="form-control form_tech" value="1" min="0" max="12">
<input type="radio" name="is_attacker_capital" class="form_is_capital" value="2" autocomplete="off" checked>N <div class="input-group-append">
</label> <span class="input-group-text">등급</span>
</div> </div>
</div>
</div> <div class="input-group mb-3">
<div class="input-group mb-1"> <div class="input-group-prepend">
<span class="input-group-text">국가 규모</span>
</div> </div>
</div> <select class="custom-select form_nation_level">
</div> <?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
<div class="card mb-2 attacker_form general_form" data-general_no='1'> <option value="<?=$nationLevel?>"><?=$name?></option>
<div class="card-header"> <?php endforeach; ?>
<div class="float-sm-left" style="line-height:25px;">출병자 설정</div> </select>
<div class="float-sm-right btn-toolbar" role="toolbar"> <div class="input-group-prepend">
<div class="btn-group btn-group-sm mr-2" role="group"> <span class="input-group-text">도시 규모</span>
<button type="button" class="btn btn-info btn-general-save">저장</button> </div>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" /> <select class="custom-select form_city_level">
<button type="button" class="btn btn-primary btn-general-load">불러오기</button> <?php foreach(getCityLevelList() as $levelID => $name): ?>
</div> <option value="<?=$levelID?>"><?=$name?></option>
</div> <?php endforeach; ?>
</div> </select>
</div> <div class="input-group-prepend">
</div><!-- <div class="col-sm"> --> <span class="input-group-text">수도</span>
<div class="col-sm defender-column"> </div>
<div class="card mb-2 defender_nation"> <div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
<div class="card-header"> <label class="btn btn-secondary">
수비국 설정 <input type="radio" name="is_attacker_capital" class="form_is_capital" value="1" autocomplete="off">Y
</div> </label>
<div class="card-body dragpad_battle"> <label class="btn btn-secondary active">
<div class="input-group mb-1"> <input type="radio" name="is_attacker_capital" class="form_is_capital" value="0" autocomplete="off">N
<div class="input-group-prepend"> </label>
<span class="input-group-text">국가 성향</span> </div>
</div>
<select class="custom-select form_nation_type" style="width:25ch;"> </div>
<?php foreach(GameConst::$availableNationType as $typeID): ?> <div class="input-group mb-1">
<?php $nationTypeObj = buildNationTypeClass($typeID) ?>
<option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option> </div>
<?php endforeach; ?> </div>
</select> </div>
<div class="input-group-prepend"> <div class="card mb-2 attacker_form general_form" data-general_no='1'>
<span class="input-group-text">기술</span> <div class="card-header">
</div> <div class="float-sm-left" style="line-height:25px;">출병자 설정</div>
<input type="number" class="form-control form_tech" value="1" min="0" max="12"> <div class="float-sm-right btn-toolbar" role="toolbar">
<div class="input-group-append"> <div class="btn-group btn-group-sm mr-2" role="group">
<span class="input-group-text">등급</span> <button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
</div> </div>
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<div class="input-group mb-3"> <button type="button" class="btn btn-info btn-general-save">저장</button>
<div class="input-group-prepend"> <input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<span class="input-group-text">국가 규모</span> <button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div> </div>
<select class="custom-select form_nation_level"> </div>
<?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?> </div>
<option value="<?=$nationLevel?>"><?=$name?></option> </div>
<?php endforeach; ?> </div><!-- <div class="col-sm"> -->
</select> <div class="col-sm defender-column">
<div class="input-group-prepend"> <div class="card mb-2 defender_nation">
<span class="input-group-text">도시 규모</span> <div class="card-header">
</div> 수비국 설정
<select class="custom-select form_city_level"> </div>
<?php foreach(getCityLevelList() as $levelID => $name): ?> <div class="card-body dragpad_battle">
<option value="<?=$levelID?>"><?=$name?></option> <div class="input-group mb-1">
<?php endforeach; ?> <div class="input-group-prepend">
</select> <span class="input-group-text">국가 성향</span>
<div class="input-group-prepend"> </div>
<span class="input-group-text">수도</span> <select class="custom-select form_nation_type" style="width:25ch;">
</div> <?php foreach(GameConst::$availableNationType as $typeID): ?>
<div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons"> <?php $nationTypeObj = buildNationTypeClass($typeID) ?>
<label class="btn btn-secondary"> <option value="<?=$typeID?>"><?=$nationTypeObj->getName()?> (<?=$nationTypeObj::$pros?>, <?=$nationTypeObj::$cons?>)</option>
<input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y <?php endforeach; ?>
</label> </select>
<label class="btn btn-secondary active"> <div class="input-group-prepend">
<input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off" checked>N <span class="input-group-text">기술</span>
</label> </div>
</div> <input type="number" class="form-control form_tech" value="1" min="0" max="12">
</div> <div class="input-group-append">
<div class="input-group mb-1"> <span class="input-group-text">등급</span>
<div class="input-group-prepend"> </div>
<span class="input-group-text">수비</span> </div>
</div> <div class="input-group mb-3">
<input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10"> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">국가 규모</span>
<span class="input-group-text">성벽</span> </div>
</div> <select class="custom-select form_nation_level">
<input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10"> <?php foreach(getNationLevelList() as $nationLevel => [$name,$chiefCnt,$cityCnt]): ?>
</div> <option value="<?=$nationLevel?>"><?=$name?></option>
</div> <?php endforeach; ?>
</div> </select>
<div class="card mb-2 defender_add_form"> <div class="input-group-prepend">
<div class="card-header"> <span class="input-group-text">도시 규모</span>
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div> </div>
<div class="float-sm-right btn-toolbar" role="toolbar"> <select class="custom-select form_city_level">
<div class="btn-group btn-group-sm mr-2" role="group"> <?php foreach(getCityLevelList() as $levelID => $name): ?>
<button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button> <option value="<?=$levelID?>"><?=$name?></option>
</div> <?php endforeach; ?>
<div class="btn-group btn-group-sm" role="group"> </select>
<button type="button" class="btn btn-success add-defender">추가</button> <div class="input-group-prepend">
</div> <span class="input-group-text">수도</span>
</div> </div>
</div> <div class="input-group-append btn-group btn-group-toggle" data-toggle="buttons">
</div> <label class="btn btn-secondary">
<div class="card mb-2 form_sample"> <input type="radio" name="is_defender_capital" class="form_is_capital" value="1" autocomplete="off">Y
<div class="card-header"> </label>
<div class="float-sm-left" style="line-height:25px;">수비자 설정</div> <label class="btn btn-secondary active">
<div class="float-sm-right btn-toolbar" role="toolbar"> <input type="radio" name="is_defender_capital" class="form_is_capital" value="0" autocomplete="off">N
<div class="btn-group btn-group-sm mr-2" role="group"> </label>
<button type="button" class="btn btn-info btn-general-save">저장</button> </div>
<input type="file" class="form_load_general_file" accept=".json" style="display: none;" /> </div>
<button type="button" class="btn btn-primary btn-general-load">불러오기</button> <div class="input-group mb-1">
</div> <div class="input-group-prepend">
<div class="btn-group btn-group-sm" role="group"> <span class="input-group-text">수비</span>
<button type="button" class="btn btn-warning copy-defender">복제</button> </div>
<button type="button" class="btn btn-danger delete-defender">제거</button> <input type="number" class="form-control form_def" id="city_def" value="1000" min="10" step="10">
</div> <div class="input-group-prepend">
</div> <span class="input-group-text">성벽</span>
</div> </div>
<div class="card-body general_detail"> <input type="number" class="form-control form_wall" id="city_wall" value="1000" min="0" step="10">
<div class="input-group mb-3"> </div>
<div class="input-group-prepend"> </div>
<span class="input-group-text">이름</span> </div>
</div> <div class="card mb-2 defender_add_form">
<input type="text" class="form-control form_general_name" value="무명" style="width:15ch;"> <div class="card-header">
<div class="input-group-prepend"> <div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<span class="input-group-text">직위</span> <div class="float-sm-right btn-toolbar" role="toolbar">
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<select class="custom-select form_officer_level" style="width:8ch;"> <button type="button" class="btn btn-dark btn-reorder_defender">수비 순서대로 정렬</button>
<option value="1">일반</option> </div>
<option value="4">태수</option> <div class="btn-group btn-group-sm" role="group">
<option value="3">군사</option> <button type="button" class="btn btn-success add-defender">추가</button>
<option value="2">종사</option> </div>
<option value="10">무장 수뇌</option> </div>
<option value="9">지장 수뇌</option> </div>
<option value="11">참모</option> </div>
<option value="12">군주</option> <div class="card mb-2 form_sample">
</select> <div class="card-header">
<div class="input-group-prepend"> <div class="float-sm-left" style="line-height:25px;">수비자 설정</div>
<span class="input-group-text">Level</span> <div class="float-sm-right btn-toolbar" role="toolbar">
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1"> <button type="button" class="btn btn-success btn-general-import-server">서버에서 가져오기</button>
</div>
</div> <div class="btn-group btn-group-sm mr-2" role="group">
<div class="input-group mb-1"> <button type="button" class="btn btn-info btn-general-save">저장</button>
<div class="input-group-prepend"> <input type="file" class="form_load_general_file" accept=".json" style="display: none;" />
<span class="input-group-text">통솔</span> <button type="button" class="btn btn-primary btn-general-load">불러오기</button>
</div> </div>
<input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1"> <div class="btn-group btn-group-sm" role="group">
<div class="input-group-prepend"> <button type="button" class="btn btn-warning copy-defender">복제</button>
<span class="input-group-text">무력</span> <button type="button" class="btn btn-danger delete-defender">제거</button>
</div> </div>
<input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1"> </div>
<div class="input-group-prepend"> </div>
<span class="input-group-text">지력</span> <div class="card-body general_detail">
</div> <div class="input-group mb-3">
<input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1"> <div class="input-group-prepend">
</div> <span class="input-group-text">이름</span>
<div class="input-group mb-1"> </div>
<div class="input-group-prepend"> <input type="text" class="form-control form_general_name" value="무명" style="width:15ch;">
<span class="input-group-text">명마</span> <div class="input-group-prepend">
</div> <span class="input-group-text">직위</span>
<select class="custom-select form_general_horse"> </div>
<option value='None'>-</option> <select class="custom-select form_officer_level" style="width:8ch;">
<?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?> <option value="1">일반</option>
<option value="<?=$horseID?>"><?=getItemName($horseID)?></option> <option value="4">태수</option>
<?php endforeach; ?> <option value="3">군사</option>
</select> <option value="2">종사</option>
<div class="input-group-prepend"> <option value="10">무장 수뇌</option>
<span class="input-group-text">무기</span> <option value="9">지장 수뇌</option>
</div> <option value="11">참모</option>
<select class="custom-select form_general_weap"> <option value="12">군주</option>
<option value='None'>-</option> </select>
<?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?> <div class="input-group-prepend">
<option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option> <span class="input-group-text">Level</span>
<?php endforeach; ?> </div>
</select> <input type="number" class="form-control form_exp_level" value="20" min="0" max="300" step="1">
<div class="input-group-prepend">
<span class="input-group-text">서적</span> </div>
</div> <div class="input-group mb-1">
<select class="custom-select form_general_book"> <div class="input-group-prepend">
<option value='None'>-</option> <span class="input-group-text">통솔</span>
<?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?> </div>
<option value="<?=$bookID?>"><?=getItemName($bookID)?></option> <input type="number" class="form-control form_leadership" value="50" min="1" max="300" step="1">
<?php endforeach; ?> <div class="input-group-prepend">
</select> <span class="input-group-text">무력</span>
</div> </div>
<div class="input-group mb-3"> <input type="number" class="form-control form_strength" value="50" min="1" max="300" step="1">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text">부상</span> <span class="input-group-text">지력</span>
</div> </div>
<input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1"> <input type="number" class="form-control form_intel" value="50" min="1" max="300" step="1">
<div class="input-group-append"> </div>
<span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span> <div class="input-group mb-1">
</div> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">명마</span>
<span class="input-group-text">군량</span> </div>
</div> <select class="custom-select form_general_horse">
<input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50"> <option value='None'>-</option>
<div class="input-group-prepend"> <?php foreach(GameConst::$allItems['horse'] as $horseID=>$cnt): ?>
<span class="input-group-text">도구</span> <option value="<?=$horseID?>"><?=getItemName($horseID)?></option>
</div> <?php endforeach; ?>
<select class="custom-select form_general_item"> </select>
<option value='None'>-</option> <div class="input-group-prepend">
<?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?> <span class="input-group-text">무기</span>
<option value="<?=$itemID?>"><?=getItemName($itemID)?></option> </div>
<?php endforeach; ?> <select class="custom-select form_general_weap">
</select> <option value='None'>-</option>
</div> <?php foreach(GameConst::$allItems['weapon'] as $weaponID=>$cnt): ?>
<div class="input-group mb-1"> <option value="<?=$weaponID?>"><?=getItemName($weaponID)?></option>
<div class="input-group-prepend"> <?php endforeach; ?>
<span class="input-group-text">병종</span> </select>
</div> <div class="input-group-prepend">
<select class="custom-select form_crewtype"> <span class="input-group-text">서적</span>
<?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?> </div>
<?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?> <select class="custom-select form_general_book">
<option value="<?=$crewTypeID?>"><?=$crewType->name?></option> <option value='None'>-</option>
<?php endforeach; ?> <?php foreach(GameConst::$allItems['book'] as $bookID=>$cnt): ?>
</select> <option value="<?=$bookID?>"><?=getItemName($bookID)?></option>
<div class="input-group-prepend"> <?php endforeach; ?>
<span class="input-group-text">병사</span> </select>
</div> </div>
<input type="number" class="form-control form_crew" value="7000" min="100" step="100"> <div class="input-group mb-3">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text">성격</span> <span class="input-group-text">부상</span>
</div> </div>
<select class="custom-select form_general_character"> <input type="number" class="form-control form_injury" value="0" min="0" max="80" step="1">
<?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?> <div class="input-group-append">
<option value="<?=$characterID?>"><?=$name?></option> <span class="input-group-text">%(<span class="injury_helptext">건강</span>)</span>
<?php endforeach; ?> </div>
</select> <div class="input-group-prepend">
</div> <span class="input-group-text">군량</span>
<div class="input-group mb-3"> </div>
<div class="input-group-prepend"> <input type="number" class="form-control form_rice" value="5000" min="50" max="40000" step="50">
<span class="input-group-text">훈련</span> <div class="input-group-prepend">
</div> <span class="input-group-text">도구</span>
<input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1"> </div>
<div class="input-group-prepend"> <select class="custom-select form_general_item">
<span class="input-group-text">사기</span> <option value='None'>-</option>
</div> <?php foreach(GameConst::$allItems['item'] as $itemID=>$cnt): ?>
<input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1"> <option value="<?=$itemID?>"><?=getItemName($itemID)?></option>
<div class="input-group-prepend"> <?php endforeach; ?>
<span class="input-group-text">전특</span> </select>
</div> </div>
<select class="custom-select form_general_special_war"> <div class="input-group mb-1">
<?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?> <div class="input-group-prepend">
<option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option> <span class="input-group-text">병종</span>
<?php endforeach; ?> </div>
</select> <select class="custom-select form_crewtype">
</div> <?php foreach(GameUnitConst::all() as $crewTypeID => $crewType): ?>
<div class="input-group mb-1"> <?php if($crewType->armType === GameUnitConst::T_CASTLE){ continue; } ?>
<div class="input-group-prepend"> <option value="<?=$crewTypeID?>"><?=$crewType->name?></option>
<span class="input-group-text">보병숙련</span> <?php endforeach; ?>
</div> </select>
<select class="custom-select form_dex1"> <div class="input-group-prepend">
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <span class="input-group-text">병사</span>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> </div>
<?php endforeach; ?> <input type="number" class="form-control form_crew" value="7000" min="100" step="100">
</select> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">성격</span>
<span class="input-group-text">궁병숙련</span> </div>
</div> <select class="custom-select form_general_character">
<select class="custom-select form_dex2"> <?php foreach(getCharacterList(false) as $characterID => [$name,$info]): ?>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <option value="<?=$characterID?>"><?=$name?></option>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <?php endforeach; ?>
<?php endforeach; ?> </select>
</select> </div>
<div class="input-group-prepend"> <div class="input-group mb-3">
<span class="input-group-text">기병숙련</span> <div class="input-group-prepend">
</div> <span class="input-group-text">훈련</span>
<select class="custom-select form_dex3"> </div>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <input type="number" class="form-control form_train" value="100" min="40" max="<?=GameConst::$maxTrainByWar?>" step="1">
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <div class="input-group-prepend">
<?php endforeach; ?> <span class="input-group-text">사기</span>
</select> </div>
</div> <input type="number" class="form-control form_atmos" value="100" min="40" max="<?=GameConst::$maxAtmosByWar?>" step="1">
<div class="input-group mb-1"> <div class="input-group-prepend">
<div class="input-group-prepend"> <span class="input-group-text">전특</span>
<span class="input-group-text">귀병숙련</span> </div>
</div> <select class="custom-select form_general_special_war">
<select class="custom-select form_dex4"> <?php foreach(SpecialityHelper::getSpecialWarList(false) as $specialWarID =>$specialObj): ?>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <option value="<?=$specialWarID?>"><?=$specialObj->getName()?></option>
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <?php endforeach; ?>
<?php endforeach; ?> </select>
</select> </div>
<div class="input-group-prepend"> <div class="input-group mb-1">
<span class="input-group-text">차병숙련</span> <div class="input-group-prepend">
</div> <span class="input-group-text">보병숙련</span>
<select class="custom-select form_dex5"> </div>
<?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?> <select class="custom-select form_dex1">
<option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<?php endforeach; ?> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
</select> <?php endforeach; ?>
<div class="input-group-prepend only_defender"> </select>
<span class="input-group-text">수비여부</span> <div class="input-group-prepend">
</div> <span class="input-group-text">궁병숙련</span>
<select class="custom-select form_defence_train only_defender"> </div>
<option value="80">훈사 80</option> <select class="custom-select form_dex2">
<option value="60">훈사 60</option> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<option value="999">안함</option> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
</select> <?php endforeach; ?>
</div> </select>
</div> <div class="input-group-prepend">
</div> <span class="input-group-text">기병숙련</span>
</div>
<select class="custom-select form_dex3">
</div><!-- <div class="col-sm"> --> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
</div> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<div class="card mb-3"> <?php endforeach; ?>
<div class="card-header"> </select>
전투 요약 </div>
</div> <div class="input-group mb-3">
<table class="table"> <div class="input-group-prepend">
<tbody id="battle_result_summary"> <span class="input-group-text">귀병숙련</span>
<tr><th style='width:18ch;'>전투 일시</th><td id='result_datetime'></td></tr> </div>
<tr><th>전투 횟수</th><td id='result_warcnt'></td></tr> <select class="custom-select form_dex4">
<tr><th>전투 페이즈</th><td id='result_phase'></td></tr> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
<tr><th>준 피해</th><td><span id='result_killed'>0</span><span id='result_varKilled'> (<span id='result_minKilled'>0</span> ~ <span id='result_maxKilled'>0</span>)</span></td></tr> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<tr><th>받은 피해</th><td><span id='result_dead'>0</span><span id='result_varDead'> (<span id='result_minDead'>0</span> ~ <span id='result_maxDead'>0</span>)</span></td></tr> <?php endforeach; ?>
<tr><th>출병자 군량 소모</th><td id='result_attackerRice'></td></tr> </select>
<tr><th>수비자 군량 소모</th><td id='result_defenderRice'></td></tr> <div class="input-group-prepend">
<tr><th>공격자 스킬</th><td id='result_attackerSkills'></td></tr> <span class="input-group-text">차병숙련</span>
<tr class='result_defenderSkills'><th>수비자1 스킬</th><td></td></tr> </div>
</tbody> <select class="custom-select form_dex5">
</table> <?php foreach(getDexLevelList() as $dexLevel => [$dexAmount, $color, $name]): ?>
</div> <option value="<?=$dexAmount?>"><?="{$name} (".number_format($dexAmount).")"?></option>
<div class="row"> <?php endforeach; ?>
<div class="col-sm"> </select>
<div class="card mb-3"> <div class="input-group-prepend only_defender">
<div class="card-header"> <span class="input-group-text">수비여부</span>
마지막 전투 로그 </div>
</div> <select class="custom-select form_defence_train only_defender">
<div class="card-body" id="generalBattleResultLog"> <option value="90">훈사 90</option>
<option value="80">훈사 80</option>
</div> <option value="60">훈사 60</option>
</div> <option value="40">훈사 40</option>
</div> <option value="999">안함</option>
<div class="col-sm"> </select>
<div class="card mb-3"> </div>
<div class="card-header"> <div class="input-group mb-1">
마지막 전투 상세 로그 <div class="input-group-prepend">
</div> <span class="input-group-text">전투 수</span>
<div class="card-body" id="generalBattleDetailLog"> </div>
<input type="number" class="form-control form_warnum" value="0" step="1">
</div> <div class="input-group-prepend">
</div> <span class="input-group-text">승리 수</span>
</div> </div>
</div> <input type="number" class="form-control form_killnum" value="0" step="1">
</div> <div class="input-group-prepend">
</body> <span class="input-group-text">사살 수</span>
</div>
<input type="number" class="form-control form_killcrew" value="0" step="1">
</div>
</div>
</div>
</div><!-- <div class="col-sm"> -->
</div>
<div class="card mb-3">
<div class="card-header">
전투 요약
</div>
<table class="table">
<tbody id="battle_result_summary">
<tr><th style='width:18ch;'>전투 일시</th><td id='result_datetime'></td></tr>
<tr><th>전투 횟수</th><td id='result_warcnt'></td></tr>
<tr><th>전투 페이즈</th><td id='result_phase'></td></tr>
<tr><th>준 피해</th><td><span id='result_killed'>0</span><span id='result_varKilled'> (<span id='result_minKilled'>0</span> ~ <span id='result_maxKilled'>0</span>)</span></td></tr>
<tr><th>받은 피해</th><td><span id='result_dead'>0</span><span id='result_varDead'> (<span id='result_minDead'>0</span> ~ <span id='result_maxDead'>0</span>)</span></td></tr>
<tr><th>출병자 군량 소모</th><td id='result_attackerRice'></td></tr>
<tr><th>수비자 군량 소모</th><td id='result_defenderRice'></td></tr>
<tr><th>공격자 스킬</th><td id='result_attackerSkills'></td></tr>
<tr class='result_defenderSkills'><th>수비자1 스킬</th><td></td></tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col-sm">
<div class="card mb-3">
<div class="card-header">
마지막 전투 로그
</div>
<div class="card-body" id="generalBattleResultLog">
</div>
</div>
</div>
<div class="col-sm">
<div class="card mb-3">
<div class="card-header">
마지막 전투 상세 로그
</div>
<div class="card-body" id="generalBattleDetailLog">
</div>
</div>
</div>
</div>
</div>
<div id="importModal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">장수 목록</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<select id="modalSelector"></select>
<p>타국 장수를 선택한 경우 숙련과 아이템은 0으로 초기화됩니다.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id='importFromDB'>가져오기</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">닫기</button>
</div>
</div>
</div>
</div>
</body>
</html> </html>
+155 -135
View File
@@ -1,40 +1,56 @@
@charset "UTF-8"; @charset "UTF-8";
/* font-boostring Block */ /* font-boostring Block */
html * {max-height:1000000px;}
html * {
html, body{ max-height: 1000000px;
background-color:black;
color:white;
line-height:1.3;
font-family:'맑은 고딕';
font-size:13px;
} }
table { font-family:'맑은 고딕'; } html,
font { font-family:'맑은 고딕'; } body {
input { font-family:'맑은 고딕'; font-size:13px; } background-color: black;
select { font-family:'굴림'; line-height:100%; } color: white;
line-height: 1.3;
.center{ font-family: '맑은 고딕';
text-align:center; font-size: 13px;
} }
table.mimic_flex{ table {
font-family: '맑은 고딕';
}
font {
font-family: '맑은 고딕';
}
input {
font-family: '맑은 고딕';
font-size: 13px;
}
select {
font-family: '굴림';
line-height: 100%;
}
.center {
text-align: center;
}
table.mimic_flex {
border-collapse: collapse; border-collapse: collapse;
border:none; border: none;
padding:0; padding: 0;
} }
.mimic_flex td, .mimic_flex th { .mimic_flex td,
border:none !important; .mimic_flex th {
border: none !important;
padding: 0px; padding: 0px;
word-break: break-all; word-break: break-all;
} }
table.tb_layout {
table.tb_layout {
border-collapse: collapse; border-collapse: collapse;
padding: 0px; padding: 0px;
font-size: 13px; font-size: 13px;
@@ -42,159 +58,161 @@ table.tb_layout {
font-family: '맑은 고딕'; font-family: '맑은 고딕';
} }
.tb_layout td, .tb_layout th { .tb_layout td,
border:solid 1px gray; .tb_layout th {
border: solid 1px gray;
padding: 0px; padding: 0px;
word-break: break-all; word-break: break-all;
font-family: '맑은 고딕';; font-family: '맑은 고딕';
;
} }
div.bar_out{ div.bar_out {
position:relative; position: relative;
border-top:solid 1px #888888; border-top: solid 1px #888888;
border-bottom:solid 1px #333333; border-bottom: solid 1px #333333;
padding:0; padding: 0;
margin:0; margin: 0;
width:100%; width: 100%;
overflow: hidden; overflow: hidden;
} }
div.bar_out div{ div.bar_out div {
position:absolute; position: absolute;
left:0; left: 0;
top:0; top: 0;
height:100%; height: 100%;
} }
div.bar_out div.bar_in{ div.bar_out div.bar_in {
width:100%; width: 100%;
} }
/* */ /* */
.ev_warning{ .ev_warning {
color:orangered; color: orangered;
} }
.ev_notice{ .ev_notice {
color:orangered; color: orangered;
} }
.ev_succes{ .ev_succes {
color:lightgreen; color: lightgreen;
} }
.ev_sell{ .ev_sell {
color:orange; color: orange;
} }
.ev_failed{ .ev_failed {
color:orangered; color: orangered;
} }
.ev_highlight{ .ev_highlight {
color:orangered; color: orangered;
} }
/* TODO: 색상값이 아니라 의미에 따라 클래스 지정 */ /* TODO: 색상값이 아니라 의미에 따라 클래스 지정 */
.o_bullet::before{ .o_bullet::before {
color:cyan; color: cyan;
content:"●"; content: "●";
} }
.o_diamond::before{ .o_diamond::before {
color:orangered; color: orangered;
content:"◆"; content: "◆";
} }
.small_war_log{ .small_war_log {
display:inline-block; display: inline-block;
} }
.small_war_log .war_type_attack{ .small_war_log .war_type_attack {
color:cyan; color: cyan;
} }
.small_war_log .war_type_defense{ .small_war_log .war_type_defense {
color:magenta; color: magenta;
} }
.small_war_log .war_type_siege{ .small_war_log .war_type_siege {
color:white; color: white;
} }
.small_war_log .name_plate {
.small_war_log .name_plate{
font-size: 0.75em; font-size: 0.75em;
} }
.small_war_log .name_plate_cover{ .small_war_log .name_plate_cover {
color:yellow; color: yellow;
} }
.small_war_log .crew_plate{ .small_war_log .crew_plate {
color:orangered; color: orangered;
font-size:90%; font-size: 90%;
} }
.t_date{ .t_date {
font-size: 0.75em; font-size: 0.75em;
} }
.t_red{ .t_red {
color:red; color: red;
} }
.t_blue{ .t_blue {
color:blue; color: blue;
} }
.t_green{ .t_green {
color:green; color: green;
} }
.t_magenta{ .t_magenta {
color:magenta; color: magenta;
} }
.t_cyan{ .t_cyan {
color:cyan; color: cyan;
} }
.t_limegreen{ .t_limegreen {
color:limegreen; color: limegreen;
} }
.t_skyblue{ .t_skyblue {
color:skyblue; color: skyblue;
} }
.t_orangered{ .t_orangered {
color:orangered; color: orangered;
} }
.t_yellow{ .t_yellow {
color:yellow; color: yellow;
} }
.t_white{ .t_white {
color:white; color: white;
} }
.float_left{ .float_left {
float:left; float: left;
} }
.tooltip{ .tooltip {
font-size:12px; font-size: 12px;
font-family: '맑은 고딕'; font-family: '맑은 고딕';
} }
.tooltip_copyable_info .tooltiptext{ .tooltip_copyable_info .tooltiptext {
display: inline; display: inline;
color: rgba(0,0,0,0); color: rgba(0, 0, 0, 0);
font-size: 0; font-size: 0;
} }
@@ -202,67 +220,69 @@ div.bar_out div.bar_in{
display: none; display: none;
} }
.hidden_but_copyable{ .hidden_but_copyable {
color: rgba(0,0,0,0); color: rgba(0, 0, 0, 0);
font-size: 0; font-size: 0;
} }
.btn-group-xs > .btn, .btn-xs { .btn-group-xs>.btn,
padding : .25rem .4rem; .btn-xs {
font-size : .875rem; padding: .25rem .4rem;
line-height : .5; font-size: .875rem;
border-radius : .2rem; line-height: .5;
border-radius: .2rem;
} }
.edit_form.viewer{ .edit_form.viewer {
max-height:200px; max-height: 200px;
overflow-y:auto; overflow-y: auto;
} }
.trumbowyg-box{ .trumbowyg-box {
margin:0; margin: 0;
border-left:none; border-left: none;
border-right:none; border-right: none;
} }
.edit_form.trumbowyg-editor{ .edit_form.trumbowyg-editor {
margin:0; margin: 0;
padding:0; padding: 0;
} }
.commandBasic{ .commandBasic {
background-color:black; background-color: black;
color:white; color: white;
} }
.compensatePositive{ .compensatePositive {
color:skyblue; color: skyblue;
} }
.compensateNegative{ .compensateNegative {
color:orange; color: orange;
} }
.compensateNeutral{ .compensateNeutral {
color:white; color: white;
} }
.commandBasic.commandImpossible{ .commandBasic.commandImpossible {
background-color:red; background-color: red;
color:white; color: white;
} }
.select2-selection--single.simple-select2-align-center .select2-selection__rendered { .select2-selection--single.simple-select2-align-center .select2-selection__rendered {
text-align: center; text-align: center;
} }
.select2-dropdown.simple-select2-align-center li.select2-results__option{ .select2-dropdown.simple-select2-align-center li.select2-results__option {
text-align: center; text-align: center;
} }
.select2-container--bootstrap4 .select2-selection--single.text-secondary .select2-selection__rendered{ .select2-container--bootstrap4 .select2-selection--single.text-secondary .select2-selection__rendered {
color:white; color: white;
} }
.select2-container--bootstrap4 .text-secondary .select2-results__option[aria-selected=false]{ .select2-container--bootstrap4 .text-secondary .select2-results__option[aria-selected=false] {
color:white; color: white;
} }
+23
View File
@@ -0,0 +1,23 @@
#inheritance_list{
display: flex;
flex-wrap: wrap;
}
.inherit_padding{
width: 33%;
padding: 10px 2px;
}
.inherit_item{
width: 33%;
padding: 10px 2px;
}
.col-form-label{
text-align:right;
padding-right:2ch;
}
.inherit_value{
text-align: right;
}
+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;
}
+2178 -2112
View File
File diff suppressed because it is too large Load Diff
+447 -447
View File
@@ -1,448 +1,448 @@
<?php <?php
namespace sammo; namespace sammo;
use sammo\Command\GeneralCommand; use sammo\Command\GeneralCommand;
use sammo\Command\NationCommand; use sammo\Command\NationCommand;
function getGeneralTurnBrief(General $generalObj, array $turnList) { function getGeneralTurnBrief(General $generalObj, array $turnList) {
$result = []; $result = [];
foreach($turnList as $turnIdx => [$action, $arg]){ foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg); $commandObj = buildGeneralCommandClass($action, $generalObj, [], $arg);
$turnText = $commandObj->getBrief(); $turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText; $result[$turnIdx] = $turnText;
} }
return $result; return $result;
} }
function getNationTurnBrief(General $generalObj, array $turnList) { function getNationTurnBrief(General $generalObj, array $turnList) {
$result = []; $result = [];
$tmpTurn = new LastTurn(); $tmpTurn = new LastTurn();
foreach($turnList as $turnIdx => [$action, $arg]){ foreach($turnList as $turnIdx => [$action, $arg]){
$commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg); $commandObj = buildNationCommandClass($action, $generalObj, [], $tmpTurn, $arg);
$turnText = $commandObj->getBrief(); $turnText = $commandObj->getBrief();
$result[$turnIdx] = $turnText; $result[$turnIdx] = $turnText;
} }
return $result; return $result;
} }
function pushGeneralCommand(int $generalID, int $turnCnt=1){ function pushGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pullGeneralCommand($generalID, -$turnCnt); pullGeneralCommand($generalID, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxTurn){ if($turnCnt >= GameConst::$maxTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx DESC', $generalID); ], 'general_id=%i ORDER BY turn_idx DESC', $generalID);
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn), 'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식' 'brief'=>'휴식'
], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn); ], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn);
} }
function pullGeneralCommand(int $generalID, int $turnCnt=1){ function pullGeneralCommand(int $generalID, int $turnCnt=1){
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pushGeneralCommand($generalID, -$turnCnt); pushGeneralCommand($generalID, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxTurn){ if($turnCnt >= GameConst::$maxTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn), 'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식' 'brief'=>'휴식'
], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt); ], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt);
$db->update('general_turn', [ $db->update('general_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'general_id=%i ORDER BY turn_idx ASC', $generalID); ], 'general_id=%i ORDER BY turn_idx ASC', $generalID);
} }
function repeatGeneralCommand(int $generalId, int $turnCnt){ function repeatGeneralCommand(int $generalId, int $turnCnt){
if($turnCnt <= 0){ if($turnCnt <= 0){
return; return;
} }
if($turnCnt >= GameConst::$maxTurn){ if($turnCnt >= GameConst::$maxTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$reqTurn = $turnCnt; $reqTurn = $turnCnt;
if($turnCnt * 2 > GameConst::$maxTurn){ if($turnCnt * 2 > GameConst::$maxTurn){
$reqTurn = GameConst::$maxTurn - $turnCnt; $reqTurn = GameConst::$maxTurn - $turnCnt;
} }
$turnList = $db->query('SELECT turn_idx, `action`, arg, brief FROM general_turn WHERE general_id=%i AND turn_idx < %i', $generalId, $reqTurn); $turnList = $db->query('SELECT turn_idx, `action`, arg, brief FROM general_turn WHERE general_id=%i AND turn_idx < %i', $generalId, $reqTurn);
foreach($turnList as $turnItem){ foreach($turnList as $turnItem){
$turnIdx = $turnItem['turn_idx']; $turnIdx = $turnItem['turn_idx'];
$turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt)); $turnTarget = iterator_to_array(Util::range($turnIdx+$turnCnt, GameConst::$maxTurn, $turnCnt));
$db->update('general_turn', [ $db->update('general_turn', [
'action'=>$turnItem['action'], 'action'=>$turnItem['action'],
'arg'=>$turnItem['arg'], 'arg'=>$turnItem['arg'],
'brief'=>$turnItem['brief'] 'brief'=>$turnItem['brief']
], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget); ], 'general_id=%i AND turn_idx IN %li', $generalId, $turnTarget);
} }
} }
function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){ function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
if($nationID == 0){ if($nationID == 0){
return; return;
} }
if($officerLevel < 5){ if($officerLevel < 5){
return; return;
} }
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pullNationCommand($nationID, $officerLevel, -$turnCnt); pullNationCommand($nationID, $officerLevel, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxChiefTurn){ if($turnCnt >= GameConst::$maxChiefTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel); ], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel);
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn), 'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식' 'brief'=>'휴식'
], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn); ], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn);
} }
function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){ function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){
if($nationID == 0){ if($nationID == 0){
return; return;
} }
if($officerLevel < 5){ if($officerLevel < 5){
return; return;
} }
if($turnCnt == 0){ if($turnCnt == 0){
return; return;
} }
if($turnCnt < 0){ if($turnCnt < 0){
pushNationCommand($nationID, $officerLevel, -$turnCnt); pushNationCommand($nationID, $officerLevel, -$turnCnt);
return; return;
} }
if($turnCnt >= GameConst::$maxChiefTurn){ if($turnCnt >= GameConst::$maxChiefTurn){
return; return;
} }
$db = DB::db(); $db = DB::db();
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn), 'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn),
'action'=>'휴식', 'action'=>'휴식',
'arg'=>'{}', 'arg'=>'{}',
'brief'=>'휴식', 'brief'=>'휴식',
], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt); ], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt);
$db->update('nation_turn', [ $db->update('nation_turn', [
'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt) 'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt)
], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel); ], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel);
} }
function _setGeneralCommand(GeneralCommand $command, array $turnList):void { function _setGeneralCommand(GeneralCommand $command, array $turnList):void {
if(!$turnList){ if(!$turnList){
return; return;
} }
$db = DB::db(); $db = DB::db();
$generalID = $command->getGeneral()->getID(); $generalID = $command->getGeneral()->getID();
$commandName = $command->getRawClassName(); $commandName = $command->getRawClassName();
$arg = $command->getArg(); $arg = $command->getArg();
$brief = $command->getBrief(); $brief = $command->getBrief();
$db->update('general_turn', [ $db->update('general_turn', [
'action'=>$commandName, 'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT), 'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief 'brief'=>$brief
], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList); ], 'general_id = %i AND turn_idx IN %li', $generalID, $turnList);
} }
function _setNationCommand(NationCommand $command, array $turnList):void { function _setNationCommand(NationCommand $command, array $turnList):void {
if(!$turnList){ if(!$turnList){
return; return;
} }
$db = DB::db(); $db = DB::db();
$nationID = $command->getNationID(); $nationID = $command->getNationID();
$officerLevel = $command->getOfficerLevel(); $officerLevel = $command->getOfficerLevel();
$commandName = $command->getRawClassName(); $commandName = $command->getRawClassName();
$arg = $command->getArg(); $arg = $command->getArg();
$brief = $command->getBrief(); $brief = $command->getBrief();
$db->update('nation_turn', [ $db->update('nation_turn', [
'action'=>$commandName, 'action'=>$commandName,
'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT), 'arg'=>Json::encode($arg, JSON::EMPTY_ARRAY_IS_DICT),
'brief'=>$brief 'brief'=>$brief
], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList); ], 'nation_id = %i AND officer_level = %i AND turn_idx IN %li', $nationID, $officerLevel, $turnList);
} }
function sanitizeArg(?array $args):?array{ function sanitizeArg(?array $args):?array{
if($args === null){ if($args === null){
return $args; return $args;
} }
$result = []; $result = [];
foreach($args as $key=>$value){ foreach($args as $key=>$value){
if(is_array($value)){ if(is_array($value)){
$result[$key] = sanitizeArg($value); $result[$key] = sanitizeArg($value);
} }
else if(is_string($value)){ else if(is_string($value)){
$result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value)); $result[$key] = StringUtil::neutralize(StringUtil::removeSpecialCharacter($value));
} }
else{ else{
$result[$key] = $value; $result[$key] = $value;
} }
} }
return $result; return $result;
} }
function checkCommandArg(?array $arg):?string{ function checkCommandArg(?array $arg):?string{
if($arg === null){ if($arg === null){
return null; return null;
} }
$defaultCheck = [ $defaultCheck = [
/*'string'=>[ /*'string'=>[
'nationName', 'optionText', 'itemType', 'nationType' 'nationName', 'optionText', 'itemType', 'nationType', 'commandType',
],*/ ],*/
'integer'=>[ 'integer'=>[
'crewType', 'destGeneralID', 'destCityID', 'destNationID', 'crewType', 'destGeneralID', 'destCityID', 'destNationID',
'amount', 'colorType', 'amount', 'colorType',
'srcArmType', 'destArmType', //숙련전환 전용 'srcArmType', 'destArmType', //숙련전환 전용
], ],
'boolean'=>[ 'boolean'=>[
'isGold', 'buyRice', 'isGold', 'buyRice',
], ],
'between'=>[ 'between'=>[
['month', [1, 12]] ['month', [1, 12]]
], ],
'min'=>[ 'min'=>[
['year', 0], ['year', 0],
['destGeneralID', 1], ['destGeneralID', 1],
['destCityID', 1], ['destCityID', 1],
['destNationID', 1], ['destNationID', 1],
['amount', 1], ['amount', 1],
['crewType', 0] ['crewType', 0]
], ],
'integerArray'=>[ 'integerArray'=>[
'destNationIDList', 'destGeneralIDList', 'amountList' 'destNationIDList', 'destGeneralIDList', 'amountList'
], ],
'stringWidthBetween'=>[ 'stringWidthBetween'=>[
['nationName', 1, 18] ['nationName', 1, 18]
] ]
]; ];
$v = new Validator($arg); $v = new Validator($arg);
$v->rules($defaultCheck); $v->rules($defaultCheck);
if (!$v->validate()){ if (!$v->validate()){
return $v->errorStr(); return $v->errorStr();
} }
return null; return null;
} }
function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{ function setGeneralCommand(int $generalID, array $rawTurnList, string $command, ?array $arg = null):array{
$turnList = []; $turnList = [];
foreach($rawTurnList as $turnIdx){ foreach($rawTurnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){ if(!is_int($turnIdx) || $turnIdx < -3 || $turnIdx >= GameConst::$maxTurn){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx, 'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx', 'test'=>'turnIdx',
'target'=>$turnIdx, 'target'=>$turnIdx,
]; ];
} }
if($turnIdx >= 0){ if($turnIdx >= 0){
$turnList[$turnIdx] = true; $turnList[$turnIdx] = true;
} }
else if($turnIdx == -1){ else if($turnIdx == -1){
//홀수 //홀수, 0부터 맞다.
foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){ foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true; $turnList[$subIdx] = true;
} }
} }
else if($turnIdx == -2){ else if($turnIdx == -2){
//짝수 //짝수, 1부터 맞다.
foreach(Util::range(0, GameConst::$maxTurn, 2) as $subIdx){ foreach(Util::range(1, GameConst::$maxTurn, 2) as $subIdx){
$turnList[$subIdx] = true; $turnList[$subIdx] = true;
} }
} }
else if($turnIdx == -3){ else if($turnIdx == -3){
//모두 //모두
foreach(Util::range(GameConst::$maxTurn) as $subIdx){ foreach(Util::range(GameConst::$maxTurn) as $subIdx){
$turnList[$subIdx] = true; $turnList[$subIdx] = true;
} }
} }
} }
$turnList = array_keys($turnList); $turnList = array_keys($turnList);
$arg = sanitizeArg($arg); $arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg); $argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){ if($argBasicTestResult !== null){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.', 'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg', 'test'=>'checkCommandArg',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll(); $env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
try{ try{
$commandObj = buildGeneralCommandClass($command, $general, $env, $arg); $commandObj = buildGeneralCommandClass($command, $general, $env, $arg);
} }
catch (\InvalidArgumentException $e){ catch (\InvalidArgumentException $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getMessage(), 'reason'=>$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
catch (\Exception $e){ catch (\Exception $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getCode().$e->getMessage(), 'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->isArgValid()){ if(!$commandObj->isArgValid()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바르지 않은 argument', 'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid', 'test'=>'isArgValid',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->hasPermissionToReserve()){ if(!$commandObj->hasPermissionToReserve()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(), 'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve', 'test'=>'hasPermissionToReserve',
'target'=>'command' 'target'=>'command'
]; ];
} }
_setGeneralCommand($commandObj, $turnList); _setGeneralCommand($commandObj, $turnList);
return [ return [
'result'=>true, 'result'=>true,
'reason'=>'success' 'reason'=>'success'
]; ];
} }
function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{ function setNationCommand(int $generalID, array $turnList, string $command, ?array $arg = null):array{
$turnList = array_unique($turnList); $turnList = array_unique($turnList);
foreach($turnList as $turnIdx){ foreach($turnList as $turnIdx){
if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){ if(!is_int($turnIdx) || $turnIdx < 0 || $turnIdx >= GameConst::$maxChiefTurn){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx, 'reason'=>'올바른 턴이 아닙니다. : '.$turnIdx,
'test'=>'turnIdx', 'test'=>'turnIdx',
'target'=>$turnIdx, 'target'=>$turnIdx,
]; ];
} }
} }
$arg = sanitizeArg($arg); $arg = sanitizeArg($arg);
$argBasicTestResult = checkCommandArg($arg); $argBasicTestResult = checkCommandArg($arg);
if($argBasicTestResult !== null){ if($argBasicTestResult !== null){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'턴이 입력되지 않았습니다.', 'reason'=>'턴이 입력되지 않았습니다.',
'test'=>'checkCommandArg', 'test'=>'checkCommandArg',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getAll(); $env = $gameStor->getAll();
$general = General::createGeneralObjFromDB($generalID); $general = General::createGeneralObjFromDB($generalID);
if($general->getVar('officer_level') < 5){ if($general->getVar('officer_level') < 5){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'수뇌가 아닙니다' 'reason'=>'수뇌가 아닙니다'
]; ];
} }
try{ try{
$commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg); $commandObj = buildNationCommandClass($command, $general, $env, $general->getLastTurn(), $arg);
} }
catch (\InvalidArgumentException $e){ catch (\InvalidArgumentException $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getMessage(), 'reason'=>$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
catch (\Exception $e){ catch (\Exception $e){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>$e->getCode().$e->getMessage(), 'reason'=>$e->getCode().$e->getMessage(),
'test'=>'build', 'test'=>'build',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->isArgValid()){ if(!$commandObj->isArgValid()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'올바르지 않은 argument', 'reason'=>'올바르지 않은 argument',
'test'=>'isArgValid', 'test'=>'isArgValid',
'target'=>'arg' 'target'=>'arg'
]; ];
} }
if(!$commandObj->hasPermissionToReserve()){ if(!$commandObj->hasPermissionToReserve()){
return [ return [
'result'=>false, 'result'=>false,
'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(), 'reason'=>'예약 불가능한 커맨드 :'.$commandObj->testPermissionToReserve(),
'test'=>'hasPermissionToReserve', 'test'=>'hasPermissionToReserve',
'target'=>'command' 'target'=>'command'
]; ];
} }
_setNationCommand($commandObj, $turnList); _setNationCommand($commandObj, $turnList);
return [ return [
'result'=>true, 'result'=>true,
'arg_test'=>true, 'arg_test'=>true,
'reason'=>'success' 'reason'=>'success'
]; ];
} }
+24
View File
@@ -378,6 +378,30 @@ function buildWarUnitTriggerClass(?string $type, WarUnit $unit, ?array $args = n
return $class->newInstanceArgs(array_merge([$unit], $args)); return $class->newInstanceArgs(array_merge([$unit], $args));
} }
function getGeneralPoolClass(string $type){
static $basePath = __NAMESPACE__.'\\GeneralPool\\';
$classPath = ($basePath.$type);
if(class_exists($classPath)){
return $classPath;
}
throw new \InvalidArgumentException("{$type}은 GeneralPool이 아님");
}
/**
* @param \MeekroDB $db
* @param int $owner
* @param int $pickCnt
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array{
/** @var AbsGeneralPool */
$class = getGeneralPoolClass(GameConst::$targetGeneralPool);
return $class::pickGeneralFromPool($db, $owner, $pickCnt, $prefix);
}
function countPureGeneralFromRawList(?array $rawGeneralList=null):int{ function countPureGeneralFromRawList(?array $rawGeneralList=null):int{
if(!$rawGeneralList){ if(!$rawGeneralList){
return 0; return 0;
+1173 -1138
View File
@@ -1,1138 +1,1173 @@
<?php <?php
namespace sammo; namespace sammo;
use Monolog\Logger; use Monolog\Logger;
/** /**
* 게임 룰에 해당하는 함수 모음 * 게임 룰에 해당하는 함수 모음
*/ */
function getNationLevelList(): array function getNationLevelList(): array
{ {
$table = [ $table = [
0 => ['방랑군', 2, 0], 0 => ['방랑군', 2, 0],
1 => ['호족', 2, 1], 1 => ['호족', 2, 1],
2 => ['군벌', 4, 2], 2 => ['군벌', 4, 2],
3 => ['주자사', 4, 5], 3 => ['주자사', 4, 5],
4 => ['주목', 6, 8], 4 => ['주목', 6, 8],
5 => ['공', 6, 11], 5 => ['공', 6, 11],
6 => ['왕', 8, 16], 6 => ['왕', 8, 16],
7 => ['황제', 8, 21], 7 => ['황제', 8, 21],
]; ];
return $table; return $table;
} }
function getCityLevelList(): array function getCityLevelList(): array
{ {
return [ return [
1 => '수', 1 => '수',
2 => '진', 2 => '진',
3 => '관', 3 => '관',
4 => '이', 4 => '이',
5 => '소', 5 => '소',
6 => '중', 6 => '중',
7 => '대', 7 => '대',
8 => '특' 8 => '특'
]; ];
} }
//한국가의 전체 전방 설정 //한국가의 전체 전방 설정
function SetNationFront($nationNo) function SetNationFront($nationNo)
{ {
if (!$nationNo) { if (!$nationNo) {
return; return;
} }
// 도시소유 국가와 선포,교전중인 국가 // 도시소유 국가와 선포,교전중인 국가
$adj3 = []; $adj3 = [];
$adj2 = []; $adj2 = [];
$adj1 = []; $adj1 = [];
$db = DB::db(); $db = DB::db();
foreach ($db->queryFirstColumn( foreach ($db->queryFirstColumn(
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i', 'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 0 AND me = %i',
$nationNo $nationNo
) as $city) { ) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) { foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj3[$adjKey] = $adjVal; $adj3[$adjKey] = $adjVal;
} }
}; };
foreach ($db->queryFirstColumn( foreach ($db->queryFirstColumn(
'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 1 AND diplomacy.term <= 5 AND me = %i', 'SELECT city FROM city JOIN diplomacy ON diplomacy.you = city.nation WHERE diplomacy.state = 1 AND diplomacy.term <= 5 AND me = %i',
$nationNo $nationNo
) as $city) { ) as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) { foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj1[$adjKey] = $adjVal; $adj1[$adjKey] = $adjVal;
} }
} }
if (!$adj3 && !$adj1) { if (!$adj3 && !$adj1) {
//평시이면 공백지 //평시이면 공백지
//NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다. //NOTE: if, else일 경우 NPC는 전쟁시에는 공백지로 출병하지 않는다는 뜻이 된다.
foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) { foreach ($db->queryFirstColumn('SELECT city from city where nation=0') as $city) {
foreach (CityConst::byID($city)->path as $adjKey => $adjVal) { foreach (CityConst::byID($city)->path as $adjKey => $adjVal) {
$adj2[$adjKey] = $adjVal; $adj2[$adjKey] = $adjVal;
} }
} }
} }
$db->update('city', [ $db->update('city', [
'front' => 0 'front' => 0
], 'nation=%i', $nationNo); ], 'nation=%i', $nationNo);
if ($adj1) { if ($adj1) {
$db->update('city', [ $db->update('city', [
'front' => 1, 'front' => 1,
], 'nation=%i and city in %li', $nationNo, array_keys($adj1)); ], 'nation=%i and city in %li', $nationNo, array_keys($adj1));
} }
if ($adj2) { if ($adj2) {
$db->update('city', [ $db->update('city', [
'front' => 2, 'front' => 2,
], 'nation=%i and city in %li', $nationNo, array_keys($adj2)); ], 'nation=%i and city in %li', $nationNo, array_keys($adj2));
} }
if ($adj3) { if ($adj3) {
$db->update('city', [ $db->update('city', [
'front' => 3, 'front' => 3,
], 'nation=%i and city in %li', $nationNo, array_keys($adj3)); ], 'nation=%i and city in %li', $nationNo, array_keys($adj3));
} }
} }
function checkSupply() function checkSupply()
{ {
$db = DB::db(); $db = DB::db();
$cities = []; $cities = [];
foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) { foreach ($db->query('SELECT city, nation FROM city WHERE nation != 0') as $city) {
$newCity = new \stdClass(); $newCity = new \stdClass();
$newCity->id = Util::toInt($city['city']); $newCity->id = Util::toInt($city['city']);
$newCity->nation = Util::toInt($city['nation']); $newCity->nation = Util::toInt($city['nation']);
$newCity->supply = false; $newCity->supply = false;
$cities[$newCity->id] = $newCity; $cities[$newCity->id] = $newCity;
} }
$queue = new \SplQueue(); $queue = new \SplQueue();
foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) { foreach ($db->queryAllLists('SELECT capital, nation FROM nation WHERE `level` > 0') as list($capitalID, $nationID)) {
if (!key_exists($capitalID, $cities)) { if (!key_exists($capitalID, $cities)) {
continue; continue;
} }
$city = $cities[$capitalID]; $city = $cities[$capitalID];
if ($nationID != $city->nation) { if ($nationID != $city->nation) {
continue; continue;
} }
$city->supply = true; $city->supply = true;
$queue->enqueue($city); $queue->enqueue($city);
} }
while (!$queue->isEmpty()) { while (!$queue->isEmpty()) {
$cityLink = $queue->dequeue(); $cityLink = $queue->dequeue();
$city = CityConst::byID($cityLink->id); $city = CityConst::byID($cityLink->id);
foreach (array_keys($city->path) as $connCityID) { foreach (array_keys($city->path) as $connCityID) {
if (!key_exists($connCityID, $cities)) { if (!key_exists($connCityID, $cities)) {
continue; continue;
} }
$connCity = $cities[$connCityID]; $connCity = $cities[$connCityID];
if ($connCity->nation != $cityLink->nation) { if ($connCity->nation != $cityLink->nation) {
continue; continue;
} }
if ($connCity->supply) { if ($connCity->supply) {
continue; continue;
} }
$connCity->supply = true; $connCity->supply = true;
$queue->enqueue($connCity); $queue->enqueue($connCity);
} }
} }
$db->update('city', [ $db->update('city', [
'supply' => 1 'supply' => 1
], 'nation=0'); ], 'nation=0');
$db->update('city', [ $db->update('city', [
'supply' => 0 'supply' => 0
], 'nation!=0'); ], 'nation!=0');
$supply = []; $supply = [];
foreach ($cities as $city) { foreach ($cities as $city) {
if ($city->supply) { if ($city->supply) {
$supply[] = $city->id; $supply[] = $city->id;
} }
} }
if ($supply) { if ($supply) {
$db->update('city', [ $db->update('city', [
'supply' => 1 'supply' => 1
], 'city IN %li', $supply); ], 'city IN %li', $supply);
} }
} }
function updateGeneralNumber(){ function updateGeneralNumber(){
$db = DB::db(); $db = DB::db();
foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){ foreach($db->queryAllLists('SELECT nation, count(*) FROM general WHERE npc != 5 GROUP BY nation') as [$nationID, $gennum]){
if($nationID === 0){ if($nationID === 0){
continue; continue;
} }
$db->update('nation', [ $db->update('nation', [
'gennum'=>$gennum 'gennum'=>$gennum
], 'nation=%i', $nationID); ], 'nation=%i', $nationID);
} }
refreshNationStaticInfo(); refreshNationStaticInfo();
} }
function updateYearly() function updateYearly()
{ {
//통계 //통계
checkStatistic(); checkStatistic();
} }
//관직 변경 해제 //관직 변경 해제
function updateQuaterly() function updateQuaterly()
{ {
$db = DB::db(); $db = DB::db();
//천도 제한 해제, 관직 변경 제한 해제 //천도 제한 해제, 관직 변경 제한 해제
$db->update('nation', [ $db->update('nation', [
'chief_set' => 0, 'chief_set' => 0,
], true); ], true);
//관직 변경 제한 해제 //관직 변경 제한 해제
$db->update('city', [ $db->update('city', [
'officer_set' => 0, 'officer_set' => 0,
], true); ], true);
} }
// 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정 // 벌점 감소와 건국제한-1 전턴제한-1 외교제한-1, 1달마다 실행, 병사 있는 장수의 군량 감소, 수입비율 조정
function preUpdateMonthly() function preUpdateMonthly()
{ {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
//연감 월결산 //연감 월결산
$result = LogHistory(); $result = LogHistory();
if ($result == false) { if ($result == false) {
return false; return false;
} }
$admin = $gameStor->getValues(['startyear', 'year', 'month']); $admin = $gameStor->getValues(['startyear', 'year', 'month']);
$logger = new ActionLogger(0, 0, $admin['year'], $admin['month']); $logger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//보급선 체크 //보급선 체크
checkSupply(); checkSupply();
//미보급도시 10% 감소 //미보급도시 10% 감소
$db->update('city', [ $db->update('city', [
'pop' => $db->sqleval('pop * 0.9'), 'pop' => $db->sqleval('pop * 0.9'),
'trust' => $db->sqleval('trust * 0.9'), 'trust' => $db->sqleval('trust * 0.9'),
'agri' => $db->sqleval('agri * 0.9'), 'agri' => $db->sqleval('agri * 0.9'),
'comm' => $db->sqleval('comm * 0.9'), 'comm' => $db->sqleval('comm * 0.9'),
'secu' => $db->sqleval('secu * 0.9'), 'secu' => $db->sqleval('secu * 0.9'),
'def' => $db->sqleval('def * 0.9'), 'def' => $db->sqleval('def * 0.9'),
'wall' => $db->sqleval('wall * 0.9'), 'wall' => $db->sqleval('wall * 0.9'),
], 'supply = 0'); ], 'supply = 0');
//미보급도시 장수 병 훈 사 5%감소 //미보급도시 장수 병 훈 사 5%감소
//NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게. //NOTE: update inner join도 가능하지만, meekrodb 기준으로 깔끔하게.
$unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0'); $unsuppliedCities = $db->query('SELECT city, nation, trust, name FROM city WHERE supply = 0');
foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) { foreach (Util::arrayGroupBy($unsuppliedCities, 'nation') as $nationID => $cityList) {
$cityIDList = Util::squeezeFromArray($cityList, 'city'); $cityIDList = Util::squeezeFromArray($cityList, 'city');
$db->update('general', [ $db->update('general', [
'crew' => $db->sqleval('crew*0.95'), 'crew' => $db->sqleval('crew*0.95'),
'atmos' => $db->sqleval('atmos*0.95'), 'atmos' => $db->sqleval('atmos*0.95'),
'train' => $db->sqleval('train*0.95'), 'train' => $db->sqleval('train*0.95'),
], 'city IN %li AND nation = %i', $cityIDList, $nationID); ], 'city IN %li AND nation = %i', $cityIDList, $nationID);
} }
//민심30이하 공백지 처리 //민심30이하 공백지 처리
$lostCities = []; $lostCities = [];
foreach ($unsuppliedCities as $unsuppliedCity) { foreach ($unsuppliedCities as $unsuppliedCity) {
if ($unsuppliedCity['trust'] >= 30) { if ($unsuppliedCity['trust'] >= 30) {
continue; continue;
} }
$lostCities[$unsuppliedCity['city']] = $unsuppliedCity; $lostCities[$unsuppliedCity['city']] = $unsuppliedCity;
} }
if ($lostCities) { if ($lostCities) {
foreach ($lostCities as $lostCity) { foreach ($lostCities as $lostCity) {
$josaYi = JosaUtil::pick($lostCity['name'], '이'); $josaYi = JosaUtil::pick($lostCity['name'], '이');
$logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다."); $logger->pushGlobalHistoryLog("<R><b>【고립】</b></><G><b>{$lostCity['name']}</b></>{$josaYi} 보급이 끊겨 <R>미지배</> 도시가 되었습니다.");
} }
$db->update('general', [ $db->update('general', [
'officer_level' => 1, 'officer_level' => 1,
'officer_city' => 0 'officer_city' => 0
], 'officer_city IN %li', array_keys($lostCities)); ], 'officer_city IN %li', array_keys($lostCities));
$db->update('city', [ $db->update('city', [
'nation' => 0, 'nation' => 0,
'officer_set' => 0, 'officer_set' => 0,
'conflict' => '{}', 'conflict' => '{}',
'term' => 0, 'term' => 0,
'front' => 0 'front' => 0
], 'city IN %li', array_keys($lostCities)); ], 'city IN %li', array_keys($lostCities));
} }
//접률감소, 건국제한-1 //접률감소, 건국제한-1
$db->update('general', [ $db->update('general', [
'connect' => $db->sqleval('floor(connect*0.99)'), 'connect' => $db->sqleval('floor(connect*0.99)'),
'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'), 'makelimit' => $db->sqleval('greatest(0, makelimit - 1)'),
], true); ], true);
//전략제한-1, 외교제한-1, 세율동기화 //전략제한-1, 외교제한-1, 세율동기화
$db->update('nation', [ $db->update('nation', [
'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'), 'strategic_cmd_limit' => $db->sqleval('greatest(0, strategic_cmd_limit - 1)'),
'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'), 'surlimit' => $db->sqleval('greatest(0, surlimit - 1)'),
'rate_tmp' => $db->sqleval('rate') 'rate_tmp' => $db->sqleval('rate')
], true); ], true);
//도시훈사 180년 60, 220년 87, 240년 100 //도시훈사 180년 60, 220년 87, 240년 100
$rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60; $rate = Util::round(($admin['year'] - $admin['startyear']) / 1.5) + 60;
if ($rate > 100) $rate = 100; if ($rate > 100) $rate = 100;
// 20 ~ 140원 // 20 ~ 140원
$develcost = ($admin['year'] - $admin['startyear'] + 10) * 2; $develcost = ($admin['year'] - $admin['startyear'] + 10) * 2;
$gameStor->city_rate = $rate; $gameStor->city_rate = $rate;
$gameStor->develcost = $develcost; $gameStor->develcost = $develcost;
//매달 사망자 수입 결산 //매달 사망자 수입 결산
processWarIncome(); processWarIncome();
//계략, 전쟁표시 해제 //계략, 전쟁표시 해제
$db->update('city', [ $db->update('city', [
'state' => $db->sqleval(<<<EOD 'state' => $db->sqleval(<<<EOD
(CASE (CASE
WHEN state=31 THEN 0 WHEN state=31 THEN 0
WHEN state=32 THEN 31 WHEN state=32 THEN 31
WHEN state=33 THEN 0 WHEN state=33 THEN 0
WHEN state=34 THEN 33 WHEN state=34 THEN 33
WHEN state=41 THEN 0 WHEN state=41 THEN 0
WHEN state=42 THEN 41 WHEN state=42 THEN 41
WHEN state=43 THEN 42 WHEN state=43 THEN 42
ELSE state END) ELSE state END)
EOD), EOD),
'term' => $db->sqleval('greatest(0, term - 1)'), 'term' => $db->sqleval('greatest(0, term - 1)'),
'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'), 'conflict' => $db->sqleval('if(term = 0,%s,conflict)', '{}'),
], true); ], true);
//첩보-1 //첩보-1
foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) { foreach ($db->queryAllLists("SELECT nation, spy FROM nation WHERE spy!='' AND spy!='{}'") as [$nationNo, $rawSpy]) {
$spyInfo = Json::decode($rawSpy); $spyInfo = Json::decode($rawSpy);
foreach ($spyInfo as $cityNo => $remainMonth) { foreach ($spyInfo as $cityNo => $remainMonth) {
if ($remainMonth <= 1) { if ($remainMonth <= 1) {
unset($spyInfo[$cityNo]); unset($spyInfo[$cityNo]);
} else { } else {
$spyInfo[$cityNo] -= 1; $spyInfo[$cityNo] -= 1;
} }
} }
$db->update('nation', [ $db->update('nation', [
'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT) 'spy' => Json::encode($spyInfo, Json::EMPTY_ARRAY_IS_DICT)
], 'nation=%i', $nationNo); ], 'nation=%i', $nationNo);
} }
return true; return true;
} }
// 외교 로그처리, 외교 상태 처리 // 외교 로그처리, 외교 상태 처리
function postUpdateMonthly() function postUpdateMonthly()
{ {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']); $admin = $gameStor->getValues(['startyear', 'year', 'month', 'scenario']);
$globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']); $globalLogger = new ActionLogger(0, 0, $admin['year'], $admin['month']);
//도시 수 측정 //도시 수 측정
$cityNations = []; $cityNations = [];
foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) { foreach ($db->queryAllLists('SELECT city, name, nation FROM city') as [$cityID, $cityName, $cityNation]) {
if (!key_exists($cityNation, $cityNations)) { if (!key_exists($cityNation, $cityNations)) {
$cityNations[$cityNation] = []; $cityNations[$cityNation] = [];
} }
$cityNations[$cityNation][] = $cityName; $cityNations[$cityNation][] = $cityName;
} }
//각 국가 전월 장수수 대비 당월 장수수로 단합도 산정 //각 국가 전월 장수수 대비 당월 장수수로 단합도 산정
//각 국가 장수수를 구하고 국력 산정 //각 국가 장수수를 구하고 국력 산정
// $query = "select nation,gennum from nation where level>0"; // $query = "select nation,gennum from nation where level>0";
// 국력= // 국력=
// 자원(국가/장수의 금,쌀) // 자원(국가/장수의 금,쌀)
// 기술력 // 기술력
// 인구수*내정% // 인구수*내정%
// 장수능력 // 장수능력
// 접속률 // 접속률
// 숙련도 // 숙련도
// 명성,공헌 // 명성,공헌
$nations = Util::convertArrayToDict($db->query('SELECT $nations = Util::convertArrayToDict($db->query('SELECT
A.nation, A.nation,
A.gennum, A.gennum,
round(( round((
round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100) round(((A.gold+A.rice)+(select sum(gold+rice) from general where nation=A.nation))/100)
+A.tech +A.tech
+if(A.level=0,0,( +if(A.level=0,0,(
select round( select round(
sum(pop)*sum(pop+agri+comm+secu+wall+def)/sum(pop_max+agri_max+comm_max+secu_max+wall_max+def_max)/100 sum(pop)*sum(pop+agri+comm+secu+wall+def)/sum(pop_max+agri_max+comm_max+secu_max+wall_max+def_max)/100
) from city where nation=A.nation and supply=1 ) from city where nation=A.nation and supply=1
)) ))
+(select sum(leadership+strength+intel) from general where nation=A.nation) +(select sum(leadership+strength+intel) from general where nation=A.nation)
+(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where nation=A.nation) +(select round(sum(dex1+dex2+dex3+dex4+dex5)/1000) from general where nation=A.nation)
+(select round(sum(experience+dedication)/100) from general where nation=A.nation) +(select round(sum(experience+dedication)/100) from general where nation=A.nation)
+(select round(avg(connect)) from general where nation=A.nation) +(select round(avg(connect)) from general where nation=A.nation)
)/10) )/10)
as power, as power,
(select sum(crew) from general where nation=A.nation) as totalCrew (select sum(crew) from general where nation=A.nation) as totalCrew
from nation A from nation A
group by A.nation'), 'nation'); group by A.nation'), 'nation');
$maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power'); $maxPowerValues = KVStorage::getValuesFromInterNamespace($db, 'nation_env', 'max_power');
foreach ($nations as $nation) { foreach ($nations as $nation) {
$nationID = $nation['nation']; $nationID = $nation['nation'];
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$genNum[$nationID] = $nation['gennum']; $genNum[$nationID] = $nation['gennum'];
$powerValues = $maxPowerValues[$nationID]??[]; $powerValues = $maxPowerValues[$nationID]??[];
//약간의 랜덤치 부여 (95% ~ 105%) //약간의 랜덤치 부여 (95% ~ 105%)
$nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000); $nation['power'] = Util::round($nation['power'] * (rand() % 101 + 950) / 1000);
$powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']); $powerValues['maxPower'] = max($powerValues['maxPower'] ?? 0, $nation['power']);
$powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew'])); $powerValues['maxCrew'] = max($powerValues['maxCrew'] ?? 0, Util::toInt($nation['totalCrew']));
if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) { if (count($cityNations[$nationID] ?? []) > count($powerValues['maxCities'] ?? [])) {
$powerValues['maxCities'] = $cityNations[$nationID]; $powerValues['maxCities'] = $cityNations[$nationID];
} }
$db->update('nation', [ $db->update('nation', [
'power' => $nation['power'] 'power' => $nation['power']
], 'nation=%i', $nationID); ], 'nation=%i', $nationID);
$nationStor->max_power = $powerValues; $nationStor->max_power = $powerValues;
} }
// 전쟁기한 세팅 // 전쟁기한 세팅
foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) { foreach($db->query('SELECT me, you, dead, term FROM diplomacy WHERE state = 0') as $dip) {
$genCount = $genNum[$dip['me']]; $genCount = $genNum[$dip['me']];
// 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산 // 25% 참여율일때 두당 10턴에 4000명 소모한다고 계산
// 4000 / 10 * 0.25 = 100 // 4000 / 10 * 0.25 = 100
$term = floor($dip['dead'] / 100 / $genCount); $term = floor($dip['dead'] / 100 / $genCount);
$dip['dead'] -= $term * 100 * $genCount; $dip['dead'] -= $term * 100 * $genCount;
$term = Util::valueFit($dip['term'] + $term, 0, 13); $term = Util::valueFit($dip['term'] + $term, 0, 13);
$db->update('diplomacy', [ $db->update('diplomacy', [
'term' => $term, 'term' => $term,
'dead' => $dip['dead'], 'dead' => $dip['dead'],
], 'me = %i AND you = %i', $dip['me'], $dip['you']); ], 'me = %i AND you = %i', $dip['me'], $dip['you']);
} }
//개전국 로그 //개전국 로그
foreach($db->query('SELECT me, you FROM diplomacy WHERE state = 1 AND term <= 1 AND me < you') as $dip){ foreach($db->query('SELECT me, you FROM diplomacy WHERE state = 1 AND term <= 1 AND me < you') as $dip){
$nation1 = getNationStaticInfo($dip['me']); $nation1 = getNationStaticInfo($dip['me']);
$name1 = $nation1['name']; $name1 = $nation1['name'];
$nation2 = getNationStaticInfo($dip['you']); $nation2 = getNationStaticInfo($dip['you']);
$name2 = $nation2['name']; $name2 = $nation2['name'];
$josaYi = JosaUtil::pick($name2, '이'); $josaYi = JosaUtil::pick($name2, '이');
$josaWa = JosaUtil::pick($name1, '와'); $josaWa = JosaUtil::pick($name1, '와');
$globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다."); $globalLogger->pushGlobalHistoryLog("<R><b>【개전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <R>전쟁</>을 시작합니다.");
} }
//휴전국 로그 //휴전국 로그
$stopWarList = []; $stopWarList = [];
foreach($db->queryAllLists('SELECT me,you FROM diplomacy WHERE state=0 AND term <= 1 ORDER BY me desc, you desc') as [$me, $you]){ foreach($db->queryAllLists('SELECT me,you FROM diplomacy WHERE state=0 AND term <= 1 ORDER BY me desc, you desc') as [$me, $you]){
if($me < $you){ if($me < $you){
$key = "{$me}_{$you}"; $key = "{$me}_{$you}";
} }
else{ else{
$key = "{$you}_{$me}"; $key = "{$you}_{$me}";
} }
if(!key_exists($key, $stopWarList)){ if(!key_exists($key, $stopWarList)){
$stopWarList[$key] = true; $stopWarList[$key] = true;
continue; continue;
} }
//양측 기간 모두 0이 되는 상황이면 휴전 //양측 기간 모두 0이 되는 상황이면 휴전
$nation1 = getNationStaticInfo($me); $nation1 = getNationStaticInfo($me);
$name1 = $nation1['name']; $name1 = $nation1['name'];
$nation2 = getNationStaticInfo($you); $nation2 = getNationStaticInfo($you);
$name2 = $nation2['name']; $name2 = $nation2['name'];
$josaWa = JosaUtil::pick($name1, '와'); $josaWa = JosaUtil::pick($name1, '와');
$josaYi = JosaUtil::pick($name2, '이'); $josaYi = JosaUtil::pick($name2, '이');
$globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다."); $globalLogger->pushGlobalHistoryLog("<R><b>【휴전】</b></><D><b>$name1</b></>{$josaWa} <D><b>$name2</b></>{$josaYi} <S>휴전</>합니다.");
$db->update('diplomacy', [ $db->update('diplomacy', [
'state'=>2, 'state'=>2,
'term'=>0, 'term'=>0,
], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you); ], '(me=%i AND you=%i) OR (you=%i AND me=%i)', $me, $you, $me, $you);
} }
$globalLogger->flush(); $globalLogger->flush();
//사상자 초기화, 외교 기한-1 //사상자 초기화, 외교 기한-1
$db->update('diplomacy', [ $db->update('diplomacy', [
'dead'=>$db->sqleval('if(state!=0, 0, dead)'), 'dead'=>$db->sqleval('if(state!=0, 0, dead)'),
'term'=>$db->sqleval('greatest(0, term-1)'), 'term'=>$db->sqleval('greatest(0, term-1)'),
], true); ], true);
//불가침 끝나면 통상으로 //불가침 끝나면 통상으로
$db->update('diplomacy', [ $db->update('diplomacy', [
'state'=>2, 'state'=>2,
], 'state = 7 AND term = 0'); ], 'state = 7 AND term = 0');
//선포 끝나면 교전으로 //선포 끝나면 교전으로
$db->update('diplomacy', [ $db->update('diplomacy', [
'state'=>0, 'state'=>0,
'term'=>6, 'term'=>6,
], 'state = 1 AND term = 0'); ], 'state = 1 AND term = 0');
//초반이후 방랑군 자동 해체 //초반이후 방랑군 자동 해체
if ($admin['year'] >= $admin['startyear'] + 2) { if ($admin['year'] >= $admin['startyear'] + 2) {
checkWander(); checkWander();
} }
// 작위 업데이트 // 작위 업데이트
updateNationState(); updateNationState();
updateGeneralNumber(); updateGeneralNumber();
refreshNationStaticInfo(); refreshNationStaticInfo();
// 천통여부 검사 // 천통여부 검사
checkEmperior(); checkEmperior();
//토너먼트 개시 //토너먼트 개시
triggerTournament(); triggerTournament();
// 시스템 거래건 등록 // 시스템 거래건 등록
registerAuction(); registerAuction();
//전방설정 //전방설정
foreach (getAllNationStaticInfo() as $nation) { foreach (getAllNationStaticInfo() as $nation) {
if ($nation['level'] <= 0) { if ($nation['level'] <= 0) {
continue; continue;
} }
SetNationFront($nation['nation']); SetNationFront($nation['nation']);
} }
} }
function checkWander() function checkWander()
{ {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['year', 'month']); $admin = $gameStor->getValues(['year', 'month']);
$wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12'); $wanderers = $db->queryFirstColumn('SELECT general.`no` FROM general LEFT JOIN nation ON general.nation = nation.nation WHERE nation.`level` = 0 AND general.`officer_level` = 12');
foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) { foreach (General::createGeneralObjListFromDB($wanderers) as $wanderer) {
$wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin); $wanderCmd = buildGeneralCommandClass('che_해산', $wanderer, $admin);
if ($wanderCmd->hasFullConditionMet()) { if ($wanderCmd->hasFullConditionMet()) {
$logger = $wanderer->getLogger(); $logger = $wanderer->getLogger();
$logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN); $logger->pushGeneralActionLog('초반 제한후 방랑군은 자동 해산됩니다.', ActionLogger::PLAIN);
$wanderCmd->run(); $wanderCmd->run();
} $wanderCmd->setNextAvailable();
} }
}
if ($wanderers) {
refreshNationStaticInfo(); if ($wanderers) {
} refreshNationStaticInfo();
} }
}
function updateNationState()
{ function updateNationState()
$db = DB::db(); {
$gameStor = KVStorage::getStorage($db, 'game_env'); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']); $history = array();
$admin = $gameStor->getValues(['killturn', 'year', 'month', 'fiction', 'startyear', 'show_img_level', 'turnterm', 'turntime']);
$assemblerCnts = [];
foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) { $assemblerCnts = [];
$assemblerCnts[$nationID] = $assemblerCnt; foreach ($db->queryAllLists('SELECT nation,count(no) FROM general WHERE npc = 5 GROUP BY nation') as [$nationID, $assemblerCnt]) {
}; $assemblerCnts[$nationID] = $assemblerCnt;
};
foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
//TODO: level이 진관수이소중대특 체계를 벗어날 수 있음 foreach ($db->query('SELECT nation,name,level,tech,aux FROM nation') as $nation) {
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']); //TODO: level이 진관수이소중대특 체계를 벗어날 수 있음
$citycount = $db->queryFirstField('SELECT count(*) FROM city WHERE nation=%i AND level>=4', $nation['nation']);
if ($citycount == 0) {
$nationlevel = 0; // 방랑군 if ($citycount == 0) {
} elseif ($citycount == 1) { $nationlevel = 0; // 방랑군
$nationlevel = 1; // 호족 } elseif ($citycount == 1) {
} elseif ($citycount <= 4) { $nationlevel = 1; // 호족
$nationlevel = 2; // 군벌 } elseif ($citycount <= 4) {
} elseif ($citycount <= 7) { $nationlevel = 2; // 군벌
$nationlevel = 3; // 주자사 } elseif ($citycount <= 7) {
} elseif ($citycount <= 10) { $nationlevel = 3; // 주자사
$nationlevel = 4; // 주목 } elseif ($citycount <= 10) {
} elseif ($citycount <= 15) { $nationlevel = 4; // 주목
$nationlevel = 5; // 공 } elseif ($citycount <= 15) {
} elseif ($citycount <= 20) { $nationlevel = 5; // 공
$nationlevel = 6; // 왕 } elseif ($citycount <= 20) {
} else { $nationlevel = 6; // 왕
$nationlevel = 7; // 황제 } else {
} $nationlevel = 7; // 황제
}
if ($nationlevel > $nation['level']) {
$levelDiff = $nationlevel - $nation['level']; if ($nationlevel > $nation['level']) {
$oldLevel = $nation['level']; $levelDiff = $nationlevel - $nation['level'];
$nation['level'] = $nationlevel; $oldLevel = $nation['level'];
$nation['level'] = $nationlevel;
$updateVals = [
'level' => $nationlevel, $updateVals = [
'gold'=>$db->sqleval('gold + %i', $nationlevel*1000), 'level' => $nationlevel,
'rice'=>$db->sqleval('rice + %i', $nationlevel*1000), 'gold'=>$db->sqleval('gold + %i', $nationlevel*1000),
]; 'rice'=>$db->sqleval('rice + %i', $nationlevel*1000),
];
switch ($nationlevel) {
case 7: switch ($nationlevel) {
$josaUl = JosaUtil::pick(getNationLevel($nationlevel), '을'); case 7:
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다."; $josaUl = JosaUtil::pick(getNationLevel($nationlevel), '을');
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]); $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭하였습니다.";
$auxVal = Json::decode($nation['aux']); pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>{$josaUl} 자칭"]);
$auxVal['can_국기변경'] = 1; $auxVal = Json::decode($nation['aux']);
$auxVal['can_국변경'] = 1; $auxVal['can_국변경'] = 1;
$updateVals['aux'] = Json::encode($auxVal); $auxVal['can_국호변경'] = 1;
break; $updateVals['aux'] = Json::encode($auxVal);
case 6: break;
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다."; case 6:
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]); $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극하였습니다.";
break; pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 등극"]);
case 5: break;
case 4: case 5:
case 3: case 4:
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다."; case 3:
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명"]); $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명되었습니다.";
break; pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>에 임명됨"]);
case 2: break;
$history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다."; case 2:
pushNationHistoryLog($nation['nation'], ["<C>●</>{$admin['year']}{$admin['month']}월:<D><b>{$nation['name']}</b></>의 군주가 <Y>" . getNationLevel($nationlevel) . "</>로 나서다"]); $history[] = "<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【작위】</b></><D><b>{$nation['name']}</b></>의 군주가 독립하여 <Y>" . getNationLevel($nationlevel) . "</>로 나섰습니다.";
break; 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']);
$db->update('nation', $updateVals, 'nation=%i', $nation['nation']);
$turnRows = [];
foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) { $turnRows = [];
foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) { foreach (Util::range(getNationChiefLevel($nation['level']), 12) as $chiefLevel) {
$turnRows[] = [ foreach (Util::range(GameConst::$maxChiefTurn) as $turnIdx) {
'nation_id' => $nation['nation'], $turnRows[] = [
'officer_level' => $chiefLevel, 'nation_id' => $nation['nation'],
'turn_idx' => $turnIdx, 'officer_level' => $chiefLevel,
'action' => '휴식', 'turn_idx' => $turnIdx,
'arg' => null, 'action' => '휴식',
'brief' => '휴식' 'arg' => null,
]; 'brief' => '휴식'
} ];
} }
$db->insertIgnore('nation_turn', $turnRows); }
$db->insertIgnore('nation_turn', $turnRows);
if ($levelDiff) {
//유니크 아이템 하나 돌리자 if ($levelDiff) {
$targetKillTurn = $admin['killturn']; //유니크 아이템 하나 돌리자
$targetKillTurn -= 24 * 60 / $admin['turnterm']; $targetKillTurn = $admin['killturn'];
$nationGenIDList = $db->queryFirstColumn( $targetKillTurn -= 24 * 60 / $admin['turnterm'];
'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2', $nationGenIDList = $db->queryFirstColumn(
$nation['nation'], 'SELECT no FROM general WHERE nation = %i AND killturn >= %i AND npc < 2',
$targetKillTurn $nation['nation'],
); $targetKillTurn
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong'], 2); );
$nationGenList = General::createGeneralObjListFromDB($nationGenIDList, ['belong', 'npc'], 2);
$uniqueLotteryWeightList = []; $chiefObj = null;
foreach ($nationGenList as $nationGen) {
$hasUnique = false; $uniqueLotteryWeightList = [];
foreach ($nationGen->getItems() as $item) { foreach ($nationGenList as $nationGen) {
if (!$item->isBuyable()) { if ($nationGen->getVar('officer_level') == 12) {
$hasUnique = true; $chiefObj = $nationGen;
break; }
} $trialCnt = count(GameConst::$allItems);
}
if ($hasUnique) { foreach ($nationGen->getItems() as $item) {
continue; if (!$item->isBuyable()) {
} $trialCnt -= 1;
}
$score = $nationGen->getVar('belong') + 5; }
if ($nationGen->getVar('officer_level') == 12) { if ($trialCnt <= 0) {
$score += 200; //NOTE: 꼬우면 군주하세요. continue;
} else if ($nationGen->getVar('officer_level') == 11) { }
$score += 70;
} else if ($nationGen->getVar('officer_level') > 4) { $score = $nationGen->getVar('belong') + 5;
$score += 35;
} if ($nationGen->getVar('officer_level') == 12) {
$uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score]; $score += 100; //NOTE: 꼬우면 군주하세요.
} } else if ($nationGen->getVar('officer_level') == 11) {
$score += 50;
foreach (Util::range($levelDiff) as $idx) { } else if ($nationGen->getVar('officer_level') > 4) {
if (!$uniqueLotteryWeightList) { $score += 35;
break; }
}
$score *= $trialCnt;
/** @var General */
$winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList); $uniqueLotteryWeightList[$nationGen->getID()] = [$nationGen, $score];
unset($uniqueLotteryWeightList[$winnerObj->getID()]); }
giveRandomUniqueItem($winnerObj, '작위보상');
$winnerObj->applyDB($db); foreach (Util::range($levelDiff) as $idx) {
} if (!$uniqueLotteryWeightList) {
} break;
} }
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0; /** @var General */
$maxAssemblerCnt = [ $winnerObj = Util::choiceRandomUsingWeightPair($uniqueLotteryWeightList);
1 => 0, unset($uniqueLotteryWeightList[$winnerObj->getID()]);
2 => 1, giveRandomUniqueItem($winnerObj, '작위보상');
3 => 3, $winnerObj->applyDB($db);
4 => 4, }
5 => 6,
6 => 7, if($chiefObj){
7 => 9 $chiefObj->increaseInheritancePoint('unifier', 250 * $levelDiff);
][$nationlevel] ?? 0; }
}
if ($assemblerCnt < $maxAssemblerCnt) { }
$lastAssemblerID = $gameStor->assembler_id ?? 0;
$assemblerCnt = $assemblerCnts[$nation['nation']] ?? 0;
while ($assemblerCnt < $maxAssemblerCnt) { $maxAssemblerCnt = [
$lastAssemblerID += 1; 1 => 0,
$npcObj = new Scenario\NPC( 2 => 1,
999, 3 => 3,
sprintf('부대장%4d', $lastAssemblerID), 4 => 4,
null, 5 => 6,
$nation['nation'], 6 => 7,
null, 7 => 9
10, ][$nationlevel] ?? 0;
10,
10, if ($assemblerCnt < $maxAssemblerCnt) {
1, $lastAssemblerID = $gameStor->assembler_id ?? 0;
$admin['year'] - 15,
$admin['year'] + 15, while ($assemblerCnt < $maxAssemblerCnt) {
'은둔', $lastAssemblerID += 1;
'척사' $npcObj = new Scenario\GeneralBuilder(
); sprintf('부대장%4d', $lastAssemblerID),
$npcObj->killturn = 70; 0,
$npcObj->gold = 0; null,
$npcObj->rice = 0; $nation['nation']
$npcObj->npc = 5; );
$npcObj->build($admin); $npcObj->setAffinity(999)->setStat(10, 10, 10)
$npcID = $npcObj->generalID; ->setSpecialSingle('척사')->setEgo('che_은둔')
->setKillturn(70)->setGoldRice(0, 0)
$db->insert('troop', [ ->setNPCType(5)->fillRemainSpecAsZero($admin);
'troop_leader' => $npcID, $npcObj->build($admin);
'name' => $npcObj->realName, $npcID = $npcObj->getGeneralID();
'nation' => $nation['nation'],
]); $db->insert('troop', [
$db->update('general', [ 'troop_leader' => $npcID,
'troop' => $npcID 'name' => $npcObj->getGeneralName(),
], 'no=%i', $npcID); 'nation' => $nation['nation'],
]);
$cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin); $db->update('general', [
_setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn))); 'troop' => $npcID
$assemblerCnt += 1; ], 'no=%i', $npcID);
$gameStor->assembler_id = $lastAssemblerID;
} $cmd = buildGeneralCommandClass('che_집합', General::createGeneralObjFromDB($npcID), $admin);
} _setGeneralCommand($cmd, iterator_to_array(Util::range(GameConst::$maxTurn)));
} $assemblerCnt += 1;
pushGlobalHistoryLog($history, $admin['year'], $admin['month']); $gameStor->assembler_id = $lastAssemblerID;
} }
}
function checkStatistic() }
{ pushGlobalHistoryLog($history, $admin['year'], $admin['month']);
$db = DB::db(); }
$gameStor = KVStorage::getStorage($db, 'game_env');
function checkStatistic()
$admin = $gameStor->getValues(['year', 'month']); {
$db = DB::db();
$nationHists = []; $gameStor = KVStorage::getStorage($db, 'game_env');
$specialHists = [];
$personalHists = []; $admin = $gameStor->getValues(['year', 'month']);
$specialHists2 = [];
$crewtypeHists = []; $nationHists = [];
$specialHists = [];
$etc = ''; $personalHists = [];
$specialHists2 = [];
$auxData = [ $crewtypeHists = [];
'generals' => [],
'nations' => [], $etc = '';
];
$auxData = [
$avgGeneral = $db->queryFirstRow( 'generals' => [],
'SELECT avg(gold) as avggold, avg(rice) as avgrice, avg(dex1+dex2+dex3+dex4) as avgdex, 'nations' => [],
max(dex1+dex2+dex3+dex4) as maxdex, avg(experience+dedication) as avgexpded, max(experience+dedication) as maxexpded ];
FROM general'
); $avgGeneral = $db->queryFirstRow(
$auxData['generals']['avg'] = $avgGeneral; 'SELECT avg(gold) as avggold, avg(rice) as avgrice, avg(dex1+dex2+dex3+dex4) as avgdex,
max(dex1+dex2+dex3+dex4) as maxdex, avg(experience+dedication) as avgexpded, max(experience+dedication) as maxexpded
$avgGeneral['avggold'] = Util::round($avgGeneral['avggold']); FROM general'
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']); );
$avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']); $auxData['generals']['avg'] = $avgGeneral;
$avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
$etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), "; $avgGeneral['avggold'] = Util::round($avgGeneral['avggold']);
$avgGeneral['avgrice'] = Util::round($avgGeneral['avgrice']);
$avgNation = $db->queryFirstRow( $avgGeneral['avgdex'] = Util::round($avgGeneral['avgdex']);
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech, $avgGeneral['avgexpded'] = Util::round($avgGeneral['avgexpded']);
min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0' $etc .= "평균 금/쌀 ({$avgGeneral['avggold']}/{$avgGeneral['avgrice']}), 평균/최고 숙련({$avgGeneral['avgdex']}/{$avgGeneral['maxdex']}), 평균/최고 경험공헌({$avgGeneral['avgexpded']}/{$avgGeneral['maxexpded']}), ";
);
$auxData['nations']['avg'] = $avgNation; $avgNation = $db->queryFirstRow(
'SELECT min(tech) as mintech, max(tech) as maxtech, avg(tech) as avgtech,
$avgNation['mintech'] = floor($avgNation['mintech']); min(power) as minpower, max(power) as maxpower, avg(power) as avgpower from nation where level>0'
$avgNation['maxtech'] = floor($avgNation['maxtech']); );
$avgNation['avgtech'] = Util::round($avgNation['avgtech']); $auxData['nations']['avg'] = $avgNation;
$avgNation['avgpower'] = Util::round($avgNation['avgpower']);
$etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), "; $avgNation['mintech'] = floor($avgNation['mintech']);
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), "; $avgNation['maxtech'] = floor($avgNation['maxtech']);
$avgNation['avgtech'] = Util::round($avgNation['avgtech']);
$nationName = ''; $avgNation['avgpower'] = Util::round($avgNation['avgpower']);
$powerHist = ''; $etc .= "최저/평균/최고 기술({$avgNation['mintech']}/{$avgNation['avgtech']}/{$avgNation['maxtech']}), ";
$etc .= "최저/평균/최고 국력({$avgNation['minpower']}/{$avgNation['avgpower']}/{$avgNation['maxpower']}), ";
$nations = Util::convertArrayToDict(
$db->query( $nationName = '';
'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc', $powerHist = '';
'nation'
), $nations = Util::convertArrayToDict(
'nation' $db->query(
); 'SELECT nation,name,type,power,gennum,gold+rice as goldrice from nation where level>0 order by power desc',
$nationCount = count($nations); 'nation'
),
$nationGeneralInfos = Util::convertArrayToDict( 'nation'
$db->query( );
'SELECT nation, sum(leadership+strength+intel) as abil,sum(gold+rice) as goldrice, $nationCount = count($nations);
sum(dex1+dex2+dex3+dex4) as dex,sum(experience+dedication) as expded
from general GROUP BY nation' $nationGeneralInfos = Util::convertArrayToDict(
), $db->query(
'nation' 'SELECT nation, sum(leadership+strength+intel) as abil,sum(gold+rice) as goldrice,
); sum(dex1+dex2+dex3+dex4) as dex,sum(experience+dedication) as expded
from general GROUP BY nation'
$nationCityInfos = Util::convertArrayToDict( ),
$db->query('SELECT nation, count(*) as cnt, sum(pop) as pop,sum(pop_max) as pop_max from city GROUP BY nation'), 'nation'
'nation' );
);
$nationCityInfos = Util::convertArrayToDict(
foreach ($nations as $nationNo => &$nation) { $db->query('SELECT nation, count(*) as cnt, sum(pop) as pop,sum(pop_max) as pop_max from city GROUP BY nation'),
$general = $nationGeneralInfos[$nationNo]; 'nation'
$city = $nationCityInfos[$nationNo]; );
$nation['generalInfo'] = $general; foreach ($nations as $nationNo => &$nation) {
$nation['cityInfo'] = $city; $general = $nationGeneralInfos[$nationNo];
$city = $nationCityInfos[$nationNo];
$nationName .= $nation['name'] . '(' . getNationType($nation['type']) . '), ';
$powerHist .= "{$nation['name']}({$nation['power']}/{$nation['gennum']}/{$city['cnt']}/{$city['pop']}/{$city['pop_max']}/{$nation['goldrice']}/{$general['goldrice']}/{$general['abil']}/{$general['dex']}/{$general['expded']}), "; $nation['generalInfo'] = $general;
$nation['cityInfo'] = $city;
if (!isset($nationHists[$nation['type']])) {
$nationHists[$nation['type']] = 0; $nationName .= $nation['name'] . '(' . getNationType($nation['type']) . '), ';
} $powerHist .= "{$nation['name']}({$nation['power']}/{$nation['gennum']}/{$city['cnt']}/{$city['pop']}/{$city['pop_max']}/{$nation['goldrice']}/{$general['goldrice']}/{$general['abil']}/{$general['dex']}/{$general['expded']}), ";
$nationHists[$nation['type']]++;
} if (!isset($nationHists[$nation['type']])) {
unset($nation); $nationHists[$nation['type']] = 0;
}
$auxData['nations']['all'] = $nations; $nationHists[$nation['type']]++;
}
$nationHist = ''; unset($nation);
foreach (GameConst::$availableNationType as $nationType) {
if (!Util::array_get($nationHists[$nationType])) { $auxData['nations']['all'] = $nations;
$nationHists[$nationType] = '-';
} $nationHist = '';
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), "; foreach (GameConst::$availableNationType as $nationType) {
} if (!Util::array_get($nationHists[$nationType])) {
$nationHists[$nationType] = '-';
$generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general'); }
$nationHist .= getNationType($nationType) . "({$nationHists[$nationType]}), ";
$genCount = 0; }
$npcCount = 0;
$generalCount = count($generals); $generals = $db->query('SELECT `no`,npc,personal,special,special2,crewtype FROM general');
foreach ($generals as $general) { $genCount = 0;
if (!isset($personalHists[$general['personal']])) { $npcCount = 0;
$personalHists[$general['personal']] = 0; $generalCount = count($generals);
}
foreach ($generals as $general) {
if (!isset($specialHists[$general['special']])) { if (!isset($personalHists[$general['personal']])) {
$specialHists[$general['special']] = 0; $personalHists[$general['personal']] = 0;
} }
if (!isset($specialHists2[$general['special2']])) { if (!isset($specialHists[$general['special']])) {
$specialHists2[$general['special2']] = 0; $specialHists[$general['special']] = 0;
} }
if ($general['npc'] < 2) { if (!isset($specialHists2[$general['special2']])) {
$genCount += 1; $specialHists2[$general['special2']] = 0;
} else { }
$npcCount += 1;
} if ($general['npc'] < 2) {
$genCount += 1;
$personalHists[$general['personal']]++; } else {
$specialHists[$general['special']]++; $npcCount += 1;
$specialHists2[$general['special2']]++; }
}
$personalHists[$general['personal']]++;
foreach ($db->queryAllLists( $specialHists[$general['special']]++;
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype' $specialHists2[$general['special2']]++;
) as [$crewtype, $cnt]) { }
$crewtypeHists[$crewtype] = $cnt;
} foreach ($db->queryAllLists(
'SELECT crewtype, count(crewtype) AS cnt FROM general WHERE recent_war != NULL GROUP BY crewtype'
$auxData['generals']['hists'] = [ ) as [$crewtype, $cnt]) {
'personal' => $personalHists, $crewtypeHists[$crewtype] = $cnt;
'special' => $specialHists, }
'special2' => $specialHists2,
'crewtype' => $crewtypeHists, $auxData['generals']['hists'] = [
'userCnt' => $genCount, 'personal' => $personalHists,
'npcCnt' => $npcCount, 'special' => $specialHists,
]; 'special2' => $specialHists2,
'crewtype' => $crewtypeHists,
$generalCountStr = "{$generalCount}({$genCount}+{$npcCount})"; 'userCnt' => $genCount,
'npcCnt' => $npcCount,
$personalHistStr = join(', ', array_map(function ($histPair) { ];
[$histKey, $cnt] = $histPair;
return getGenChar($histKey) . '(' . $cnt . ')'; $generalCountStr = "{$generalCount}({$genCount}+{$npcCount})";
}, Util::convertDictToArray($personalHists)));
$personalHistStr = join(', ', array_map(function ($histPair) {
$specialHistsStr = join(', ', array_map(function ($histPair) { [$histKey, $cnt] = $histPair;
[$histKey, $cnt] = $histPair; return getGenChar($histKey) . '(' . $cnt . ')';
return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')'; }, Util::convertDictToArray($personalHists)));
}, Util::convertDictToArray($specialHists)));
$specialHistsStr = join(', ', array_map(function ($histPair) {
$specialHists2Str = join(', ', array_map(function ($histPair) { [$histKey, $cnt] = $histPair;
[$histKey, $cnt] = $histPair; return getGeneralSpecialDomesticName($histKey) . '(' . $cnt . ')';
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')'; }, Util::convertDictToArray($specialHists)));
}, Util::convertDictToArray($specialHists2)));
$specialHists2Str = join(', ', array_map(function ($histPair) {
$specialHistsAllStr = "$specialHistsStr // $specialHists2Str"; [$histKey, $cnt] = $histPair;
return getGeneralSpecialWarName($histKey) . '(' . $cnt . ')';
$crewtypeHistsStr = join(', ', array_map(function ($histPair) { }, Util::convertDictToArray($specialHists2)));
[$histKey, $cnt] = $histPair;
return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')'; $specialHistsAllStr = "$specialHistsStr // $specialHists2Str";
}, Util::convertDictToArray($crewtypeHists)));
$crewtypeHistsStr = join(', ', array_map(function ($histPair) {
$db->insert('statistic', [ [$histKey, $cnt] = $histPair;
'year' => $admin['year'], return GameUnitConst::byID($histKey)->getShortName() . '(' . $cnt . ')';
'month' => $admin['month'], }, Util::convertDictToArray($crewtypeHists)));
'nation_count' => $nationCount,
'nation_name' => $nationName, $db->insert('statistic', [
'nation_hist' => $nationHist, 'year' => $admin['year'],
'gen_count' => $generalCountStr, 'month' => $admin['month'],
'personal_hist' => $personalHistStr, 'nation_count' => $nationCount,
'special_hist' => $specialHistsAllStr, 'nation_name' => $nationName,
'power_hist' => $powerHist, 'nation_hist' => $nationHist,
'crewtype' => $crewtypeHistsStr, 'gen_count' => $generalCountStr,
'etc' => $etc, 'personal_hist' => $personalHistStr,
'aux' => Json::encode($auxData) 'special_hist' => $specialHistsAllStr,
]); 'power_hist' => $powerHist,
} 'crewtype' => $crewtypeHistsStr,
'etc' => $etc,
'aux' => Json::encode($auxData)
function convForOldGeneral(array $general, int $year, int $month) ]);
{ }
$general['history'] = getGeneralHistoryLogAll($general['no']);
return [
'server_id' => UniqueConst::$serverID, function convForOldGeneral(array $general, int $year, int $month)
'general_no' => $general['no'], {
'owner' => $general['owner'], $general['history'] = getGeneralHistoryLogAll($general['no']);
'name' => $general['name'], return [
'last_yearmonth' => $year * 100 + $month, 'server_id' => UniqueConst::$serverID,
'turntime' => $general['turntime'], 'general_no' => $general['no'],
'data' => Json::encode($general) 'owner' => $general['owner'],
]; 'name' => $general['name'],
} 'last_yearmonth' => $year * 100 + $month,
'turntime' => $general['turntime'],
function storeOldGeneral(int $no, int $year, int $month) 'data' => Json::encode($general)
{ ];
$db = DB::db(); }
$general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
if (!$general) { function storeOldGeneral(int $no, int $year, int $month)
return; {
} $db = DB::db();
$data = convForOldGeneral($general, $year, $month); $general = $db->queryFirstRow('SELECT * FROM general WHERE `no` = %i', $no);
$db->insertUpdate( if (!$general) {
'ng_old_generals', return;
$data, }
$data $data = convForOldGeneral($general, $year, $month);
); $db->insertUpdate(
} 'ng_old_generals',
$data,
function storeOldGenerals(int $nation, int $year, int $month) $data
{ );
$db = DB::db(); }
foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
$data = convForOldGeneral($general, $year, $month); function storeOldGenerals(int $nation, int $year, int $month)
$db->insertUpdate( {
'ng_old_generals', $db = DB::db();
$data, foreach ($db->query('SELECT * FROM general WHERE nation = %i', $nation) as $general) {
$data $data = convForOldGeneral($general, $year, $month);
); $db->insertUpdate(
} 'ng_old_generals',
} $data,
$data
function checkEmperior() );
{ }
$db = DB::db(); }
$gameStor = KVStorage::getStorage($db, 'game_env');
function checkEmperior()
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']); {
if ($admin['isunited'] != 0) { $db = DB::db();
return; $gameStor = KVStorage::getStorage($db, 'game_env');
}
$admin = $gameStor->getValues(['year', 'month', 'isunited', 'conlimit']);
$remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2'); if ($admin['isunited'] != 0) {
return;
if (!$remainNations || count($remainNations) != 1) { }
return;
} $remainNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0 LIMIT 2');
$nationID = $remainNations[0]; if (!$remainNations || count($remainNations) != 1) {
return;
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); }
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID); $nationID = $remainNations[0];
if (!$cityCnt) {
return; $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
}
$cityCnt = $db->queryFirstField('SELECT count(city) FROM city WHERE nation=%i', $nationID);
if ($cityCnt != count(CityConst::all())) { if (!$cityCnt) {
return; return;
} }
checkStatistic(); if ($cityCnt != count(CityConst::all())) {
return;
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID); }
$nationName = $nation['name'];
checkStatistic();
$josaYi = JosaUtil::pick($nationName, '이');
$nation = $db->queryFirstRow('SELECT * FROM nation WHERE nation=%i', $nationID);
$nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']); $nationName = $nation['name'];
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
$josaYi = JosaUtil::pick($nationName, '이');
$gameStor->isunited = 2;
$gameStor->conlimit = $gameStor->conlimit * 100; $nationLogger = new ActionLogger(0, $nationID, $admin['year'], $admin['month']);
$nationLogger->pushNationalHistoryLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일");
foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
CheckHall($hallGeneralNo); foreach(General::createGeneralObjListFromDB($db->queryFirstColumn('SELECT `no` FROM general WHERE npc = 0')) as $genObj){
} if($genObj->getNationID() == $nationID){
if($genObj->getVar('officer_level') > 4){
[$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city'); $genObj->increaseInheritancePoint('unifier', 2000);
$pop = "{$totalPop} / {$totalMaxPop}"; };
$poprate = round($totalPop / $totalMaxPop * 100, 2). " %"; }
$genObj->mergeTotalInheritancePoint();
$chiefs = Util::convertArrayToDict( }
$db->query(
'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5', $gameStor->isunited = 2;
$nationID $gameStor->conlimit = $gameStor->conlimit * 100;
),
'officer_level' foreach ($db->queryFirstColumn('SELECT no FROM general WHERE npc<2 AND age>=%i', GameConst::$minPushHallAge) as $hallGeneralNo) {
); CheckHall($hallGeneralNo);
}
$nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID);
$nation['generals'] = $nationGenerals; [$totalPop, $totalMaxPop] = $db->queryFirstList('SELECT SUM(pop), SUM(pop_max) FROM city');
$pop = "{$totalPop} / {$totalMaxPop}";
$tigers = $db->query( $poprate = round($totalPop / $totalMaxPop * 100, 2). " %";
'SELECT value, name
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no $chiefs = Util::convertArrayToDict(
WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5', $db->query(
$nationID 'SELECT no,name,picture,belong,officer_level FROM general WHERE nation=%i AND officer_level >= 5',
); // 오호장군 $nationID
),
$tigerstr = join(', ', array_map(function ($arr) { 'officer_level'
$number = number_format($arr['value']); );
return "{$arr['name']}{$number}";
}, $tigers)); $nationGenerals = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nationID);
$nation['generals'] = $nationGenerals;
$eagles = $db->query(
'SELECT value, name $tigers = $db->query(
FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no 'SELECT value, name
WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7', FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
$nationID WHERE rank_data.nation_id = %i AND rank_data.type = "killnum" AND value > 0 ORDER BY value DESC LIMIT 5',
); // 건안칠자 $nationID
); // 오호장군
$eaglestr = join(', ', array_map(function ($arr) {
$number = number_format($arr['value']); $tigerstr = join(', ', array_map(function ($arr) {
return "{$arr['name']}{$number}"; $number = number_format($arr['value']);
}, $eagles)); return "{$arr['name']}{$number}";
}, $tigers));
$rawGeneralList = $db->query('SELECT no, name, npc, owner FROM general WHERE nation=%i ORDER BY dedication DESC', $nationID);
foreach ($rawGeneralList as $rawGeneral) { $eagles = $db->query(
$generalLogger = new ActionLogger($rawGeneral['no'], $nationID, $admin['year'], $admin['month']); 'SELECT value, name
$generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH); FROM rank_data LEFT JOIN general ON rank_data.general_id = general.no
$generalLogger->flush(); WHERE rank_data.nation_id = %i AND rank_data.type = "firenum" AND value > 0 ORDER BY value DESC LIMIT 7',
} $nationID
); // 건안칠자
$gen = join(', ', array_column($rawGeneral, 'name'));
$eaglestr = join(', ', array_map(function ($arr) {
$stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic'); $number = number_format($arr['value']);
$genCnt = $db->queryFirstField('SELECT count(*) FROM general'); return "{$arr['name']}{$number}";
}, $eagles));
$statNC = "1 / {$stat['nc']}";
$statGC = "{$genCnt} / {$stat['gc']}"; $rawGeneralList = $db->query('SELECT no, name, npc, owner FROM general WHERE nation=%i ORDER BY dedication DESC', $nationID);
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']); foreach ($rawGeneralList as $rawGeneral) {
$statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1'); $generalLogger = new ActionLogger($rawGeneral['no'], $nationID, $admin['year'], $admin['month']);
$generalLogger->pushGeneralActionLog("<D><b>{$nationName}</b></>{$josaYi} 전토를 통일하였습니다.", ActionLogger::YEAR_MONTH);
$nation = $nation; $generalLogger->flush();
$nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']); }
$nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->notice; $gen = join(', ', array_column($rawGeneral, 'name'));
$nation['scout_msg'] = $nationStor->scout_msg;
$nation['aux'] += $nationStor->max_power; $stat = $db->queryFirstRow('SELECT max(nation_count) as nc, max(gen_count) as gc FROM statistic');
$nation['history'] = getNationHistoryLogAll($nation['nation']); $genCnt = $db->queryFirstField('SELECT count(*) FROM general');
storeOldGenerals(0, $admin['year'], $admin['month']); $statNC = "1 / {$stat['nc']}";
storeOldGenerals($nation['nation'], $admin['year'], $admin['month']); $statGC = "{$genCnt} / {$stat['gc']}";
$statNation = $db->queryFirstRow('SELECT nation_count,nation_name,nation_hist from statistic where nation_count=%i LIMIT 1', $stat['nc']);
$db->insert('ng_old_nations', [ $statGeneral = $db->queryFirstRow('SELECT gen_count,personal_hist,special_hist,aux from statistic order by no desc LIMIT 1');
'server_id' => UniqueConst::$serverID,
'nation' => $nation['nation'], $nation = $nation;
'data' => Json::encode($nation) $nation['generals'] = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=%i', $nation['nation']);
]); $nation['aux'] = Json::decode($nation['aux']);
$nation['msg'] = $nationStor->notice;
$noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0'); $nation['scout_msg'] = $nationStor->scout_msg;
$db->insert('ng_old_nations', [ $nation['aux'] += $nationStor->max_power;
'server_id' => UniqueConst::$serverID, $nation['history'] = getNationHistoryLogAll($nation['nation']);
'nation' => 0,
'data' => Json::encode([ storeOldGenerals(0, $admin['year'], $admin['month']);
'nation' => 0, storeOldGenerals($nation['nation'], $admin['year'], $admin['month']);
'name' => '재야',
'generals' => $noNationGeneral $db->insert('ng_old_nations', [
]) 'server_id' => UniqueConst::$serverID,
]); 'nation' => $nation['nation'],
'data' => Json::encode($nation)
$nationHistory = getNationHistoryLogAll($nation['nation']); ]);
$serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games'); $noNationGeneral = $db->queryFirstColumn('SELECT `no` FROM general WHERE nation=0');
$serverName = UniqueConst::$serverName; $db->insert('ng_old_nations', [
'server_id' => UniqueConst::$serverID,
$db->update('ng_games', [ 'nation' => 0,
'winner_nation' => $nation['nation'] 'data' => Json::encode([
], 'server_id=%s', UniqueConst::$serverID); 'nation' => 0,
'name' => '재야',
$db->insert('emperior', [ 'generals' => $noNationGeneral
'phase' => $serverName . $serverCnt . '기', ])
'server_id' => UniqueConst::$serverID, ]);
'nation_count' => $statNC,
'nation_name' => $statNation['nation_name'], $nationHistory = getNationHistoryLogAll($nation['nation']);
'nation_hist' => $statNation['nation_hist'],
'gen_count' => $statGC, $serverCnt = $db->queryFirstField('SELECT count(*) FROM ng_games');
'personal_hist' => $statGeneral['personal_hist'], $serverName = UniqueConst::$serverName;
'special_hist' => $statGeneral['special_hist'],
'name' => $nation['name'], $db->update('ng_games', [
'type' => $nation['type'], 'winner_nation' => $nation['nation']
'color' => $nation['color'], ], 'server_id=%s', UniqueConst::$serverID);
'year' => $admin['year'],
'month' => $admin['month'], $db->insert('emperior', [
'power' => $nation['power'], 'phase' => $serverName . $serverCnt . '기',
'gennum' => $nation['gennum'], 'server_id' => UniqueConst::$serverID,
'citynum' => $cityCnt, 'nation_count' => $statNC,
'pop' => $pop, 'nation_name' => $statNation['nation_name'],
'poprate' => $poprate, 'nation_hist' => $statNation['nation_hist'],
'gold' => $nation['gold'], 'gen_count' => $statGC,
'rice' => $nation['rice'], 'personal_hist' => $statGeneral['personal_hist'],
'l12name' => $chiefs[12]['name'], 'special_hist' => $statGeneral['special_hist'],
'l12pic' => $chiefs[12]['picture'], 'name' => $nation['name'],
'l11name' => $chiefs[11]['name'], 'type' => $nation['type'],
'l11pic' => $chiefs[11]['picture'], 'color' => $nation['color'],
'l10name' => $chiefs[10]['name'], 'year' => $admin['year'],
'l10pic' => $chiefs[10]['picture'], 'month' => $admin['month'],
'l9name' => $chiefs[9]['name'], 'power' => $nation['power'],
'l9pic' => $chiefs[9]['picture'], 'gennum' => $nation['gennum'],
'l8name' => $chiefs[8]['name'], 'citynum' => $cityCnt,
'l8pic' => $chiefs[8]['picture'], 'pop' => $pop,
'l7name' => $chiefs[7]['name'], 'poprate' => $poprate,
'l7pic' => $chiefs[7]['picture'], 'gold' => $nation['gold'],
'l6name' => $chiefs[6]['name'], 'rice' => $nation['rice'],
'l6pic' => $chiefs[6]['picture'], 'l12name' => $chiefs[12]['name'],
'l5name' => $chiefs[5]['name'], 'l12pic' => $chiefs[12]['picture'],
'l5pic' => $chiefs[5]['picture'], 'l11name' => $chiefs[11]['name'],
'tiger' => $tigerstr, 'l11pic' => $chiefs[11]['picture'],
'eagle' => $eaglestr, 'l10name' => $chiefs[10]['name'],
'gen' => $gen, 'l10pic' => $chiefs[10]['picture'],
'history' => JSON::encode($nationHistory), 'l9name' => $chiefs[9]['name'],
'aux' => $statGeneral['aux'] 'l9pic' => $chiefs[9]['picture'],
]); 'l8name' => $chiefs[8]['name'],
'l8pic' => $chiefs[8]['picture'],
$history = ["<C>●</>{$admin['year']}{$admin['month']}월:<Y><b>【통일】</b></><D><b>{$nation['name']}</b></>{$josaYi} 전토를 통일하였습니다."]; 'l7name' => $chiefs[7]['name'],
pushGlobalHistoryLog($history, $admin['year'], $admin['month']); 'l7pic' => $chiefs[7]['picture'],
'l6name' => $chiefs[6]['name'],
//연감 월결산 'l6pic' => $chiefs[6]['picture'],
LogHistory(); '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){
$inheritStor = KVStorage::getStorage(DB::db(), "inheritance_{$userID}");
$totalPoint = 0;
foreach($inheritStor->getAll() as [$value,]){
$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);
}
}
+274 -270
View File
@@ -1,270 +1,274 @@
<?php <?php
namespace sammo; namespace sammo;
/** /**
* 템플릿 생성과 관련된 함수들을 모아두는 파일 * 템플릿 생성과 관련된 함수들을 모아두는 파일
* *
* NOTE: 아직 converter와 명확한 구분이 되어있지 않음. * NOTE: 아직 converter와 명확한 구분이 되어있지 않음.
* TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음 * TODO: legacy template들을 전부 template 폴더로 모아둘 필요 있음
* TODO: side effect를 제거 * TODO: side effect를 제거
*/ */
/** /**
* 관리자 권한이 필요함을 출력. * 관리자 권한이 필요함을 출력.
* @return void * @return void
*/ */
function requireAdminPermissionHTML() function requireAdminPermissionHTML()
{ {
ob_start(); ob_start();
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>관리메뉴</title> <title>관리메뉴</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1024" /> <meta name="viewport" content="width=1024" />
<?= WebUtil::printCSS('../d_shared/common.css') ?> <?= WebUtil::printCSS('../d_shared/common.css') ?>
<?= WebUtil::printCSS('css/common.css') ?> <?= WebUtil::printCSS('css/common.css') ?>
</head> </head>
<body> <body>
관리자가 아닙니다.<br> 관리자가 아닙니다.<br>
<?= banner() ?> <?= banner() ?>
</body> </body>
</html> </html>
<?php <?php
return ob_get_clean(); return ob_get_clean();
} }
function turnTable() function turnTable()
{ {
$turnList = []; $turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>"; $turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) { foreach (Util::range(1, GameConst::$maxTurn) as $turnIdx) {
$turnText = $turnIdx + 1; $turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>"; $turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
} }
$turnText = join("\n", $turnList); $turnText = join("\n", $turnList);
return " return "
<select id='generalTurnSelector' name=turn[] size=11 multiple> <select id='generalTurnSelector' name=turn[] size=11 multiple>
<option value='-3'>전체</option> <option value='-3'>전체</option>
<option value='-1'>홀턴</option> <option value='-1'>홀턴</option>
<option value='-2'>짝턴</option> <option value='-2'>짝턴</option>
{$turnText} {$turnText}
</select> </select>
"; ";
} }
function chiefTurnTable() function chiefTurnTable()
{ {
$turnList = []; $turnList = [];
$turnList[] = "<option selected value='0'>1턴</option>"; $turnList[] = "<option selected value='0'>1턴</option>";
foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) { foreach (Util::range(1, GameConst::$maxChiefTurn) as $turnIdx) {
$turnText = $turnIdx + 1; $turnText = $turnIdx + 1;
$turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>"; $turnList[] = "<option value='{$turnIdx}'>{$turnText}턴</option>";
} }
$turnText = join("\n", $turnList); $turnText = join("\n", $turnList);
return " return "
<select id='chiefTurnSelector' name=turn[] size=6 multiple> <select id='chiefTurnSelector' name=turn[] size=6 multiple>
{$turnText} {$turnText}
</select> </select>
"; ";
} }
function displayiActionObjInfo(?iAction $action) function displayiActionObjInfo(?iAction $action)
{ {
if ($action === null) { if ($action === null) {
$info = ''; $info = '';
$text = '-'; $text = '-';
} else { } else {
$info = $action->getInfo(); $info = $action->getInfo();
$text = $action->getName(); $text = $action->getName();
} }
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $text, 'text' => $text,
'info' => $info, 'info' => $info,
]); ]);
} }
function displayCharInfo(string $type): string function displayCharInfo(string $type): string
{ {
$class = buildPersonalityClass($type); $class = buildPersonalityClass($type);
$info = $class->getInfo(); $info = $class->getInfo();
$text = $class->getName(); $text = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $text, 'text' => $text,
'info' => $info, 'info' => $info,
]); ]);
} }
function displaySpecialWarInfo(?string $type): string function displaySpecialWarInfo(?string $type): string
{ {
$class = buildGeneralSpecialWarClass($type); $class = buildGeneralSpecialWarClass($type);
$info = $class->getInfo(); $info = $class->getInfo();
$name = $class->getName(); $name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $name, 'text' => $name,
'info' => $info, 'info' => $info,
]); ]);
} }
function displaySpecialDomesticInfo(?string $type): string function displaySpecialDomesticInfo(?string $type): string
{ {
$class = buildGeneralSpecialDomesticClass($type); $class = buildGeneralSpecialDomesticClass($type);
$info = $class->getInfo(); $info = $class->getInfo();
$name = $class->getName(); $name = $class->getName();
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('tooltip', [ return $templates->render('tooltip', [
'text' => $name, 'text' => $name,
'info' => $info, 'info' => $info,
]); ]);
} }
function allButton(bool $seizeNPCMode) function allButton(bool $seizeNPCMode)
{ {
if ($seizeNPCMode) { if ($seizeNPCMode) {
$site = "a_npcList.php"; $site = "a_npcList.php";
$call = "빙의일람"; $call = "빙의일람";
} else { } else {
$site = "a_vote.php"; $site = "a_vote.php";
$call = "설문조사"; $call = "설문조사";
} }
if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) { if (\file_exists(__DIR__ . "/d_setting/templates/allButton.php")) {
$templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/d_setting/templates');
} else { } else {
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
} }
return $templates->render('allButton', [ return $templates->render('allButton', [
'call' => $call, 'call' => $call,
'site' => $site 'site' => $site
]); ]);
} }
function commandButton() function commandButton()
{ {
$session = Session::getInstance(); $session = Session::getInstance();
$userID = Session::getUserID(); $userID = Session::getUserID();
if (!$session->isGameLoggedIn()) { if (!$session->isGameLoggedIn()) {
return ''; return '';
} }
$db = DB::db(); $db = DB::db();
$me = $db->queryFirstRow("select no,nation,officer_level,belong,permission,penalty from general where owner=%i", $userID); $me = $db->queryFirstRow("select no,nation,officer_level,belong,permission,penalty from general where owner=%i", $userID);
$nation = $db->queryFirstRow("select nation,level,color,secretlimit from nation where nation=%i", $me['nation']) ?? [ $nation = $db->queryFirstRow("select nation,level,color,secretlimit from nation where nation=%i", $me['nation']) ?? [
'nation' => 0, 'nation' => 0,
'level' => 0, 'level' => 0,
'secretlimit' => 99, 'secretlimit' => 99,
'color' => '#000000' 'color' => '#000000'
]; ];
$bgColor = Util::array_get($nation['color']) ?: '#000000'; $bgColor = Util::array_get($nation['color']) ?: '#000000';
$fgColor = newColor($bgColor); $fgColor = newColor($bgColor);
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
$showSecret = false; $showSecret = false;
$permission = checkSecretPermission($me); $permission = checkSecretPermission($me);
if ($permission >= 1) { if ($permission >= 1) {
$showSecret = true; $showSecret = true;
} else if ($me['officer_level'] == 0) { } else if ($me['officer_level'] == 0) {
$showSecret = false; $showSecret = false;
} }
return $templates->render('commandButton', [ return $templates->render('commandButton', [
'bgColor' => $bgColor, 'bgColor' => $bgColor,
'fgColor' => $fgColor, 'fgColor' => $fgColor,
'meLevel' => $me['officer_level'], 'meLevel' => $me['officer_level'],
'nationLevel' => $nation['level'], 'nationLevel' => $nation['level'],
'showSecret' => $showSecret, 'showSecret' => $showSecret,
'permission' => $permission, 'permission' => $permission,
]); ]);
} }
function formatWounded(int $value, int $wound): string function formatWounded(int $value, int $wound): string
{ {
if ($wound == 0) { if ($wound == 0) {
return "$value"; return "$value";
} }
$woundedValue = intdiv($value * (100 - $wound), 100); $woundedValue = intdiv($value * (100 - $wound), 100);
return "<font color=red>$woundedValue</font>"; return "<font color=red>$woundedValue</font>";
} }
function formatDefenceTrain(int $value): string function formatDefenceTrain(int $value): string
{ {
if ($value === 999) { if ($value === 999) {
return "×"; return "×";
} else if ($value >= 80) { } else if ($value >= 90){
return ""; return "";
} else { } else if ($value >= 80) {
return ""; return "";
} } else if ($value >= 60) {
} return "○";
} else{
function formatLeadershipBonus(int $value): string return "△";
{ }
if ($value == 0) { }
return '';
} function formatLeadershipBonus(int $value): string
return "<font color=cyan>+{$value}</font>"; {
} if ($value == 0) {
return '';
function formatName(string $name, int $npc): string }
{ return "<font color=cyan>+{$value}</font>";
if ($npc == 1) { }
$name = "<font color='skyblue'>$name</font>";
} else if ($npc > 1) { function formatName(string $name, int $npc): string
$name = "<font color='cyan'>$name</font>"; {
} if ($npc == 1) {
return $name; $name = "<font color='skyblue'>$name</font>";
} } else if ($npc > 1) {
$name = "<font color='cyan'>$name</font>";
function getMapHtml(?string $mapTheme = null) }
{ return $name;
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); }
if ($mapTheme === null) { function getMapHtml(?string $mapTheme = null)
$db = DB::db(); {
$gameStor = KVStorage::getStorage($db, 'game_env'); $templates = new \League\Plates\Engine(__DIR__ . '/templates');
$mapTheme = $gameStor->map_theme ?? 'che';
} if ($mapTheme === null) {
$db = DB::db();
return $templates->render('map', [ $gameStor = KVStorage::getStorage($db, 'game_env');
'mapTheme' => $mapTheme $mapTheme = $gameStor->map_theme ?? 'che';
]); }
}
return $templates->render('map', [
function getInvitationList(array $nationList) 'mapTheme' => $mapTheme
{ ]);
$templates = new \League\Plates\Engine(__DIR__ . '/templates'); }
foreach ($nationList as &$nation) { function getInvitationList(array $nationList)
$nation['textColor'] = newColor($nation['color']); {
} $templates = new \League\Plates\Engine(__DIR__ . '/templates');
return $templates->render('invitationList', [
'nationList' => $nationList foreach ($nationList as &$nation) {
]); $nation['textColor'] = newColor($nation['color']);
} }
return $templates->render('invitationList', [
'nationList' => $nationList
]);
}
+12 -7
View File
@@ -523,7 +523,7 @@ function selection($tnmt_type, $tnmt, $phase) {
if($phase < 31) { if($phase < 31) {
$gameStor->phase+=1; $gameStor->phase+=1;
} else { } else {
$gameStor->tournamemt = 4; $gameStor->tournament = 4;
$gameStor->phase=0; $gameStor->phase=0;
} }
} }
@@ -689,7 +689,8 @@ function setGift($tnmt_type, $tnmt, $phase) {
'grp_no'=>$general['grp_no'], 'grp_no'=>$general['grp_no'],
'reward'=>$cost, 'reward'=>$cost,
'msg'=>"<span class='ev_highlight'>16강 진출</span>", 'msg'=>"<span class='ev_highlight'>16강 진출</span>",
'logger'=>$logger 'logger'=>$logger,
'inheritance_point'=>10,
]; ];
} }
//8강자 명성 돈 //8강자 명성 돈
@@ -723,6 +724,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
//포상 장수 이름, 금액 //포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost; $resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>"; $resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>4강 진출</span>";
General::createGeneralObjFromDB($generalID)->increaseInheritancePoint('tournament', 10);
} }
//결승자 명성 돈 //결승자 명성 돈
$cost = $admin['develcost'] * 6; $cost = $admin['develcost'] * 6;
@@ -739,6 +741,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
//포상 장수 이름, 금액 //포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost; $resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>준우승</span>으"; $resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>준우승</span>으";
$resultHelper[$generalID]['inheritance_point'] = 50;
if($general['lose'] > 0){ if($general['lose'] > 0){
$runnerUp = $general; $runnerUp = $general;
} }
@@ -761,6 +764,7 @@ function setGift($tnmt_type, $tnmt, $phase) {
//포상 장수 이름, 금액 //포상 장수 이름, 금액
$resultHelper[$generalID]['reward'] += $cost; $resultHelper[$generalID]['reward'] += $cost;
$resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>우승</span>으"; $resultHelper[$generalID]['msg'] = "<span class='ev_highlight'>우승</span>으";
$resultHelper[$generalID]['inheritance_point'] = 100;
$winner = $general; $winner = $general;
} }
@@ -775,9 +779,6 @@ function setGift($tnmt_type, $tnmt, $phase) {
$runnerUpLogger = $resultHelper[$runnerUp['no']]['logger']; $runnerUpLogger = $resultHelper[$runnerUp['no']]['logger'];
$runnerUpLogger->pushGeneralHistoryLog("<C>{$tp}</> 대회에서 준우승"); $runnerUpLogger->pushGeneralHistoryLog("<C>{$tp}</> 대회에서 준우승");
$winnerRewardText = number_format($resultHelper[$winner['no']]['reward']); $winnerRewardText = number_format($resultHelper[$winner['no']]['reward']);
$runnerUpRewardText = number_format($resultHelper[$runnerUp['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}</> 대회에서 <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); $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']); $rewardText = number_format($general['reward']);
/** @var ActionLogger */ /** @var ActionLogger */
$logger = $general['logger']; $logger = $general['logger'];
$logger->pushGeneralActionLog("<C>{$tp}</> 대회의 {$general['msg']}로 <C>{$rewardText}</>의 <S>상금</>, 약간의 <S>명성</> 획득!", ActionLogger::EVENT_PLAIN); $logger->pushGeneralActionLog("<C>{$tp}</> 대회의 {$general['msg']}로 <C>{$rewardText}</>의 <S>상금</>, 약간의 <S>명성</> 획득!", ActionLogger::EVENT_PLAIN);
//TODO: 토너먼트의 다른 값이 모두 sql에 직접 입력하므로 기반을 바꿔야함.
$generalObjList[$generalID]->increaseInheritancePoint('tournament', $general['inheritance_point']);
} }
//우승자 번호 //우승자 번호
+7 -5
View File
@@ -61,7 +61,7 @@ $scenario = $gameStor->scenario_text;
$nationID = $generalObj->getNationID(); $nationID = $generalObj->getNationID();
if($nationID){ if($nationID){
$nationStor = KVStorage::getStorage($db, $nationID, 'nation_env'); $nationStor = KVStorage::getStorage($db, $nationID, 'nation_env');
$nationStor->cacheValues(['notice', 'online_genenerals']); $nationStor->cacheAll();
} }
$valid = 0; $valid = 0;
@@ -79,9 +79,11 @@ if ($gameStor->fiction == 0) {
} }
if ($gameStor->npcmode == 0) { if ($gameStor->npcmode == 0) {
$npcmode = "불가능"; $npcmode = "불가능";
} else { } else if($gameStor->npcmode == 1){
$npcmode = "가능"; $npcmode = "가능";
$valid = 1; $valid = 1;
} else {
$npcmode = "선택 생성";
} }
$color = "cyan"; $color = "cyan";
$mapTheme = $gameStor->map_theme; $mapTheme = $gameStor->map_theme;
@@ -134,7 +136,7 @@ $(function(){
<body class="img_back"> <body class="img_back">
<div id="container"> <div id="container">
<div><?=allButton($gameStor->npcmode!=0)?></div> <div><?=allButton($gameStor->npcmode==1)?></div>
<table class="tb_layout bg0" style="width:1000px;"> <table class="tb_layout bg0" style="width:1000px;">
<tr height=50> <tr height=50>
<td colspan=5 id="server_title" align=center><font size=4>삼국지 모의전투 HiDCHe <?=$serverName.$serverCnt?>기 (<font color=cyan><?=$scenario?></font>)</font></td> <td colspan=5 id="server_title" align=center><font size=4>삼국지 모의전투 HiDCHe <?=$serverName.$serverCnt?>기 (<font color=cyan><?=$scenario?></font>)</font></td>
@@ -341,7 +343,7 @@ else if($session->userGrade == 4){
<button id="msg_submit">서신전달&amp;갱신</button><br> <button id="msg_submit">서신전달&amp;갱신</button><br>
내용 없이 '서신전달&amp;갱신'을 누르면 메세지창이 갱신됩니다. 내용 없이 '서신전달&amp;갱신'을 누르면 메세지창이 갱신됩니다.
</div> </div>
<div><?=allButton($gameStor->npcmode!=0)?></div> <div><?=allButton($gameStor->npcmode==1)?></div>
<div id="message_board"><div style="left:0;" class="board_side bg0"> <div id="message_board"><div style="left:0;" class="board_side bg0">
<div class="board_header bg0" id='public_talk_position'>전체 메시지(최고99자)</div> <div class="board_header bg0" id='public_talk_position'>전체 메시지(최고99자)</div>
<section class="public_message"> <section class="public_message">
@@ -361,7 +363,7 @@ else if($session->userGrade == 4){
<button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="diplomacy">이전 메시지 불러오기</button> <button type="button" class="load_old_message btn btn-secondary btn-block" data-msg_type="diplomacy">이전 메시지 불러오기</button>
</section> </section>
</div></div> </div></div>
<div style="clear:left;"><?=allButton($gameStor->npcmode!=0)?><?=banner()?></div> <div style="clear:left;"><?=allButton($gameStor->npcmode==1)?><?=banner()?></div>
</div> </div>
<?php <?php
if ($con == 1) { if ($con == 1) {
+18 -1
View File
@@ -102,7 +102,7 @@ if($session->userGrade < 5 && !$allowReset){
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="confirm_password" class="col-sm-3 col-form-label">시나리오 선택</label> <label for="scenario_sel" class="col-sm-3 col-form-label">시나리오 선택</label>
<div class="col-sm-9"> <div class="col-sm-9">
<select class="form-control" name="scenario" size="1" id="scenario_sel"> <select class="form-control" name="scenario" size="1" id="scenario_sel">
</select> </select>
@@ -138,6 +138,20 @@ if($session->userGrade < 5 && !$allowReset){
</div> </div>
</div> </div>
<div class="form-group row">
<label for="block_general_create" class="col-sm-3 col-form-label">장수 임의 생성</label>
<div class="col-sm-9">
<div id="block_general_create" class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary">
<input type="radio" name="block_general_create" value="0" checked>가능
</label>
<label class="btn btn-secondary active">
<input type="radio" name="block_general_create" value="1">불가
</label>
</div>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label for="npcmode" class="col-sm-3 col-form-label">NPC 빙의</label> <label for="npcmode" class="col-sm-3 col-form-label">NPC 빙의</label>
<div class="col-sm-9"> <div class="col-sm-9">
@@ -148,6 +162,9 @@ if($session->userGrade < 5 && !$allowReset){
<label class="btn btn-secondary active"> <label class="btn btn-secondary active">
<input type="radio" name="npcmode" value="0" checked>불가 <input type="radio" name="npcmode" value="0" checked>불가
</label> </label>
<label class="btn btn-secondary">
<input type="radio" name="npcmode" value="2">선택 생성 가능
</label>
</div> </div>
</div> </div>
</div> </div>
+101 -100
View File
@@ -1,101 +1,102 @@
<?php <?php
namespace sammo; namespace sammo;
include 'lib.php'; include 'lib.php';
include "func.php"; include "func.php";
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) { if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'affected'=>0, 'affected'=>0,
'status'=>'no_reserved_table' 'status'=>'no_reserved_table'
]); ]);
} }
$reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1'); $reserved = $db->queryFirstRow('SELECT `date`, options FROM reserved_open ORDER BY `date` ASC LIMIT 1');
if(!$reserved){ if(!$reserved){
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'affected'=>0, 'affected'=>0,
'status'=>'no_reserved' 'status'=>'no_reserved'
]); ]);
} }
$reservedDate = new \DateTime($reserved['date']); $reservedDate = new \DateTime($reserved['date']);
$now = new \DateTime(); $now = new \DateTime();
$status = 'not_yet'; $status = 'not_yet';
list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']); list($isUnited, $lastTurn) = $gameStor->getValuesAsArray(['isunited', 'turntime']);
if($isUnited === null || $lastTurn === null){ if($isUnited === null || $lastTurn === null){
$isUnited = 2; $isUnited = 2;
$lastTurn = '2000-01-01'; $lastTurn = '2000-01-01';
} }
if($lastTurn !== null){ if($lastTurn !== null){
$lastTurn = new \DateTime($lastTurn); $lastTurn = new \DateTime($lastTurn);
} }
if($lastTurn === null){ if($lastTurn === null){
//이미 리셋된 상태임 //이미 리셋된 상태임
} }
else if(file_exists(__DIR__.'/.htaccess')){ else if(file_exists(__DIR__.'/.htaccess')){
//일단 서버는 닫혀 있음 //일단 서버는 닫혀 있음
} }
else if( else if(
$isUnited == 2 && $isUnited == 2 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp() $now->getTimestamp() - $lastTurn->getTimestamp() > $reservedDate->getTimestamp() - $now->getTimestamp()
){ ){
//정지 상태 & 중간 넘음 //정지 상태 & 중간 넘음
AppConf::getList()[DB::prefix()]->closeServer(); ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed'; $status = 'closed';
} }
else if( else if(
$isUnited > 0 && $isUnited > 0 &&
$now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2 $now->getTimestamp() - $lastTurn->getTimestamp() > ($reservedDate->getTimestamp() - $now->getTimestamp()) * 2
){ ){
//천통 & 비정지 상태 & 2/3 넘음 //천통 & 비정지 상태 & 2/3 넘음
AppConf::getList()[DB::prefix()]->closeServer(); ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed'; $status = 'closed';
} }
else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){ else if($reservedDate->getTimestamp() - $now->getTimestamp() <= 60*10){
//어쨌든 간에 10분 남았다면. //어쨌든 간에 10분 남았다면.
AppConf::getList()[DB::prefix()]->closeServer(); ServConfig::getServerList()[DB::prefix()]->closeServer();
$status = 'closed'; $status = 'closed';
} }
if($now < $reservedDate){ if($now < $reservedDate){
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'affected'=>0, 'affected'=>0,
'status'=>$status 'status'=>$status
]); ]);
} }
$options = Json::decode($reserved['options']); $options = Json::decode($reserved['options']);
$result = ResetHelper::buildScenario( $result = ResetHelper::buildScenario(
$options['turnterm'], $options['turnterm'],
$options['sync'], $options['sync'],
$options['scenario'], $options['scenario'],
$options['fiction'], $options['fiction'],
$options['extend'], $options['extend'],
$options['npcmode'], $options['block_general_create'],
$options['show_img_level'], $options['npcmode'],
$options['tournament_trig'], $options['show_img_level'],
$options['join_mode'], $options['tournament_trig'],
$options['starttime'], $options['join_mode'],
$options['autorun_user']?:null $options['starttime'],
); $options['autorun_user']?:null
);
$result['affected']=1;
$result['affected']=1;
$prefix = DB::prefix();
AppConf::getList()[$prefix]->openServer(); $prefix = DB::prefix();
ServConfig::getServerList()[$prefix]->openServer();
Json::die($result); Json::die($result);
+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,
]);
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
//로그인 검사
$session = Session::requireGameLogin([]);
$generalID = Session::getGeneralID();
$db = DB::db();
$rawList = Util::convertArrayToDict($db->query('SELECT no, name, npc, nation FROM general'), 'no');
$nationID = $rawList[$generalID]['nation'];
$result = [
'result'=>true,
'reason'=>'success',
'nationID'=>$nationID,
'generalID'=>$generalID,
'column'=>['no', 'name', 'npc']
];
$resultItem = [];
foreach(Util::arrayGroupBy($rawList, 'nation') as $subNationID=>$generals){
$subNation = [];
foreach($generals as $general){
$subNation[] = [$general['no'], $general['name'], $general['npc']];
}
$resultItem[$subNationID] = $subNation;
}
$result['list'] = $resultItem;
$result['nation'] = Util::convertArrayToDict($db->query('SELECT nation, name, color FROM nation'), 'nation');
Json::die($result);
+109 -109
View File
@@ -1,109 +1,109 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
//로그인 검사 //로그인 검사
$session = Session::requireLogin(); $session = Session::requireLogin([]);
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$withToken = Util::getPost('with_token', 'bool', false); $withToken = Util::getPost('with_token', 'bool', false);
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
if($session->isGameLoggedIn()){ if($session->isGameLoggedIn()){
increaseRefresh("장수일람", 2); increaseRefresh("장수일람", 2);
$me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID); $me = $db->queryFirstRow('SELECT con, turntime FROM general WHERE owner=%i', $userID);
$con = checkLimit($me['con']); $con = checkLimit($me['con']);
if ($con >= 2) { if ($con >= 2) {
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.' 'reason'=>'접속 제한중입니다. 1턴 이내에 너무 많은 갱신을 하셨습니다.'
]); ]);
} }
} }
else{ else{
$availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00'; $availableNextCall = $session->availableNextCallGetGeneralList??'2000-01-01 00:00:00';
$now = new \DateTimeImmutable(); $now = new \DateTimeImmutable();
if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){ if($now <= new \DateTimeImmutable($availableNextCall) && $session->userGrade < 5){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall 'reason'=>"장수 리스트는 10초에 한번 갱신 가능합니다.\n다음 시간 : ".$availableNextCall
]); ]);
} }
$availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s'); $availableNextCall = $now->add(new \DateInterval('PT10S'))->format('Y-m-d H:i:s');
$session->availableNextCallGetGeneralList = $availableNextCall; $session->availableNextCallGetGeneralList = $availableNextCall;
} }
$session->setReadOnly(); $session->setReadOnly();
$rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general'); $rawGeneralList = $db->queryAllLists('SELECT owner,no,picture,imgsvr,npc,age,nation,special,special2,personal,name,owner_name as ownerName,injury,leadership,strength,intel,experience,dedication,officer_level,killturn,connect from general');
$ownerNameList = []; $ownerNameList = [];
if($gameStor->isunited){ if($gameStor->isunited){
foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){ foreach(RootDB::db()->queryAllLists('SELECT no, name FROM member') as [$ownerID, $ownerName]){
$ownerNameList[$ownerID] = $ownerName; $ownerNameList[$ownerID] = $ownerName;
} }
} }
$generalList = []; $generalList = [];
foreach($rawGeneralList as $rawGeneral){ foreach($rawGeneralList as $rawGeneral){
[$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral; [$owner,$no,$picture,$imgsvr,$npc,$age,$nation,$special,$special2,$personal,$name,$ownerName,$injury,$leadership,$strength,$intel,$experience,$dedication,$officerLevel,$killturn,$connectCnt] = $rawGeneral;
if(key_exists($owner, $ownerNameList)){ if(key_exists($owner, $ownerNameList)){
$ownerName = $ownerNameList[$owner]; $ownerName = $ownerNameList[$owner];
} }
$nationArr = getNationStaticInfo($nation); $nationArr = getNationStaticInfo($nation);
$lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']); $lbonus = calcLeadershipBonus($officerLevel, $nationArr['level']);
$generalList[] = [ $generalList[] = [
$no, $no,
$picture, $picture,
$imgsvr, $imgsvr,
$npc, $npc,
$age, $age,
$nationArr['name'], $nationArr['name'],
getGeneralSpecialDomesticName($special), getGeneralSpecialDomesticName($special),
getGeneralSpecialWarName($special2), getGeneralSpecialWarName($special2),
getGenChar($personal), getGenChar($personal),
$name, $name,
$npc==1?$ownerName:null, $npc==1?$ownerName:null,
$injury, $injury,
$leadership, $leadership,
$lbonus, $lbonus,
$strength, $strength,
$intel, $intel,
getExpLevel($experience), getExpLevel($experience),
getHonor($experience), getHonor($experience),
getDed($dedication), getDed($dedication),
getOfficerLevelText($officerLevel, $nationArr['level']), getOfficerLevelText($officerLevel, $nationArr['level']),
$killturn, $killturn,
$connectCnt $connectCnt
]; ];
} }
$result = [ $result = [
'result'=>'true', 'result'=>'true',
'list'=>$generalList, 'list'=>$generalList,
]; ];
if($withToken){ if($withToken){
$now = (new \DateTimeImmutable())->format('Y-m-d H:i:s'); $now = (new \DateTimeImmutable())->format('Y-m-d H:i:s');
$tokens = []; $tokens = [];
foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){ foreach($db->query('SELECT * FROM select_npc_token WHERE `valid_until`>=%s', $now) as $token){
$validUntil = $token['valid_until']; $validUntil = $token['valid_until'];
foreach(Json::decode($token['pick_result']) as $pickResult){ foreach(Json::decode($token['pick_result']) as $pickResult){
$tokens[$pickResult['no']]=$pickResult['keepCnt']; $tokens[$pickResult['no']]=$pickResult['keepCnt'];
} }
} }
$result['token'] = $tokens; $result['token'] = $tokens;
} }
Json::die($result); Json::die($result);
+1 -1
View File
@@ -37,7 +37,7 @@ list(
$npcmode $npcmode
) = $gameStor->getValuesAsArray(['maxgeneral', 'turnterm', 'npcmode']); ) = $gameStor->getValuesAsArray(['maxgeneral', 'turnterm', 'npcmode']);
if(!$npcmode){ if($npcmode!=1){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'빙의 가능한 서버가 아닙니다' 'reason'=>'빙의 가능한 서버가 아닙니다'
+90
View File
@@ -0,0 +1,90 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
function sortTokens(&$tokens){
usort($tokens, function($lhs, $rhs){
return array_sum($lhs['dex'])<=>array_sum($rhs['dex']);
});
}
function putInfoText(&$info){
if(key_exists('specialDomestic', $info)){
$class = buildGeneralSpecialDomesticClass($info['specialDomestic']);
$info['specialDomesticName'] = $class->getName();
$info['specialDomesticInfo'] = $class->getInfo();
}
if(key_exists('specialWar', $info)){
$class = buildGeneralSpecialDomesticClass($info['specialWar']);
$info['specialWarName'] = $class->getName();
$info['specialWarInfo'] = $class->getInfo();
}
}
$session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$npcmode = $gameStor->getValue('npcmode');
if($npcmode!=2){
Json::die([
'result'=>false,
'reason'=>'선택 가능한 서버가 아닙니다'
]);
}
$rawGeneral = $db->queryFirstRow('SELECT no, aux FROM general WHERE `owner` = %i', $userID);
if($rawGeneral){
$generalAux = Json::decode($rawGeneral['aux']);
if(key_exists('next_change', $generalAux)&& $generalAux['next_change'] > $now){
Json::die([
'result'=>false,
'reason'=>'아직 다시 고를 수 없습니다'
]);
}
}
$tokens = $db->query('SELECT unique_name, reserved_until, info FROM `select_pool` WHERE `owner`=%i AND `reserved_until`>=%s', $userID, $now);
if($tokens){
$pick = [];
$valid_until = null;
$specialInfo = [];
foreach($tokens as $token){
$valid_until = $token['reserved_until'];
$info = Json::decode($token['info']);
putInfoText($info);
$info['uniqueName'] = $token['unique_name'];
$pick[] = $info;
}
sortTokens($pick);//좀 무식하지만..
Json::die([
'result'=>true,
'pick'=>$pick,
'validUntil'=>$valid_until
]);
}
$pick = [];
$valid_until = null;
foreach(pickGeneralFromPool($db, $userID, 14) as $pickObj){
$valid_until = $pickObj->getValidUntil();
$info = $pickObj->getInfo();
putInfoText($info);
$pick[] = $info;
}
sortTokens($pick);//좀 무식하지만..
Json::die([
'result'=>true,
'pick'=>$pick,
'validUntil'=>$valid_until
]);
+214 -208
View File
@@ -1,209 +1,215 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
if(!class_exists('\\sammo\\DB')){ if(!class_exists('\\sammo\\DB')){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'DB리셋 필요' 'reason'=>'DB리셋 필요'
]); ]);
} }
$serverName = DB::prefix(); $serverName = DB::prefix();
$serverAcl = $session->acl[$serverName]??[]; $serverAcl = $session->acl[$serverName]??[];
$allowReset = in_array('reset', $serverAcl); $allowReset = in_array('reset', $serverAcl);
$allowFullReset = in_array('fullReset',$serverAcl); $allowFullReset = in_array('fullReset',$serverAcl);
$allowReset |= $allowFullReset; $allowReset |= $allowFullReset;
$reserve_open = Util::getPost('reserve_open'); $reserve_open = Util::getPost('reserve_open');
if($reserve_open && $reserve_open < date('Y-m-d H:i')){ if($reserve_open && $reserve_open < date('Y-m-d H:i')){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.' 'reason'=>'현재 시간보다 이전 시간대를 예약 시간으로 지정했습니다.'
]); ]);
} }
$pre_reserve_open = Util::getPost('pre_reserve_open'); $pre_reserve_open = Util::getPost('pre_reserve_open');
if($pre_reserve_open && !$reserve_open){ if($pre_reserve_open && !$reserve_open){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.' 'reason'=>'가오픈 예약을 위해선 오픈 예약을 지정해야합니다.'
]); ]);
} }
if($pre_reserve_open && $pre_reserve_open >= $reserve_open){ if($pre_reserve_open && $pre_reserve_open >= $reserve_open){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.' 'reason'=>'가오픈 시간이 오픈 예약 시점보다 이전이어야 합니다.'
]); ]);
} }
if($session->userGrade < 5 && !$allowReset){ if($session->userGrade < 5 && !$allowReset){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'관리자 아님' 'reason'=>'관리자 아님'
]); ]);
} }
$v = new Validator($_POST); $v = new Validator($_POST);
$v->rule('required', [ $v->rule('required', [
'turnterm', 'turnterm',
'sync', 'sync',
'scenario', 'scenario',
'fiction', 'fiction',
'extend', 'extend',
'join_mode', 'block_general_create',
'npcmode', 'join_mode',
'show_img_level', 'npcmode',
'autorun_user_minutes' 'show_img_level',
])->rule('integer', [ 'autorun_user_minutes'
'turnterm', ])->rule('integer', [
'sync', 'turnterm',
'scenario', 'sync',
'fiction', 'scenario',
'extend', 'fiction',
'npcmode', 'extend',
'show_img_level', 'block_general_create',
'tournament_trig', 'npcmode',
'autorun_user_minutes' 'show_img_level',
])->rule('in', 'join_mode', ['onlyRandom', 'full']); 'tournament_trig',
if(!$v->validate()){ 'autorun_user_minutes'
Json::die([ ])->rule('in', 'join_mode', ['onlyRandom', 'full']);
'result'=>false, if(!$v->validate()){
'reason'=>$v->errorStr() Json::die([
]); 'result'=>false,
} 'reason'=>$v->errorStr()
]);
$allowReset = true; }
if($session->userGrade < 5 && !$allowFullReset){
//리셋 가능한 조건인지 테스트 $allowReset = true;
$allowReset = false; if($session->userGrade < 5 && !$allowFullReset){
//리셋 가능한 조건인지 테스트
if(file_exists(__DIR__.'/.htaccess')){ $allowReset = false;
$allowReset = true;
} if(file_exists(__DIR__.'/.htaccess')){
else{ $allowReset = true;
$db = DB::db(); }
$gameStor = KVStorage::getStorage($db, 'game_env'); else{
if($gameStor->isunited){ $db = DB::db();
$allowReset = true; $gameStor = KVStorage::getStorage($db, 'game_env');
} if($gameStor->isunited){
} $allowReset = true;
} }
}
if(!$allowReset){ }
Json::die([
'result'=>false, if(!$allowReset){
'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.' Json::die([
]); 'result'=>false,
} 'reason'=>'부족한 권한: 서버가 닫혀있거나, 천통되어 있을 경우에만 리셋 가능합니다.'
]);
$turnterm = (int)$_POST['turnterm']; }
$sync = (int)$_POST['sync'];
$scenario = (int)$_POST['scenario']; $turnterm = (int)$_POST['turnterm'];
$fiction = (int)$_POST['fiction']; $sync = (int)$_POST['sync'];
$extend = (int)$_POST['extend']; $scenario = (int)$_POST['scenario'];
$npcmode = (int)$_POST['npcmode']; $fiction = (int)$_POST['fiction'];
$show_img_level = (int)$_POST['show_img_level']; $extend = (int)$_POST['extend'];
$tournament_trig = (int)$_POST['tournament_trig']; $npcmode = (int)$_POST['npcmode'];
$join_mode = $_POST['join_mode']; $block_general_create = (bool)$_POST['block_general_create'];
$autorun_user_minutes = (int)$_POST['autorun_user_minutes']; $show_img_level = (int)$_POST['show_img_level'];
$autorun_user_options = []; $tournament_trig = (int)$_POST['tournament_trig'];
foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){ $join_mode = $_POST['join_mode'];
$autorun_user_options[$autorun_option] = 1; $autorun_user_minutes = (int)$_POST['autorun_user_minutes'];
} $autorun_user_options = [];
if($autorun_user_minutes > 0 && !$autorun_user_options){ foreach(Util::getPost('autorun_user', 'array_string', []) as $autorun_option){
Json::die([ $autorun_user_options[$autorun_option] = 1;
'result'=>false, }
'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
]); if($autorun_user_minutes > 0 && !$autorun_user_options){
} Json::die([
'result'=>false,
if($autorun_user_minutes < 0){ 'reason'=>'적어도 자동 행동 중 하나는 선택을 해야합니다.'
Json::die([ ]);
'result'=>false, }
'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
]); if($autorun_user_minutes < 0){
} Json::die([
'result'=>false,
$autorun_user = $autorun_user_minutes?[ 'reason'=>'자동 행동 기한이 0보다 작을 수 없습니다.'
'limit_minutes'=>$autorun_user_minutes, ]);
'options'=>$autorun_user_options }
]:null;
$autorun_user = $autorun_user_minutes?[
if($reserve_open){ 'limit_minutes'=>$autorun_user_minutes,
$reserve_open = new \DateTime($reserve_open); 'options'=>$autorun_user_options
$db = DB::db(); ]:null;
if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) { if($reserve_open){
$clearResult = ResetHelper::clearDB(); $reserve_open = new \DateTime($reserve_open);
if(!$clearResult['result']){ $db = DB::db();
Json::die($clearResult);
} if (!$db->queryFirstField("SHOW TABLES LIKE 'storage'")) {
} $clearResult = ResetHelper::clearDB();
if(!$clearResult['result']){
if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) { Json::die($clearResult);
Json::die([ }
'result'=>false, }
'reason'=>'예약 테이블이 없음!'
]); if (!$db->queryFirstField("SHOW TABLES LIKE 'reserved_open'")) {
} Json::die([
'result'=>false,
$scenarioObj = new Scenario($scenario, true); 'reason'=>'예약 테이블이 없음!'
$open_date = $reserve_open->format('Y-m-d H:i:s'); ]);
}
$reserveInfo = [
'turnterm'=>$turnterm, $scenarioObj = new Scenario($scenario, true);
'sync'=>$sync, $open_date = $reserve_open->format('Y-m-d H:i:s');
'scenario'=>$scenario,
'scenarioName'=>$scenarioObj->getTitle(), $reserveInfo = [
'fiction'=>$fiction, 'turnterm'=>$turnterm,
'extend'=>$extend, 'sync'=>$sync,
'npcmode'=>$npcmode, 'scenario'=>$scenario,
'show_img_level'=>$show_img_level, 'scenarioName'=>$scenarioObj->getTitle(),
'tournament_trig'=>$tournament_trig, 'fiction'=>$fiction,
'gameConf'=>$scenarioObj->getGameConf(), 'extend'=>$extend,
'join_mode'=>$join_mode, 'block_general_create'=>$block_general_create,
'starttime'=>$open_date, 'npcmode'=>$npcmode,
'autorun_user'=>$autorun_user 'show_img_level'=>$show_img_level,
]; 'tournament_trig'=>$tournament_trig,
'gameConf'=>$scenarioObj->getGameConf(),
'join_mode'=>$join_mode,
if($pre_reserve_open){ 'starttime'=>$open_date,
$pre_reserve_open = new \DateTime($pre_reserve_open); 'autorun_user'=>$autorun_user
$open_date = $pre_reserve_open->format('Y-m-d H:i:s'); ];
}
if($pre_reserve_open){
$pre_reserve_open = new \DateTime($pre_reserve_open);
$db->delete('reserved_open', true); $open_date = $pre_reserve_open->format('Y-m-d H:i:s');
$db->insert('reserved_open', [ }
'options'=>Json::encode($reserveInfo),
'date'=>$open_date
]);
AppConf::getList()[DB::prefix()]->closeServer(); $db->delete('reserved_open', true);
Json::die([ $db->insert('reserved_open', [
'result'=>true, 'options'=>Json::encode($reserveInfo),
'reason'=>'예약' 'date'=>$open_date
]); ]);
} ServConfig::getServerList()[DB::prefix()]->closeServer();
Json::die([
Json::die(ResetHelper::buildScenario( 'result'=>true,
$turnterm, 'reason'=>'예약'
$sync, ]);
$scenario, }
$fiction,
$extend, Json::die(ResetHelper::buildScenario(
$npcmode, $turnterm,
$show_img_level, $sync,
$tournament_trig, $scenario,
$join_mode, $fiction,
TimeUtil::now(), $extend,
$autorun_user $block_general_create,
$npcmode,
$show_img_level,
$tournament_trig,
$join_mode,
TimeUtil::now(),
$autorun_user
)); ));
+102 -102
View File
@@ -1,103 +1,103 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
if($session->userGrade < 6){ if($session->userGrade < 6){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'관리자 아님' 'reason'=>'관리자 아님'
]); ]);
} }
$fullReset = Util::getPost('full_reset', 'bool', false); $fullReset = Util::getPost('full_reset', 'bool', false);
$host = Util::getPost('db_host'); $host = Util::getPost('db_host');
$port = Util::getPost('db_port', 'int'); $port = Util::getPost('db_port', 'int');
$username = Util::getPost('db_id'); $username = Util::getPost('db_id');
$password = Util::getPost('db_pw'); $password = Util::getPost('db_pw');
$dbName = Util::getPost('db_name'); $dbName = Util::getPost('db_name');
if(!$host || !$port || !$username || !$password || !$dbName){ if(!$host || !$port || !$username || !$password || !$dbName){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'입력 값이 올바르지 않습니다' 'reason'=>'입력 값이 올바르지 않습니다'
]); ]);
} }
if($fullReset && class_exists('\\sammo\\DB')){ if($fullReset && class_exists('\\sammo\\DB')){
$mysqli_obj = DB::db()->get(); $mysqli_obj = DB::db()->get();
if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){ if($mysqli_obj->multi_query(file_get_contents(__DIR__.'/sql/reset.sql'))){
while(true){ while(true){
if (!$mysqli_obj->more_results()) { if (!$mysqli_obj->more_results()) {
break; break;
} }
if(!$mysqli_obj->next_result()){ if(!$mysqli_obj->next_result()){
break; break;
} }
} }
} }
} }
if($fullReset){ if($fullReset){
FileUtil::delInDir(__DIR__."/logs"); FileUtil::delInDir(__DIR__."/logs");
FileUtil::delInDir(__DIR__."/data"); FileUtil::delInDir(__DIR__."/data");
if(file_exists(__DIR__.'/d_setting/DB.php')){ if(file_exists(__DIR__.'/d_setting/DB.php')){
@unlink(__DIR__.'/d_setting/DB.php'); @unlink(__DIR__.'/d_setting/DB.php');
} }
if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){ if(file_exists(__DIR__.'/d_setting/UniqueConst.php')){
@unlink(__DIR__.'/d_setting/UniqueConst.php'); @unlink(__DIR__.'/d_setting/UniqueConst.php');
} }
} }
function dbConnFail($params){ function dbConnFail($params){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'DB 접속에 실패했습니다.' 'reason'=>'DB 접속에 실패했습니다.'
]); ]);
} }
$db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4'); $db = new \MeekroDB($host,$username,$password,$dbName,$port,'utf8mb4');
$db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true; $db->connect_options[MYSQLI_OPT_INT_AND_FLOAT_NATIVE] = true;
$db->throw_exception_on_nonsql_error = false; $db->throw_exception_on_nonsql_error = false;
$db->nonsql_error_handler = 'dbConnFail'; $db->nonsql_error_handler = 'dbConnFail';
$mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨. $mysqli_obj = $db->get(); //로그인에 실패할 경우 자동으로 dbConnFail()이 실행됨.
$prefix = basename(__DIR__); $prefix = basename(__DIR__);
$result = Util::generateFileUsingSimpleTemplate( $result = Util::generateFileUsingSimpleTemplate(
__DIR__.'/d_setting/DB.orig.php', __DIR__.'/d_setting/DB.orig.php',
__DIR__.'/d_setting/DB.php',[ __DIR__.'/d_setting/DB.php',[
'host'=>$host, 'host'=>$host,
'user'=>$username, 'user'=>$username,
'password'=>$password, 'password'=>$password,
'dbName'=>$dbName, 'dbName'=>$dbName,
'port'=>$port, 'port'=>$port,
'prefix'=>$prefix 'prefix'=>$prefix
], true ], true
); );
if($result !== true){ if($result !== true){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>$result 'reason'=>$result
]); ]);
} }
ResetHelper::clearDB(); ResetHelper::clearDB();
AppConf::getList()[$prefix]->closeServer(); ServConfig::getServerList()[$prefix]->closeServer();
Json::die([ Json::die([
'result'=>true, 'result'=>true,
'reason'=>'success' 'reason'=>'success'
]); ]);
+83
View File
@@ -0,0 +1,83 @@
<?php
namespace sammo;
use Nette\Caching\Cache;
include "lib.php";
include "func.php";
if(!class_exists('\\sammo\\UniqueConst')){
Json::die([
'result'=>false,
'reason'=>'서버 초기화되지 않음'
]);
}
if(!prepareDir('data/file_cache')){
Json::die([
'result'=>false,
'reason'=>'cache 불가'
]);
}
$storage = new \Nette\Caching\Storages\FileStorage('data/file_cache');
$cache = new Cache($storage);
$serverID = UniqueConst::$serverID;
$mapInfo = $cache->load("recent_map");
//로그인 검사
$now = time();
if($mapInfo && ($now - $mapInfo['timestamp'] < 600)){
$mapEtag = $mapInfo['etag'];
$mapModified = $mapInfo['timestamp'];
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mapModified)." GMT");
header("Etag: $mapEtag");
if (
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']??'2000-01-01') === $mapModified ||
trim($_SERVER['HTTP_IF_NONE_MATCH']??'') === $mapEtag
) {
header("HTTP/1.1 304 Not Modified");
die();
}
Json::die($mapInfo['data'], 0);
}
$defaultPost = [
'year' => null,
'month' => null,
'aux' => null,
'neutralView' => true,
'showMe' => false,
];
$history = formatHistoryToHTML(getGlobalHistoryLogRecent(10));
$rawMap = getWorldMap([
'year' => null,
'month' => null,
'aux' => null,
'neutralView' => true,
'showMe' => false,
]);
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$mapTheme = $gameStor->map_theme ?? 'che';
$rawMap['history'] = $history;
$rawMap['theme'] = $mapTheme;
$etag = hash('sha256', $serverID.$now);
$map = [
'etag'=>$etag,
'timestamp'=>$now,
'data'=>$rawMap,
];
$cache->save("recent_map", $map);
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $now)." GMT");
header("Etag: $etag");
Json::die($map['data'], 0);
+360 -359
View File
@@ -1,360 +1,361 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$action = Util::getPost('action'); $action = Util::getPost('action');
$officerLevel = Util::getPost('officerLevel', 'int'); $officerLevel = Util::getPost('officerLevel', 'int');
$destGeneralID = Util::getPost('destGeneralID', 'int'); $destGeneralID = Util::getPost('destGeneralID', 'int');
$destCityID = Util::getPost('destCityID', 'int'); $destCityID = Util::getPost('destCityID', 'int');
//로그인 검사 //로그인 검사
$session = Session::requireGameLogin()->setReadOnly(); $session = Session::requireGameLogin()->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$gameStor->cacheValues(['startyear','year','month','scenario']); $gameStor->cacheValues(['startyear','year','month','scenario']);
$me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID); $me = $db->queryFirstRow('SELECT no,nation,officer_level from general where owner=%i', $userID);
$myOfficerLevel = $me['officer_level']; $myOfficerLevel = $me['officer_level'];
$nationID = $me['nation']; $nationID = $me['nation'];
//수뇌가 아니면 아무것도 할 수 없음 //수뇌가 아니면 아무것도 할 수 없음
if($myOfficerLevel < 5){ if($myOfficerLevel < 5){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'수뇌가 아닙니다.' 'reason'=>'수뇌가 아닙니다.'
]); ]);
} }
if($action === '추방' && $destGeneralID==0){ if($action === '추방' && $destGeneralID==0){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'장수가 지정되지 않았습니다.' 'reason'=>'장수가 지정되지 않았습니다.'
]); ]);
} }
if($destGeneralID==0){ if($destGeneralID==0){
$general = new DummyGeneral(true); $general = new DummyGeneral(true);
} $general->setVar('nation', $nationID);
else{ }
$general = General::createGeneralObjFromDB($destGeneralID, [ else{
'name', 'leadership', 'strength', 'intel', 'gold','rice', $general = General::createGeneralObjFromDB($destGeneralID, [
'troop','officer_level','npc','picture','imgsvr', 'name', 'leadership', 'strength', 'intel', 'gold','rice',
'permission','penalty','belong', 'crewtype', 'troop','officer_level','npc','picture','imgsvr',
'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit', 'permission','penalty','belong', 'crewtype',
], 1); 'experience', 'dedication', 'betray', 'dedlevel', 'explevel', 'makelimit',
], 1);
if($general instanceof DummyGeneral){
Json::die([ if($general instanceof DummyGeneral){
'result'=>false, Json::die([
'reason'=>'올바르지 않은 장수입니다.' 'result'=>false,
]); 'reason'=>'올바르지 않은 장수입니다.'
} ]);
}
if($nationID != $general->getNationID()){
Json::die([ if($nationID != $general->getNationID()){
'result'=>false, Json::die([
'reason'=>'아국 장수가 아닙니다' 'result'=>false,
]); 'reason'=>'아국 장수가 아닙니다'
} ]);
} }
}
if($officerLevel == 12){
Json::die([ if($officerLevel == 12){
'result'=>false, Json::die([
'reason'=>'군주를 대상으로 할 수 없습니다.' 'result'=>false,
]); 'reason'=>'군주를 대상으로 할 수 없습니다.'
} ]);
}
function do수뇌임명(General $general, int $targetOfficerLevel):?string{
$generalID = $general->getID(); function do수뇌임명(General $general, int $targetOfficerLevel):?string{
$nationID = $general->getNationID(); $generalID = $general->getID();
$nationID = $general->getNationID();
$db = DB::db();
$db = DB::db();
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
[$chiefSet, $nationLevel] = $db->queryFirstList('SELECT chief_set,level FROM nation WHERE nation = %i',$nationID);
// 임명가능 레벨
$lv = getNationChiefLevel($nationLevel); // 임명가능 레벨
$lv = getNationChiefLevel($nationLevel);
if($targetOfficerLevel < $lv){
return '임명불가능한 관직입니다.'; if($targetOfficerLevel < $lv){
} return '임명불가능한 관직입니다.';
}
if(isOfficerSet($chiefSet, $targetOfficerLevel)){
return '지금은 임명할 수 없습니다.'; if(isOfficerSet($chiefSet, $targetOfficerLevel)){
} return '지금은 임명할 수 없습니다.';
}
//기존 장수 일반으로
$db->update('general', [ //기존 장수 일반으로
'officer_level'=>1, $db->update('general', [
'officer_city'=>0, 'officer_level'=>1,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID); 'officer_city'=>0,
], 'nation=%i AND officer_level=%i AND no!=%i', $nationID, $targetOfficerLevel, $generalID);
if($targetOfficerLevel === 11){
if($targetOfficerLevel === 11){
}
else if($targetOfficerLevel % 2 == 0){ }
if($general->getVar('strength') < GameConst::$chiefStatMin){ else if($targetOfficerLevel % 2 == 0){
return '무력이 부족합니다.'; if($general->getVar('strength') < GameConst::$chiefStatMin){
} return '무력이 부족합니다.';
}
}
else{ }
if($general->getVar('intel') < GameConst::$chiefStatMin){ else{
return '지력이 부족합니다.'; if($general->getVar('intel') < GameConst::$chiefStatMin){
} return '지력이 부족합니다.';
} }
}
//신임 장수
$general->setVar('officer_level', $targetOfficerLevel); //신임 장수
$general->setVar('officer_city', 0); $general->setVar('officer_level', $targetOfficerLevel);
$db->update('nation', [ $general->setVar('officer_city', 0);
'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)), $db->update('nation', [
], 'nation=%i', $nationID); 'chief_set'=> $db->sqleval('chief_set | %i', doOfficerSet(0, $targetOfficerLevel)),
$general->applyDB($db); ], 'nation=%i', $nationID);
$general->applyDB($db);
return null;
} return null;
}
function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
$nationID = $general->getNationID(); function do도시임명(General $general, int $cityID, int $targetOfficerLevel):?string{
$nationID = $general->getNationID();
$db = DB::db();
$db = DB::db();
if(CityConst::byID($cityID) === null){
return '올바르지 않은 도시입니다'; if(CityConst::byID($cityID) === null){
} return '올바르지 않은 도시입니다';
}
$officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
if($officerSet === null){ $officerSet = $db->queryFirstField('SELECT officer_set FROM city WHERE nation=%i AND city=%i', $nationID, $cityID);
return '아국 도시가 아닙니다'; if($officerSet === null){
} return '아국 도시가 아닙니다';
}
if(isOfficerSet($officerSet, $targetOfficerLevel)){
return '이미 다른 장수가 임명되어있습니다'; if(isOfficerSet($officerSet, $targetOfficerLevel)){
} return '이미 다른 장수가 임명되어있습니다';
}
//기존 장수 일반으로
$db->update('general', [ //기존 장수 일반으로
'officer_level'=>1, $db->update('general', [
'officer_city'=>0, 'officer_level'=>1,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID()); 'officer_city'=>0,
], 'officer_level=%i AND officer_city=%i AND no!=%i', $targetOfficerLevel, $cityID, $general->getID());
if($general instanceof DummyGeneral){
return null; if($general instanceof DummyGeneral){
} return null;
}
if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
return '무력이 부족합니다.'; if($targetOfficerLevel === 4 && $general->getVar('strength') < GameConst::$chiefStatMin){
} return '무력이 부족합니다.';
}
if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
return '지력이 부족합니다.'; if($targetOfficerLevel === 3 && $general->getVar('intel') < GameConst::$chiefStatMin){
} return '지력이 부족합니다.';
}
//신임 장수
$db->update('city', [ //신임 장수
'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)), $db->update('city', [
], 'city=%i AND nation=%i', $cityID, $nationID); 'officer_set'=>$db->sqleval('officer_set | %i', doOfficerSet(0, $targetOfficerLevel)),
$general->setVar('officer_level', $targetOfficerLevel); ], 'city=%i AND nation=%i', $cityID, $nationID);
$general->setVar('officer_city', $cityID); $general->setVar('officer_level', $targetOfficerLevel);
$general->applyDB($db); $general->setVar('officer_city', $cityID);
$general->applyDB($db);
return null;
} return null;
}
function do추방(General $general, int $myOfficerLevel):?string{
$generalID = $general->getID(); function do추방(General $general, int $myOfficerLevel):?string{
$generalName = $general->getVar('name'); $generalID = $general->getID();
$nationID = $general->getNationID(); $generalName = $general->getVar('name');
$nationID = $general->getNationID();
//추방할사람이 외교권자이면 불가
$permission = checkSecretPermission($general->getRaw()); //추방할사람이 외교권자이면 불가
if($permission == 4){ $permission = checkSecretPermission($general->getRaw());
return '외교권자는 추방할 수 없습니다.'; if($permission == 4){
} return '외교권자는 추방할 수 없습니다.';
}
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $db = DB::db();
$env = $gameStor->getValues(['startyear','year','month','scenario']); $gameStor = KVStorage::getStorage($db, 'game_env');
$env = $gameStor->getValues(['startyear','year','month','scenario']);
$nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name']; $nation = $db->queryFirstRow('SELECT name,chief_set,color FROM nation WHERE nation=%i', $nationID);
$nationName = $nation['name'];
$logger = $general->getLogger();
$logger = $general->getLogger();
//이미 지정했다면 무시
if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) { //이미 지정했다면 무시
return '이미 추방 권한을 사용했습니다.'; if(isOfficerSet($nation['chief_set'], $myOfficerLevel) || ($myOfficerLevel == 0 && $myOfficerLevel == 12)) {
} return '이미 추방 권한을 사용했습니다.';
$gold = 0; }
$rice = 0; $gold = 0;
// 금쌀1000이상은 남김 $rice = 0;
if($general->getVar('gold') > GameConst::$defaultGold) { // 금쌀1000이상은 남김
$gold = $general->getVar('gold') - GameConst::$defaultGold; if($general->getVar('gold') > GameConst::$defaultGold) {
$general->setVar('gold', GameConst::$defaultGold); $gold = $general->getVar('gold') - GameConst::$defaultGold;
} $general->setVar('gold', GameConst::$defaultGold);
if($general->getVar('rice') > GameConst::$defaultRice) { }
$rice = $general->getVar('rice') - GameConst::$defaultRice; if($general->getVar('rice') > GameConst::$defaultRice) {
$general->setVar('rice', GameConst::$defaultRice); $rice = $general->getVar('rice') - GameConst::$defaultRice;
} $general->setVar('rice', GameConst::$defaultRice);
}
$general->setVar('nation', 0);
$general->setVar('officer_level', 0); $general->setVar('nation', 0);
$general->setVar('officer_city', 0); $general->setVar('officer_level', 0);
$general->setVar('belong', 0); $general->setVar('officer_city', 0);
$oldMakeLimit = $general->getVar('makelimit'); $general->setVar('belong', 0);
$general->setVar('makelimit', 12); $oldMakeLimit = $general->getVar('makelimit');
$general->setVar('permission', 'normal'); $general->setVar('makelimit', 12);
$general->setVar('permission', 'normal');
$josaYi = JosaUtil::pick($generalName, '이');
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>에서 <R>추방</>당했습니다."); $josaYi = JosaUtil::pick($generalName, '이');
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN); $logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} <D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.");
$logger->pushGeneralActionLog("<D><b>{$nationName}</b></>에서 <R>추방</>당했습니다.", ActionLogger::PLAIN);
// 명성/공헌 N*10%감소
if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){ // 명성/공헌 N*10%감소
$general->setVar('makelimit', $oldMakeLimit); if($env['year'] <= $env['startyear'] && $general->getNPCType() < 2){
} $general->setVar('makelimit', $oldMakeLimit);
else{ }
$betrayCnt = $general->getVar('betray'); else{
$general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt); $betrayCnt = $general->getVar('betray');
$general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt); $general->addExperience(-$general->getVar('experience')*0.1*$betrayCnt);
$general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt); $general->addDedication(-$general->getVar('dedication')*0.1*$betrayCnt);
} $general->increaseVarWithLimit('betray', 1, null, GameConst::$maxBetrayCnt);
}
//부대장일 경우
if($general->getVar('troop') == $generalID){ //부대장일 경우
// 모두 탈퇴 if($general->getVar('troop') == $generalID){
$db->update('general', [ // 모두 탈퇴
'troop'=>0, $db->update('general', [
], 'troop = %i', $generalID); 'troop'=>0,
$db->delete('troop', 'troop_leader=%i', $generalID); ], 'troop = %i', $generalID);
} $db->delete('troop', 'troop_leader=%i', $generalID);
$general->setVar('troop', 0); }
$general->setVar('troop', 0);
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
if($general->getNPCType() >= 2 && ($env['scenario'] < 100 || Util::randBool(0.01))) {
$str = Util::choiceRandom([
'날 버리다니... 곧 전장에서 복수해주겠다...', $str = Util::choiceRandom([
'추방이라... 내가 무얼 잘못했단 말인가...', '날 버리다니... 곧 전장에서 복수해주겠다...',
'어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...', '추방이라... 내가 무얼 잘못했단 말인가...',
'인덕이 제일이거늘... 추방이 웬말인가... 저주한다!', '어디 추방해가면서 잘되나 보자... 꼭 복수하겠다...',
'날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.' '인덕이 제일이거늘... 추방이 웬말인가... 저주한다!',
]); '날 추방했으니 그 복수로 적국에 정보를 팔아 넘겨야겠군요. 그럼 이만.'
]);
$src = new MessageTarget(
$generalID, $src = new MessageTarget(
$generalName, $generalID,
$nationID, $generalName,
$nation['name'], $nationID,
$nation['color'], $nation['name'],
GetImageURL($general->getVar('imgsvr'), $general->getVar('picture')) $nation['color'],
); GetImageURL($general->getVar('imgsvr'), $general->getVar('picture'))
$msg = new Message( );
Message::MSGTYPE_PUBLIC, $msg = new Message(
$src, Message::MSGTYPE_PUBLIC,
$src, $src,
$str, $src,
new \DateTime(), $str,
new \DateTime('9999-12-31'), new \DateTime(),
[] new \DateTime('9999-12-31'),
); []
$msg->send(); );
} $msg->send();
}
if($env['year'] < $env['startyear']+3) {
//초반엔 군주 부상 증가(엔장 임관지양) if($env['year'] < $env['startyear']+3) {
$db->update('general', [ //초반엔 군주 부상 증가(엔장 임관지양)
'injury'=>$db->sqleval('least(injury + 1, %i)', 80), $db->update('general', [
], 'nation=%i AND officer_level=12', $nationID); 'injury'=>$db->sqleval('least(injury + 1, %i)', 80),
], 'nation=%i AND officer_level=12', $nationID);
$db->update('nation', [
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0), $db->update('nation', [
'gold'=>$db->sqleval('gold + %i', $gold), 'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'rice'=>$db->sqleval('rice + %i', $rice), 'gold'=>$db->sqleval('gold + %i', $gold),
], 'nation = %i', $nationID); 'rice'=>$db->sqleval('rice + %i', $rice),
} else { ], 'nation = %i', $nationID);
//이번분기는 추방불가(초반 제외) } else {
$db->update('nation', [ //이번분기는 추방불가(초반 제외)
'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)), $db->update('nation', [
'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0), 'chief_set'=>$db->sqleval('chief_set | %i', doOfficerSet(0, $myOfficerLevel)),
'gold'=>$db->sqleval('gold + %i', $gold), 'gennum'=>$db->sqleval('gennum - %i', $general->getNPCType()!=5?1:0),
'rice'=>$db->sqleval('rice + %i', $rice), 'gold'=>$db->sqleval('gold + %i', $gold),
], 'nation = %i', $nationID); 'rice'=>$db->sqleval('rice + %i', $rice),
} ], 'nation = %i', $nationID);
}
$logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
$general->applyDB($db); $logger->pushGeneralHistoryLog("<D>{$nation['name']}</>에서 추방됨");
$general->applyDB($db);
return null;
} return null;
}
if($action == "임명") {
if(2 <= $officerLevel && $officerLevel <= 4){ if($action == "임명") {
if(!$destCityID){ if(2 <= $officerLevel && $officerLevel <= 4){
Json::die([ if(!$destCityID){
'result'=>false, Json::die([
'reason'=>'도시가 지정되지 않았습니다.' 'result'=>false,
]); 'reason'=>'도시가 지정되지 않았습니다.'
} ]);
$result = do도시임명($general, $destCityID, $officerLevel); }
if($result !== null){ $result = do도시임명($general, $destCityID, $officerLevel);
Json::die([ if($result !== null){
'result'=>false, Json::die([
'reason'=>$result 'result'=>false,
]); 'reason'=>$result
} ]);
Json::die([ }
'result'=>true, Json::die([
'reason'=>'success' 'result'=>true,
]); 'reason'=>'success'
} ]);
}
if(5 <= $officerLevel && $officerLevel < 12){
$result = do수뇌임명($general, $officerLevel); if(5 <= $officerLevel && $officerLevel < 12){
if($result !== null){ $result = do수뇌임명($general, $officerLevel);
Json::die([ if($result !== null){
'result'=>false, Json::die([
'reason'=>$result 'result'=>false,
]); 'reason'=>$result
} ]);
Json::die([ }
'result'=>true, Json::die([
'reason'=>'success' 'result'=>true,
]); 'reason'=>'success'
} ]);
}
Json::die([
'result'=>false, Json::die([
'reason'=>'올바르지 않은 지정입니다.' 'result'=>false,
]); 'reason'=>'올바르지 않은 지정입니다.'
} ]);
}
if($action == "추방") {
$result = do추방($general, $myOfficerLevel); if($action == "추방") {
if($result !== null){ $result = do추방($general, $myOfficerLevel);
Json::die([ if($result !== null){
'result'=>false, Json::die([
'reason'=>$result 'result'=>false,
]); 'reason'=>$result
} ]);
Json::die([ }
'result'=>true, Json::die([
'reason'=>'success' 'result'=>true,
]); 'reason'=>'success'
} ]);
}
Json::die([
'result'=>false, Json::die([
'reason'=>'올바르지 않은 명령입니다.' 'result'=>false,
'reason'=>'올바르지 않은 명령입니다.'
]); ]);
+1 -1
View File
@@ -59,7 +59,7 @@ list(
$npcmode $npcmode
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode']); ) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode']);
if(!$npcmode){ if($npcmode!=1){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'빙의 가능한 서버가 아닙니다' 'reason'=>'빙의 가능한 서버가 아닙니다'
+170
View File
@@ -0,0 +1,170 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$pick = Util::getPost('pick');
$leadership = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
$strength = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
$intel = Util::getPost('leadership', 'int', GameConst::$defaultStatMin);
$personal = Util::getPost('personal', 'string', null);
$use_own_picture = Util::getPost('use_own_picture', 'bool', false);
if(!$pick){
Json::die([
'result'=>false,
'reason'=>'장수를 선택하지 않았습니다'
]);
}
$session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$rootDB = RootDB::db();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$hasGeneralID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
if($hasGeneralID){
Json::die([
'result'=>false,
'reason'=>'이미 장수를 생성했습니다.'
]);
}
$env = $gameStor->getValues(['startyear', 'year', 'month', 'maxgeneral', 'npcmode', 'show_img_level', 'icon_path', 'turnterm', 'turntime']);
$env['fiction'] = false;
$npcmode = $env['npcmode'];
$maxgeneral = $env['maxgeneral'];
if($npcmode!=2){
Json::die([
'result'=>false,
'reason'=>'선택 가능한 서버가 아닙니다'
]);
}
$selectInfo = $db->queryFirstField('SELECT info FROM select_pool WHERE `owner` = %i AND `reserved_until`>=%s AND `unique_name`=%s', $userID, $now, $pick);
if(!$selectInfo){
Json::die([
'result'=>false,
'reason'=>'유효한 장수 목록이 없습니다.'
]);
}
$selectInfo = Json::decode($selectInfo);
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
if(!$ownerInfo){
Json::die([
'result'=>false,
'reason'=>'멤버 정보를 가져오지 못했습니다.'
]);
}
$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2');
if ($gencount >= $maxgeneral) {
Json::die([
'result'=>false,
'reason'=>'더 이상 등록 할 수 없습니다.'
]);
}
$poolClass = getGeneralPoolClass(GameConst::$targetGeneralPool);
/** @var AbsGeneralPool */
$pickedGeneral = new $poolClass($db, $selectInfo, $now);
$builder = $pickedGeneral->getGeneralBuilder();
foreach(GameConst::$generalPoolAllowOption as $allowOption){
if($allowOption == 'stat'){
$leadership = Util::valueFit($leadership, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
$strength = Util::valueFit($strength, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
$intel = Util::valueFit($intel, GameConst::$defaultStatMin, GameConst::$defaultStatMax);
if($leadership + $strength + $intel > GameConst::$defaultStatTotal){
Json::die([
'result'=>false,
'reason'=>'스탯의 총 합이 올바르지 않습니다.'
]);
}
$builder->setStat($leadership, $strength, $intel);
}
else if($allowOption == 'picture' && $use_own_picture){
$builder->setPicture($ownerInfo['imgsvr'], $ownerInfo['picture']);
}
else if($allowOption == 'ego'){
if(!$personal || $personal == 'Random'){
$personal = Util::choiceRandom(GameConst::$availablePersonality);
}
if(!array_search($personal, GameConst::$availablePersonality)){
Json::die([
'result'=>false,
'reason'=>'올바르지 않은 성격입니다.'
]);
}
$builder->setEgo($personal);
}
}
$userNick = $ownerInfo['name'];
$builder->setOwner($userID);
$builder->setOwnerName($userNick);
$builder->setKillturn(5);
$builder->setNPCType(0);
$builder->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * $env['turnterm']));
$builder->fillRemainSpecAsZero($env);
$builder->build($env);
$generalID = $builder->getGeneralID();
if(!$generalID){
Json::die([
'result'=>false,
'reason'=>'장수 등록에 실패했습니다.'
]);
}
$pickedGeneral->occupyGeneralName();
$db->update('select_pool',[
'owner'=>null,
'reserved_until'=>null,
], '(owner=%i or reserved_until < %s) AND general_id is NULL', $userID, $now);
$josaYi = JosaUtil::pick($userNick, '이');
$generalName = $builder->getGeneralName();
$josaRo = JosaUtil::pick($generalName, '로');
$cityName = CityConst::byID($builder->getCityID())->name;
$logger = new ActionLogger($generalID, 0, $env['year'], $env['month']);
$logger->pushGeneralHistoryLog("<Y>{$generalName}</>, <G>{$cityName}</>에서 등장");
$logger->pushGlobalActionLog("<G><b>{$cityName}</b></>에서 <Y>{$userNick}</>{$josaYi} <Y>{$generalName}</>{$josaRo} 등장합니다.");
$logger->flush();
pushAdminLog(["가입 : {$userID} // {$session->userName} // {$pick} // ".getenv("REMOTE_ADDR")]);
$rootDB->insert('member_log', [
'member_no' => $userID,
'date'=>TimeUtil::now(),
'action_type'=>'make_general',
'action'=>Json::encode([
'server'=>DB::prefix(),
'type'=>'select',
'generalID'=>$generalID,
'generalName'=>$generalName
])
]);
Json::die([
'result'=>true,
'reason'=>'success'
]);
+6 -5
View File
@@ -43,7 +43,7 @@ $session = Session::requireLogin([
'game'=>null, 'game'=>null,
'me'=>null 'me'=>null
])->setReadOnly(); ])->setReadOnly();
$userID = Session::getUserID(); $userID = $session->userID;
if(!class_exists('\\sammo\\DB')){ if(!class_exists('\\sammo\\DB')){
Json::die([ Json::die([
@@ -91,7 +91,8 @@ if(file_exists(__DIR__.'/.htaccess')){
'scenarioName'=>$options['scenarioName'], 'scenarioName'=>$options['scenarioName'],
'turnterm'=>$options['turnterm'], 'turnterm'=>$options['turnterm'],
'fictionMode'=>($options['fiction']?'가상':'사실'), 'fictionMode'=>($options['fiction']?'가상':'사실'),
'npcMode'=>($options['npcmode']?'가능':'불가'), 'block_general_create'=>(!!$options['block_general_create']),
'npcMode'=>([0=>'불가',1=>'가능',2=>'선택 생성'][$options['npcmode']]),
'openDatetime'=>$reserved['date'], 'openDatetime'=>$reserved['date'],
'starttime'=>$options['starttime'], 'starttime'=>$options['starttime'],
'gameConf'=>$options['gameConf'], 'gameConf'=>$options['gameConf'],
@@ -104,7 +105,7 @@ if(file_exists(__DIR__.'/.htaccess')){
//TODO: 천통시에도 예약 오픈 알림이 필요..? //TODO: 천통시에도 예약 오픈 알림이 필요..?
$admin = $gameStor->getValues(['isunited', 'npcmode', 'year', 'month', 'scenario', 'scenario_text', 'maxgeneral', 'turnterm', 'opentime', 'turntime', 'join_mode', 'fiction', 'autorun_user']); $admin = $gameStor->getValues(['isunited', 'npcmode', 'year', 'month', 'scenario', 'scenario_text', 'maxgeneral', 'turnterm', 'opentime', 'turntime', 'join_mode', 'fiction', 'block_general_create', 'autorun_user']);
$admin['maxUserCnt'] = $admin['maxgeneral']; $admin['maxUserCnt'] = $admin['maxgeneral'];
$admin['npcMode'] = $admin['npcmode']; $admin['npcMode'] = $admin['npcmode'];
$admin['turnTerm'] = $admin['turnterm']; $admin['turnTerm'] = $admin['turnterm'];
@@ -124,8 +125,8 @@ $admin['scenario'] = $admin['scenario_text'];
$admin['userCnt'] = $genCnt; $admin['userCnt'] = $genCnt;
$admin['npcCnt'] = $npcCnt; $admin['npcCnt'] = $npcCnt;
$admin['nationCnt'] = $nationCnt; $admin['nationCnt'] = $nationCnt;
$admin['block_general_create'] = !!$admin['block_general_create'];
$admin['npcMode'] = $admin['npcMode']?'가능':'불가'; $admin['npcMode'] = [0=>'불가',1=>'가능',2=>'선택 생성'][$admin['npcMode']];
$admin['fictionMode'] = $admin['fiction']?'가상':'사실'; $admin['fictionMode'] = $admin['fiction']?'가상':'사실';
$otherTextInfo = []; $otherTextInfo = [];
+81 -76
View File
@@ -1,77 +1,82 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireGameLogin([])->setReadOnly(); $session = Session::requireGameLogin([])->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
$generalID = $session->generalID; $generalID = $session->generalID;
increaseRefresh("내정보 수정", 0); increaseRefresh("내정보 수정", 0);
$action = Util::getPost('action'); $action = Util::getPost('action');
$tnmt = Util::getPost('tnmt', 'int', 1); $tnmt = Util::getPost('tnmt', 'int', 1);
$defence_train = Util::getPost('defence_train', 'int', 80); $defence_train = Util::getPost('defence_train', 'int', 80);
$use_treatment = Util::getPost('use_treatment', 'int', 10); $use_treatment = Util::getPost('use_treatment', 'int', 10);
//$detachNPC = Util::getPost('detachNPC', 'bool'); $use_auto_nation_turn = Util::getPost('use_auto_nation_turn', 'int', 1);
$detachNPC = false; //$detachNPC = Util::getPost('detachNPC', 'bool');
$detachNPC = false;
if ($defence_train <= 40) {
$defence_train = 40; if ($defence_train <= 40) {
} $defence_train = 40;
}
if($defence_train <= 90){
$defence_train = Util::round($defence_train, -1); if($defence_train <= 90){
} $defence_train = Util::round($defence_train, -1);
else{ }
$defence_train = 999; else{
} $defence_train = 999;
}
if($tnmt < 0 || $tnmt > 1){
$tnmt = 1; if($tnmt < 0 || $tnmt > 1){
} $tnmt = 1;
}
$db = DB::db();
$me = General::createGeneralObjFromDB($generalID); $db = DB::db();
$me = General::createGeneralObjFromDB($generalID);
if($defence_train != $me->getVar('defence_train')){
if($defence_train == 999){ if($defence_train != $me->getVar('defence_train')){
$me->increaseVar('myset', -1); if($defence_train == 999){
$me->setVar('defence_train', $defence_train); $me->increaseVar('myset', -1);
$me->increaseVar('train', -3); $me->setVar('defence_train', $defence_train);
$me->increaseVar('atmos', -3); $me->increaseVarWithLimit('train', -3, 20);
} $me->increaseVarWithLimit('atmos', -3, 20);
else{ }
$me->increaseVar('myset', -1); else{
$me->setVar('defence_train', $defence_train); $me->increaseVar('myset', -1);
} $me->setVar('defence_train', $defence_train);
} }
}
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
$me->setAuxVar('use_treatment', Util::valueFit($use_treatment, 10, 100));
if($me->getVar('tnmt') != $tnmt){
$me->setVar('tnmt', $tnmt); if($use_auto_nation_turn != $me->getAuxVar('use_auto_nation_turn')){
} $me->setAuxVar('use_auto_nation_turn', $use_auto_nation_turn);
}
if($me->getNPCType() == 1 && $detachNPC){
$turnterm = $gameStor->turnterm; if($me->getVar('tnmt') != $tnmt){
$me->setVar('tnmt', $tnmt);
if($turnterm < 10){ }
$targetKillTurn = 30 / $turnterm;
} if($me->getNPCType() == 1 && $detachNPC){
else{ $turnterm = $gameStor->turnterm;
$targetKillTurn = 60 / $turnterm;
} if($turnterm < 10){
$me->setVar('killturn', $targetKillTurn); $targetKillTurn = 30 / $turnterm;
} }
else{
$me->applyDB($db); $targetKillTurn = 60 / $turnterm;
}
Json::die([ $me->setVar('killturn', $targetKillTurn);
'result'=>true, }
'reason'=>'success'
$me->applyDB($db);
Json::die([
'result'=>true,
'reason'=>'success'
]); ]);
+467 -451
View File
@@ -1,451 +1,467 @@
<?php <?php
namespace sammo; namespace sammo;
include "lib.php"; include "lib.php";
include "func.php"; include "func.php";
WebUtil::requireAJAX(); WebUtil::requireAJAX();
$session = Session::requireLogin([])->setReadOnly(); $session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID(); $userID = Session::getUserID();
increaseRefresh("시뮬레이터", 0); increaseRefresh("시뮬레이터", 0);
$query = Util::getPost('query'); $query = Util::getPost('query');
if($query === null){ if($query === null){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'입력값이 없습니다.' 'reason'=>'입력값이 없습니다.'
]); ]);
} }
$action = Util::getPost('action'); $action = Util::getPost('action');
if($action === null || !in_array($action, ['reorder', 'battle'])){ if($action === null || !in_array($action, ['reorder', 'battle'])){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'원하는 동작이 지정되지 않았습니다.' 'reason'=>'원하는 동작이 지정되지 않았습니다.'
]); ]);
} }
$query = Json::decode($query); $query = Json::decode($query);
if($query === null){ if($query === null){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>'올바르지 않은 JSON입니다.' 'reason'=>'올바르지 않은 JSON입니다.'
]); ]);
} }
$defaultCheck = [ $defaultCheck = [
'required'=>[ 'required'=>[
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation', 'defenderGenerals', 'defenderCity', 'defenderNation',
'year', 'month', 'repeatCnt' 'year', 'month', 'repeatCnt'
], ],
'integer'=>[ 'integer'=>[
'year','month','repeatCnt' 'year','month','repeatCnt'
], ],
'between'=>[ 'between'=>[
['month', [1, 12]] ['month', [1, 12]]
], ],
'in'=>[ 'in'=>[
['repeatCnt', [1, 1000]] ['repeatCnt', [1, 1000]]
], ],
'min'=>[ 'min'=>[
['year', 0] ['year', 0]
], ],
'array'=>[ 'array'=>[
'attackerGeneral', 'attackerCity', 'attackerNation', 'attackerGeneral', 'attackerCity', 'attackerNation',
'defenderGenerals', 'defenderCity', 'defenderNation' 'defenderGenerals', 'defenderCity', 'defenderNation'
], ],
]; ];
$v = new Validator($query); $v = new Validator($query);
$v->rules($defaultCheck); $v->rules($defaultCheck);
if(!$v->validate()){ if(!$v->validate()){
Json::die([ Json::die([
'result'=>false, 'result'=>false,
'reason'=>$v->errorStr() 'reason'=>$v->errorStr()
]); ]);
} }
$year = $query['year']; $year = $query['year'];
$month = $query['month']; $month = $query['month'];
$repeatCnt = $query['repeatCnt']; $repeatCnt = $query['repeatCnt'];
$rawAttacker = $query['attackerGeneral']; $rawAttacker = $query['attackerGeneral'];
$rawAttacker['turntime'] = TimeUtil::now(); $rawAttacker['turntime'] = TimeUtil::now();
$rawAttackerCity = $query['attackerCity']; $rawAttackerCity = $query['attackerCity'];
$rawAttackerNation = $query['attackerNation']; $rawAttackerNation = $query['attackerNation'];
$rawDefenderList = $query['defenderGenerals']; $rawDefenderList = $query['defenderGenerals'];
$rawDefenderCity = $query['defenderCity']; $rawDefenderCity = $query['defenderCity'];
$rawDefenderNation = $query['defenderNation']; $rawDefenderNation = $query['defenderNation'];
$generalCheck = [ $generalCheck = [
'required'=>[ 'required'=>[
'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train', 'no', 'name', 'nation', 'turntime', 'personal', 'special2', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item', 'intel', 'intel_exp', 'book', 'strength', 'strength_exp', 'weapon', 'injury', 'leadership', 'leadership_exp', 'horse', 'item',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
'recent_war' 'recent_war', 'warnum', 'killnum', 'killcrew',
], ],
'integer'=>[ 'integer'=>[
'no', 'nation', 'crew', 'crewtype', 'atmos', 'train', 'no', 'nation', 'crew', 'crewtype', 'atmos', 'train',
'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp', 'intel', 'intel_exp', 'strength', 'strength_exp', 'injury', 'leadership', 'leadership_exp',
'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5', 'explevel', 'experience', 'dedication', 'officer_level', 'officer_city', 'gold', 'rice', 'dex1', 'dex2', 'dex3', 'dex4', 'dex5',
], 'warnum', 'killnum', 'killcrew',
'min'=>[ ],
['no', 1], 'min'=>[
['nation', 1], ['no', 1],
['crew', 0], ['nation', 1],
['intel', 0], ['crew', 0],
['strength', 0], ['intel', 0],
['leadership', 0], ['strength', 0],
['experience', 0], ['leadership', 0],
['gold', 0], ['experience', 0],
['rice', 0], ['gold', 0],
['dex1', 0], ['rice', 0],
['dex2', 0], ['dex1', 0],
['dex3', 0], ['dex2', 0],
['dex4', 0], ['dex3', 0],
['dex5', 0], ['dex4', 0],
], ['dex5', 0],
'between'=>[ ['warnum', 0],
['train', [40, GameConst::$maxTrainByWar]], ['killnum', 0],
['atmos', [40, GameConst::$maxAtmosByWar]], ['killcrew', 0],
['explevel', [0, 300]], ],
['injury', [0, 80]], 'between'=>[
['officer_level', [1, 12]] ['train', [40, GameConst::$maxTrainByWar]],
], ['atmos', [40, GameConst::$maxAtmosByWar]],
'in'=>[ ['explevel', [0, 300]],
['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)], ['injury', [0, 80]],
['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)], ['officer_level', [1, 12]]
['crewtype', array_keys(GameUnitConst::all())], ],
['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])], 'in'=>[
['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])], ['personal', array_merge(GameConst::$availablePersonality, GameConst::$optionalPersonality)],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])], ['special2', array_merge(GameConst::$availableSpecialWar, GameConst::$optionalSpecialWar)],
['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])], ['crewtype', array_keys(GameUnitConst::all())],
] ['horse', array_merge(array_keys(GameConst::$allItems['horse']), ['None'])],
]; ['weapon', array_merge(array_keys(GameConst::$allItems['weapon']), ['None'])],
['book', array_merge(array_keys(GameConst::$allItems['book']), ['None'])],
$v = new Validator($rawAttacker); ['item', array_merge(array_keys(GameConst::$allItems['item']), ['None'])],
$v->rules($generalCheck); ]
if(!$v->validate()){ ];
Json::die([
'result'=>false, $v = new Validator($rawAttacker);
'reason'=>'[출병자]'.$v->errorStr() $v->rules($generalCheck);
]); if(!$v->validate()){
} Json::die([
'result'=>false,
$defenderList = []; 'reason'=>'[출병자]'.$v->errorStr()
foreach($rawDefenderList as $idx=>$rawDefenderGeneral){ ]);
$v = new Validator($rawDefenderGeneral); }
$v->rules($generalCheck); $rawAttacker['owner'] = 0;
if(!$v->validate()){
$idx+=1; $defenderList = [];
Json::die([ foreach($rawDefenderList as $idx=>$rawDefenderGeneral){
'result'=>false, $v = new Validator($rawDefenderGeneral);
'reason'=>"[수비자{$idx}]".$v->errorStr() $v->rules($generalCheck);
]); if(!$v->validate()){
} $idx+=1;
$defenderList[] = new General($rawDefenderGeneral, null, $rawDefenderCity, $rawAttackerNation, $year, $month, true); Json::die([
} 'result'=>false,
'reason'=>"[수비자{$idx}]".$v->errorStr()
]);
$cityCheck = [ }
'required'=>[ $rawDefenderGeneral['owner'] = 0;
'city', 'nation', 'supply', 'name',
'pop', 'agri', 'comm', 'secu', 'def', 'wall', $defenderList[] = new General($rawDefenderGeneral, extractRankVar($rawDefenderGeneral), $rawDefenderCity, $rawAttackerNation, $year, $month, true);
'trust', 'level', }
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'dead', 'state', 'conflict',
], $cityCheck = [
'numeric'=>[ 'required'=>[
'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead' 'city', 'nation', 'supply', 'name',
], 'pop', 'agri', 'comm', 'secu', 'def', 'wall',
'integer'=>[ 'trust', 'level',
'city', 'nation', 'supply', 'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max', 'dead', 'state', 'conflict',
'state', ],
], 'numeric'=>[
'min'=>[ 'pop', 'agri', 'comm', 'secu', 'def', 'wall', 'trust', 'dead'
['def', 0], ],
['wall', 0], 'integer'=>[
['trust', 0], 'city', 'nation', 'supply',
['pop', 0], 'pop_max', 'agri_max', 'comm_max', 'secu_max', 'def_max', 'wall_max',
['comm', 0], 'state',
['secu', 0], ],
['city', 1], 'min'=>[
['nation', 0] ['def', 0],
], ['wall', 0],
'in'=>[ ['trust', 0],
['level', array_keys(getCityLevelList())] ['pop', 0],
] ['comm', 0],
]; ['secu', 0],
['city', 1],
$v = new Validator($rawAttackerCity); ['nation', 0]
$v->rules($cityCheck); ],
if(!$v->validate()){ 'in'=>[
Json::die([ ['level', array_keys(getCityLevelList())]
'result'=>false, ]
'reason'=>'[출병도시]'.$v->errorStr() ];
]);
} $v = new Validator($rawAttackerCity);
$v->rules($cityCheck);
$v = new Validator($rawDefenderCity); if(!$v->validate()){
$v->rules($cityCheck); Json::die([
if(!$v->validate()){ 'result'=>false,
Json::die([ 'reason'=>'[출병도시]'.$v->errorStr()
'result'=>false, ]);
'reason'=>'[수비도시]'.$v->errorStr() }
]);
} $v = new Validator($rawDefenderCity);
$v->rules($cityCheck);
$nationCheck = [ if(!$v->validate()){
'required'=>[ Json::die([
'type', 'tech', 'level', 'capital', 'result'=>false,
'nation', 'name', 'gold', 'rice', 'gennum' 'reason'=>'[수비도시]'.$v->errorStr()
], ]);
'integer'=>[ }
'level', 'capital', 'nation', 'gennum',
], $nationCheck = [
'numeric'=>[ 'required'=>[
'tech', 'gold', 'rice' 'type', 'tech', 'level', 'capital',
], 'nation', 'name', 'gold', 'rice', 'gennum'
'min'=>[ ],
['tech', 0], 'integer'=>[
['gold', 0], 'level', 'capital', 'nation', 'gennum',
['rice', 0], ],
['gennum', 1], 'numeric'=>[
], 'tech', 'gold', 'rice'
'in'=>[ ],
['type', GameConst::$availableNationType], 'min'=>[
['level', array_keys(getNationLevelList())] ['tech', 0],
] ['gold', 0],
]; ['rice', 0],
['gennum', 1],
$v = new Validator($rawAttackerNation); ],
$v->rules($nationCheck); 'in'=>[
if(!$v->validate()){ ['type', GameConst::$availableNationType],
Json::die([ ['level', array_keys(getNationLevelList())]
'result'=>false, ]
'reason'=>'[출병국]'.$v->errorStr() ];
]);
} $v = new Validator($rawAttackerNation);
$v->rules($nationCheck);
$v = new Validator($rawDefenderNation); if(!$v->validate()){
$v->rules($nationCheck); Json::die([
if(!$v->validate()){ 'result'=>false,
Json::die([ 'reason'=>'[출병국]'.$v->errorStr()
'result'=>false, ]);
'reason'=>'[수비국]'.$v->errorStr() }
]);
} $v = new Validator($rawDefenderNation);
$v->rules($nationCheck);
if($action == 'reorder'){ if(!$v->validate()){
usort($defenderList, function(General $lhs, General $rhs){ Json::die([
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); 'result'=>false,
}); 'reason'=>'[수비국]'.$v->errorStr()
]);
$order = []; }
foreach($defenderList as $defenderGeneral){
$order[] = $defenderGeneral->getID(); if($action == 'reorder'){
} usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
Json::die([ });
'result'=>true,
'reason'=>'success', $order = [];
'order'=>$order foreach($defenderList as $defenderGeneral){
]); $order[] = $defenderGeneral->getID();
} }
usort($defenderList, function(General $lhs, General $rhs){ Json::die([
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs)); 'result'=>true,
}); 'reason'=>'success',
'order'=>$order
$rawDefenderList = array_map(function(General $general){ ]);
return $general->getRaw(); }
}, $defenderList);
unset($defenderList); usort($defenderList, function(General $lhs, General $rhs){
return -(extractBattleOrder($lhs) <=> extractBattleOrder($rhs));
$db = DB::db(); });
$gameStor = KVStorage::getStorage($db, 'game_env');
$startYear = $gameStor->startyear; $rawDefenderList = array_map(function(General $general){
$cityRate = Util::round(($year - $startYear) / 1.5) + 60; return $general->getRaw();
}, $defenderList);
unset($defenderList);
function simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation, $db = DB::db();
$rawDefenderList, $rawDefenderCity, $rawDefenderNation, $gameStor = KVStorage::getStorage($db, 'game_env');
$startYear, $year, $month, $cityRate $startYear = $gameStor->startyear;
){ $cityRate = Util::round(($year - $startYear) / 1.5) + 60;
$attacker = new WarUnitGeneral(
new General($rawAttacker, null, $rawAttackerCity, $rawAttackerNation, $year, $month), function extractRankVar(array $rawVal):array{
$rawAttackerNation, $rankVars = [];
true foreach($rawVal as $rawKey=>$rawVal){
); if(key_exists($rawKey, General::RANK_COLUMN)){
$city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate); $rankVars[$rawKey] = $rawVal;
}
$iterDefender = new \ArrayIterator($rawDefenderList); }
$iterDefender->rewind(); return $rankVars;
}
$battleResult = [];
function simulateBattle(
$attackerRice = $rawAttacker['rice']; $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$defenderRice = 0; $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) ){
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) { $attacker = new WarUnitGeneral(
if($prevDefender !== null){ new General($rawAttacker, extractRankVar($rawAttacker), $rawAttackerCity, $rawAttackerNation, $year, $month),
$prevDefender->getLogger()->rollback(); $rawAttackerNation,
$battleResult[] = $prevDefender; true
if($prevDefender instanceof WarUnitGeneral){ );
$defenderRice -= $prevDefender->getVar('rice'); $city = new WarUnitCity($rawDefenderCity, $rawDefenderNation, $year, $month, $cityRate);
}
} $iterDefender = new \ArrayIterator($rawDefenderList);
$iterDefender->rewind();
if(!$reqNext){
return null; $battleResult = [];
}
$attackerRice = $rawAttacker['rice'];
if(!$iterDefender->valid()){ $defenderRice = 0;
return null;
} $getNextDefender = function(?WarUnit $prevDefender, bool $reqNext)
use ($iterDefender, $rawDefenderCity, $rawDefenderNation, $year, $month, &$battleResult, &$defenderRice) {
$defenderObj = new General($iterDefender->current(), null, $rawDefenderCity, $rawDefenderNation, $year, $month); if($prevDefender !== null){
if(extractBattleOrder($defenderObj) <= 0){ $prevDefender->getLogger()->rollback();
return null; $battleResult[] = $prevDefender;
} if($prevDefender instanceof WarUnitGeneral){
$defenderRice -= $prevDefender->getVar('rice');
$defenderRice += $defenderObj->getVar('rice'); }
}
$retVal = new WarUnitGeneral(
$defenderObj, if(!$reqNext){
$rawDefenderNation, return null;
false }
);
$iterDefender->next(); if(!$iterDefender->valid()){
return $retVal; return null;
}; }
$conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear); $defenderObj = new General($iterDefender->current(), extractRankVar($iterDefender->current()), $rawDefenderCity, $rawDefenderNation, $year, $month);
if(extractBattleOrder($defenderObj) <= 0){
$rawDefenderCity = $city->getRaw(); return null;
$updateAttackerNation = []; }
$updateDefenderNation = [];
$defenderRice += $defenderObj->getVar('rice');
$attackerRice -= $attacker->getVar('rice');
$retVal = new WarUnitGeneral(
if($city->getPhase() > 0){ $defenderObj,
$rice = $city->getKilled() / 100 * 0.8; $rawDefenderNation,
$rice *= $city->getCrewType()->rice; false
$rice *= getTechCost($rawDefenderNation['tech']); );
$rice *= $cityRate / 100 - 0.2; $iterDefender->next();
Util::setRound($rice); return $retVal;
};
$defenderRice += $rice;
} $conquerCity = processWar_NG($attacker, $getNextDefender, $city, $year - $startYear);
$totalDead = $attacker->getKilled() + $attacker->getDead(); $rawDefenderCity = $city->getRaw();
$attackerCityDead = $totalDead * 0.4; $updateAttackerNation = [];
$defenderCityDead = $totalDead * 0.6; $updateDefenderNation = [];
return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice]; $attackerRice -= $attacker->getVar('rice');
}
if($city->getPhase() > 0){
$lastWarLog = []; $rice = $city->getKilled() / 100 * 0.8;
$rice *= $city->getCrewType()->rice;
$attackerKilled = 0; $rice *= getTechCost($rawDefenderNation['tech']);
$attackerDead = 0; $rice *= $cityRate / 100 - 0.2;
Util::setRound($rice);
$attackerMaxKilled = 0;
$attackerMinKilled = PHP_INT_MAX; $defenderRice += $rice;
}
$attackerMaxDead = 0;
$attackerMinDead = PHP_INT_MAX; $totalDead = $attacker->getKilled() + $attacker->getDead();
$attackerCityDead = $totalDead * 0.4;
$defenderCityDead = $totalDead * 0.6;
$attackerAvgRice = 0;
$defenderAvgRice = 0; return [$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice];
}
$avgPhase = 0;
$avgWar = 0; $lastWarLog = [];
$attackerActivatedSkills = []; $attackerKilled = 0;
$defendersActivatedSkills = []; $attackerDead = 0;
foreach(Util::range($repeatCnt) as $repeatIdx){ $attackerMaxKilled = 0;
/** @var WarUnit $attacker */ $attackerMinKilled = PHP_INT_MAX;
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$rawAttacker, $rawAttackerCity, $rawAttackerNation, $attackerMaxDead = 0;
$rawDefenderList, $rawDefenderCity, $rawDefenderNation, $attackerMinDead = PHP_INT_MAX;
$startYear, $year, $month, $cityRate
);
$lastWarLog = Util::mapWithKey(function($key, $values){ $attackerAvgRice = 0;
return ConvertLog(join('<br>', $values)); $defenderAvgRice = 0;
}, $attacker->getLogger()->rollback());
$avgPhase = 0;
$avgPhase += $attacker->getPhase() / $repeatCnt; $avgWar = 0;
$killed = $attacker->getKilled(); $attackerActivatedSkills = [];
$dead = $attacker->getDead(); $defendersActivatedSkills = [];
$attackerKilled += $killed / $repeatCnt; foreach(Util::range($repeatCnt) as $repeatIdx){
$attackerDead += $dead / $repeatCnt; /** @var WarUnit $attacker */
[$attacker, $city, $battleResult, $conquerCity, $attackerRice, $defenderRice] = simulateBattle(
$attackerMaxKilled = max($attackerMaxKilled, $killed); $rawAttacker, $rawAttackerCity, $rawAttackerNation,
$attackerMinKilled = min($attackerMinKilled, $killed); $rawDefenderList, $rawDefenderCity, $rawDefenderNation,
$startYear, $year, $month, $cityRate
$attackerMaxDead = max($attackerMaxDead, $dead); );
$attackerMinDead = min($attackerMinDead, $dead); $lastWarLog = Util::mapWithKey(function($key, $values){
return ConvertLog(join('<br>', $values));
$attackerAvgRice += $attackerRice / $repeatCnt; }, $attacker->getLogger()->rollback());
$defenderAvgRice += $defenderRice / $repeatCnt;
$avgPhase += $attacker->getPhase() / $repeatCnt;
$avgWar += count($battleResult) / $repeatCnt;
$killed = $attacker->getKilled();
foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){ $dead = $attacker->getDead();
if(!key_exists($skillName, $attackerActivatedSkills)){
$attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt; $attackerKilled += $killed / $repeatCnt;
} $attackerDead += $dead / $repeatCnt;
else{
$attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt; $attackerMaxKilled = max($attackerMaxKilled, $killed);
} $attackerMinKilled = min($attackerMinKilled, $killed);
}
$attackerMaxDead = max($attackerMaxDead, $dead);
foreach($battleResult as $idx=>$defender){ $attackerMinDead = min($attackerMinDead, $dead);
while($idx >= count($defendersActivatedSkills)){
$defendersActivatedSkills[] = []; $attackerAvgRice += $attackerRice / $repeatCnt;
} $defenderAvgRice += $defenderRice / $repeatCnt;
$activatedSkills = &$defendersActivatedSkills[$idx]; $avgWar += count($battleResult) / $repeatCnt;
foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
if(!key_exists($skillName, $activatedSkills)){ foreach($attacker->getActivatedSkillLog() as $skillName => $skillCnt){
$activatedSkills[$skillName] = $skillCnt / $repeatCnt; if(!key_exists($skillName, $attackerActivatedSkills)){
} $attackerActivatedSkills[$skillName] = $skillCnt / $repeatCnt;
else{ }
$activatedSkills[$skillName] += $skillCnt / $repeatCnt; else{
} $attackerActivatedSkills[$skillName] += $skillCnt / $repeatCnt;
} }
}
}
} foreach($battleResult as $idx=>$defender){
while($idx >= count($defendersActivatedSkills)){
Json::die([ $defendersActivatedSkills[] = [];
'result'=>true, }
'datetime'=>$rawAttacker['turntime'],
'reason'=>'success', $activatedSkills = &$defendersActivatedSkills[$idx];
'lastWarLog'=>$lastWarLog, foreach($defender->getActivatedSkillLog() as $skillName => $skillCnt){
'avgWar'=>$avgWar, if(!key_exists($skillName, $activatedSkills)){
'phase'=>$avgPhase, $activatedSkills[$skillName] = $skillCnt / $repeatCnt;
'killed'=>$attackerKilled, }
'maxKilled'=>$attackerMaxKilled, else{
'minKilled'=>$attackerMinKilled, $activatedSkills[$skillName] += $skillCnt / $repeatCnt;
'dead'=>$attackerDead, }
'maxDead'=>$attackerMaxDead, }
'minDead'=>$attackerMinDead,
'attackerRice'=>$attackerAvgRice, }
'defenderRice'=>$defenderAvgRice, }
'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills'=>$defendersActivatedSkills, Json::die([
]); 'result'=>true,
'datetime'=>$rawAttacker['turntime'],
'reason'=>'success',
'lastWarLog'=>$lastWarLog,
'avgWar'=>$avgWar,
'phase'=>$avgPhase,
'killed'=>$attackerKilled,
'maxKilled'=>$attackerMaxKilled,
'minKilled'=>$attackerMinKilled,
'dead'=>$attackerDead,
'maxDead'=>$attackerMaxDead,
'minDead'=>$attackerMinDead,
'attackerRice'=>$attackerAvgRice,
'defenderRice'=>$defenderAvgRice,
'attackerSkills'=>$attackerActivatedSkills,
'defendersSkills'=>$defendersActivatedSkills,
]);
+151
View File
@@ -0,0 +1,151 @@
<?php
namespace sammo;
include "lib.php";
include "func.php";
WebUtil::requireAJAX();
$pick = Util::getPost('pick');
if(!$pick){
Json::die([
'result'=>false,
'reason'=>'장수를 선택하지 않았습니다'
]);
}
$session = Session::requireLogin([])->setReadOnly();
$userID = Session::getUserID();
$db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env');
$rootDB = RootDB::db();
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$generalID = $db->queryFirstField('SELECT no FROM general WHERE owner = %i', $userID);
if(!$generalID){
Json::die([
'result'=>false,
'reason'=>'장수가 생성하지 않았습니다. 이미 사망하지 않았는지 확인해보세요.'
]);
}
list(
$year,
$month,
$maxgeneral,
$npcmode,
$turnterm
) = $gameStor->getValuesAsArray(['year', 'month', 'maxgeneral', 'npcmode', 'turnterm']);
if($npcmode!=2){
Json::die([
'result'=>false,
'reason'=>'선택 가능한 서버가 아닙니다'
]);
}
$info = $db->queryFirstField('SELECT info FROM select_pool WHERE `owner` = %i AND `reserved_until`>=%s AND `unique_name`=%s', $userID, $now, $pick);
if(!$info){
Json::die([
'result'=>false,
'reason'=>'유효한 장수 목록이 없습니다.'
]);
}
$ownerInfo = RootDB::db()->queryFirstRow('SELECT `name`,`picture`,`imgsvr` FROM member WHERE `NO`=%i',$userID);
if(!$ownerInfo){
Json::die([
'result'=>false,
'reason'=>'멤버 정보를 가져오지 못했습니다.'
]);
}
$info = Json::decode($info);
$generalObj = General::createGeneralObjFromDB($generalID);
$oldGeneralName = $generalObj->getName();
$db->update('select_pool', [
'general_id'=>-$generalID,
'owner'=>null,
'reserved_until'=>null
], 'unique_name=%s AND `reserved_until` IS NOT NULL AND owner = %i', $info['uniqueName'], $userID);
if($db->affectedRows()==0){
Json::die([
'result'=>false,
'reason'=>'동시성 제어에 문제가 발생했습니다. 버그 제보를 부탁드립니다.'
]);
}
$db->update('select_pool', [
'general_id'=>null,
'owner'=>null,
'reserved_until'=>null,
], 'unique_name != %s AND general_id = %i', $info['uniqueName'], $generalID);
$db->update('select_pool', [
'general_id'=>$generalID,
], 'general_id=%i', -$generalID);
if($db->affectedRows()==0){
Json::die([
'result'=>false,
'reason'=>'장수 선택 과정에 문제가 발생했습니다.. 버그 제보를 부탁드립니다.'
]);
}
$db->update('select_pool',[
'owner'=>null,
'reserved_until'=>null,
], '(owner=%i or reserved_until < %s) AND general_id is NULL', $userID, $now);
if(key_exists('leadership', $info)){
$generalObj->updateVar('leadership', $info['leadership']);
$generalObj->updateVar('strength', $info['strength']);
$generalObj->updateVar('intel', $info['intel']);
}
if(key_exists('picture', $info)){
$generalObj->updateVar('imgsvr', $info['imgsvr']);
$generalObj->updateVar('picture', $info['picture']);
}
if(key_exists('generalName', $info)){
$generalObj->updateVar('name', $info['generalName']);
}
if(key_exists('dex', $info)){
$generalObj->updateVar('dex1', $info['dex'][0]);
$generalObj->updateVar('dex2', $info['dex'][1]);
$generalObj->updateVar('dex3', $info['dex'][2]);
$generalObj->updateVar('dex4', $info['dex'][3]);
$generalObj->updateVar('dex5', $info['dex'][4]);
}
if(key_exists('ego', $info)){
$generalObj->updateVar('personal', $info['ego']);
}
if(key_exists('specialDomestic', $info)){
$generalObj->updateVar('special', $info['specialDomestic']);
}
if(key_exists('specialWar', $info)){
$generalObj->updateVar('special2', $info['specialWar']);
}
$generalObj->setAuxVar('next_change', TimeUtil::nowAddMinutes(12 * $turnterm));
$userNick = $ownerInfo['name'];
$generalObj->setVar('owner_name', $userNick);
$josaYi = JosaUtil::pick($userNick, '이');
$generalName = $info['generalName'];
$josaRo = JosaUtil::pick($generalName, '로');
$logger = $generalObj->getLogger();
$logger->pushGeneralHistoryLog("장수를 <Y>{$oldGeneralName}</>에서 <Y>{$generalName}</>{$josaRo} 변경");
$logger->pushGlobalActionLog("<Y>{$userNick}</>{$josaYi} 장수를 <Y>{$oldGeneralName}</>에서 <Y>{$generalName}</>{$josaRo} 변경합니다.");
$generalObj->applyDB($db);
Json::die([
'result'=>true,
'reason'=>'success'
]);
+6 -2
View File
@@ -24,7 +24,12 @@ if (!$member) {
$db = DB::db(); $db = DB::db();
$gameStor = KVStorage::getStorage($db, 'game_env'); $gameStor = KVStorage::getStorage($db, 'game_env');
$admin = $gameStor->getValues(['block_general_create','show_img_level','maxgeneral']);
if($admin['block_general_create']){
MessageBox("잘못된 접근입니다!!!");
echo "<script>history.go(-1);</script>";
exit(1);
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@@ -66,7 +71,6 @@ echo Json::encode((object)$charInfoText);
<tr><td align=center><?=info(0)?></td></tr> <tr><td align=center><?=info(0)?></td></tr>
</table> </table>
<?php <?php
$admin = $gameStor->getValues(['show_img_level','maxgeneral']);
$gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc<2'); $gencount = $db->queryFirstField('SELECT count(no) FROM general WHERE npc<2');
+4 -2
View File
@@ -185,10 +185,10 @@ if($relYear < 3){
$experience = 0; $experience = 0;
} }
else{ else{
$expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 5'); $expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4');
$targetGenOrder = Util::round($expGenCount * 0.2); $targetGenOrder = Util::round($expGenCount * 0.2);
$experience = $db->queryFirstField( $experience = $db->queryFirstField(
'SELECT experience FROM general WHERE nation != 0 AND npc < 5 ORDER BY experience ASC LIMIT %i, 1', 'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1',
$targetGenOrder - 1 $targetGenOrder - 1
); );
$experience *= 0.8; $experience *= 0.8;
@@ -266,6 +266,8 @@ foreach(Util::range(GameConst::$maxTurn) as $turnIdx){
} }
$db->insert('general_turn', $turnRows); $db->insert('general_turn', $turnRows);
resetInheritanceUser($userID);
$rank_data = []; $rank_data = [];
foreach(array_keys(General::RANK_COLUMN) as $rankColumn){ foreach(array_keys(General::RANK_COLUMN) as $rankColumn){
$rank_data[] = [ $rank_data[] = [
+931 -799
View File
@@ -1,800 +1,932 @@
jQuery(function($){ jQuery(function($) {
var $generalForm = $('.form_sample .general_detail'); var $generalForm = $('.form_sample .general_detail');
var $defenderHeaderForm = $('.form_sample .card-header'); var $defenderHeaderForm = $('.form_sample .card-header');
var $defenderColumn = $('.defender-column'); var $defenderColumn = $('.defender-column');
var defenderNoList = {}; var defenderNoList = {};
var $attackerCard = $('.attacker_form'); var $attackerCard = $('.attacker_form');
var initBasicEvent = function(){ var initBasicEvent = function() {
$('.form_injury').change(function(){ if (window.nation) {
var $this = $(this); $('.form_city_level').val(window.city.level);
var $general = getGeneralDetail($this); $('.form_def').val(parseInt(window.city.def));
var $helptext = $general.find('.injury_helptext'); $('.form_wall').val(parseInt(window.city.wall));
$('.form_nation_type').val(window.nation.type);
var injury = parseInt($this.val()); $('.form_nation_level').val(window.nation.level);
//FIXME: PHP 코드와 항상 일치하도록 변경 $('.form_tech').val(parseInt(window.nation.tech / 1000));
var text = '건강'; if (window.nation.capital == window.city.city) {
var color = 'white'; $('.attacker_nation .form_is_capital:first').click();
if(injury > 60){ $('.defender_nation .form_is_capital:first').click();
text = '위독'; } else {
color = 'red'; $('.attacker_nation .form_is_capital:last').click();
} $('.defender_nation .form_is_capital:last').click();
else if(injury > 40){ }
text = '심각'; } else {
color = 'magenta'; $('.attacker_nation .form_is_capital:last').click();
} $('.defender_nation .form_is_capital:last').click();
else if(injury > 20){ }
text = '중상';
color = 'orange'; $('.form_injury').change(function() {
} var $this = $(this);
else if(injury > 0){ var $general = getGeneralDetail($this);
text = '경상'; var $helptext = $general.find('.injury_helptext');
color = 'yellow';
} var injury = parseInt($this.val());
$helptext.html(text).css('color', color); //FIXME: PHP 코드와 항상 일치하도록 변경
}); var text = '건강';
var color = 'white';
$('.export_general').click(function(){ if (injury > 60) {
var $btn = $(this); text = '위독';
var $general = getGeneralDetail($btn); color = 'red';
} else if (injury > 40) {
var values = exportGeneralInfo($general); text = '심각';
console.log(values); color = 'magenta';
}); } else if (injury > 20) {
$('.delete-defender').click(function(){ text = '중상';
var $card = getGeneralFrame($(this)); color = 'orange';
deleteDefender($card); } else if (injury > 0) {
}); text = '경상';
$('.copy-defender').click(function(){ color = 'yellow';
var $card = getGeneralFrame($(this)); }
copyDefender($card); $helptext.html(text).css('color', color);
}); });
$('.add-defender').click(function(){ $('.export_general').click(function() {
addDefender(); var $btn = $(this);
}); var $general = getGeneralDetail($btn);
$('.btn-general-load').click(function(){ var values = exportGeneralInfo($general);
var $file = $(this).prev(); console.log(values);
$file[0].click(); });
}) $('.delete-defender').click(function() {
var $card = getGeneralFrame($(this));
$('.form_load_general_file').on('change', function(e){ deleteDefender($card);
e.preventDefault(); });
var $this = $(this); $('.copy-defender').click(function() {
var $card = getGeneralFrame($this); var $card = getGeneralFrame($(this));
copyDefender($card);
var files = e.target.files; });
importGeneralInfoByFile(files, $card); $('.add-defender').click(function() {
return false; addDefender();
}); });
$('.btn-general-save').click(function(){ $('.btn-general-load').click(function() {
var $this = $(this); var $file = $(this).prev();
var $general = getGeneralDetail($this); $file[0].click();
var generalData = exportGeneralInfo($general); })
var filename = "general_{0}.json".format(generalData.name); $('.form_load_general_file').on('change', function(e) {
var saveData = JSON.stringify({ e.preventDefault();
objType:'general', var $this = $(this);
data:generalData var $card = getGeneralFrame($this);
}, null, 4);
var files = e.target.files;
download(saveData, filename, 'application/json');
}); importGeneralInfoByFile(files, $card);
return false;
$('.btn-battle-load').click(function(){ });
var $file = $(this).prev();
$file[0].click(); $('.btn-general-import-server').click(function() {
}) var $this = $(this);
var $card = getGeneralFrame($this);
$('.form_load_battle_file').on('change', function(e){
e.preventDefault(); var $modal = $('#importModal');
var $this = $(this); $modal.data('target', $card);
var files = e.target.files; $modal.modal('show');
});
importBattleInfoByFile(files);
return false; $('.btn-general-save').click(function() {
}); var $this = $(this);
var $general = getGeneralDetail($this);
$('.btn-battle-save').click(function(){ var generalData = exportGeneralInfo($general);
var battleData = exportAllData();
var filename = "battle_{0}.json".format(moment().format('YYYYMMDD_hhmmss')); var filename = "general_{0}.json".format(generalData.name);
var saveData = JSON.stringify({ var saveData = JSON.stringify({
objType:'battle', objType: 'general',
data:battleData data: generalData
}, null, 4); }, null, 4);
download(saveData, filename, 'application/json'); download(saveData, filename, 'application/json');
}) });
var $generals = $('.general_detail'); $('.btn-battle-load').click(function() {
$generals.bind('dragover dragleave', function(e) { var $file = $(this).prev();
e.stopPropagation() $file[0].click();
e.preventDefault() })
})
$generals.bind('drop', function(e){ $('.form_load_battle_file').on('change', function(e) {
e.preventDefault(); e.preventDefault();
var $this = $(this); var $this = $(this);
var $card = getGeneralFrame($this); var files = e.target.files;
var files = e.originalEvent.dataTransfer.files; importBattleInfoByFile(files);
return false;
importGeneralInfoByFile(files, $card); });
return false;
}); $('.btn-battle-save').click(function() {
var battleData = exportAllData();
var $battlePad = $('.dragpad_battle'); var filename = "battle_{0}.json".format(moment().format('YYYYMMDD_hhmmss'));
$battlePad.bind('dragover dragleave', function(e) { var saveData = JSON.stringify({
e.stopPropagation() objType: 'battle',
e.preventDefault() data: battleData
}) }, null, 4);
$battlePad.bind('drop', function(e){
e.preventDefault(); download(saveData, filename, 'application/json');
})
var files = e.originalEvent.dataTransfer.files;
var $generals = $('.general_detail');
importBattleInfoByFile(files); $generals.bind('dragover dragleave', function(e) {
return false; e.stopPropagation()
}); e.preventDefault()
} })
$generals.bind('drop', function(e) {
var importGeneralInfo = function($general, data){ e.preventDefault();
var setVal = function(query, val){ var $this = $(this);
$general.find(query).val(val).change(); var $card = getGeneralFrame($this);
}
var files = e.originalEvent.dataTransfer.files;
setVal('.form_general_name', data.name);
importGeneralInfoByFile(files, $card);
setVal('.form_officer_level', data.officer_level); return false;
setVal('.form_exp_level', data.explevel); });
setVal('.form_injury', data.injury);
var $battlePad = $('.dragpad_battle');
setVal('.form_leadership', data.leadership); $battlePad.bind('dragover dragleave', function(e) {
setVal('.form_general_horse', data.horse); e.stopPropagation()
setVal('.form_strength', data.strength); e.preventDefault()
setVal('.form_general_weap', data.weapon); })
setVal('.form_intel', data.intel); $battlePad.bind('drop', function(e) {
setVal('.form_general_book', data.book); e.preventDefault();
setVal('.form_general_item', data.item);
var files = e.originalEvent.dataTransfer.files;
setVal('.form_injury', data.injury);
importBattleInfoByFile(files);
setVal('.form_rice', data.rice); return false;
});
setVal('.form_general_character', data.personal); }
setVal('.form_general_special_war', data.special2);
var importGeneralInfo = function($general, data) {
setVal('.form_crew', data.crew); var setVal = function(query, val) {
setVal('.form_crewtype', data.crewtype); $general.find(query).val(val).change();
setVal('.form_atmos', data.atmos); }
setVal('.form_train', data.train);
setVal('.form_general_name', data.name);
setVal('.form_dex1', data.dex1);
setVal('.form_dex2', data.dex2); setVal('.form_officer_level', data.officer_level);
setVal('.form_dex3', data.dex3); setVal('.form_exp_level', data.explevel);
setVal('.form_dex4', data.dex4);
setVal('.form_dex5', data.dex5); setVal('.form_leadership', data.leadership);
setVal('.form_defence_train', data.defence_train); setVal('.form_general_horse', data.horse);
setVal('.form_strength', data.strength);
if(!setGeneralNo($general, data.no)){ setVal('.form_general_weap', data.weapon);
setGeneralNo($general, generateNewGeneralNo()); setVal('.form_intel', data.intel);
} setVal('.form_general_book', data.book);
} setVal('.form_general_item', data.item);
var exportGeneralInfo = function($general){ setVal('.form_injury', data.injury);
var getInt = function(query){
return parseInt($general.find(query).val()); setVal('.form_rice', data.rice);
}
setVal('.form_general_character', data.personal);
var getVal = function(query){ setVal('.form_general_special_war', data.special2);
return $general.find(query).val();
} setVal('.form_crew', data.crew);
setVal('.form_crewtype', data.crewtype);
return { setVal('.form_atmos', data.atmos);
no:getGeneralNo($general), setVal('.form_train', data.train);
name:getVal('.form_general_name'),
officer_level:getInt('.form_officer_level'), setVal('.form_dex1', data.dex1);
explevel:getInt('.form_exp_level'), setVal('.form_dex2', data.dex2);
setVal('.form_dex3', data.dex3);
leadership:getInt('.form_leadership'), setVal('.form_dex4', data.dex4);
horse:getVal('.form_general_horse'), setVal('.form_dex5', data.dex5);
strength:getInt('.form_strength'), setVal('.form_defence_train', data.defence_train);
weapon:getVal('.form_general_weap'),
intel:getInt('.form_intel'), setVal('.form_warnum', data.warnum);
book:getVal('.form_general_book'), setVal('.form_killnum', data.killnum);
item:getVal('.form_general_item'), setVal('.form_killcrew', data.killcrew);
injury:getInt('.form_injury'), if (!setGeneralNo($general, data.no)) {
setGeneralNo($general, generateNewGeneralNo());
rice:getInt('.form_rice'), }
}
personal:getVal('.form_general_character'),
special2:getVal('.form_general_special_war'), var exportGeneralInfo = function($general) {
var getInt = function(query) {
crew:getInt('.form_crew'), return parseInt($general.find(query).val());
crewtype:getInt('.form_crewtype'), }
atmos:getInt('.form_atmos'),
train:getInt('.form_train'), var getVal = function(query) {
return $general.find(query).val();
dex1:getInt('.form_dex1'), }
dex2:getInt('.form_dex2'),
dex3:getInt('.form_dex3'), return {
dex4:getInt('.form_dex4'), no: getGeneralNo($general),
dex5:getInt('.form_dex5'), name: getVal('.form_general_name'),
defence_train:getInt('.form_defence_train'), officer_level: getInt('.form_officer_level'),
}; explevel: getInt('.form_exp_level'),
}
leadership: getInt('.form_leadership'),
var importBattleInfoByFile = function(files){ horse: getVal('.form_general_horse'),
if(files === null){ strength: getInt('.form_strength'),
alert('파일 에러!'); weapon: getVal('.form_general_weap'),
return false; intel: getInt('.form_intel'),
} book: getVal('.form_general_book'),
item: getVal('.form_general_item'),
if(files.length < 1){
alert("파일 에러!"); injury: getInt('.form_injury'),
return false;
} rice: getInt('.form_rice'),
personal: getVal('.form_general_character'),
var file = files[0]; special2: getVal('.form_general_special_war'),
if(file.size > 1024*1024){
alert('파일이 너무 큽니다!'); crew: getInt('.form_crew'),
return false; crewtype: getInt('.form_crewtype'),
} atmos: getInt('.form_atmos'),
if(file.type === ''){ train: getInt('.form_train'),
alert('폴더를 업로드할 수 없습니다!');
return false; dex1: getInt('.form_dex1'),
} dex2: getInt('.form_dex2'),
dex3: getInt('.form_dex3'),
var reader = new FileReader(); dex4: getInt('.form_dex4'),
reader.onload = function(){ dex5: getInt('.form_dex5'),
var battleData = {};
try { defence_train: getInt('.form_defence_train'),
battleData = JSON.parse(reader.result);
} catch(e) { warnum: getInt('.form_warnum'),
alert('올바르지 않은 파일 형식입니다'); killnum: getInt('.form_killnum'),
return false; killcrew: getInt('.form_killcrew'),
}
};
if(!('objType' in battleData)){ }
alert('파일 형식을 확인할 수 없습니다');
return false; var importBattleInfoByFile = function(files) {
} if (files === null) {
alert('파일 에러!');
if(battleData.objType != 'battle'){ return false;
alert('전투 데이터가 아닙니다'); }
return false;
} if (files.length < 1) {
alert("파일 에러!");
importBattleInfo(battleData.data); return false;
return true; }
};
try { var file = files[0];
if (file.size > 1024 * 1024) {
reader.readAsText(file); alert('파일이 너무 큽니다!');
} return false;
catch(e) { }
alert('파일을 읽는데 실패했습니다.'); if (file.type === '') {
return false; alert('폴더를 업로드할 수 없습니다!');
} return false;
}
return true;
} var reader = new FileReader();
reader.onload = function() {
var importGeneralInfoByFile = function(files, $card){ var battleData = {};
if($card === undefined){ try {
$card = addDefender(); battleData = JSON.parse(reader.result);
} } catch (e) {
alert('올바르지 않은 파일 형식입니다');
if(files === null){ return false;
alert('파일 에러!'); }
return false;
} if (!('objType' in battleData)) {
alert('파일 형식을 확인할 수 없습니다');
if(files.length < 1){ return false;
alert("파일 에러!"); }
return false;
} if (battleData.objType != 'battle') {
alert('전투 데이터가 아닙니다');
return false;
var file = files[0]; }
if(file.size > 1024*1024){
alert('파일이 너무 큽니다!'); importBattleInfo(battleData.data);
return false; return true;
} };
if(file.type === ''){
alert('폴더를 업로드할 수 없습니다!'); try {
return false;
} reader.readAsText(file);
} catch (e) {
var reader = new FileReader(); alert('파일을 읽는데 실패했습니다.');
reader.onload = function(){ return false;
var generalData = {}; }
try {
generalData = JSON.parse(reader.result); return true;
} catch(e) { }
alert('올바르지 않은 파일 형식입니다');
return false; var importGeneralInfoByFile = function(files, $card) {
} if ($card === undefined) {
$card = addDefender();
if(!('objType' in generalData)){ }
alert('파일 형식을 확인할 수 없습니다');
return false; if (files === null) {
} alert('파일 에러!');
return false;
if(generalData.objType == 'battle'){ }
importBattleInfo(generalData.data);
return true; if (files.length < 1) {
} alert("파일 에러!");
if(generalData.objType != 'general'){ return false;
alert('장수 데이터가 아닙니다'); }
return false;
}
var file = files[0];
$card.find('.form_load_general_file').val(''); if (file.size > 1024 * 1024) {
alert('파일이 너무 큽니다!');
importGeneralInfo($card, generalData.data); return false;
return true; }
}; if (file.type === '') {
alert('폴더를 업로드할 수 없습니다!');
try { return false;
}
reader.readAsText(file);
} var reader = new FileReader();
catch(e) { reader.onload = function() {
alert('파일을 읽는데 실패했습니다.'); var generalData = {};
return false; try {
} generalData = JSON.parse(reader.result);
} catch (e) {
return true; alert('올바르지 않은 파일 형식입니다');
} return false;
}
var extendGeneralInfoForDB = function(generalData){
if (!('objType' in generalData)) {
var dbVal = { alert('파일 형식을 확인할 수 없습니다');
nation: (generalData.no)<=1 ? 1 : 2, return false;
city: (generalData.no)<=1 ? 1 : 3, }
turntime:'2018-08-26 12:00',
special:defaultSpecialDomestic, if (generalData.objType == 'battle') {
leadership_exp:0, importBattleInfo(generalData.data);
strength_exp:0, return true;
intel_exp:0, }
if (generalData.objType != 'general') {
gold:10000, alert('장수 데이터가 아닙니다');
return false;
dedication:0, }
recent_war:'2018-08-26 12:00', $card.find('.form_load_general_file').val('');
experience:Math.pow(generalData.explevel, 2),
}; importGeneralInfo($card, generalData.data);
return true;
return $.extend({}, generalData, dbVal); };
}
try {
var getGeneralFrame = function($btn){
var $card = $btn.closest('.general_form'); reader.readAsText(file);
return $card; } catch (e) {
} alert('파일을 읽는데 실패했습니다.');
return false;
var getGeneralDetail = function($btn){ }
var $card = getGeneralFrame($btn);
var $general = $card.find('.general_detail'); return true;
return $general; }
}
var extendGeneralInfoForDB = function(generalData) {
var getGeneralNo = function($btn){
return parseInt(getGeneralFrame($btn).data('general_no')); var dbVal = {
} nation: (generalData.no) <= 1 ? 1 : 2,
city: (generalData.no) <= 1 ? 1 : 3,
var setGeneralNo = function($btn, value){ turntime: '2018-08-26 12:00',
if(value == 1){ special: defaultSpecialDomestic,
//1번은 무조건 공격자임 leadership_exp: 0,
return false; strength_exp: 0,
} intel_exp: 0,
if(value in defenderNoList){
return false; gold: 10000,
}
var $card = getGeneralFrame($btn); dedication: 0,
$card.data('general_no', value);
defenderNoList[value] = $card; recent_war: '2018-08-26 12:00',
return true; experience: Math.pow(generalData.explevel, 2),
} };
var generateNewGeneralNo = function(){ return $.extend({}, generalData, dbVal);
while(true){ }
var newGeneralNo = parseInt(Math.random()*(1<<24))+2;
if(newGeneralNo in defenderNoList){ var getGeneralFrame = function($btn) {
continue; var $card = $btn.closest('.general_form');
} return $card;
return newGeneralNo; }
}
} var getGeneralDetail = function($btn) {
var $card = getGeneralFrame($btn);
var deleteGeneralNo = function($btn){ var $general = $card.find('.general_detail');
var $card = getGeneralFrame($btn); return $general;
$card.removeData('general_no'); }
var generalNo = getGeneralNo($card);
delete defenderNoList[generalNo]; var getGeneralNo = function($btn) {
} return parseInt(getGeneralFrame($btn).data('general_no'));
}
var addDefender = function($cardAfter){
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>'); var setGeneralNo = function($btn, value) {
if (value == 1) {
if($cardAfter === undefined){ //1번은 무조건 공격자임
$defenderColumn.append($newCard); return false;
} }
else{ if (value in defenderNoList) {
$cardAfter.after($newCard); return false;
} }
var $card = getGeneralFrame($btn);
$newCard.append($defenderHeaderForm.clone(true,true)); $card.data('general_no', value);
$newCard.append($generalForm.clone(true,true)); defenderNoList[value] = $card;
return true;
$newGeneral = getGeneralDetail($newCard); }
setGeneralNo($newCard, generateNewGeneralNo());
var generateNewGeneralNo = function() {
return $newCard; while (true) {
} var newGeneralNo = parseInt(Math.random() * (1 << 24)) + 2;
if (newGeneralNo in defenderNoList) {
var deleteDefender = function($card){ continue;
deleteGeneralNo($card); }
$card.detach(); return newGeneralNo;
} }
}
var copyDefender = function($card){
var $general = getGeneralDetail($card); var deleteGeneralNo = function($btn) {
var $card = getGeneralFrame($btn);
var generalData = exportGeneralInfo($general); $card.removeData('general_no');
var $newObj = addDefender($card); var generalNo = getGeneralNo($card);
importGeneralInfo(getGeneralDetail($newObj), generalData); delete defenderNoList[generalNo];
} }
var importBattleInfo = function(battleData){ var addDefender = function($cardAfter) {
var $newCard = $('<div class="card mb-2 defender_form general_form"></div>');
$('.form_load_battle_file').val('');
console.log(battleData); if ($cardAfter === undefined) {
$defenderColumn.append($newCard);
var $attackerNation = $('.attacker_nation'); } else {
var $defenderNation = $('.defender_nation'); $cardAfter.after($newCard);
}
var attackerGeneral = battleData.attackerGeneral;
var attackerCity = battleData.attackerCity; $newCard.append($defenderHeaderForm.clone(true, true));
var attackerNation = battleData.attackerNation; $newCard.append($generalForm.clone(true, true));
var defenderGenerals = battleData.defenderGenerals; $newGeneral = getGeneralDetail($newCard);
var defenderCity = battleData.defenderCity; setGeneralNo($newCard, generateNewGeneralNo());
var defenderNation = battleData.defenderNation;
return $newCard;
$('#year').val(battleData.year); }
$('#month').val(battleData.month);
$('#repeat_cnt').val(battleData.repeatCnt); var deleteDefender = function($card) {
deleteGeneralNo($card);
$('.delete-defender').click(); $card.detach();
}
$attackerNation.find('.form_nation_type').val(attackerNation.type);
$attackerNation.find('.form_tech').val(Math.floor(attackerNation.tech/1000)); var copyDefender = function($card) {
$attackerNation.find('.form_nation_level').val(attackerNation.level); var $general = getGeneralDetail($card);
if(attackerNation.capital == 1){
$attackerNation.find('.form_is_capital:first').click(); var generalData = exportGeneralInfo($general);
} var $newObj = addDefender($card);
else{ importGeneralInfo(getGeneralDetail($newObj), generalData);
$attackerNation.find('.form_is_capital:last').click(); }
}
$attackerNation.find('.form_city_level').val(attackerCity.level); var importBattleInfo = function(battleData) {
importGeneralInfo($('.attacker_form'), attackerGeneral); $('.form_load_battle_file').val('');
console.log(battleData);
$defenderNation.find('.form_nation_type').val(defenderNation.type);
$defenderNation.find('.form_tech').val(Math.floor(defenderNation.tech/1000)); var $attackerNation = $('.attacker_nation');
$defenderNation.find('.form_nation_level').val(defenderNation.level); var $defenderNation = $('.defender_nation');
if(defenderNation.capital == 1){
$defenderNation.find('.form_is_capital:first').click(); var attackerGeneral = battleData.attackerGeneral;
} var attackerCity = battleData.attackerCity;
else{ var attackerNation = battleData.attackerNation;
$defenderNation.find('.form_is_capital:last').click();
} var defenderGenerals = battleData.defenderGenerals;
$defenderNation.find('.form_city_level').val(defenderCity.level); var defenderCity = battleData.defenderCity;
$('#city_def').val(defenderCity.def); var defenderNation = battleData.defenderNation;
$('#city_wall').val(defenderCity.wall);
$('#year').val(battleData.year);
$.each(defenderGenerals, function(idx, defenderGeneral){ $('#month').val(battleData.month);
var $card = addDefender(); $('#repeat_cnt').val(battleData.repeatCnt);
importGeneralInfo($card, defenderGeneral);
}); $('.delete-defender').click();
}
$attackerNation.find('.form_nation_type').val(attackerNation.type);
var exportAllData = function(){ $attackerNation.find('.form_tech').val(Math.floor(attackerNation.tech / 1000));
var $attackerNation = $('.attacker_nation'); $attackerNation.find('.form_nation_level').val(attackerNation.level);
var $defenderNation = $('.defender_nation'); if (attackerNation.capital == 1) {
$attackerNation.find('.form_is_capital:first').click();
var attackerGeneral = exportGeneralInfo($('.attacker_form')); } else {
$attackerNation.find('.form_is_capital:last').click();
var attackerCity = { }
level:parseInt($attackerNation.find('.form_city_level').val()), $attackerNation.find('.form_city_level').val(attackerCity.level);
};
importGeneralInfo($('.attacker_form'), attackerGeneral);
var attackerNation = {
type:$attackerNation.find('.form_nation_type').val(), $defenderNation.find('.form_nation_type').val(defenderNation.type);
tech:parseInt($attackerNation.find('.form_tech').val()) * 1000, $defenderNation.find('.form_tech').val(Math.floor(defenderNation.tech / 1000));
level:parseInt($attackerNation.find('.form_nation_level').val()), $defenderNation.find('.form_nation_level').val(defenderNation.level);
capital:$attackerNation.find('.form_is_capital:checked').val()=='1'?1:2, if (defenderNation.capital == 1) {
} $defenderNation.find('.form_is_capital:first').click();
} else {
var defenderGenerals = $('.defender_form').map(function(){ $defenderNation.find('.form_is_capital:last').click();
return exportGeneralInfo($(this)); }
}).toArray(); $defenderNation.find('.form_city_level').val(defenderCity.level);
$('#city_def').val(defenderCity.def);
var defenderCity = { $('#city_wall').val(defenderCity.wall);
def: parseInt($('#city_def').val()),
wall: parseInt($('#city_wall').val()), $.each(defenderGenerals, function(idx, defenderGeneral) {
level:parseInt($defenderNation.find('.form_city_level').val()), var $card = addDefender();
}; importGeneralInfo($card, defenderGeneral);
});
var defenderNation = { }
type:$defenderNation.find('.form_nation_type').val(),
tech:parseInt($defenderNation.find('.form_tech').val()) * 1000, var exportAllData = function() {
level:parseInt($defenderNation.find('.form_nation_level').val()), var $attackerNation = $('.attacker_nation');
capital:$defenderNation.find('.form_is_capital:checked').val()=='1'?3:4, var $defenderNation = $('.defender_nation');
}
var attackerGeneral = exportGeneralInfo($('.attacker_form'));
var year = parseInt($('#year').val());
var month = parseInt($('#month').val()); var attackerCity = {
var repeatCnt = parseInt($('#repeat_cnt').val()); level: parseInt($attackerNation.find('.form_city_level').val()),
};
return {
attackerGeneral:attackerGeneral, var attackerNation = {
attackerCity:attackerCity, type: $attackerNation.find('.form_nation_type').val(),
attackerNation:attackerNation, tech: parseInt($attackerNation.find('.form_tech').val()) * 1000,
level: parseInt($attackerNation.find('.form_nation_level').val()),
defenderGenerals:defenderGenerals, capital: $attackerNation.find('.form_is_capital:checked').val() == '1' ? 1 : 2,
defenderCity:defenderCity, }
defenderNation:defenderNation,
var defenderGenerals = $('.defender_form').map(function() {
year:year, return exportGeneralInfo($(this));
month:month, }).toArray();
repeatCnt:repeatCnt,
}; var defenderCity = {
} def: parseInt($('#city_def').val()),
wall: parseInt($('#city_wall').val()),
var extendAllDataForDB = function(allData){ level: parseInt($defenderNation.find('.form_city_level').val()),
var defaultNation = { };
nation:0,
name:'재야', var defenderNation = {
capital:0, type: $defenderNation.find('.form_nation_type').val(),
level:0, tech: parseInt($defenderNation.find('.form_tech').val()) * 1000,
gold:0, level: parseInt($defenderNation.find('.form_nation_level').val()),
rice:2000, capital: $defenderNation.find('.form_is_capital:checked').val() == '1' ? 3 : 4,
type:'None', }
tech:0,
gennum:200, var year = parseInt($('#year').val());
}; var month = parseInt($('#month').val());
var repeatCnt = parseInt($('#repeat_cnt').val());
var defaultCity = {
nation:0, return {
supply:1, attackerGeneral: attackerGeneral,
name:'도시', attackerCity: attackerCity,
attackerNation: attackerNation,
pop:500000,
agri:10000, defenderGenerals: defenderGenerals,
comm:10000, defenderCity: defenderCity,
secu:10000, defenderNation: defenderNation,
def:1000,
wall:1000, year: year,
month: month,
trust:100, repeatCnt: repeatCnt,
};
pop_max:600000, }
agri_max:12000,
comm_max:12000, var extendAllDataForDB = function(allData) {
secu_max:10000, var defaultNation = {
def_max:12000, nation: 0,
wall_max:12000, name: '재야',
capital: 0,
dead:0, level: 0,
gold: 0,
state:0, rice: 2000,
type: 'None',
conflict:'{}', tech: 0,
}; gennum: 200,
};
var attackerNation = $.extend({}, defaultNation, allData.attackerNation);
attackerNation.nation = 1; var defaultCity = {
attackerNation.name = '출병국'; nation: 0,
supply: 1,
var attackerCity = $.extend({}, defaultCity, allData.attackerCity); name: '도시',
attackerCity.nation = 1;
attackerCity.city = 1; pop: 500000,
agri: 10000,
var attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral); comm: 10000,
if(2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4){ secu: 10000,
attackerGeneral.officer_city = 1; def: 1000,
} wall: 1000,
else{
attackerGeneral.officer_city = 0; trust: 100,
}
pop_max: 600000,
var defenderNation = $.extend({}, defaultNation, allData.defenderNation); agri_max: 12000,
defenderNation.nation = 2; comm_max: 12000,
defenderNation.name = '수비국'; secu_max: 10000,
def_max: 12000,
var defenderCity = $.extend({}, defaultCity, allData.defenderCity); wall_max: 12000,
defenderCity.nation = 2;
defenderCity.city = 3; dead: 0,
defenderCity.wall_max = defenderCity.wall/5*6;
defenderCity.def_max = defenderCity.def/5*6; state: 0,
var defenderGenerals = []; conflict: '{}',
$.each(allData.defenderGenerals, function(){ };
var defenderGeneral = extendGeneralInfoForDB(this);
if(2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4){ var attackerNation = $.extend({}, defaultNation, allData.attackerNation);
defenderGeneral.officer_city = 3; attackerNation.nation = 1;
} attackerNation.name = '출병국';
else{
defenderGeneral.officer_city = 0; var attackerCity = $.extend({}, defaultCity, allData.attackerCity);
} attackerCity.nation = 1;
attackerCity.city = 1;
defenderGenerals.push(defenderGeneral);
}); var attackerGeneral = extendGeneralInfoForDB(allData.attackerGeneral);
if (2 <= attackerGeneral.officer_level && attackerGeneral.officer_level <= 4) {
attackerGeneral.officer_city = 1;
return $.extend({}, allData, { } else {
attackerGeneral:attackerGeneral, attackerGeneral.officer_city = 0;
attackerCity:attackerCity, }
attackerNation:attackerNation,
var defenderNation = $.extend({}, defaultNation, allData.defenderNation);
defenderGenerals:defenderGenerals, defenderNation.nation = 2;
defenderCity:defenderCity, defenderNation.name = '수비국';
defenderNation:defenderNation,
}); var defenderCity = $.extend({}, defaultCity, allData.defenderCity);
} defenderCity.nation = 2;
defenderCity.city = 3;
var parseSkillCount = function(skills){ defenderCity.wall_max = parseInt(defenderCity.wall / 5 * 6);
var result = []; defenderCity.def_max = parseInt(defenderCity.def / 5 * 6);
$.each(skills, function(key, value){
result.push("{0}({1}회)".format(key, toPretty(value))); var defenderGenerals = [];
}) $.each(allData.defenderGenerals, function() {
var defenderGeneral = extendGeneralInfoForDB(this);
if(result.length == 0){ if (2 <= defenderGeneral.officer_level && defenderGeneral.officer_level <= 4) {
return '-'; defenderGeneral.officer_city = 3;
} } else {
return result.join(', '); defenderGeneral.officer_city = 0;
} }
var toPretty = function(number){ defenderGenerals.push(defenderGeneral);
if(isInt(number)){ });
number = parseInt(number);
}
else{ return $.extend({}, allData, {
number = parseFloat(number).toFixed(2); attackerGeneral: attackerGeneral,
} attackerCity: attackerCity,
return numberWithCommas(number); attackerNation: attackerNation,
}
defenderGenerals: defenderGenerals,
var showBattleResult = function(result){ defenderCity: defenderCity,
$('#result_datetime').html(result.datetime); defenderNation: defenderNation,
$('#result_warcnt').html(toPretty(result.avgWar)); });
$('#result_phase').html(toPretty(result.phase)); }
$('#result_killed').html(toPretty(result.killed));
if(result.minKilled != result.maxKilled){ var parseSkillCount = function(skills) {
$('#result_maxKilled').html(toPretty(result.maxKilled)); var result = [];
$('#result_minKilled').html(toPretty(result.minKilled)); $.each(skills, function(key, value) {
$('#result_varKilled').show(); result.push("{0}({1}회)".format(key, toPretty(value)));
} })
else{
$('#result_varKilled').hide(); if (result.length == 0) {
} return '-';
$('#result_dead').html(toPretty(result.dead)); }
if(result.minDead != result.maxDead){ return result.join(', ');
$('#result_maxDead').html(toPretty(result.maxDead)); }
$('#result_minDead').html(toPretty(result.minDead));
$('#result_varDead').show(); var toPretty = function(number) {
} if (isInt(number)) {
else{ number = parseInt(number);
$('#result_varDead').hide(); } else {
} number = parseFloat(number).toFixed(2);
}
$('#result_attackerRice').html(toPretty(result.attackerRice)); return numberWithCommas(number);
$('#result_defenderRice').html(toPretty(result.defenderRice)); }
$('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
var showBattleResult = function(result) {
$('.result_defenderSkills').detach(); $('#result_datetime').html(result.datetime);
$('#result_warcnt').html(toPretty(result.avgWar));
var $summary = $('#battle_result_summary'); $('#result_phase').html(toPretty(result.phase));
$('#result_killed').html(toPretty(result.killed));
$.each(result.defendersSkills, function(idx, defenderSkills){ if (result.minKilled != result.maxKilled) {
console.log(defenderSkills); $('#result_maxKilled').html(toPretty(result.maxKilled));
var $result = $("<tr class='result_defenderSkills'><th>수비자{0} 스킬</th><td></td></tr>".format(idx + 1)); $('#result_minKilled').html(toPretty(result.minKilled));
$result.find('td').html(parseSkillCount(defenderSkills)); $('#result_varKilled').show();
$summary.append($result); } else {
}); $('#result_varKilled').hide();
}
$('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog); $('#result_dead').html(toPretty(result.dead));
$('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog); if (result.minDead != result.maxDead) {
$('#result_maxDead').html(toPretty(result.maxDead));
} $('#result_minDead').html(toPretty(result.minDead));
$('#result_varDead').show();
var beginBattle = function(){ } else {
var data = extendAllDataForDB(exportAllData()); $('#result_varDead').hide();
console.log(data); }
$.ajax({
type:'post', $('#result_attackerRice').html(toPretty(result.attackerRice));
url:'j_simulate_battle.php', $('#result_defenderRice').html(toPretty(result.defenderRice));
dataType:'json', $('#result_attackerSkills').html(parseSkillCount(result.attackerSkills));
data:{
action:'battle', $('.result_defenderSkills').detach();
query:JSON.stringify(data),
} var $summary = $('#battle_result_summary');
}).then(function(result){
console.log(result); $.each(result.defendersSkills, function(idx, defenderSkills) {
if(!result.result){ console.log(defenderSkills);
alert(result.reason); var $result = $("<tr class='result_defenderSkills'><th>수비자{0} 스킬</th><td></td></tr>".format(idx + 1));
return; $result.find('td').html(parseSkillCount(defenderSkills));
} $summary.append($result);
showBattleResult(result); });
}, function(result){ $('#generalBattleResultLog').html(result.lastWarLog.generalBattleResultLog);
alert('전투 개시 실패!'); $('#generalBattleDetailLog').html(result.lastWarLog.generalBattleDetailLog);
});
} }
var beginBattle = function() {
var reorderDefender = function(defenderOrder){ var data = extendAllDataForDB(exportAllData());
$.each(defenderOrder, function(idx, generalNo){ console.log(data);
$.ajax({
if(!(generalNo in defenderNoList)){ type: 'post',
//음..? url: 'j_simulate_battle.php',
alert("{0}이 수비자 리스트에 없습니다. 버그인 듯 합니다.".format(generalNo)); dataType: 'json',
return true; data: {
} action: 'battle',
query: JSON.stringify(data),
var $defenderObj = defenderNoList[generalNo]; }
$defenderObj.detach(); }).then(function(result) {
$defenderColumn.append($defenderObj); console.log(result);
}) if (!result.result) {
} alert(result.reason);
return;
var requestReorderDefender = function(){ }
var data = extendAllDataForDB(exportAllData()); showBattleResult(result);
console.log(data);
$.ajax({ }, function(result) {
type:'post', alert('전투 개시 실패!');
url:'j_simulate_battle.php', });
dataType:'json', }
data:{
action:'reorder',
query:JSON.stringify(data), var reorderDefender = function(defenderOrder) {
} $.each(defenderOrder, function(idx, generalNo) {
}).then(function(result){
console.log(result); if (!(generalNo in defenderNoList)) {
if(!result.result){ //음..?
alert(result.reason); alert("{0}이 수비자 리스트에 없습니다. 버그인 듯 합니다.".format(generalNo));
return; return true;
} }
reorderDefender(result.order);
var $defenderObj = defenderNoList[generalNo];
}, function(result){ $defenderObj.detach();
alert('재정렬 실패!'); $defenderColumn.append($defenderObj);
}); })
} }
initBasicEvent(); var requestReorderDefender = function() {
$attackerCard.append($generalForm.clone(true,true)); var data = extendAllDataForDB(exportAllData());
addDefender(); console.log(data);
$.ajax({
$('.btn-begin_battle').click(function(){ type: 'post',
beginBattle(); url: 'j_simulate_battle.php',
}); dataType: 'json',
data: {
$('.btn-reorder_defender').click(function(){ action: 'reorder',
requestReorderDefender(); query: JSON.stringify(data),
}) }
}).then(function(result) {
console.log(result);
if (!result.result) {
alert(result.reason);
return;
}
reorderDefender(result.order);
}, function(result) {
alert('재정렬 실패!');
});
}
var initGeneralList = false;
$('#importFromDB').click(function() {
var generalID = $('#modalSelector').val();
console.log(generalID);
$.post({
url: 'j_export_simulator_object.php',
dataType: 'json',
data: {
destGeneralID: generalID
}
}).then(function(data) {
if (!data.result) {
alert(data.reason);
return false;
}
var $modal = $('#importModal');
var $card = $modal.data('target');
importGeneralInfo($card, data.general);
$modal.modal('hide');
}, errUnknown);
});
$('#importModal').on('show.bs.modal', function(e) {
if (!initGeneralList) {
var $list = $('#modalSelector');
var addNation = function(generalList, nationName, color) {
generalList.sort(function(lhs, rhs) {
if (lhs.npc != rhs.npc) {
return lhs.npc - rhs.npc;
}
if (lhs.name < rhs.name) {
return -1;
}
if (lhs.name > rhs.name) {
return 1;
}
return 0;
})
var $optGroup = $('<optgroup label="{0}"></optgroup>'.format(nationName));
$optGroup.css('background-color', color);
$optGroup.css('color', isBrightColor(color) ? 'black' : 'white');
$.each(generalList, function(idx, general) {
$item = $('<option value="{0}">{1}</option>'.format(general.no, general.name));
if (general.npc) {
$item.css('color', getNpcColor(general.npc));
} else {
$item.css('color', 'white');
}
$item.css('background-color', 'black');
$optGroup.append($item);
});
$list.append($optGroup);
}
$.post({
url: 'j_get_basic_general_list.php',
dataType: 'json',
data: {
req: 2,
}
}).then(function(data) {
if (!data.result) {
alert(data.reason);
$('#importModal').modal('hide');
return false;
}
var nations = data.nation;
var myNationID = data.nationID;
$list.empty();
//자국 먼저
if (0 in data.list) {
nations[0] = {
nation: 0,
name: '재야',
color: '#000000'
};
}
addNation(combineArray(data.list[myNationID], data.column), nations[myNationID].name, nations[myNationID].color);
for (var nationID in data.list) {
if (nationID == myNationID) {
continue;
}
addNation(combineArray(data.list[nationID], data.column), nations[nationID].name, nations[nationID].color);
}
initGeneralList = true;
}, errUnknown);
}
});
initBasicEvent();
$attackerCard.append($generalForm.clone(true, true));
addDefender();
$('.btn-begin_battle').click(function() {
beginBattle();
});
$('.btn-reorder_defender').click(function() {
requestReorderDefender();
})
}); });
+194 -200
View File
@@ -1,201 +1,195 @@
function changePermission(isAmbassador, rawGeneralList){ function changePermission(isAmbassador, rawGeneralList) {
console.log(isAmbassador); console.log(isAmbassador);
console.log(rawGeneralList); console.log(rawGeneralList);
var generalList = []; var generalList = [];
$.each(rawGeneralList, function(idx, value){ $.each(rawGeneralList, function(idx, value) {
generalList.push(parseInt(value.id)); generalList.push(parseInt(value.id));
}) })
$.post({ $.post({
url:'j_general_set_permission.php', url: 'j_general_set_permission.php',
dataType:'json', dataType: 'json',
data:{ data: {
isAmbassador:isAmbassador, isAmbassador: isAmbassador,
genlist:generalList genlist: generalList
}, },
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
alert('변경하지 못했습니다.'); alert('변경하지 못했습니다.');
return false; return false;
} }
if(!data.result){ if (!data.result) {
alert('변경하지 못했습니다. : '+data.reason); alert('변경하지 못했습니다. : ' + data.reason);
return false; return false;
} }
alert('변경했습니다.'); alert('변경했습니다.');
location.reload(); location.reload();
}, errUnknown); }, errUnknown);
} }
$(function(){ $(function() {
$('#selectAmbassador').select2({ $('#selectAmbassador').select2({
theme: 'bootstrap4', theme: 'bootstrap4',
placeholder: "", placeholder: "",
allowClear: true, allowClear: true,
language: "ko", language: "ko",
width:300, width: 300,
maximumSelectionLength: 2, maximumSelectionLength: 2,
containerCss: { containerCss: {
display: "inline-block !important;", display: "inline-block !important;",
color: 'white !important' color: 'white !important'
}, },
data:candidateAmbassadors, data: candidateAmbassadors,
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary', //containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary', dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
}); });
$('#selectAuditor').select2({ $('#selectAuditor').select2({
theme: 'bootstrap4', theme: 'bootstrap4',
placeholder: "", placeholder: "",
allowClear: true, allowClear: true,
language: "ko", language: "ko",
width:300, width: 300,
maximumSelectionLength: 2, maximumSelectionLength: 2,
containerCss: { containerCss: {
display: "inline-block !important;", display: "inline-block !important;",
color: 'white !important' color: 'white !important'
}, },
data:candidateAuditors, data: candidateAuditors,
//containerCssClass: 'simple-select2-align-center bg-secondary text-secondary', //containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary', dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
}); });
$('#changeAmbassador').click(function(){ $('#changeAmbassador').click(function() {
if(!confirm('외교권자를 변경할까요?')){ if (!confirm('외교권자를 변경할까요?')) {
return false; return false;
} }
changePermission(true, $('#selectAmbassador').select2('data')); changePermission(true, $('#selectAmbassador').select2('data'));
return false; return false;
}); });
$('#changeAuditor').click(function(){ $('#changeAuditor').click(function() {
if(!confirm('조언자를 변경할까요?')){ if (!confirm('조언자를 변경할까요?')) {
return false; return false;
} }
changePermission(false, $('#selectAuditor').select2('data')); changePermission(false, $('#selectAuditor').select2('data'));
return false; return false;
}); });
$('#btn_kick').click(function(){ $('#btn_kick').click(function() {
var $kickSelect = $('#genlist_kick option:selected'); var $kickSelect = $('#genlist_kick option:selected');
var generalID = $kickSelect.val(); var generalID = $kickSelect.val();
if(!generalID){ if (!generalID) {
alert('장수를 선택해주세요'); alert('장수를 선택해주세요');
return false; return false;
} }
var generalName = $kickSelect.data('name'); var generalName = $kickSelect.data('name');
if(!confirm('{0}를 추방하시겠습니까?'.format(generalName))){ if (!confirm('{0}를 추방하시겠습니까?'.format(generalName))) {
return false; return false;
} }
$.post({ $.post({
url:'j_myBossInfo.php', url: 'j_myBossInfo.php',
dataType:'json', dataType: 'json',
data:{ data: {
action:'추방', action: '추방',
destGeneralID:generalID destGeneralID: generalID
}, },
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
alert('추방하지 못했습니다.'); alert('추방하지 못했습니다.');
return false; return false;
} }
if(!data.result){ if (!data.result) {
alert('추방하지 못했습니다. : '+data.reason); alert('추방하지 못했습니다. : ' + data.reason);
return false; return false;
} }
alert('{0}를 추방했습니다.'.format(generalName)); alert('{0}를 추방했습니다.'.format(generalName));
location.reload(); location.reload();
}, errUnknown); }, errUnknown);
return false; return false;
}); });
$('.btn_appoint').click(function(){ $('.btn_appoint').click(function() {
var $btn = $(this); var $btn = $(this);
var officerLevel = $btn.data('officer_level'); var officerLevel = $btn.data('officer_level');
var officerLevelText = $btn.data('officer_level_text'); var officerLevelText = $btn.data('officer_level_text');
var cityID = 0; var cityID = 0;
var cityName = '_'; var cityName = '_';
var $generalSelect = $('#genlist_{0} option:selected'.format(officerLevel)); var $generalSelect = $('#genlist_{0} option:selected'.format(officerLevel));
var $citySelect = $('#citylist_{0} option:selected'.format(officerLevel)); var $citySelect = $('#citylist_{0} option:selected'.format(officerLevel));
var generalID = $generalSelect.val(); var generalID = parseInt($generalSelect.val());
var generalName = $generalSelect.data('name'); var generalName = $generalSelect.data('name');
var generalOfficerLevel = $generalSelect.data('officer_level'); var generalOfficerLevel = $generalSelect.data('officer_level');
if(officerLevel >= 5){ if (officerLevel >= 5) {
if(generalID == 0){ if (generalID == 0) {
if(!confirm('{0}직을 비우시겠습니까?'.format(officerLevelText))){ if (!confirm('{0}직을 비우시겠습니까?'.format(officerLevelText))) {
return false; return false;
} }
} } else if (generalOfficerLevel >= 5) {
else if(generalOfficerLevel >= 5){ if (!confirm('이미 수뇌인 {0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))) {
if(!confirm('이미 수뇌인 {0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))){ return false;
return false; }
} } else {
} if (!confirm('{0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))) {
else{ return false;
if(!confirm('{0}을(를) {1}직에 임명하시겠습니까?'.format(generalName, officerLevelText))){ }
return false; }
} } else {
} cityID = $citySelect.val();
} if (!cityID) {
else{ alert('도시를 선택해주세요');
cityID = $citySelect.val(); return false;
if(!cityID){ }
alert('도시를 선택해주세요'); cityName = $citySelect.find('option:selected .name_field').text();
return false;
} if (generalID == 0) {
cityName = $citySelect.find('option:selected .name_field').text(); if (!confirm('{0} {1}직을 비우시겠습니까?'.format(cityName, officerLevelText))) {
return false;
if(generalID == 0){ }
if(!confirm('{0} {1}직을 비우시겠습니까?'.format(cityName, officerLevelText))){ } else if (generalOfficerLevel >= 5) {
return false; if (!confirm('수뇌인 {0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))) {
} return false;
} }
else if(generalOfficerLevel >= 5){ } else {
if(!confirm('수뇌인 {0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))){ if (!confirm('{0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))) {
return false; return false;
} }
} }
else{ }
if(!confirm('{0}을(를) {1} {2}직에 임명하시겠습니까?'.format(generalName, cityName, officerLevelText))){
return false; $.post({
} url: 'j_myBossInfo.php',
} dataType: 'json',
} data: {
action: '임명',
$.post({ destGeneralID: generalID,
url:'j_myBossInfo.php', destCityID: cityID,
dataType:'json', officerLevel: officerLevel
data:{ },
action:'임명', }).then(function(data) {
destGeneralID:generalID, if (!data) {
destCityID:cityID, alert('임명하지 못했습니다.');
officerLevel:officerLevel return false;
}, }
}).then(function(data){ if (!data.result) {
if(!data){ alert('임명하지 못했습니다. : ' + data.reason);
alert('임명하지 못했습니다.'); return false;
return false; }
}
if(!data.result){ if (generalID) {
alert('임명하지 못했습니다. : '+data.reason); alert('{0}을(를) 임명했습니다.'.format(generalName));
return false; } else {
} alert('관직을 비웠습니다.');
}
if(generalID){
alert('{0}을(를) 임명했습니다.'.format(generalName)); location.reload();
} }, errUnknown);
else{
alert('관직을 비웠습니다.'); })
}
location.reload();
}, errUnknown);
})
}) })
+171 -103
View File
@@ -3,8 +3,8 @@
* @see https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery * @see https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
* @param {string} string escape하고자 하는 문자열 * @param {string} string escape하고자 하는 문자열
* @returns {string} * @returns {string}
*/ */
var escapeHtml = (function (string) { var escapeHtml = (function(string) {
var entityMap = { var entityMap = {
'&': '&amp;', '&': '&amp;',
'<': '&lt;', '<': '&lt;',
@@ -32,58 +32,70 @@ function isInt(n) {
return +n === n && !(n % 1); return +n === n && !(n % 1);
} }
;(function(ns){ ;
(function(ns) {
//https://gist.github.com/demouth/3217440 //https://gist.github.com/demouth/3217440
/** /**
* mb_strwidth * mb_strwidth
* @param String * @param String
* @return int * @return int
* @see http://php.net/manual/ja/function.mb-strwidth.php * @see http://php.net/manual/ja/function.mb-strwidth.php
*/ */
var mb_strwidth = function(str){ var mb_strwidth = function(str) {
var i=0,l=str.length,c='',length=0; var i = 0,
for(;i<l;i++){ l = str.length,
c=str.charCodeAt(i); c = '',
if(0x0000<=c&&c<=0x0019){ length = 0;
length += 0; for (; i < l; i++) {
}else if(0x0020<=c&&c<=0x1FFF){ c = str.charCodeAt(i);
length += 1; if (0x0000 <= c && c <= 0x0019) {
}else if(0x2000<=c&&c<=0xFF60){ length += 0;
length += 2; } else if (0x0020 <= c && c <= 0x1FFF) {
}else if(0xFF61<=c&&c<=0xFF9F){ length += 1;
length += 1; } else if (0x2000 <= c && c <= 0xFF60) {
}else if(0xFFA0<=c){ length += 2;
length += 2; } else if (0xFF61 <= c && c <= 0xFF9F) {
} length += 1;
} } else if (0xFFA0 <= c) {
return length; length += 2;
}; }
}
/** return length;
* mb_strimwidth };
* @param String
* @param int /**
* @param int * mb_strimwidth
* @param String * @param String
* @return String * @param int
* @see http://www.php.net/manual/ja/function.mb-strimwidth.php * @param int
*/ * @param String
var mb_strimwidth = function(str,start,width,trimmarker){ * @return String
if(typeof trimmarker === 'undefined') trimmarker=''; * @see http://www.php.net/manual/ja/function.mb-strimwidth.php
var trimmakerWidth = mb_strwidth(trimmarker),i=start,l=str.length,trimmedLength=0,trimmedStr=''; */
for(;i<l;i++){ var mb_strimwidth = function(str, start, width, trimmarker) {
var charCode=str.charCodeAt(i),c=str.charAt(i),charWidth=mb_strwidth(c),next=str.charAt(i+1),nextWidth=mb_strwidth(next); if (typeof trimmarker === 'undefined') trimmarker = '';
trimmedLength += charWidth; var trimmakerWidth = mb_strwidth(trimmarker),
trimmedStr += c; i = start,
if(trimmedLength+trimmakerWidth+nextWidth>width){ l = str.length,
trimmedStr += trimmarker; trimmedLength = 0,
break; trimmedStr = '';
} for (; i < l; i++) {
} var charCode = str.charCodeAt(i),
return trimmedStr; c = str.charAt(i),
}; charWidth = mb_strwidth(c),
ns.mb_strwidth = mb_strwidth; next = str.charAt(i + 1),
ns.mb_strimwidth = mb_strimwidth; nextWidth = mb_strwidth(next);
trimmedLength += charWidth;
trimmedStr += c;
if (trimmedLength + trimmakerWidth + nextWidth > width) {
trimmedStr += trimmarker;
break;
}
}
return trimmedStr;
};
ns.mb_strwidth = mb_strwidth;
ns.mb_strimwidth = mb_strimwidth;
})(window); })(window);
/** /**
@@ -93,7 +105,7 @@ function isInt(n) {
*/ */
function convertDictById(arr) { function convertDictById(arr) {
var result = {}; var result = {};
arr.forEach(function (v, i) { arr.forEach(function(v, i) {
result[v.id] = v; result[v.id] = v;
}); });
return result; return result;
@@ -106,7 +118,7 @@ function convertDictById(arr) {
*/ */
function convertSet(arr) { function convertSet(arr) {
var result = {}; var result = {};
arr.forEach(function (v) { arr.forEach(function(v) {
result[v] = true; result[v] = true;
}); });
return result; return result;
@@ -115,10 +127,10 @@ function convertSet(arr) {
/** /**
* {0}, {1}, {2}형태로 포맷해주는 함수 * {0}, {1}, {2}형태로 포맷해주는 함수
*/ */
String.prototype.format = function() { String.prototype.format = function() {
var args = arguments; var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) { return this.replace(/{(\d+)}/g, function(match, number) {
return (typeof args[number] != 'undefined') ? args[number] : match; return (typeof args[number] != 'undefined') ? args[number] : match;
}); });
}; };
@@ -134,12 +146,11 @@ function hexToRgb(hex) {
} }
function isBrightColor(color){ function isBrightColor(color) {
color = hexToRgb(color); color = hexToRgb(color);
if ((color.r*0.299 + color.g*0.587 + color.b*0.114) > 140){ if ((color.r * 0.299 + color.g * 0.587 + color.b * 0.114) > 140) {
return true; return true;
} } else {
else{
return false; return false;
} }
} }
@@ -177,7 +188,7 @@ function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} }
function linkifyStrWithOpt(text){ function linkifyStrWithOpt(text) {
return linkifyStr(text, {}); return linkifyStr(text, {});
} }
@@ -188,14 +199,14 @@ function linkifyStrWithOpt(text){
* @param {object} options * @param {object} options
* @returns {string} * @returns {string}
*/ */
var TemplateEngine = function (html, options) { var TemplateEngine = function(html, options) {
var re = /<%(.+?)%>/g, var re = /<%(.+?)%>/g,
reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g, reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g,
code = 'with(obj) { var r=[];\n', code = 'with(obj) { var r=[];\n',
cursor = 0, cursor = 0,
result, result,
match; match;
var add = function (line, js) { var add = function(line, js) {
js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') : js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : ''); (code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
return add; return add;
@@ -208,82 +219,97 @@ var TemplateEngine = function (html, options) {
} }
add(html.substr(cursor, html.length - cursor)); add(html.substr(cursor, html.length - cursor));
code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, ' '); code = (code + 'return r.join(""); }').replace(/[\r\t\n]/g, ' ');
try { result = new Function('obj', code).apply(options, [options]); } try { result = new Function('obj', code).apply(options, [options]); } catch (err) { console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n"); }
catch (err) { console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n"); }
return result; return result;
} }
function getIconPath(imgsvr, picture){ function getIconPath(imgsvr, picture) {
// ../d_shared/common_path.js 필요 // ../d_shared/common_path.js 필요
if(!imgsvr){ if (!imgsvr) {
return pathConfig.sharedIcon+'/'+picture; return pathConfig.sharedIcon + '/' + picture;
} } else {
else{ return pathConfig.root + '/d_pic/' + picture;
return pathConfig.root+'/d_pic/'+picture;
} }
} }
function activeFlip($obj){ function activeFlip($obj) {
var $result; var $result;
if($obj === undefined){ if ($obj === undefined) {
$result = $('img[data-flip]'); $result = $('img[data-flip]');
} } else {
else{
$result = $obj.find('img[data-flip]'); $result = $obj.find('img[data-flip]');
} }
$result.each(function(){ $result.each(function() {
activeFlipItem($(this)); activeFlipItem($(this));
}); });
} }
function activeFlipItem($img){ function combineObject(item, columnList) {
var newItem = {};
for (var columnIdx in columnList) {
var columnName = columnList[columnIdx];
newItem[columnName] = item[columnIdx];
}
return newItem;
}
function combineArray(array, columnList) {
var result = [];
for (var key in array) {
var item = array[key];
result[key] = combineObject(item, columnList);
}
return result;
}
function activeFlipItem($img) {
var imageList = []; var imageList = [];
imageList.push($img.attr('src')); imageList.push($img.attr('src'));
$.each($img.data('flip').split(','), function(idx, value){ $.each($img.data('flip').split(','), function(idx, value) {
var value = $.trim(value); var value = $.trim(value);
if(!value){ if (!value) {
return true; return true;
} }
imageList.push(value); imageList.push(value);
}); });
if(imageList.length <= 1){ if (imageList.length <= 1) {
return; return;
} }
$img.data('computed_flip_array', imageList); $img.data('computed_flip_array', imageList);
$img.data('computed_flip_idx', 0); $img.data('computed_flip_idx', 0);
$img.click(function(){ $img.click(function() {
var arr = $img.data('computed_flip_array'); var arr = $img.data('computed_flip_array');
var idx = $img.data('computed_flip_idx'); var idx = $img.data('computed_flip_idx');
idx = (idx + 1)%(arr.length); idx = (idx + 1) % (arr.length);
$img.attr('src', arr[idx]); $img.attr('src', arr[idx]);
$img.data('computed_flip_idx', idx); $img.data('computed_flip_idx', idx);
}); });
$img.css('cursor','pointer'); $img.css('cursor', 'pointer');
} }
jQuery(function($){ jQuery(function($) {
$('.obj_tooltip').mouseover(function(){ $('.obj_tooltip').mouseover(function() {
var $objTooltip = $(this); var $objTooltip = $(this);
if($objTooltip.data('setObjTooltip')){ if ($objTooltip.data('setObjTooltip')) {
return true; return true;
} }
var tooltipClassText = $objTooltip.data('tooltip-class'); var tooltipClassText = $objTooltip.data('tooltip-class');
if(!tooltipClassText){ if (!tooltipClassText) {
tooltipClassText = ''; tooltipClassText = '';
} }
var template = '<div class="tooltip {0}" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>' var template = '<div class="tooltip {0}" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'
.format(tooltipClassText); .format(tooltipClassText);
$objTooltip.tooltip({ $objTooltip.tooltip({
title:function(){ title: function() {
return $.trim($(this).find('.tooltiptext').html()); return $.trim($(this).find('.tooltiptext').html());
}, },
template:template, template: template,
html:true html: true
}).tooltip('show'); }).tooltip('show');
$objTooltip.data('setObjTooltip', true); $objTooltip.data('setObjTooltip', true);
@@ -297,21 +323,21 @@ jQuery(function($){
activeFlip(); activeFlip();
var customCSS = localStorage.getItem('sam_customCSS'); var customCSS = localStorage.getItem('sam_customCSS');
if(customCSS){ if (customCSS) {
var $style = $('<style type="text/css"></style>'); var $style = $('<style type="text/css"></style>');
$style.text(customCSS); $style.text(customCSS);
$style.appendTo($('head')); $style.appendTo($('head'));
} }
}); });
function errUnknown(){ function errUnknown() {
alert('작업을 실패했습니다.'); alert('작업을 실패했습니다.');
} }
function errUnknownToast(){ function errUnknownToast() {
$.toast({ $.toast({
title: '에러!', title: '에러!',
content: '작업을 실패했습니다.', content: '작업을 실패했습니다.',
@@ -320,8 +346,8 @@ function errUnknownToast(){
}); });
} }
function quickReject(errMsg){ function quickReject(errMsg) {
if(errMsg === undefined){ if (errMsg === undefined) {
errMsg = '작업을 실패했습니다.'; errMsg = '작업을 실패했습니다.';
} }
var deferred = $.Deferred(); var deferred = $.Deferred();
@@ -329,8 +355,8 @@ function quickReject(errMsg){
return deferred.promise(); return deferred.promise();
} }
function nl2br(text){ function nl2br(text) {
return text.replace(/\n/g,"<br>"); return text.replace(/\n/g, "<br>");
} }
/* /*
function br2nl (text) { function br2nl (text) {
@@ -338,12 +364,54 @@ function br2nl (text) {
} }
*/ */
function getNpcColor(npcType){ function getNpcColor(npcType) {
if(npcType >= 2){ if (npcType >= 2) {
return 'cyan'; return 'cyan';
} }
if(npcType == 1){ if (npcType == 1) {
return 'skyblue'; return 'skyblue';
} }
return null; return null;
}
function initTooltip($obj) {
if ($obj === undefined) {
$obj = $('.obj_tooltip');
} else if (!$obj.hasClass('obj_tooltip')) {
$obj = $obj.find('.obj_tooltip');
}
console.log($obj);
$obj.each(function() {
$target = $(this);
if ($target.data('installHandler')) {
return true;
}
$target.data('installHandler', true);
$target.mouseover(function() {
var $objTooltip = $(this);
if ($objTooltip.data('setObjTooltip')) {
return true;
}
var tooltipClassText = $objTooltip.data('tooltip-class');
if (!tooltipClassText) {
tooltipClassText = '';
}
var template = '<div class="tooltip {0}" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'
.format(tooltipClassText);
$objTooltip.tooltip({
title: function() {
return $.trim($(this).find('.tooltiptext').html());
},
template: template,
html: true
}).tooltip('show');
$objTooltip.data('setObjTooltip', true);
});
});
} }
File diff suppressed because one or more lines are too long
+8
View File
@@ -0,0 +1,8 @@
/**
* @license
* Lodash <https://lodash.com/>
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/
File diff suppressed because one or more lines are too long
+74 -76
View File
@@ -1,4 +1,3 @@
/* /*
function showCityGeneral(cityIdx){ function showCityGeneral(cityIdx){
@@ -21,13 +20,13 @@ function loadScenarioPreview(scenarioIdx){
function loadScenarios(){ function loadScenarios() {
$.ajax({ $.ajax({
method:'post', method: 'post',
url:'j_load_scenarios.php', url: 'j_load_scenarios.php',
dataType:'json' dataType: 'json'
}).then(function(result){ }).then(function(result) {
if(!result.result){ if (!result.result) {
var deferred = $.Deferred(); var deferred = $.Deferred();
deferred.reject('fail'); deferred.reject('fail');
return deferred.promise(); return deferred.promise();
@@ -37,18 +36,18 @@ function loadScenarios(){
var list = {}; var list = {};
$.each(result.scenario, function(idx, value){ $.each(result.scenario, function(idx, value) {
var title = value.title || "-"; var title = value.title || "-";
var pat = /【(.*?)[0-9\-_\.a-zA-Z]*】/; var pat = /【(.*?)[0-9\-_\.a-zA-Z]*】/;
var category = pat.exec(title); var category = pat.exec(title);
category = category?category[1]:'-'; category = category ? category[1] : '-';
value.title = title; value.title = title;
value.category = category; value.category = category;
value.idx = idx; value.idx = idx;
value.year = value.year || 180; value.year = value.year || 180;
if(!(category in list)){ if (!(category in list)) {
list[category] = {}; list[category] = {};
} }
@@ -56,12 +55,12 @@ function loadScenarios(){
}); });
var $select = $('#scenario_sel'); var $select = $('#scenario_sel');
$.each(list, function(category, items){ $.each(list, function(category, items) {
var $optgroup = $('<optgroup>').attr('label', category); var $optgroup = $('<optgroup>').attr('label', category);
$.each(items, function(idx, scenario){ $.each(items, function(idx, scenario) {
var $option = $('<option>') var $option = $('<option>')
.data('scenario',scenario) .data('scenario', scenario)
.val(idx) .val(idx)
.html(scenario.title); .html(scenario.title);
$optgroup.append($option); $optgroup.append($option);
@@ -75,7 +74,7 @@ function loadScenarios(){
}); });
} }
function scenarioPreview(){ function scenarioPreview() {
var $select = $(this); var $select = $(this);
var $option = $select.find('option:selected'); var $option = $select.find('option:selected');
@@ -89,125 +88,124 @@ function scenarioPreview(){
$year.html('{0}년'.format(scenario.year)); $year.html('{0}년'.format(scenario.year));
$npc.html('{0}명'.format(scenario.npc_cnt)); $npc.html('{0}명'.format(scenario.npc_cnt));
if(scenario.npcEx_cnt == 0){ if (scenario.npcEx_cnt == 0) {
$npcEx.html(''); $npcEx.html('');
} } else {
else{
$npcEx.html('+{0}명'.format(scenario.npcEx_cnt)); $npcEx.html('+{0}명'.format(scenario.npcEx_cnt));
} }
$nation.html(''); $nation.html('');
$.each(scenario.nation, function(idx, nation){ $.each(scenario.nation, function(idx, nation) {
$nation.append('<span style="color:{0}">{1}</span> {2}명. {3}<br>'.format( $nation.append('<span style="color:{0}">{1}</span> {2}명. {3}<br>'.format(
nation.color, nation.name, nation.generals, nation.cities.join(', ') nation.color, nation.name, nation.generals, nation.cities.join(', ')
)); ));
}); });
} }
function formSetup(){ function formSetup() {
$.validator.addMethod("autorun_user", function(value,element){ $.validator.addMethod("autorun_user", function(value, element) {
var parent = $(element).parent('.input-group'); var parent = $(element).parent('.input-group');
var checkCnt = parent.find('input:checked').length; var checkCnt = parent.find('input:checked').length;
if(value <= 0){ if (value <= 0) {
if(checkCnt > 0){ if (checkCnt > 0) {
return false; return false;
} }
return true; return true;
} }
if(checkCnt == 0){ if (checkCnt == 0) {
return false; return false;
} }
return true; return true;
}, "유효 시간과 옵션은 동시에 설정해야합니다."); }, "유효 시간과 옵션은 동시에 설정해야합니다.");
$('#game_form').validate({ $('#game_form').validate({
rules:{ rules: {
turnterm:"required", turnterm: "required",
sync:"required", sync: "required",
scenario:"required", scenario: "required",
fiction:"required", fiction: "required",
extend:"required", extend: "required",
npcmode:"required", npcmode: "required",
show_img_level:"required", show_img_level: "required",
tournament_trig:"required", tournament_trig: "required",
join_mode:'required', join_mode: 'required',
autorun_user_minutes:{required: true, autorun_user: true, min:0} autorun_user_minutes: { required: true, autorun_user: true, min: 0 }
}, },
errorElement: "div", errorElement: "div",
errorPlacement: function ( error, element ) { errorPlacement: function(error, element) {
// Add the `help-block` class to the error element // Add the `help-block` class to the error element
error.addClass( "invalid-feedback" ); error.addClass("invalid-feedback");
if ( element.prop( "type" ) === "checkbox" ) { if (element.prop("type") === "checkbox") {
error.insertAfter( element.parent( "label" ) ); error.insertAfter(element.parent("label"));
} else { } else {
error.insertAfter( element ); error.insertAfter(element);
} }
}, },
highlight: function ( element, errorClass, validClass ) { highlight: function(element, errorClass, validClass) {
$( element ).addClass( "is-invalid" ).removeClass( "is-valid" ); $(element).addClass("is-invalid").removeClass("is-valid");
}, },
unhighlight: function (element, errorClass, validClass) { unhighlight: function(element, errorClass, validClass) {
$( element ).addClass( "is-valid" ).removeClass( "is-invalid" ); $(element).addClass("is-valid").removeClass("is-invalid");
} }
}); });
$('#game_form').submit(function(e){ $('#game_form').submit(function(e) {
e.preventDefault(); e.preventDefault();
if(!$("#game_form").valid()){ if (!$("#game_form").valid()) {
return; return;
} }
var autorun_user_minutes = parseInt($('#autorun_user_minutes').val()); var autorun_user_minutes = parseInt($('#autorun_user_minutes').val());
var autorun_user = []; var autorun_user = [];
if(autorun_user_minutes > 0){ if (autorun_user_minutes > 0) {
$('.autorun_user_chk:checked').each(function(){ $('.autorun_user_chk:checked').each(function() {
autorun_user.push($(this).data('key')); autorun_user.push($(this).data('key'));
}); });
} }
$.ajax({ $.ajax({
cache:false, cache: false,
type:'post', type: 'post',
url:'j_install.php', url: 'j_install.php',
dataType:'json', dataType: 'json',
data:{ data: {
turnterm:$('#turnterm input:radio:checked').val(), turnterm: $('#turnterm input:radio:checked').val(),
sync:$('#sync input:radio:checked').val(), sync: $('#sync input:radio:checked').val(),
scenario:$('#scenario_sel').val(), scenario: $('#scenario_sel').val(),
fiction:$('#fiction input:radio:checked').val(), fiction: $('#fiction input:radio:checked').val(),
extend:$('#extend input:radio:checked').val(), extend: $('#extend input:radio:checked').val(),
npcmode:$('#npcmode input:radio:checked').val(), block_general_create: $('#block_general_create input:radio:checked').val(),
show_img_level:$('#show_img_level input:radio:checked').val(), npcmode: $('#npcmode input:radio:checked').val(),
tournament_trig:$('#tournament_trig input:radio:checked').val(), show_img_level: $('#show_img_level input:radio:checked').val(),
reserve_open:$('#reserve_open').val(), tournament_trig: $('#tournament_trig input:radio:checked').val(),
pre_reserve_open:$('#pre_reserve_open').val(), reserve_open: $('#reserve_open').val(),
join_mode:$('#join_mode input:radio:checked').val(), pre_reserve_open: $('#pre_reserve_open').val(),
autorun_user_minutes:autorun_user_minutes, join_mode: $('#join_mode input:radio:checked').val(),
autorun_user:autorun_user autorun_user_minutes: autorun_user_minutes,
autorun_user: autorun_user
} }
}).then(function(result){ }).then(function(result) {
var deferred = $.Deferred(); var deferred = $.Deferred();
if(!result.result){ if (!result.result) {
alert(result.reason); alert(result.reason);
deferred.reject('fail'); deferred.reject('fail');
} } else {
else{
alert('게임이 리셋되었습니다.'); alert('게임이 리셋되었습니다.');
deferred.resolve(); deferred.resolve();
} }
return deferred.promise(); return deferred.promise();
}).then(function(){ }).then(function() {
location.href = '..'; location.href = '..';
}); });
}); });
} }
$(function(){ $(function() {
loadScenarios(); loadScenarios();
$('#scenario_sel').change(scenarioPreview); $('#scenario_sel').change(scenarioPreview);
formSetup(); formSetup();
}) })
+685 -653
View File
@@ -1,654 +1,686 @@
function is_touch_device() {
function is_touch_device() { var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' '); var mq = function(query) {
var mq = function(query) { return window.matchMedia(query).matches;
return window.matchMedia(query).matches; }
}
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) { return true;
return true; }
}
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
// include the 'heartz' as a way to have a non matching MQ to help terminate the join // https://git.io/vznFH
// https://git.io/vznFH var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
var query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join(''); return mq(query);
return mq(query); }
}
function reloadWorldMap(option, drawTarget) {
function reloadWorldMap(option){ if (drawTarget === undefined || drawTarget === null) {
var $world_map = $('.world_map'); drawTarget = '.world_map'
}
if($world_map.length == 0){ var $world_map = $(drawTarget);
return;
} if ($world_map.length == 0) {
return;
var defaultOption = { }
isDetailMap:true, //복잡 지도, 단순 지도
clickableAll:false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도. var defaultOption = {
selectCallback:null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행. isDetailMap: true, //복잡 지도, 단순 지도
hrefTemplate:'#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨 clickableAll: false, //어떤 경우든 클릭을 가능하게 함. 해당 동작의 동작 가능성 여부와는 별도.
useCachedMap:false, //맵 캐시를 사용 selectCallback: null, //callback을 지정시 clickable과 관계 없이 해당 함수를 실행.
hrefTemplate: '#', //도시가 클릭가능할 경우 지정할 href값. {0}은 도시 id로 변환됨
//아래부터는 post query에 들어갈 녀석 useCachedMap: false, //맵 캐시를 사용
year:null, //year값, 연감등에 사용
month:null, //month값, 연감등에 사용 //아래부터는 post query에 들어갈 녀석
aux:null, //기타 넣고 싶은 값을 입력 year: null, //year값, 연감등에 사용
neutralView:false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정 month: null, //month값, 연감등에 사용
showMe:true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개 aux: null, //기타 넣고 싶은 값을 입력
targetJson:'j_map.php', neutralView: false, //clickable, 소속 국가, 첩보 여부 등을 반환여부를 설정
showMe: true, //반환 값에 본인이 위치한 도시 값을 반환하도록 설정. neutralView와 별개
//기타 보조 값
startYear:null, targetJson: 'j_map.php',
}; reqType: 'post',
dynamicMapTheme: false,
option = $.extend(defaultOption, option); callback: null,
var useCachedMap = option.useCachedMap; //기타 보조 값
var isDetailMap = option.isDetailMap; startYear: null,
var clickableAll = option.clickableAll; };
var selectCallback = option.selectCallback;
var hrefTemplate = option.hrefTemplate; option = $.extend(defaultOption, option);
var cityPosition = getCityPosition(); var useCachedMap = option.useCachedMap;
var isDetailMap = option.isDetailMap;
var storedOldMapKey = 'sam.{0}.map'.format(serverNick); var clickableAll = option.clickableAll;
var storedStartYear = 'sam.{0}.startYear'.format(serverNick); var selectCallback = option.selectCallback;
//OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity var hrefTemplate = option.hrefTemplate;
function checkReturnObject(obj){ var cityPosition = getCityPosition();
if(!obj.result){
var obj = $.Deferred(); var storedOldMapKey = 'sam.{0}.map'.format(serverNick);
obj.reject('fail'); var storedStartYear = 'sam.{0}.startYear'.format(serverNick);
return obj.promise(); //OBJ : startYear, year, month, cityList, nationList, spyList, shownByGeneralList, myCity
}
function checkReturnObject(obj) {
if(!$.isNumeric(obj.startYear) if (!obj.result) {
||!$.isNumeric(obj.year) var obj = $.Deferred();
||!$.isNumeric(obj.month) obj.reject('fail');
){ return obj.promise();
var obj = $.Deferred(); }
obj.reject('fail');
return obj.promise(); if (!$.isNumeric(obj.startYear) ||
} !$.isNumeric(obj.year) ||
!$.isNumeric(obj.month)
if(useCachedMap){ ) {
localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj])); var obj = $.Deferred();
localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear)); obj.reject('fail');
} return obj.promise();
}
$world_map.removeClass('draw_required');
if (useCachedMap) {
return obj; localStorage.setItem(storedOldMapKey, JSON.stringify([serverID, obj]));
} localStorage.setItem(storedStartYear, JSON.stringify(obj.startYear));
}
function setMapBackground(obj){
var startYear = obj.startYear; $world_map.removeClass('draw_required');
var year = obj.year;
var month = obj.month; return obj;
}
if(isDetailMap){
$world_map.addClass('map_detail').removeClass('map_basic');
}
else{ function setMapBackground(obj) {
$world_map.addClass('map_basic').removeClass('map_detail'); function setTheme() {
} var oldTheme = $world_map.data('currentTheme');
var newTheme = obj.theme;
var $map_title = $('.map_title_text'); if (oldTheme === newTheme) {
if(year < startYear + 1){ return;
$map_title.css('color', 'magenta'); }
} if (oldTheme) {
else if(year < startYear + 2){ $world_map.removeClass('map_theme_' + oldTheme);
$map_title.css('color', 'orange'); }
} $world_map.addClass('map_theme_' + newTheme);
else if(year < startYear + 3){ $world_map.data('currentTheme', newTheme);
$map_title.css('color', 'yellow'); }
} if (option.dynamicMapTheme) {
setTheme();
$map_title_tooltip = $('.map_title .tooltiptext'); }
$map_title_tooltip.empty(); var startYear = obj.startYear;
var year = obj.year;
var tooltipTexts = []; var month = obj.month;
if(year < startYear + 3){
var startYearText = []; if (isDetailMap) {
var remainYear = startYear + 3 - year; $world_map.addClass('map_detail').removeClass('map_basic');
var remainMonth = 12 - month + 1; } else {
if(remainMonth > 0){ $world_map.addClass('map_basic').removeClass('map_detail');
remainYear -= 1; }
}
if(remainYear){ var $map_title = $('.map_title_text');
startYearText.push('{0}년'.format(remainYear)); if (year < startYear + 1) {
} $map_title.css('color', 'magenta');
if(remainMonth){ } else if (year < startYear + 2) {
startYearText.push('{0}개월'.format(remainMonth)); $map_title.css('color', 'orange');
} } else if (year < startYear + 3) {
$map_title.css('color', 'yellow');
tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3)); }
}
$map_title_tooltip = $('.map_title .tooltiptext');
var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1; $map_title_tooltip.empty();
var nextTechLimitYear = currentTechLimit * 5 + startYear;
var tooltipTexts = [];
tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit+1)); if (year < startYear + 3) {
$map_title_tooltip.html(tooltipTexts.join('<br>')); var startYearText = [];
var remainYear = startYear + 3 - year;
$world_map.removeClass('map_string map_summer map_fall map_winter'); var remainMonth = 12 - month + 1;
if(month <= 3){ if (remainMonth > 0) {
$world_map.addClass('map_spring'); remainYear -= 1;
} }
else if(month <= 6){ if (remainYear) {
$world_map.addClass('map_summer'); startYearText.push('{0}년'.format(remainYear));
} }
else if(month <= 9){ if (remainMonth) {
$world_map.addClass('map_fall'); startYearText.push('{0}개월'.format(remainMonth));
} }
else{
$world_map.addClass('map_winter'); tooltipTexts.push('초반제한 기간 : {0} ({1}년)'.format(startYearText.join(' '), startYear + 3));
} }
$map_title.html('{0}年 {1}月'.format(year, month)); var currentTechLimit = Math.floor(Math.max(0, year - startYear) / 5) + 1;
var nextTechLimitYear = currentTechLimit * 5 + startYear;
return obj;
} tooltipTexts.push('기술등급 제한 : {0}등급 ({1}년 해제)'.format(currentTechLimit, nextTechLimitYear, currentTechLimit + 1));
$map_title_tooltip.html(tooltipTexts.join('<br>'));
function convertCityObjs(obj){
//원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다. $world_map.removeClass('map_string map_summer map_fall map_winter');
if (month <= 3) {
function toCityObj(arr){ $world_map.addClass('map_spring');
return { } else if (month <= 6) {
id:arr[0], $world_map.addClass('map_summer');
level:arr[1], } else if (month <= 9) {
state:arr[2], $world_map.addClass('map_fall');
nationId:(arr[3]>0)?arr[3]:null, } else {
region:arr[4], $world_map.addClass('map_winter');
supply:(arr[5]!=0) }
};
} $map_title.html('{0}年 {1}月'.format(year, month));
function toNationObj(arr){ return obj;
return { }
id:arr[0],
name:arr[1], function convertCityObjs(obj) {
color:arr[2], //원본 Obj는 굉장히 간소하게 온다, Object 형태로 변환해서 사용한다.
capital:arr[3]
}; function toCityObj(arr) {
} return {
id: arr[0],
var cityList = obj.cityList.map(toCityObj); level: arr[1],
var nationList = obj.nationList.map(toNationObj); state: arr[2],
nationList = convertDictById(nationList); //array of object -> dict nationId: (arr[3] > 0) ? arr[3] : null,
region: arr[4],
var spyList = obj.spyList; supply: (arr[5] != 0)
var shownByGeneralList = convertSet(obj.shownByGeneralList);//Array -> Set };
}
var myCity = obj.myCity;
var myNation = obj.myNation; function toNationObj(arr) {
return {
id: arr[0],
function mergePositionInfo(city){ name: arr[1],
var id = city.id; color: arr[2],
if(!(id in cityPosition)){ capital: arr[3]
return city; };
} }
var xy_val = cityPosition[id];
city.name = xy_val[0]; var cityList = obj.cityList.map(toCityObj);
city.x = xy_val[1]; var nationList = obj.nationList.map(toNationObj);
city.y = xy_val[2]; nationList = convertDictById(nationList); //array of object -> dict
return city;
} var spyList = obj.spyList;
var shownByGeneralList = convertSet(obj.shownByGeneralList); //Array -> Set
function mergeNationInfo(city){
//nationId 값으로 isCapital, color, nation을 통합 var myCity = obj.myCity;
var myNation = obj.myNation;
var nationId = city.nationId;
if(nationId === null || !(nationId in nationList)){
city.nationId = null; function mergePositionInfo(city) {
city.nation = null; var id = city.id;
city.color = null; if (!(id in cityPosition)) {
city.isCapital = false; return city;
return city; }
} var xy_val = cityPosition[id];
city.name = xy_val[0];
var nationObj = nationList[nationId]; city.x = xy_val[1];
city.nation = nationObj.name; city.y = xy_val[2];
city.color = nationObj.color; return city;
city.isCapital = (nationObj.capital == city.id); }
return city; function mergeNationInfo(city) {
} //nationId 값으로 isCapital, color, nation을 통합
function mergeClickable(city){ var nationId = city.nationId;
//clickable = (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll if (nationId === null || !(nationId in nationList)) {
var id = city.id; city.nationId = null;
var nationId = city.nationId; city.nation = null;
var clickable = 0; city.color = null;
if(id in spyList){ city.isCapital = false;
clickable |= spyList[id] << 3; return city;
} }
if(myNation !== null && nationId == myNation){
clickable |= 4; var nationObj = nationList[nationId];
} city.nation = nationObj.name;
if(shownByGeneralList.hasOwnProperty(id)){ city.color = nationObj.color;
clickable |= 2; city.isCapital = (nationObj.capital == city.id);
}
if(myCity !== null && id == myCity){ return city;
clickable |= 2; }
}
if(clickableAll){ function mergeClickable(city) {
clickable |= 1; //clickable = (defaultCity << 4 ) | (remainSpy << 3) | (ourCity << 2) | (shownByGeneral << 1) | clickableAll
} var id = city.id;
var nationId = city.nationId;
var clickable = 16;
city.clickable = clickable; if (id in spyList) {
return city; clickable |= spyList[id] << 3;
} }
if (myNation !== null && nationId == myNation) {
cityList = cityList clickable |= 4;
.map(mergePositionInfo) }
.map(mergeNationInfo) if (shownByGeneralList.hasOwnProperty(id)) {
.map(mergeClickable) clickable |= 2;
.map(formatCityInfo); }
if (myCity !== null && id == myCity) {
return { clickable |= 2;
'cityList' : cityList, }
'myCity' : myCity if (clickableAll) {
}; clickable |= 1;
} }
function drawDetailWorldMap(obj){
city.clickable = clickable;
var $map_body = $('.world_map .map_body'); return city;
}
var cityList = obj.cityList;
var myCity = obj.myCity; cityList = cityList
.map(mergePositionInfo)
cityList.forEach(function(city){ .map(mergeNationInfo)
var id = city.id; .map(mergeClickable)
$('.city_base_{0}'.format(id)).detach(); .map(formatCityInfo);
//이전 도시는 지운다.
return {
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id)); 'cityList': cityList,
$cityObj.addClass('city_level_{0}'.format(city.level)); 'myCity': myCity
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15}); };
}
if('color' in city && city.color !== null){
var $bgObj = $('<div class="city_bg"></div>'); function drawDetailWorldMap(obj) {
$cityObj.append($bgObj);
$bgObj.css({'background-image':'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color))}); var $map_body = $(drawTarget + ' .map_body');
}
var cityList = obj.cityList;
var $linkObj = $('<a class="city_link"></a>'); var myCity = obj.myCity;
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id});
$cityObj.append($linkObj); cityList.forEach(function(city) {
var id = city.id;
var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level)); $('.city_base_{0}'.format(id)).detach();
$linkObj.append($imgObj); //이전 도시는 지운다.
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
$cityObj.addClass('city_level_{0}'.format(city.level));
if(city.state > 0){ $cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
$linkObj.append($stateObj); if ('color' in city && city.color !== null) {
} var $bgObj = $('<div class="city_bg"></div>');
$cityObj.append($bgObj);
if(city.nationId && city.nationId > 0){ $bgObj.css({ 'background-image': 'url({0}/b{1}.png)'.format(pathConfig.gameImage, convColorValue(city.color)) });
var flagType = city.supply?'f':'d'; }
var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
if(city.isCapital){ var $linkObj = $('<a class="city_link"></a>');
var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage)); $linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
$flagObj.append($capitalObj); $cityObj.append($linkObj);
}
$imgObj.append($flagObj); var $imgObj = $('<div class="city_img"><img src="{0}/cast_{1}.gif"><div class="city_filler"></div></div>'.format(pathConfig.gameImage, city.level));
} $linkObj.append($imgObj);
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
$imgObj.append($nameObj);
if (city.state > 0) {
var $stateObj = $('<div class="city_state"><img src="{0}/event{1}.gif"></div>'.format(pathConfig.gameImage, city.state));
$map_body.append($cityObj); $linkObj.append($stateObj);
}
}); if (city.nationId && city.nationId > 0) {
var flagType = city.supply ? 'f' : 'd';
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city'); var $flagObj = $('<div class="city_flag"><img src="{0}/{1}{2}.gif"></div>'.format(pathConfig.gameImage, flagType, convColorValue(city.color)));
if (city.isCapital) {
return obj; var $capitalObj = $('<div class="city_capital"><img src="{0}/event51.gif"></div>'.format(pathConfig.gameImage));
} $flagObj.append($capitalObj);
}
function drawBasicWorldMap(obj){ $imgObj.append($flagObj);
}
var $map_body = $('.world_map .map_body');
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
var cityList = obj.cityList; $imgObj.append($nameObj);
var myCity = obj.myCity;
cityList.forEach(function(city){ $map_body.append($cityObj);
var id = city.id;
$('.city_base_{0}'.format(id)).detach();
//이전 도시는 지운다. });
var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id)); $world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
$cityObj.addClass('city_level_{0}'.format(city.level));
$cityObj.data('obj', city).css({'left':city.x-20,'top':city.y-15}); return obj;
}
var $linkObj = $('<a class="city_link"></a>');
$linkObj.data({'text':city.text,'nation':city.nation,'id':city.id}); function drawBasicWorldMap(obj) {
$cityObj.append($linkObj);
var $map_body = $(drawTarget + ' .map_body');
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
if('color' in city && city.color !== null){ var cityList = obj.cityList;
$imgObj.css({'background-color':city.color}); var myCity = obj.myCity;
}
$linkObj.append($imgObj); cityList.forEach(function(city) {
var id = city.id;
if(city.state > 0){ $('.city_base_{0}'.format(id)).detach();
var state_text = 'wrong'; //이전 도시는 지운다.
if(city.state < 10){
state_text = 'good'; var $cityObj = $('<div class="city_base city_base_{0}"></div>'.format(id));
} $cityObj.addClass('city_level_{0}'.format(city.level));
else if(city.state < 40){ $cityObj.data('obj', city).css({ 'left': city.x - 20, 'top': city.y - 15 });
state_text = 'bad';
} var $linkObj = $('<a class="city_link"></a>');
else if(city.state < 50){ $linkObj.data({ 'text': city.text, 'nation': city.nation, 'id': city.id });
state_text = 'war'; $cityObj.append($linkObj);
}
var $imgObj = $('<div class="city_img"><div class="city_filler"></div></div>');
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text)); if ('color' in city && city.color !== null) {
$imgObj.append($stateObj); $imgObj.css({ 'background-color': city.color });
} }
$linkObj.append($imgObj);
//단순 표기에서는 깃발 여부가 없음
if(city.isCapital){ if (city.state > 0) {
var $capitalObj = $('<div class="city_capital"></div>'); var state_text = 'wrong';
$imgObj.append($capitalObj); if (city.state < 10) {
} state_text = 'good';
} else if (city.state < 40) {
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name)); state_text = 'bad';
$imgObj.append($nameObj); } else if (city.state < 50) {
state_text = 'war';
$map_body.append($cityObj); }
});
var $stateObj = $('<div class="city_state city_state_{0}"></div>'.format(state_text));
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city'); $imgObj.append($stateObj);
}
return obj;
} //단순 표기에서는 깃발 여부가 없음
if (city.isCapital) {
function setMouseWork(obj){ var $capitalObj = $('<div class="city_capital"></div>');
var $tooltip = $('.world_map .city_tooltip'); $imgObj.append($capitalObj);
var $tooltip_city = $tooltip.find('.city_name'); }
var $tooltip_nation = $tooltip.find('.nation_name');
var $nameObj = $('<span class="city_detail_name">{0}</span>'.format(city.name));
var $objs = $('.world_map .city_link'); $imgObj.append($nameObj);
var $map_body = $('.world_map .map_body'); $map_body.append($cityObj);
});
//터치스크린 탭
$world_map.find('.city_base_{0} .city_filler'.format(myCity)).addClass('my_city');
if(!option.neutralView && is_touch_device()){
$objs.on('touchstart', function(e){ return obj;
if(window.sam_toggleSingleTap){ }
return true;
} function setMouseWork(obj) {
var $this = $(this); var $tooltip = $(drawTarget + ' .city_tooltip');
var $tooltip_city = $tooltip.find('.city_name');
var touchMode = $this.data('touchMode'); var $tooltip_nation = $tooltip.find('.nation_name');
if($tooltip_city.data('target') != $this.data('id')){
$this.data('touchMode', 1); var $objs = $(drawTarget + ' .city_link');
}
else if(touchMode === undefined){ var $map_body = $(drawTarget + ' .map_body');
$this.data('touchMode', 1);
} //터치스크린 탭
else{
$this.data('touchMode', touchMode + 1); if (!option.neutralView && is_touch_device()) {
} $objs.on('touchstart', function(e) {
$map_body.data('touchMode', 1); if (window.sam_toggleSingleTap) {
return true;
$tooltip_city.data('target', $this.data('id')); }
var $this = $(this);
}); var touchMode = $this.data('touchMode');
if ($tooltip_city.data('target') != $this.data('id')) {
$objs.on('touchend', function(e){ $this.data('touchMode', 1);
if(window.sam_toggleSingleTap){ } else if (touchMode === undefined) {
return true; $this.data('touchMode', 1);
} } else {
var $this = $(this); $this.data('touchMode', touchMode + 1);
var position = $this.parent().position(); }
$tooltip_city.html($this.data('text')); $map_body.data('touchMode', 1);
var nation_text = $this.data('nation'); $tooltip_city.data('target', $this.data('id'));
if(nation_text){
$tooltip_nation.html(nation_text).show();
} });
else{
$tooltip_nation.html('').hide(); $objs.on('touchend', function(e) {
} if (window.sam_toggleSingleTap) {
return true;
$tooltip.css({'top': position.top + 25, 'left': position.left + 35}).show(); }
var $this = $(this);
var touchMode = $this.data('touchMode'); var position = $this.parent().position();
if(touchMode <= 1){ $tooltip_city.html($this.data('text'));
return false;
} var nation_text = $this.data('nation');
if (nation_text) {
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다. $tooltip_nation.html(nation_text).show();
$this.data('touchMode', 0); } else {
}); $tooltip_nation.html('').hide();
}
$map_body.on('touchend',function(e){
if(window.sam_toggleSingleTap){ var left = position.left;
return true; var top = position.top;
}
//위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치 var scale = $map_body.data('scale');
$tooltip.hide(); if (scale) {
}); left /= scale;
top /= scale;
} }
//Mouse over 모드 작동 $tooltip.css({ 'top': top + 25, 'left': left + 35 }).show();
$map_body.on('mousemove', function(e){ var touchMode = $this.data('touchMode');
if($(this).data('touchMode')){ if (touchMode <= 1) {
return true; return false;
} }
var parentOffset = $map_body.offset(); //xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
var relX = e.pageX - parentOffset.left; $this.data('touchMode', 0);
var relY = e.pageY - parentOffset.top; });
$tooltip.css({'top': relY + 10, 'left': relX + 10}); $map_body.on('touchend', function(e) {
}); if (window.sam_toggleSingleTap) {
return true;
$objs.on('mouseenter', function(e){ }
if($map_body.data('touchMode')){ //위의 touchend bind에 해당하지 않는 경우 -> 빈 지도 터치
return true; $tooltip.hide();
} });
var $this = $(this); }
$tooltip_city.data('target', $this.data('id')); //Mouse over 모드 작동
$tooltip_city.html($this.data('text'));
var nation_text = $this.data('nation'); $map_body.on('mousemove', function(e) {
if(nation_text){ if ($(this).data('touchMode')) {
$tooltip_nation.html(nation_text).show(); return true;
} }
else{
$tooltip_nation.html('').hide(); var rect = this.getBoundingClientRect();
} var left = (e.clientX - rect.left - this.clientLeft + this.scrollLeft);
var top = (e.clientY - rect.top - this.clientTop + this.scrollTop);
$tooltip.show();
}); var scale = $map_body.data('scale');
if (scale) {
$objs.on('mouseleave', function(event){ left /= scale;
$tooltip.hide(); top /= scale;
}); }
$objs.on('click', function(e){ $tooltip.css({ 'top': top + 10, 'left': left + 10 });
//xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다. });
var touchMode = $(this).data('touchMode');
if(touchMode === undefined){ $objs.on('mouseenter', function(e) {
return; if ($map_body.data('touchMode')) {
} return true;
}
if(touchMode === 1){
return false; var $this = $(this);
}
}); $tooltip_city.data('target', $this.data('id'));
$tooltip_city.html($this.data('text'));
var nation_text = $this.data('nation');
return obj; if (nation_text) {
} $tooltip_nation.html(nation_text).show();
} else {
function setCityClickable(obj){ $tooltip_nation.html('').hide();
}
obj.cityList.forEach(function(city){
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id)); $tooltip.show();
});
if('clickable' in city && city.clickable > 0){
$cityLink.attr('href',hrefTemplate.format(city.id)); $objs.on('mouseleave', function(event) {
} $tooltip.hide();
});
if(selectCallback){
$cityLink.click(function(){ $objs.on('click', function(e) {
return selectCallback(city); //xxx: touchend 다음 click 이벤트가 갈 수도 있고, 안 갈 수도 있다.
}); var touchMode = $(this).data('touchMode');
} if (touchMode === undefined) {
}); return;
}
return obj;
} if (touchMode === 1) {
return false;
function saveCityInfo(obj){ }
$world_map.data('cityInfo', obj); });
return obj;
}
return obj;
var $hideCityNameBtn = $world_map.find('.map_toggle_cityname'); }
if(localStorage.getItem('sam.hideMapCityName') == 'yes'){
$world_map.addClass('hide_cityname'); function setCityClickable(obj) {
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
} obj.cityList.forEach(function(city) {
var $cityLink = $world_map.find('.city_base_{0} .city_link'.format(city.id));
$hideCityNameBtn.click(function(){
//이전 상태 확인 if ('clickable' in city && city.clickable > 0) {
var state = !$hideCityNameBtn.hasClass('active'); $cityLink.attr('href', hrefTemplate.format(city.id));
if(state){ }
$world_map.addClass('hide_cityname');
localStorage.setItem('sam.hideMapCityName', 'yes'); if (selectCallback) {
} $cityLink.click(function() {
else{ return selectCallback(city);
$world_map.removeClass('hide_cityname'); });
localStorage.setItem('sam.hideMapCityName', 'no'); }
} });
});
return obj;
var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap'); }
if(localStorage.getItem('sam.toggleSingleTap') == 'yes'){
window.sam_toggleSingleTap = true; function saveCityInfo(obj) {
$toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true'); $world_map.data('cityInfo', obj);
} return obj;
else{ }
window.sam_toggleSingleTap = false;
} var $hideCityNameBtn = $world_map.find('.map_toggle_cityname');
if (localStorage.getItem('sam.hideMapCityName') == 'yes') {
var $map_body = $('.world_map .map_body'); $world_map.addClass('hide_cityname');
$hideCityNameBtn.addClass('active').attr('aria-pressed', 'true');
$toggleSingleTapBtn.click(function(){ }
//이전 상태 확인
var state = !$toggleSingleTapBtn.hasClass('active'); $hideCityNameBtn.click(function() {
if(state){ //이전 상태 확인
$map_body.removeData('touchMode'); var state = !$hideCityNameBtn.hasClass('active');
localStorage.setItem('sam.toggleSingleTap', 'yes'); if (state) {
window.sam_toggleSingleTap = true; $world_map.addClass('hide_cityname');
} localStorage.setItem('sam.hideMapCityName', 'yes');
else{ } else {
localStorage.setItem('sam.toggleSingleTap', 'no'); $world_map.removeClass('hide_cityname');
window.sam_toggleSingleTap = false; localStorage.setItem('sam.hideMapCityName', 'no');
} }
}); });
if(isDetailMap){ var $toggleSingleTapBtn = $world_map.find('.map_toggle_single_tap');
$world_map.addClass('map_detail'); if (localStorage.getItem('sam.toggleSingleTap') == 'yes') {
} window.sam_toggleSingleTap = true;
else{ $toggleSingleTapBtn.addClass('active').attr('aria-pressed', 'true');
$world_map.removeClass('map_datail'); } else {
} window.sam_toggleSingleTap = false;
}
//deferred mode of jQuery. != promise-then.
var deferred = $.ajax({ var $map_body = $(drawTarget + ' .map_body');
url: option.targetJson,
type: 'post', $toggleSingleTapBtn.click(function() {
dataType:'json', //이전 상태 확인
data: { var state = !$toggleSingleTapBtn.hasClass('active');
data: JSON.stringify({ if (state) {
neutralView:option.neutralView, $map_body.removeData('touchMode');
year:option.year, localStorage.setItem('sam.toggleSingleTap', 'yes');
month:option.month, window.sam_toggleSingleTap = true;
showMe:option.showMe, } else {
aux:option.aux localStorage.setItem('sam.toggleSingleTap', 'no');
}) window.sam_toggleSingleTap = false;
} }
}); });
deferred if (isDetailMap) {
.then(checkReturnObject) $world_map.addClass('map_detail');
.then(setMapBackground) } else {
.then(convertCityObjs) $world_map.removeClass('map_datail');
.then(isDetailMap?drawDetailWorldMap:drawBasicWorldMap) }
.then(setMouseWork)
.then(setCityClickable) //deferred mode of jQuery. != promise-then.
.then(saveCityInfo); var deferred = $.ajax({
url: option.targetJson,
if($world_map.hasClass('draw_required')){ type: option.reqType,
if(useCachedMap){ dataType: 'json',
//일단 불러옴 ifModified: true,
do{ data: {
var storedMap = localStorage.getItem(storedOldMapKey); data: JSON.stringify({
if(!storedMap){ neutralView: option.neutralView,
break; year: option.year,
} month: option.month,
storedMap = JSON.parse(storedMap); showMe: option.showMe,
var storedServerID = storedMap[0]; aux: option.aux
if(storedServerID != serverID){ })
break; }
} });
storedMap = storedMap[1]; var rawObject = null;
storedMap = setMapBackground(storedMap);
storedMap = convertCityObjs(storedMap); deferred
if(isDetailMap){ .then(function(data) {
storedMap = drawDetailWorldMap(storedMap); rawObject = data;
} return data;
else{ })
storedMap = drawBasicWorldMap(storedMap); .then(checkReturnObject)
} .then(setMapBackground)
storedMap = setMouseWork(storedMap); .then(convertCityObjs)
storedMap = setCityClickable(storedMap); .then(isDetailMap ? drawDetailWorldMap : drawBasicWorldMap)
storedMap = saveCityInfo(storedMap); .then(setMouseWork)
}while(false); .then(setCityClickable)
} .then(saveCityInfo)
else if(option.year && option.month){ .then(function(data) {
var startYear = localStorage.getItem(storedStartYear); if (option.callback) {
if(startYear){ option.callback(data, rawObject);
startYear = JSON.parse(startYear); }
}
else{ });
startYear = option.year;
} if ($world_map.hasClass('draw_required')) {
var tmp = { if (useCachedMap) {
year : option.year, //일단 불러옴
month : option.month, do {
startYear : startYear var storedMap = localStorage.getItem(storedOldMapKey);
}; if (!storedMap) {
setMapBackground(tmp); break;
} }
storedMap = JSON.parse(storedMap);
var storedServerID = storedMap[0];
} if (storedServerID != serverID) {
} break;
$(function(){ }
if(is_touch_device()){
$('.map_body .map_toggle_single_tap').show(); storedMap = storedMap[1];
} storedMap = setMapBackground(storedMap);
storedMap = convertCityObjs(storedMap);
if (isDetailMap) {
storedMap = drawDetailWorldMap(storedMap);
} else {
storedMap = drawBasicWorldMap(storedMap);
}
storedMap = setMouseWork(storedMap);
storedMap = setCityClickable(storedMap);
storedMap = saveCityInfo(storedMap);
} while (false);
} else if (option.year && option.month) {
var startYear = localStorage.getItem(storedStartYear);
if (startYear) {
startYear = JSON.parse(startYear);
} else {
startYear = option.year;
}
var tmp = {
year: option.year,
month: option.month,
startYear: startYear
};
setMapBackground(tmp);
}
}
}
$(function() {
if (is_touch_device()) {
$('.map_body .map_toggle_single_tap').show();
}
}) })
+166 -165
View File
@@ -1,166 +1,167 @@
jQuery(function($){ jQuery(function($) {
var initCustomCSSForm = function(){ var initCustomCSSForm = function() {
var lastTimeOut = null; var lastTimeOut = null;
var $obj = $('#custom_css'); var $obj = $('#custom_css');
var key = 'sam_customCSS'; var key = 'sam_customCSS';
var text = localStorage.getItem(key); var text = localStorage.getItem(key);
if(text){ if (text) {
$obj.val(text); $obj.val(text);
console.log(text); console.log(text);
} }
if($obj.on('change keyup paste', function(){ if ($obj.on('change keyup paste', function() {
var newText = $obj.val(); var newText = $obj.val();
if(text == newText){ if (text == newText) {
return; return;
} }
if(lastTimeOut){ if (lastTimeOut) {
clearTimeout(lastTimeOut); clearTimeout(lastTimeOut);
} }
$obj.css('background-color', '#222222'); $obj.css('background-color', '#222222');
lastTimeOut = setTimeout(function(){ lastTimeOut = setTimeout(function() {
text = $obj.val(); text = $obj.val();
localStorage.setItem(key, text); localStorage.setItem(key, text);
$obj.css('background-color', 'black'); $obj.css('background-color', 'black');
}, 500); }, 500);
})); }));
} }
$('.load_old_log').click(function(){ $('.load_old_log').click(function() {
var $thisBtn = $(this); var $thisBtn = $(this);
var logType = $thisBtn.data('log_type'); var logType = $thisBtn.data('log_type');
var $last = $('.log_{0}:last'.format(logType)); var $last = $('.log_{0}:last'.format(logType));
var reqTo = null; var reqTo = null;
if($last.length){ if ($last.length) {
reqTo = $last.data('seq'); reqTo = $last.data('seq');
} }
$.post({ $.post({
url:'j_general_log_old.php', url: 'j_general_log_old.php',
dataType:'json', dataType: 'json',
data:{ data: {
to:reqTo, to: reqTo,
type:logType type: logType
} }
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
return quickReject('로그를 받아오지 못했습니다.'); return quickReject('로그를 받아오지 못했습니다.');
} }
if(!data.result){ if (!data.result) {
return quickReject('로그를 받아오지 못했습니다. : '+data.reason); return quickReject('로그를 받아오지 못했습니다. : ' + data.reason);
} }
var keys = Object.keys(data.log); var keys = Object.keys(data.log);
if(keys.length > 1 && keys[0] < keys[1]){ if (keys.length > 1 && keys[0] < keys[1]) {
keys.reverse(); keys.reverse();
} }
if(keys == 0){ if (keys == 0) {
$thisBtn.hide(); $thisBtn.hide();
return; return;
} }
var html = []; var html = [];
$.each(keys, function(_, key){ $.each(keys, function(_, key) {
if($('#log_{0}_{1}'.format(logType, key)).length){ if ($('#log_{0}_{1}'.format(logType, key)).length) {
return true; return true;
} }
var item = data.log[key]; var item = data.log[key];
html.push("<div class='log_{0}' id='log_{0}_{1}' data-seq='{1}'>{2}</div>".format(logType, key, item)); html.push("<div class='log_{0}' id='log_{0}_{1}' data-seq='{1}'>{2}</div>".format(logType, key, item));
}); });
$('#{0}Plate'.format(logType)).append(html); $('#{0}Plate'.format(logType)).append(html);
}, errUnknown) }, errUnknown)
.fail(function(reason){ .fail(function(reason) {
alert(reason); alert(reason);
location.reload(); location.reload();
}); });
}) })
initCustomCSSForm(); initCustomCSSForm();
$('#die_immediately').click(function(){ $('#die_immediately').click(function() {
if(!confirm('정말로 삭제하시겠습니까?')){ if (!confirm('정말로 삭제하시겠습니까?')) {
return false; return false;
} }
$.post({ $.post({
url:'j_die_immediately.php', url: 'j_die_immediately.php',
dataType:'json', dataType: 'json',
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
return quickReject('실패했습니다.'); return quickReject('실패했습니다.');
} }
if(!data.result){ if (!data.result) {
return quickReject(data.reason); return quickReject(data.reason);
} }
location.replace('..'); location.replace('..');
}, errUnknown) }, errUnknown)
.fail(function(reason){ .fail(function(reason) {
alert(reason); alert(reason);
location.reload(); location.reload();
}); });
return false; return false;
return false; return false;
}); });
$('#vacation').click(function(){ $('#vacation').click(function() {
if(!confirm('휴가 기능을 신청할까요?')){ if (!confirm('휴가 기능을 신청할까요?')) {
return false; return false;
} }
$.post({ $.post({
url:'j_vacation.php', url: 'j_vacation.php',
dataType:'json', dataType: 'json',
}).then(function(data){ }).then(function(data) {
if(!data){ if (!data) {
return quickReject('실패했습니다.'); return quickReject('실패했습니다.');
} }
if(!data.result){ if (!data.result) {
return quickReject(data.reason); return quickReject(data.reason);
} }
location.reload(); location.reload();
}, errUnknown) }, errUnknown)
.fail(function(reason){ .fail(function(reason) {
alert(reason); alert(reason);
location.reload(); location.reload();
}); });
return false; return false;
return false; return false;
}); });
$('#set_my_setting').click(function(){ $('#set_my_setting').click(function() {
$.post({ $.post({
url:'j_set_my_setting.php', url: 'j_set_my_setting.php',
dataType:'json', dataType: 'json',
data:{ data: {
tnmt:$('.tnmt:checked').val(), tnmt: $('.tnmt:checked').val(),
defence_train:$('#defence_train').val(), defence_train: $('#defence_train').val(),
use_treatment:$('#use_treatment').val(), use_treatment: $('#use_treatment').val(),
} use_auto_nation_turn: $('#use_auto_nation_turn').val(),
}).then(function(data){ }
if(!data){ }).then(function(data) {
return quickReject('실패했습니다.'); if (!data) {
} return quickReject('실패했습니다.');
if(!data.result){ }
return quickReject(data.reason); if (!data.result) {
} return quickReject(data.reason);
}
location.reload();
location.reload();
}, errUnknown)
.fail(function(reason){ }, errUnknown)
alert(reason); .fail(function(reason) {
location.reload(); alert(reason);
}); location.reload();
return false; });
return false; return false;
}); return false;
});
}); });
+5 -3
View File
@@ -35,7 +35,7 @@ jQuery(function($) {
//checkCommandArg 참고 //checkCommandArg 참고
var availableArgumentList = { var availableArgumentList = {
'string': [ 'string': [
'nationName', 'optionText', 'itemType', 'nationType', 'itemCode', 'nationName', 'optionText', 'itemType', 'nationType', 'itemCode', 'commandType',
], ],
'int': [ 'int': [
'crewType', 'destGeneralID', 'destCityID', 'destNationID', 'crewType', 'destGeneralID', 'destCityID', 'destNationID',
@@ -73,9 +73,11 @@ jQuery(function($) {
} }
}, },
'integerArray': function($obj) { 'integerArray': function($obj) {
return $obj.map(function() { var result = [];
return parseInt($(this).val()); $obj.each(function() {
result.push(parseInt($(this).val()));
}); });
return result;
} }
} }
+210
View File
@@ -0,0 +1,210 @@
var templateGeneralCard = '<div class="general_card">\
<h4 class="bg1 with_border"><%generalName%></h4>\
<h4><img src="<%iconPath%>" height=64 width=64></h4><p>\
<%if(leadership){%>\
<%leadership%> / <%strength%> / <%intel%><br>\
<%}%>\
<%if(personalText){%><%personalText%><br><%}%>\
<%if(specialDomesticText||specialWarText){%>\
<%specialDomesticText%> / <%specialWarText%><br>\
<%}%>\
<%if(dex){%><br>\
보병: <%parseInt(dex[0]/1000)%>K<br>\
궁병: <%parseInt(dex[1]/1000)%>K<br>\
기병: <%parseInt(dex[2]/1000)%>K<br>\
귀병: <%parseInt(dex[3]/1000)%>K<br>\
차병: <%parseInt(dex[4]/1000)%>K<br>\
<%}%>\
</p>\
<button type="subject" class="with_skin with_border select_btn" data-name="<%generalName%>" value="<%uniqueName%>" name="pick">선택하기</button>\
</div>';
var templateSpecial =
'<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\
<span class="tooltiptext">\
<%info%>\
</span>\
</span>\
';
function pickGeneral() {
$btn = $(this);
if (hasGeneralID) {
if (!confirm('이 장수를 선택할까요? : {0}'.format($btn.data('name')))) {
return false;
}
$.post({
url: 'j_update_picked_general.php',
dataType: 'json',
data: {
pick: $btn.val()
}
}).then(function(result) {
if (!result.result) {
alert(result.reason);
location.refresh();
}
alert('선택한 장수로 변경했습니다.');
location.href = './';
});
return false;
}
currentGeneralInfo = cards[$btn.val()];
var $card = $btn.closest('.general_card');
var $leftPad = $('#left_pad');
$leftPad.empty();
$card.clone().appendTo($leftPad);
initTooltip($leftPad);
return false;
}
function buildGeneral() {
if (!currentGeneralInfo) {
alert('장수를 선택해주세요!');
return false;
}
if (!confirm('이 장수로 생성할까요?')) {
return false;
}
$.post({
url: 'j_select_picked_general.php',
dataType: 'json',
data: {
pick: currentGeneralInfo.uniqueName,
use_own_picture: $('#use_own_picture').is(':checked'),
leadership: parseInt($('#leadership').val()),
strength: parseInt($('#leadership').val()),
intel: parseInt($('#leadership').val()),
personal: $('#selChar').val()
}
}).then(function(result) {
if (!result.result) {
alert(result.reason);
location.refresh();
}
alert('선택한 장수로 생성했습니다.');
location.href = './';
});
return false;
}
function updateOutdateTimer() {
var $validUntilText = $('#valid_until_text');
var now = Date.now();
var validUntil = $validUntilText.data('until');
if (validUntil <= 0) {
return;
} else if (validUntil < now) {
$validUntilText.data('until', 0);
$('#valid_until').hide();
$('#outdate_token').show();
return;
} else if (validUntil - now <= 30000) {
$validUntilText.css('color', "rgb(255, {0}, {0})".format(255 * (validUntil - now) / 30000));
}
setTimeout(updateOutdateTimer, 1000);
}
function printGenerals(value) {
$('.card_holder').empty();
$('#valid_until').show();
$('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white');
$('#outdate_token').hide();
var pick = $.map(value.pick, function(value, key) {
return value;
});
var emptyCard = {
'leadership': null,
'strength': null,
'intel': null,
'personalText': null,
'specialDomesticText': null,
'specialWarText': null,
'dex': null
};
$.each(pick, function(idx, cardData) {
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
if (cardData.specialDomestic !== undefined) {
cardData.specialDomesticText = TemplateEngine(templateSpecial, {
text: cardData.specialDomesticName,
info: cardData.specialDomesticInfo
});
cardData.specialWarText = '-';
}
if (cardData.specialWar !== undefined) {
cardData.specialWarText = TemplateEngine(templateSpecial, {
text: cardData.specialWarName,
info: cardData.specialWarInfo
});
if (cardData.specialDomesticText === undefined) {
cardData.specialDomesticText = '-';
}
}
//FIXME: ego로 적었던것 같음!
if (cardData.personal in characterInfo) {
cardData.personalText = TemplateEngine(templateSpecial, {
text: characterInfo[cardData.personal].name,
info: characterInfo[cardData.personal].info
});
} else {
cardData.personalText = cardData.personal;
}
cards[cardData.uniqueName] = cardData;
var $card = $(TemplateEngine(templateGeneralCard, $.extend({}, emptyCard, cardData)));
$('.card_holder').append($card);
$card.find('.select_btn').click(pickGeneral);
$card.find('.obj_tooltip').tooltip({
title: function() {
return $.trim($(this).find('.tooltiptext').html());
},
html: true
});
});
updateOutdateTimer();
}
$(function($) {
$.post('j_get_select_pool.php').then(function(value) {
if (!value.result) {
alert(value.reason);
return;
}
console.log(value);
printGenerals(value);
});
if (hasGeneralID) {
$('#create_plate').hide();
}
$('#build_general').on('click', buildGeneral);
$.each(validCustomOption, function(idx, value) {
if (value == 'picture') {
$('.custom_picture').show();
} else if (value == 'ego') {
$('.custom_personality').show();
} else if (value == 'stat') {
$('.custom_stat').show();
}
});
});
+352 -359
View File
@@ -1,360 +1,353 @@
var templateGeneralCard = var templateGeneralCard =
'<div class="general_card">\ '<div class="general_card">\
<h4 class="bg1 with_border"><%name%></h4>\ <h4 class="bg1 with_border"><%name%></h4>\
<h4><img src="<%iconPath%>" height=64 width=64></h4>\ <h4><img src="<%iconPath%>" height=64 width=64></h4>\
<p><%leadership%> / <%strength%> / <%intel%><br>\ <p><%leadership%> / <%strength%> / <%intel%><br>\
<%nation%><br>\ <%nation%><br>\
<%personalText%><br>\ <%personalText%><br>\
<%specialText%> / <%special2Text%></p>\ <%specialText%> / <%special2Text%></p>\
<button type="subject" class="with_skin with_border select_btn" data-name="<%name%>" value="<%no%>" name="pick">빙의하기</button>\ <button type="subject" class="with_skin with_border select_btn" data-name="<%name%>" value="<%no%>" name="pick">빙의하기</button>\
<label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>회)</label>\ <label><input <%keepCnt?"":disabled="disabled"%> type="checkbox" value="<%no%>" name="keep[]" class="keep_select">보관(<%keepCnt%>회)</label>\
</div>'; </div>';
var templateSpecial = var templateSpecial =
'<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\ '<span class="obj_tooltip" data-toggle="tooltip" data-placement="top"><%text%>\
<span class="tooltiptext">\ <span class="tooltiptext">\
<%info%>\ <%info%>\
</span>\ </span>\
</span>\ </span>\
'; ';
var templateGeneralRow = var templateGeneralRow =
'<tr>\ '<tr>\
<td><img class="generalIcon" width="64" height="64" src="<%iconPath%>"></td>\ <td><img class="generalIcon" width="64" height="64" src="<%iconPath%>"></td>\
<td style="<%userCSS%>"><%name%><%nameAux%></td>\ <td style="<%userCSS%>"><%name%><%nameAux%></td>\
<td><%age%>세</td>\ <td><%age%>세</td>\
<td><%personalWithTooltip%></td>\ <td><%personalWithTooltip%></td>\
<td><%specialDomesticWithTooltip%> / <%speicalWarWithTooltip%></td>\ <td><%specialDomesticWithTooltip%> / <%speicalWarWithTooltip%></td>\
<td>Lv <%explevel%></td>\ <td>Lv <%explevel%></td>\
<td><%nation%></td>\ <td><%nation%></td>\
<td><%experience%></td>\ <td><%experience%></td>\
<td><%dedication%></td>\ <td><%dedication%></td>\
<td><%officerLevel%></td>\ <td><%officerLevel%></td>\
<td><%total%></td>\ <td><%total%></td>\
<td><%leadership%></td>\ <td><%leadership%></td>\
<td><%strength%></td>\ <td><%strength%></td>\
<td><%intel%></td>\ <td><%intel%></td>\
<td><%killturn%></td>\ <td><%killturn%></td>\
</tr>'; </tr>';
function pickGeneral(){ function pickGeneral() {
$btn = $(this); $btn = $(this);
if (!confirm('빙의할까요? : {0}'.format($btn.data('name')))) { if (!confirm('빙의할까요? : {0}'.format($btn.data('name')))) {
return false; return false;
} }
$.post({ $.post({
url:'j_select_npc.php', url: 'j_select_npc.php',
dataType:'json', dataType: 'json',
data:{ data: {
pick:$btn.val() pick: $btn.val()
} }
}).then(function(result){ }).then(function(result) {
if(!result.result){ if (!result.result) {
alert(result.reason); alert(result.reason);
location.refresh(); location.refresh();
} }
alert('빙의에 성공했습니다.'); alert('빙의에 성공했습니다.');
location.href = './'; location.href = './';
}); });
return false; return false;
} }
function updateOutdateTimer(){ function updateOutdateTimer() {
var $validUntilText = $('#valid_until_text'); var $validUntilText = $('#valid_until_text');
var now = Date.now(); var now = Date.now();
var validUntil = $validUntilText.data('until'); var validUntil = $validUntilText.data('until');
if(validUntil <= 0){ if (validUntil <= 0) {
return; return;
} } else if (validUntil < now) {
else if(validUntil < now){ $validUntilText.data('until', 0);
$validUntilText.data('until',0); $('#valid_until').hide();
$('#valid_until').hide(); $('#outdate_token').show();
$('#outdate_token').show(); return;
return; } else if (validUntil - now <= 30000) {
} $validUntilText.css('color', "rgb(255, {0}, {0})".format(255 * (validUntil - now) / 30000));
else if(validUntil - now <= 30000){ }
$validUntilText.css('color', "rgb(255, {0}, {0})".format(255*(validUntil - now)/30000));
} setTimeout(updateOutdateTimer, 1000);
}
setTimeout(updateOutdateTimer, 1000);
} function updatePickMoreTimer() {
var $btn = $('#btn_pick_more');
function updatePickMoreTimer(){
var $btn = $('#btn_pick_more'); var now = Date.now();
var remain = ($btn.data('available') - now) / 1000;
var now = Date.now(); if (remain <= 0) {
var remain = ($btn.data('available') - now) / 1000; $btn.prop('disabled', false)
if(remain <= 0){ $btn.html('다른 장수 보기');
$btn.prop('disabled', false) return;
$btn.html('다른 장수 보기'); }
return;
} $btn.html('다른 장수 보기({0}초)'.format(Math.ceil(remain)));
$btn.html('다른 장수 보기({0}초)'.format(Math.ceil(remain))); setTimeout(updatePickMoreTimer, 250);
}
setTimeout(updatePickMoreTimer, 250);
} function printGenerals(value) {
$('.card_holder').empty();
function printGenerals(value){ $('#valid_until').show();
$('.card_holder').empty(); $('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color', 'white');
$('#valid_until').show(); $('#outdate_token').hide();
$('#valid_until_text').html(value.validUntil).data('until', (new Date(value.validUntil)).getTime()).css('color','white'); var time = Date.now() + value.pickMoreSeconds * 1000;
$('#outdate_token').hide(); $('#btn_pick_more').data('available', time).prop('disabled', true);
var time = Date.now() + value.pickMoreSeconds*1000;
$('#btn_pick_more').data('available', time).prop('disabled',true); var pick = $.map(value.pick, function(value, key) {
return value;
var pick = $.map(value.pick, function(value, key) { });
return value;
}); pick.sort(function(lhs, rhs) {
var lsum = lhs.leadership + lhs.strength + lhs.intel;
pick.sort(function(lhs, rhs){ var rsum = rhs.leadership + rhs.strength + rhs.intel;
var lsum = lhs.leadership+lhs.strength+lhs.intel; return lsum - rsum;
var rsum = rhs.leadership+rhs.strength+rhs.intel; });
return lsum - rsum;
}); $.each(pick, function(idx, cardData) {
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture);
$.each(pick, function(idx, cardData){ if (cardData.special in specialInfo) {
cardData.iconPath = getIconPath(cardData.imgsvr, cardData.picture); cardData.specialText = TemplateEngine(templateSpecial, {
if(cardData.special in specialInfo){ text: cardData.special,
cardData.specialText = TemplateEngine(templateSpecial, { info: specialInfo[cardData.special]
text:cardData.special, });
info:specialInfo[cardData.special] } else {
}); cardData.specialText = cardData.special;
} }
else{
cardData.specialText = cardData.special; if (cardData.special2 in specialInfo) {
} cardData.special2Text = TemplateEngine(templateSpecial, {
text: cardData.special2,
if(cardData.special2 in specialInfo){ info: specialInfo[cardData.special2]
cardData.special2Text = TemplateEngine(templateSpecial, { });
text:cardData.special2, } else {
info:specialInfo[cardData.special2] cardData.special2Text = cardData.special2;
}); }
}
else{ if (cardData.personal in characterInfo) {
cardData.special2Text = cardData.special2; cardData.personalText = TemplateEngine(templateSpecial, {
} text: cardData.personal,
info: characterInfo[cardData.personal]
if(cardData.personal in characterInfo){ });
cardData.personalText = TemplateEngine(templateSpecial, { } else {
text:cardData.personal, cardData.personalText = cardData.personal;
info:characterInfo[cardData.personal] }
});
}
else{ var $card = $(TemplateEngine(templateGeneralCard, cardData));
cardData.personalText = cardData.personal;
} $('.card_holder').append($card);
$card.find('.select_btn').click(pickGeneral);
$card.find('.obj_tooltip').tooltip({
var $card = $(TemplateEngine(templateGeneralCard, cardData)); title: function() {
return $.trim($(this).find('.tooltiptext').html());
$('.card_holder').append($card); },
$card.find('.select_btn').click(pickGeneral); html: true
$card.find('.obj_tooltip').tooltip({ });
title:function(){ });
return $.trim($(this).find('.tooltiptext').html());
}, updatePickMoreTimer();
html:true updateOutdateTimer();
}); }
});
function printGeneralList(value) {
updatePickMoreTimer(); var tokenList = value.token;
updateOutdateTimer(); var generalList = $.map(value.list, function(general) {
} general = {
no: general[0],
function printGeneralList(value){ picture: general[1],
var tokenList = value.token; imgsvr: general[2],
var generalList = $.map(value.list, function(general){ npc: general[3],
general = { age: general[4],
no:general[0], nation: general[5],
picture:general[1], special: general[6],
imgsvr:general[2], special2: general[7],
npc:general[3], personal: general[8],
age:general[4], name: general[9],
nation:general[5], ownerName: general[10],
special:general[6], injury: general[11],
special2:general[7], leadership: general[12],
personal:general[8], lbonus: general[13],
name:general[9], strength: general[14],
ownerName:general[10], intel: general[15],
injury:general[11], explevel: general[16],
leadership:general[12], experience: general[17],
lbonus:general[13], dedication: general[18],
strength:general[14], officerLevel: general[19],
intel:general[15], killturn: general[20],
explevel:general[16], connect: general[21],
experience:general[17], reserved: 0
dedication:general[18], };
officerLevel:general[19], if (general.npc < 2) {
killturn:general[20], general.reserved = 2;
connect:general[21], }
reserved:0 if (general.no in tokenList) {
}; general.reserved = 1;
if(general.npc < 2){ }
general.reserved = 2;
} general.userCSS = "";
if(general.no in tokenList){ general.nameAux = "";
general.reserved = 1;
} if (general.reserved == 1) {
general.userCSS = 'color:violet';
general.userCSS = ""; } else if (general.npc >= 2) {
general.nameAux = ""; general.userCSS = 'color:cyan';
} else if (general.npc == 1) {
if(general.reserved == 1){ general.userCSS = 'color:skyblue';
general.userCSS = 'color:violet'; }
}
else if(general.npc >= 2){ if (general.ownerName) {
general.userCSS = 'color:cyan'; general.nameAux += '<br><small>({0})</small>'.format(general.ownerName);
} }
else if(general.npc == 1){
general.userCSS = 'color:skyblue'; if (general.reserved == 1) {
} general.nameAux += '<br><small>({0}회)</small>'.format(tokenList[general.no]);
}
if(general.ownerName){
general.nameAux += '<br><small>({0})</small>'.format(general.ownerName);
} general.total = general.leadership + general.strength + general.intel;
general.iconPath = getIconPath(general.imgsvr, general.picture);
if(general.reserved == 1){
general.nameAux += '<br><small>({0}회)</small>'.format(tokenList[general.no]); general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, {
} text: general.special,
info: specialInfo[general.special]
});
general.total = general.leadership + general.strength + general.intel;
general.iconPath = getIconPath(general.imgsvr, general.picture); general.speicalWarWithTooltip = TemplateEngine(templateSpecial, {
text: general.special2,
general.specialDomesticWithTooltip = TemplateEngine(templateSpecial, { info: specialInfo[general.special2]
text:general.special, });
info:specialInfo[general.special]
}); general.personalWithTooltip = TemplateEngine(templateSpecial, {
text: general.personal,
general.speicalWarWithTooltip = TemplateEngine(templateSpecial, { info: characterInfo[general.personal]
text:general.special2, });
info:specialInfo[general.special2]
}); return general;
});
general.personalWithTooltip = TemplateEngine(templateSpecial, {
text:general.personal, generalList.sort(function(lhs, rhs) {
info:characterInfo[general.personal] if (lhs.reserved > rhs.reserved) {
}); return -1;
}
return general; if (lhs.reserved < rhs.reserved) {
}); return 1;
}
generalList.sort(function(lhs, rhs){ if (lhs.total != rhs.total) {
if(lhs.reserved > rhs.reserved){ return rhs.total - lhs.total;
return -1; }
} if (lhs.leadership != rhs.leadership) {
if(lhs.reserved < rhs.reserved){ return rhs.leadership - lhs.total;
return 1; }
}
if(lhs.total != rhs.total){ if (lhs.name < rhs.name) {
return rhs.total - lhs.total; return -1;
} }
if(lhs.leadership != rhs.leadership){ if (lhs.name > rhs.name) {
return rhs.leadership - lhs.total; return 1;
} }
return 0;
if(lhs.name < rhs.name){ });
return -1;
} window.generalList = generalList;
if(lhs.name > rhs.name){ _printGeneralList(true);
return 1; }
}
return 0; function _printGeneralList(clear) {
}); var $generalTable = $('#general_list');
if (clear) {
window.generalList = generalList; $generalTable.empty();
_printGeneralList(true); $generalTable.data('lastIdx', 0);
} $('#row_print_more').show();
}
function _printGeneralList(clear){
var $generalTable = $('#general_list'); generalList = window.generalList;
if(clear){
$generalTable.empty(); var idxFrom = $generalTable.data('lastIdx');
$generalTable.data('lastIdx', 0); var idxTo = Math.min(idxFrom + 50, generalList.length);
$('#row_print_more').show(); $generalTable.data('lastIdx', idxTo);
}
for (var idx = idxFrom; idx < idxFrom + 50; idx++) {
generalList = window.generalList; var general = generalList[idx];
$generalTable.append(TemplateEngine(templateGeneralRow, general));
var idxFrom = $generalTable.data('lastIdx'); }
var idxTo = Math.min(idxFrom + 50, generalList.length);
$generalTable.data('lastIdx', idxTo); if (idxTo == generalList.length) {
$('#row_print_more').hide();
for(var idx = idxFrom; idx < idxFrom + 50; idx++){ }
var general = generalList[idx];
$generalTable.append(TemplateEngine(templateGeneralRow, general)); $generalTable.find('.obj_tooltip').tooltip({
} title: function() {
return $.trim($(this).find('.tooltiptext').html());
if(idxTo == generalList.length){ },
$('#row_print_more').hide(); html: true
} });
$('#tb_general_list').show();
$generalTable.find('.obj_tooltip').tooltip({ }
title:function(){
return $.trim($(this).find('.tooltiptext').html()); $(function($) {
}, window.generalList = [];
html:true
}); $.post('j_get_select_npc_token.php').then(function(value) {
$('#tb_general_list').show(); if (!value.result) {
} alert(value.reason);
return;
$(function($){ }
window.generalList = [];
console.log(value);
$.post('j_get_select_npc_token.php').then(function(value){ printGenerals(value);
if(!value.result){ });
alert(value.reason);
return; $('#btn_pick_more').click(function() {
} var generals = $.map($('.keep_select:checked'), function(value) {
return $(value).val();
console.log(value); });
printGenerals(value); console.log(generals);
}); $.post({
url: 'j_get_select_npc_token.php',
$('#btn_pick_more').click(function(){ dataType: 'json',
var generals = $.map($('.keep_select:checked'), function(value){ data: {
return $(value).val(); refresh: true,
}); keep: generals
console.log(generals); }
$.post({ }).then(function(result) {
url:'j_get_select_npc_token.php', if (!result.result) {
dataType:'json', alert(result.reason);
data:{ location.refresh();
refresh:true, }
keep:generals console.log(result);
} printGenerals(result);
}).then(function(result){ });
if(!result.result){ });
alert(result.reason);
location.refresh(); $('#btn_load_general_list').click(function() {
} $.post({
console.log(result); url: 'j_get_general_list.php',
printGenerals(result); dataType: 'json',
}); data: {
}); with_token: true
}
$('#btn_load_general_list').click(function(){ }).then(function(result) {
$.post({ if (!result.result) {
url:'j_get_general_list.php', alert(result.reason);
dataType:'json', return false;
data:{ }
with_token:true printGeneralList(result);
} });
}).then(function(result){ });
if(!result.result){
alert(result.reason); $('#btn_print_more').click(function() {
return false; _printGeneralList();
} })
printGeneralList(result);
});
});
$('#btn_print_more').click(function(){
_printGeneralList();
})
}); });
+74 -57
View File
@@ -1,57 +1,74 @@
<?php <?php
namespace sammo; namespace sammo;
/** @var \Composer\Autoload\ClassLoader $loader */ /** @var \Composer\Autoload\ClassLoader $loader */
$loader = require __DIR__.'/../vendor/autoload.php'; $loader = require __DIR__.'/../vendor/autoload.php';
$loader->addPsr4('sammo\\', __DIR__.'/sammo', true); $loader->addPsr4('sammo\\', __DIR__.'/sammo', true);
$loader->addClassMap((function () { $loader->addClassMap((function () {
$d_settingMap = []; $d_settingMap = [];
foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) { foreach (glob(__DIR__.'/d_setting/*.orig.php') as $filepath) {
$filepath = str_replace('.orig.php', '.php', $filepath); $filepath = str_replace('.orig.php', '.php', $filepath);
$filename = basename($filepath); $filename = basename($filepath);
$classname = explode('.', $filename)[0]; $classname = explode('.', $filename)[0];
$d_settingMap['sammo\\'.$classname] = $filepath; $d_settingMap['sammo\\'.$classname] = $filepath;
}; };
return $d_settingMap; return $d_settingMap;
})()); })());
//디버그용 매크로 //디버그용 매크로
ini_set("session.cache_expire", 10080); // minutes ini_set("session.cache_expire", 10080); // minutes
// 각종 변수 // 각종 변수
define('STEP_LOG', true); define('STEP_LOG', true);
define('PROCESS_LOG', true); define('PROCESS_LOG', true);
ob_start(); ob_start();
// 에러 메세지 출력 // 에러 메세지 출력
function Error($message='', $url="") function Error($message='', $url="")
{ {
if (!$url) { if (!$url) {
$url = $_SERVER['REQUEST_URI']; $url = $_SERVER['REQUEST_URI'];
} }
$e = new \Exception(); $e = new \Exception();
logError("aux_err", $message, '', getExceptionTraceAsString($e)); logError("aux_err", $message, '', getExceptionTraceAsString($e));
$templates = new \League\Plates\Engine(__DIR__.'/templates'); $templates = new \League\Plates\Engine(__DIR__.'/templates');
ob_get_flush(); ob_get_flush();
WebUtil::setHeaderNoCache(); WebUtil::setHeaderNoCache();
die($templates->render('error', [ die($templates->render('error', [
'message' => $message 'message' => $message
])); ]));
} }
function MessageBox($str) function MessageBox($str)
{ {
echo "<script>alert('$str');</script>"; echo "<script>alert('$str');</script>";
} }
function LogText($prefix, $variable) function LogText($prefix, $variable)
{ {
$text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable)); $text = sprintf('%s : %s'."\r\n", $prefix, TVarDumper::dump($variable));
file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND); file_put_contents(ROOT.'/d_log/'.UniqueConst::$serverName.'_dbg_logs.txt', $text, FILE_APPEND);
} }
function prepareDir(string $dirPath, bool $forceCreate=true):bool{
if(file_exists($dirPath)){
if(is_dir($dirPath)){
return true;
}
if(!$forceCreate){
throw new \RuntimeException('이미 파일이 있습니다');
}
if(!unlink($dirPath)){
return false;
}
return mkdir($dirPath);
}
return mkdir($dirPath, 0777, true);
}
+12 -2
View File
@@ -43,7 +43,7 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
$iterDefender = new \ArrayIterator($defenderList); $iterDefender = new \ArrayIterator($defenderList);
$iterDefender->rewind(); $iterDefender->rewind();
$getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderNation, $db) { $getNextDefender = function(?WarUnit $prevDefender, bool $reqNext) use ($iterDefender, $rawDefenderNation, $rawDefenderCity, $db) {
if($prevDefender !== null){ if($prevDefender !== null){
$prevDefender->applyDB($db); $prevDefender->applyDB($db);
} }
@@ -57,6 +57,7 @@ function processWar(General $attackerGeneral, array $rawAttackerNation, array $r
} }
$nextDefender = $iterDefender->current(); $nextDefender = $iterDefender->current();
$nextDefender->setRawCity($rawDefenderCity);
if(extractBattleOrder($nextDefender) <= 0){ if(extractBattleOrder($nextDefender) <= 0){
return null; return null;
} }
@@ -260,6 +261,15 @@ function processWar_NG(
$attacker->addTrain(1); $attacker->addTrain(1);
$defender->addTrain(1); $defender->addTrain(1);
$attackerCrewTypeCoef = $attacker->getCrewType()->getAttackCoef($defender->getCrewType()) * $defender->getCrewType()->getDefenceCoef($attacker->getCrewType());
$defenderCrewTypeCoef = $defender->getCrewType()->getAttackCoef($attacker->getCrewType()) * $attacker->getCrewType()->getDefenceCoef($defender->getCrewType());
if($attackerCrewTypeCoef > $defenderCrewTypeCoef && $attacker instanceof WarUnitGeneral){
$attacker->getGeneral()->increaseInheritancePoint('snipe_combat', 1);
}
if($defenderCrewTypeCoef > $attackerCrewTypeCoef && $defender instanceof WarUnitGeneral){
$defender->getGeneral()->increaseInheritancePoint('snipe_combat', 1);
}
$attackerName = $attacker->getName(); $attackerName = $attacker->getName();
$attackerCrewTypeName = $attacker->getCrewTypeName(); $attackerCrewTypeName = $attacker->getCrewTypeName();
@@ -521,7 +531,7 @@ function ConquerCity(array $admin, General $general, array $city) {
$lord = new General($db->queryFirstRow( $lord = new General($db->queryFirstRow(
'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1', 'SELECT %l FROM general WHERE nation = %i AND officer_level = %i LIMIT 1',
Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'dedication', 'dedlevel', 'aux'], 1)[0]), Util::formatListOfBackticks(General::mergeQueryColumn(['npc', 'gold', 'rice', 'experience', 'explevel', 'belong', 'dedication', 'dedlevel', 'aux'], 1)[0]),
$defenderNationID, $defenderNationID,
12 12
), null, $city, $loseNation, $year, $month, false); ), null, $city, $loseNation, $year, $month, false);
+72
View File
@@ -0,0 +1,72 @@
<?php
namespace sammo;
use sammo\AbsGeneralPool;
use sammo\GameConst;
use sammo\Json;
use sammo\Util;
abstract class AbsFromUserPool extends AbsGeneralPool{
public function occupyGeneralName(): bool
{
$generalID = $this->getGeneralBuilder()->getGeneralID();
if($generalID === null){
throw new \RuntimeException('build되지 않음');
}
$db= $this->db;
$db->update('select_pool', [
'general_id'=>$generalID,
'owner'=>null,
'reserved_until'=>null,
], 'unique_name = %s AND owner IS NOT NULL', $this->uniqueName);
return $db->affectedRows()!=0;
}
static public function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array{
$oNow = new \DateTimeImmutable();
$now = $oNow->format('Y-m-d H:i:s');
$db->update('select_pool', [
'reserved_until'=>null,
'owner'=>null,
],'reserved_until < %s AND general_id IS NULL', $now);
$pool = [];
foreach($db->query('SELECT id, unique_name, info FROM select_pool WHERE reserved_until IS NULL AND general_id IS NULL', $pickCnt) as $cand){
$cand['info'] = Json::decode($cand['info']);
$dexTotal = array_sum($cand['info']['dex']);
$pool[] = [$cand, $dexTotal];
}
if(count($pool) < $pickCnt){
throw new \RuntimeException('pool 부족');
}
$gameStor = KVStorage::getStorage($db, 'game_env');
$result = [];
$validUntil = TimeUtil::nowAddMinutes(2 * $gameStor->turnterm);
while(count($result) < $pickCnt){
$cand = Util::choiceRandomUsingWeightPair($pool);
$poolID = $cand['id'];
if(key_exists($poolID, $result)){
continue;
}
$candInfo = $cand['info'];
$candInfo['uniqueName'] = $cand['unique_name'];
//하나씩 한다.
$db->update('select_pool', [
'owner'=>$owner,
'reserved_until'=>$validUntil,
], 'id = %i AND reserved_until IS NULL AND owner IS NULL and general_id IS NULL', $poolID);
if($db->affectedRows()==0){
continue;
}
$result[$poolID] = new static($db, $candInfo, $validUntil);
}
return array_values($result);
}
}
+111
View File
@@ -0,0 +1,111 @@
<?php
namespace sammo;
use MeekroDB;
use sammo\GameConst;
use sammo\Scenario\GeneralBuilder;
use sammo\Util;
abstract class AbsGeneralPool{
protected $builder;
protected $info;
protected $db=null;
protected $uniqueName;
protected $generalName;
protected $validUntil;
/*
* info = [
* uniqueName
* generalName
* imgsvr
* picture
*
* leadership
* strength
* intel
*
* experience
* dedication
*
* dex[5]
*
* specialDomestic
* specialWar
*/
public function __construct(\MeekroDB $db, array $info, string $validUntil)
{
$this->db = $db;
$this->info = $info;
$this->uniqueName = $info['uniqueName'];
$this->generalName = $info['generalName'];
$this->builder = new GeneralBuilder(
$info['generalName'],
$info['imgsvr'],
$info['picture'],
0
);
$this->validUntil = $validUntil;
$builder = $this->builder;
if(key_exists('leadership', $info)){
$builder->setStat($info['leadership'], $info['strength'], $info['intel']);
}
if(key_exists('experience', $info)){
$builder->setExpDed($info['experience'], $info['dedication']);
}
if(key_exists('dex', $info)){
$builder->setDex($info['dex'][0], $info['dex'][1], $info['dex'][2], $info['dex'][3], $info['dex'][4]);
}
if(key_exists('specialDomestic', $info) || key_exists('specialWar', $info)){
$builder->setSpecial($info['specialDomestic']??GameConst::$defaultSpecialDomestic, $info['specialWar']??GameConst::$defaultSpecialWar);
}
}
public function getUniqueName():string{
return $this->uniqueName;
}
public function getInfo():array{
return $this->info;
}
static protected function checkDuplicatedCnt(\MeekroDB $db, string $name):int{
$duplicateCnt = 0;
foreach(GeneralBuilder::$prefixList as $npcPrefix){
$testName = "{$npcPrefix}{$name}";
$duplicateCnt += $db->queryFirstField('SELECT count(no) FROM general WHERE name LIKE %s', $testName.'%');
}
return $duplicateCnt;
}
public function getGeneralBuilder():GeneralBuilder{
if(!$this->generalName){
throw new \RuntimeException('generalName not picked');
}
return $this->builder;
}
public function getValidUntil():string{
return $this->validUntil;
}
/**
* @param \MeekroDB $db
* @param int $owner
* @param int $pickCnt
* @param null|string $prefix
* @return AbsGeneralPool[]
*/
static abstract public function pickGeneralFromPool(\MeekroDB $db, int $owner, int $pickCnt, ?string $prefix=null):array;
abstract public function occupyGeneralName():bool;
abstract public static function getPoolName():string;
abstract public static function initPool(\MeekroDB $db);
}
+31 -21
View File
@@ -1,22 +1,32 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_삼략 extends \sammo\BaseItem{ class che_계략_삼략 extends \sammo\BaseItem{
protected $id = 22; protected $id = 22;
protected $rawName = '삼략'; protected $rawName = '삼략';
protected $name = '삼략(계략)'; protected $name = '삼략(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.2; if($varType == 'success') return $value + 0.2;
} }
return $value; return $value;
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.1;
}
if($statName === 'warMagicSuccessProb'){
return $value + 0.1;
}
return $value;
}
} }
+31 -21
View File
@@ -1,22 +1,32 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_육도 extends \sammo\BaseItem{ class che_계략_육도 extends \sammo\BaseItem{
protected $id = 21; protected $id = 21;
protected $rawName = '육도'; protected $rawName = '육도';
protected $name = '육도(계략)'; protected $name = '육도(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p<br>[전투] 계략 시도 확률 +10%p, 계략 성공 확률 +10%p';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.2; if($varType == 'success') return $value + 0.2;
} }
return $value; return $value;
} }
public function onCalcStat(General $general, string $statName, $value, $aux=null){
if($statName === 'warMagicTrialProb'){
return $value + 0.1;
}
if($statName === 'warMagicSuccessProb'){
return $value + 0.1;
}
return $value;
}
} }
+30 -30
View File
@@ -1,31 +1,31 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_이추 extends \sammo\BaseItem{ class che_계략_이추 extends \sammo\BaseItem{
protected $id = 5; protected $id = 5;
protected $rawName = '이추'; protected $rawName = '이추';
protected $name = '이추(계략)'; protected $name = '이추(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +10%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p';
protected $cost = 1000; protected $cost = 1000;
protected $consumable = true; protected $consumable = true;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 1000; protected $reqSecu = 1000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.1; if($varType == 'success') return $value + 0.2;
} }
return $value; return $value;
} }
function isConsumableNow(string $actionType, string $command):bool{ function isConsumableNow(string $actionType, string $command):bool{
if($actionType == 'GeneralCommand' && $command == '계략'){ if($actionType == 'GeneralCommand' && $command == '계략'){
return true; return true;
} }
return false; return false;
} }
} }
+30 -30
View File
@@ -1,31 +1,31 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
class che_계략_향낭 extends \sammo\BaseItem{ class che_계략_향낭 extends \sammo\BaseItem{
protected $id = 5; protected $id = 5;
protected $rawName = '항냥'; protected $rawName = '항냥';
protected $name = '항냥(계략)'; protected $name = '항냥(계략)';
protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +20%p'; protected $info = '[계략] 화계·탈취·파괴·선동 : 성공률 +50%p';
protected $cost = 3000; protected $cost = 3000;
protected $consumable = true; protected $consumable = true;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 2000; protected $reqSecu = 2000;
public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{ public function onCalcDomestic(string $turnType, string $varType, float $value, $aux=null):float{
if($turnType == '계략'){ if($turnType == '계략'){
if($varType == 'success') return $value + 0.2; if($varType == 'success') return $value + 0.5;
} }
return $value; return $value;
} }
function isConsumableNow(string $actionType, string $command):bool{ function isConsumableNow(string $actionType, string $command):bool{
if($actionType == 'GeneralCommand' && $command == '계략'){ if($actionType == 'GeneralCommand' && $command == '계략'){
return true; return true;
} }
return false; return false;
} }
} }
@@ -6,4 +6,18 @@ use \sammo\General;
class che_명마_07_기주마 extends \sammo\BaseStatItem{ class che_명마_07_기주마 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 공격 시 페이즈 +1";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'initWarPhase'){
return $value + 1;
}
return $value;
}
} }
@@ -1,9 +1,26 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_퇴각부상무효;
use sammo\WarUnitTriggerCaller;
class che_명마_07_백마 extends \sammo\BaseStatItem{ class che_명마_07_백마 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 전투 종료로 인한 부상 없음";
}
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_퇴각부상무효($unit, BaseWarUnitTrigger::TYPE_ITEM),
);
}
} }
@@ -1,9 +1,27 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_퇴각부상무효;
use sammo\WarUnitTriggerCaller;
class che_명마_12_사륜거 extends \sammo\BaseStatItem{ class che_명마_12_사륜거 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 전투 종료로 인한 부상 없음";
}
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_퇴각부상무효($unit, BaseWarUnitTrigger::TYPE_ITEM),
);
}
} }
@@ -2,9 +2,26 @@
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_02_단궁 extends \sammo\BaseStatItem{ class che_무기_02_단궁 extends \sammo\BaseStatItem{
protected $cost = 3000; protected $cost = 3000;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 2000; protected $reqSecu = 2000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 1% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 102, 0.01, 10, 30),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
} }
@@ -2,8 +2,25 @@
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_07_맥궁 extends \sammo\BaseStatItem{ class che_무기_07_맥궁 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 20% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 107, 0.2, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
} }
@@ -2,8 +2,25 @@
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_09_동호비궁 extends \sammo\BaseStatItem{ class che_무기_09_동호비궁 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 20% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 109, 0.15, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
} }
@@ -2,8 +2,25 @@
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_11_이광궁 extends \sammo\BaseStatItem{ class che_무기_11_이광궁 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 10% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 111, 0.10, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
} }
@@ -2,8 +2,25 @@
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_저격발동;
use sammo\WarUnitTrigger\che_저격시도;
use sammo\WarUnitTriggerCaller;
class che_무기_13_양유기궁 extends \sammo\BaseStatItem{ class che_무기_13_양유기궁 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 새로운 상대와 전투 시 10% 확률로 저격 발동, 성공 시 사기+10";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM + che_저격시도::TYPE_DEDUP_TYPE_BASE * 113, 0.05, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
} }
@@ -0,0 +1,29 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_반계시도;
use \sammo\WarUnitTrigger\che_반계발동;
class che_반계_백우선 extends \sammo\BaseItem{
protected $id = 45;
protected $rawName = '백우선';
protected $name = '백우선(반계)';
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301, false, '계략약화'),
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301),
new che_반계발동($unit)
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTrigger\WarActivateSkills;
use \sammo\WarUnitTrigger\che_반계시도;
use \sammo\WarUnitTrigger\che_반계발동;
class che_반계_파초선 extends \sammo\BaseItem{
protected $id = 45;
protected $rawName = '파초선';
protected $name = '파초선(반계)';
protected $info = '[전투] 상대의 계략 성공 확률 -10%p, 상대의 계략을 40% 확률로 되돌림';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302, false, '계략약화'),
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM +BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302),
new che_반계발동($unit)
);
}
}
@@ -0,0 +1,34 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use sammo\BaseWarUnitTrigger;
use sammo\WarUnitTrigger\che_부상무효;
use sammo\WarUnitTrigger\WarActivateSkills;
class che_부적_태현청생부 extends \sammo\BaseItem{
protected $id = 9;
protected $rawName = '태현청생부';
protected $name = '태현청생부(부적)';
protected $info = '[전투] 저격 불가, 부상 없음';
protected $cost = 200;
protected $consumable = false;
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_부상무효($unit, BaseWarUnitTrigger::TYPE_NONE),
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
);
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_NONE, false, '저격불가')
);
}
}
@@ -7,4 +7,18 @@ class che_서적_01_효경전 extends \sammo\BaseStatItem{
protected $cost = 1000; protected $cost = 1000;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 1000; protected $reqSecu = 1000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +1%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicTrialProb'){
return $value + 0.01;
}
return $value;
}
} }
@@ -7,4 +7,18 @@ class che_서적_02_회남자 extends \sammo\BaseStatItem{
protected $cost = 3000; protected $cost = 3000;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 2000; protected $reqSecu = 2000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +1%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicTrialProb'){
return $value + 0.01;
}
return $value;
}
} }
@@ -7,4 +7,18 @@ class che_서적_03_변도론 extends \sammo\BaseStatItem{
protected $cost = 6000; protected $cost = 6000;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 3000; protected $reqSecu = 3000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +2%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicTrialProb'){
return $value + 0.02;
}
return $value;
}
} }
@@ -7,4 +7,18 @@ class che_서적_04_건상역주 extends \sammo\BaseStatItem{
protected $cost = 10000; protected $cost = 10000;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 4000; protected $reqSecu = 4000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +2%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicTrialProb'){
return $value + 0.02;
}
return $value;
}
} }
@@ -7,4 +7,18 @@ class che_서적_05_여씨춘추 extends \sammo\BaseStatItem{
protected $cost = 15000; protected $cost = 15000;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 5000; protected $reqSecu = 5000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +3%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicTrialProb'){
return $value + 0.03;
}
return $value;
}
} }
@@ -7,4 +7,18 @@ class che_서적_06_사민월령 extends \sammo\BaseStatItem{
protected $cost = 21000; protected $cost = 21000;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 6000; protected $reqSecu = 6000;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +3%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicTrialProb'){
return $value + 0.03;
}
return $value;
}
} }
@@ -1,9 +1,26 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\WarActivateSkills;
use sammo\WarUnitTriggerCaller;
class che_서적_07_논어 extends \sammo\BaseStatItem{ class che_서적_07_논어 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략 성공 확률 -10%p";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*207, false, '계략약화')
);
}
} }
@@ -1,9 +1,28 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_반계발동;
use sammo\WarUnitTrigger\che_반계시도;
use sammo\WarUnitTriggerCaller;
class che_서적_07_사마법 extends \sammo\BaseStatItem{ class che_서적_07_사마법 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략을 20% 확률로 되돌림";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*207, 0.2),
new che_반계발동($unit)
);
}
} }
@@ -6,4 +6,18 @@ use \sammo\General;
class che_서적_07_위료자 extends \sammo\BaseStatItem{ class che_서적_07_위료자 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 시도 확률 +20%p";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicTrialProb'){
return $value + 0.2;
}
return $value;
}
} }
@@ -6,4 +6,18 @@ use \sammo\General;
class che_서적_08_전론 extends \sammo\BaseStatItem{ class che_서적_08_전론 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 계략 성공 시 대미지 +20%";
}
public function onCalcStat(General $general, string $statName, $value, $aux=null){
$value = parent::onCalcStat($general, $statName, $value, $aux);
if($statName === 'warMagicSuccessDamage'){
return $value * 1.2;
}
return $value;
}
} }
@@ -1,9 +1,26 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\WarActivateSkills;
use sammo\WarUnitTriggerCaller;
class che_서적_11_춘추전 extends \sammo\BaseStatItem{ class che_서적_11_춘추전 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략 성공 확률 -10%p";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new WarActivateSkills($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*211, false, '계략약화')
);
}
} }
@@ -1,9 +1,28 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use sammo\WarUnit;
use sammo\WarUnitTrigger\che_반계발동;
use sammo\WarUnitTrigger\che_반계시도;
use sammo\WarUnitTriggerCaller;
class che_서적_12_산해경 extends \sammo\BaseStatItem{ class che_서적_12_산해경 extends \sammo\BaseStatItem{
protected $cost = 200; protected $cost = 200;
protected $buyable = false; protected $buyable = false;
public function __construct()
{
parent::__construct();
$this->info .= "<br>[전투] 상대의 계략을 20% 확률로 되돌림";
}
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_반계시도($unit, BaseWarUnitTrigger::TYPE_ITEM, 0.2),
new che_반계발동($unit)
);
}
} }
@@ -0,0 +1,35 @@
<?php
namespace sammo\ActionItem;
use \sammo\iAction;
use \sammo\General;
use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller;
use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도;
class che_의술_상한잡병론 extends \sammo\BaseItem{
protected $id = 24;
protected $rawName = '상한잡병론';
protected $name = '상한잡병론(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200;
protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general)
);
}
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{
return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*301),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
);
}
}
+34 -34
View File
@@ -1,35 +1,35 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\GeneralTrigger; use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller; use \sammo\GeneralTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동; use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도; use sammo\WarUnitTrigger\che_전투치료시도;
use sammo\BaseWarUnitTrigger; use sammo\BaseWarUnitTrigger;
use sammo\WarUnitTriggerCaller; use sammo\WarUnitTriggerCaller;
class che_의술_청낭서 extends \sammo\BaseItem{ class che_의술_청낭서 extends \sammo\BaseItem{
protected $id = 23; protected $id = 23;
protected $rawName = '청낭서'; protected $rawName = '청낭서';
protected $name = '청낭서(의술)'; protected $name = '청낭서(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general) new GeneralTrigger\che_도시치료($general)
); );
} }
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{ {
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM), new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*302),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM) new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
); );
} }
} }
@@ -1,35 +1,35 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\GeneralTrigger; use \sammo\GeneralTrigger;
use \sammo\GeneralTriggerCaller; use \sammo\GeneralTriggerCaller;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use sammo\WarUnitTrigger\che_전투치료발동; use sammo\WarUnitTrigger\che_전투치료발동;
use sammo\WarUnitTrigger\che_전투치료시도; use sammo\WarUnitTrigger\che_전투치료시도;
class che_의술_태평청령 extends \sammo\BaseItem{ class che_의술_태평청령 extends \sammo\BaseItem{
protected $id = 24; protected $id = 24;
protected $rawName = '태평청령'; protected $rawName = '태평청령';
protected $name = '태평청령(의술)'; protected $name = '태평청령(의술)';
protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 20% 확률로 치료 발동(아군 피해 1/3 감소)'; protected $info = '[군사] 매 턴마다 자신(100%)과 소속 도시 장수(적 포함 50%) 부상 회복<br>[전투] 페이즈마다 40% 확률로 치료 발동(아군 피해 1/3 감소, 부상 회복)';
protected $cost = 200; protected $cost = 200;
protected $consumable = false; protected $consumable = false;
public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{ public function getPreTurnExecuteTriggerList(General $general):?GeneralTriggerCaller{
return new GeneralTriggerCaller( return new GeneralTriggerCaller(
new GeneralTrigger\che_도시치료($general) new GeneralTrigger\che_도시치료($general)
); );
} }
public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller public function getBattlePhaseSkillTriggerList(\sammo\WarUnit $unit): ?WarUnitTriggerCaller
{ {
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM), new che_전투치료시도($unit, BaseWarUnitTrigger::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*303),
new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM) new che_전투치료발동($unit, BaseWarUnitTrigger::TYPE_ITEM)
); );
} }
} }
@@ -0,0 +1,28 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동;
class che_저격_매화수전 extends \sammo\BaseItem{
protected $id = 70;
protected $rawName = '매화수전';
protected $name = '매화수전(저격)';
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*304, 0.5, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
@@ -0,0 +1,28 @@
<?php
namespace sammo\ActionItem;
use sammo\BaseWarUnitTrigger;
use \sammo\iAction;
use \sammo\General;
use \sammo\SpecialityHelper;
use \sammo\WarUnit;
use sammo\WarUnitTriggerCaller;
use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동;
class che_저격_비도 extends \sammo\BaseItem{
protected $id = 70;
protected $rawName = '비도';
protected $name = '비도(저격)';
protected $info = '[전투] 새로운 상대와 전투 시 50% 확률로 저격 발동, 성공 시 사기+10';
protected $cost = 200;
protected $consumable = false;
public function getBattlePhaseSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller(
new che_저격시도($unit, che_저격시도::TYPE_ITEM+BaseWarUnitTrigger::TYPE_DEDUP_TYPE_BASE*305, 0.5, 20, 40),
new che_저격발동($unit, che_저격발동::TYPE_ITEM)
);
}
}
+34 -27
View File
@@ -1,28 +1,35 @@
<?php <?php
namespace sammo\ActionItem; namespace sammo\ActionItem;
use \sammo\iAction; use \sammo\iAction;
use \sammo\General; use \sammo\General;
use \sammo\WarUnitTriggerCaller; use \sammo\WarUnitTriggerCaller;
use \sammo\WarUnit; use \sammo\WarUnit;
use \sammo\WarUnitTrigger\che_저격시도; use \sammo\WarUnitTrigger\che_저격시도;
use \sammo\WarUnitTrigger\che_저격발동; use \sammo\WarUnitTrigger\che_저격발동;
use \sammo\BaseWarUnitTrigger; use \sammo\BaseWarUnitTrigger;
class che_저격_수극 extends \sammo\BaseItem{ class che_저격_수극 extends \sammo\BaseItem{
protected $id = 2; protected $id = 2;
protected $rawName = '수극'; protected $rawName = '수극';
protected $name = '수극(저격)'; protected $name = '수극(저격)';
protected $info = '[전투] 전투 개시 전 20% 확률로 저격 시도. 1회용'; protected $info = '[전투] 전투 개시 전 50% 확률로 저격 시도. 1회용';
protected $cost = 1000; protected $cost = 1000;
protected $consumable = true; protected $consumable = true;
protected $buyable = true; protected $buyable = true;
protected $reqSecu = 1000; protected $reqSecu = 1000;
public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{ public function getBattleInitSkillTriggerList(WarUnit $unit):?WarUnitTriggerCaller{
return new WarUnitTriggerCaller( return new WarUnitTriggerCaller(
new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.2, 20, 40), new che_저격시도($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM, 0.5, 20, 40),
new che_저격발동($unit) new che_저격발동($unit, BaseWarUnitTrigger::TYPE_CONSUMABLE_ITEM)
); );
} }
function isConsumableNow(string $actionType, string $command):bool{
if($actionType == 'GeneralTrigger' && $command == 'che_아이템치료'){
return true;
}
return false;
}
} }

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