From d926e4b8bc2564646acc6607482bcc547db8bb5c Mon Sep 17 00:00:00 2001 From: hide_d Date: Sun, 12 Sep 2021 04:59:34 +0900 Subject: [PATCH] =?UTF-8?q?api:=20=EA=B7=9C=EA=B2=A9=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hwe/api.php | 90 +++++++ hwe/api_join.php | 393 ------------------------------ hwe/func_converter.php | 49 +++- hwe/sammo/API/General/Join.php | 426 +++++++++++++++++++++++++++++++++ hwe/sammo/BaseAPI.php | 26 ++ src/sammo/Json.php | 1 + src/sammo/TimeUtil.php | 73 +++--- 7 files changed, 620 insertions(+), 438 deletions(-) create mode 100644 hwe/api.php delete mode 100644 hwe/api_join.php create mode 100644 hwe/sammo/API/General/Join.php create mode 100644 hwe/sammo/BaseAPI.php diff --git a/hwe/api.php b/hwe/api.php new file mode 100644 index 00000000..af91d505 --- /dev/null +++ b/hwe/api.php @@ -0,0 +1,90 @@ +getMessage()); +} + +if (!key_exists('path', $input)) { + Json::dieWithReason('path가 지정되지 않았습니다.'); +} + +if (key_exists('args', $input) && !is_array($input['args'])) { + Json::dieWithReason('args가 array가 아닙니다.' . gettype($input['args'])); +} + +try { + $obj = buildAPIExecutorClass($input['path'], $input['args'] ?? []); + $api = + $validateResult = $obj->validateArgs(); + if ($validateResult !== null) { + Json::dieWithReason($validateResult); + } + + $sessionMode = $obj->getRequiredSessionMode(); + if ($sessionMode === BaseAPI::NO_SESSION) { + $session = null; + } else { + if ($sessionMode & BaseAPI::REQ_GAME_LOGIN) { + $session = Session::requireGameLogin(); + } else if ($sessionMode & BaseAPI::REQ_LOGIN) { + $session = Session::requireLogin(); + } else { + Json::dieWithReason("올바르지 않은 SessionMode: {$sessionMode}"); + } + + if ($sessionMode & BaseAPI::REQ_READ_ONLY) { + $session->setReadOnly(); + } + } + + $modifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) + ? new \DateTimeImmutable($_SERVER['HTTP_IF_MODIFIED_SINCE'], new \DateTimeZone("UTC")) + : null; + $reqEtags = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : null; + + $result = $obj->launch($session, $modifiedSince, $reqEtags); + if (is_string($result)) { + Json::dieWithReason($result); + } + + $cacheResult = $obj->tryCache(); + if ($cacheResult !== null) { + /** @var \DateTimeInterface $lastModified */ + [$lastModified, $etag] = $cacheResult; + + if ($lastModified !== null) { + header("Last-Modified: " . gmdate("D, d M Y H:i:s", TimeUtil::DateTimeToSeconds($lastModified, true)) . " GMT"); + } + if ($etag !== null) { + header("Etag: $etag"); + } + + if ($modifiedSince !== null && $lastModified !== null && TimeUtil::DateIntervalToSeconds($modifiedSince->diff($lastModified)) == 0) { + header("HTTP/1.1 304 Not Modified"); + die(); + } + if ($reqEtags !== null && $reqEtags === $etag) { + header("HTTP/1.1 304 Not Modified"); + die(); + } + } + + if ($result === null) { + Json::die([ + 'result' => true, + 'reason' => 'success' + ], $cacheResult === null ? Json::NO_CACHE : 0); + } + Json::die($result, $cacheResult === null ? Json::NO_CACHE : 0); +} catch (\Exception $e) { + Json::dieWithReason($e->getMessage()); +} catch (mixed $e) { + Json::dieWithReason($e); +} diff --git a/hwe/api_join.php b/hwe/api_join.php deleted file mode 100644 index f90f63bb..00000000 --- a/hwe/api_join.php +++ /dev/null @@ -1,393 +0,0 @@ -rule('required', [ - 'name', - 'leadership', - 'strength', - 'intel', - 'pic', - 'character', - ]) - ->rule('integer', [ - 'leadership', - 'strength', - 'intel', - 'inheritTurntime', - ]) - ->rule('boolean', [ - 'pic' - ]) - ->rule('stringWidthBetween', 'name', 1, 18) - ->rule('min', [ - 'leadership', - 'strength', - 'intel' - ], GameConst::$defaultStatMin) - ->rule('max', [ - 'leadership', - 'strength', - 'intel' - ], GameConst::$defaultStatMax) - ->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random'])) - ->rule('in', 'inheritSpecial', GameConst::$availableSpecialWar) - ->rule('min', 'inheritTurntime', 0) - ->rule('in', 'inheritCity', array_keys(CityConst::all())) - ->rule('integerArray', 'inheritBonusStat'); - -if (!$v->validate()) { - Json::dieWithReason($v->errorStr()); -} - -$session = Session::requireLogin()->setReadOnly(); -$userID = Session::getUserID(); -//NOTE: 이 페이지에서는 세션에 데이터를 등록하지 않음. 로그인은 이후에. - -$name = $input['name']; -$name = htmlspecialchars($name); -$name = StringUtil::removeSpecialCharacter($name); -$name = WebUtil::htmlPurify($name); -$name = StringUtil::textStrip($name); -$pic = $input['pic']; -$character = $input['character']; - -$leadership = $input['leadership']; -$strength = $input['strength']; -$intel = $input['intel']; - -$inheritSpecial = $input['inheritSpecial']??null; -$inheritTurntime =$input['inheritTurntime']??null; -$inheritCity = $input['inheritCity']??null; -$inheritBonusStat = $input['inheritBonusStat']??null; - -$rootDB = RootDB::db(); -//회원 테이블에서 정보확인 -$member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID); - -if (!$member) { - Json::dieWithReason("잘못된 접근입니다!!!"); -} - -$db = DB::db(); -$gameStor = KVStorage::getStorage($db, 'game_env'); -$gameStor->cacheValues(['year', 'month', 'maxgeneral', 'scenario', 'show_img_level', 'turnterm', 'turntime', 'genius', 'npcmode']); -########## 동일 정보 존재여부 확인. ########## - -$gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2'); -$oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID); -$oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name); - -if ($oldGeneral) { - Json::dieWithReason("이미 등록하셨습니다!"); -} -if ($oldName) { - Json::dieWithReason("이미 있는 장수입니다. 다른 이름으로 등록해 주세요!"); -} -if ($gameStor->maxgeneral <= $gencount) { - Json::dieWithReason("더이상 등록할 수 없습니다!"); -} -if ($name == '') { - Json::dieWithReason("이름이 짧습니다. 다시 가입해주세요!"); -} -if (mb_strwidth($name) > 18) { - Json::dieWithReason("이름이 유효하지 않습니다. 다시 가입해주세요!"); -} -if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) { - Json::dieWithReason("능력치가 " . GameConst::$defaultStatTotal . "을 넘어섰습니다. 다시 가입해주세요!"); -} - -if ($inheritBonusStat) { - if (count($inheritBonusStat) != 3) { - Json::dieWithReason("보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!"); - } - $sum = array_sum($inheritBonusStat); - if ($sum < 3 || $sum > 5) { - Json::dieWithReason("보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!"); - } - foreach ($inheritBonusStat as $stat) { - if ($stat < 0) { - Json::dieWithReason("보너스 능력치가 음수입니다. 다시 가입해주세요!"); - } - } -} - -$admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']); - -$inheritTotalPoint = resetInheritanceUser($userID); -$inheritRequiredPoint = 0; - -if ($inheritCity !== null) { - $inheritRequiredPoint += GameConst::$inheritBornCityPoint; -} -if ($inheritBonusStat !== null) { - $inheritRequiredPoint += GameConst::$inheritBornMaxBonusStat; -} -if ($inheritSpecial !== null) { - $inheritRequiredPoint += GameConst::$inheritBornSpecialPoint; -} -if ($inheritTurntime !== null) { - $inheritRequiredPoint += GameConst::$inheritBornTurntimePoint; -} - -if ($inheritTotalPoint < $inheritRequiredPoint) { - Json::dieWithReason("유산 포인트가 부족합니다. 다시 가입해주세요!"); -} - -if ($inheritSpecial !== null && $gameStor->genius == 0) { - Json::dieWithReason("이미 천재가 모두 나타났습니다. 다시 가입해주세요!"); -} - -if ($inheritCity !== null && !key_exists($inheritCity, CityConst::all())) { - Json::dieWithReason("도시가 잘못 지정되었습니다. 다시 가입해주세요!"); -} - -if ($inheritSpecial) { - $genius = true; -} else { - // 현재 1% - $genius = Util::randBool(0.01); -} - -if ($genius && $gameStor->genius > 0) { - $gameStor->genius = $gameStor->genius - 1; -} else { - $genius = false; -} - -if ($inheritCity !== null) { - $city = $inheritCity; -} else { - // 공백지에서만 태어나게 - $city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1"); - if (!$city) { - $city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1"); - } -} - -if ($inheritBonusStat) { - [$pleadership, $pstrength, $pintel] = $inheritBonusStat; -} else { - $pleadership = 0; - $pstrength = 0; - $pintel = 0; - foreach (Util::range(Util::randRangeInt(3, 5)) as $statIdx) { - switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) { - case 0: - $pleadership++; - break; - case 1: - $pstrength++; - break; - case 2: - $pintel++; - break; - } - } -} - -$leadership = $leadership + $pleadership; -$strength = $strength + $pstrength; -$intel = $intel + $pintel; - -$relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0); - -$age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1)); -// 아직 남았고 천재등록상태이면 특기 부여 -if ($genius) { - $specage2 = $age; - if ($inheritSpecial) { - $special2 = $inheritSpecial; - } else { - $special2 = SpecialityHelper::pickSpecialWar([ - 'leadership' => $leadership, - 'strength' => $strength, - 'intel' => $intel, - 'dex1' => 0, - 'dex2' => 0, - 'dex3' => 0, - 'dex4' => 0, - 'dex5' => 0 - ]); - } -} else { - $specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 6 - $relYear / 2), 3) + $age; - $special2 = GameConst::$defaultSpecialWar; -} -//내특 -$specage = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 12 - $relYear / 2), 3) + $age; -$special = GameConst::$defaultSpecialDomestic; - -if ($admin['scenario'] >= 1000) { - $specage2 = $age + 3; - $specage = $age + 3; -} - -if ($relYear < 3) { - $experience = 0; -} else { - $expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4'); - $targetGenOrder = Util::round($expGenCount * 0.2); - $experience = $db->queryFirstField( - 'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1', - $targetGenOrder - 1 - ); - $experience *= 0.8; -} - -if ($inheritTurntime === null) { - $inheritTurntime = $inheritTurntime % ($gameStor->turnterm * 60); - $inheritTurntime += Util::randRangeInt(0, 999999) / 1000000; - $turntime = cutTurn($admin['turntime'], $admin['turnterm']); - $turntime = TimeUtil::nowAddSeconds($inheritTurntime, true); -} else { - $turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime'])); -} - - -$now = TimeUtil::now(true); -if ($now >= $turntime) { - $turntime = addTurn($turntime, $admin['turnterm']); -} - -//특회 전콘 -if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "" && $pic) { - $face = $member['picture']; - $imgsvr = $member['imgsvr']; -} else { - $face = "default.jpg"; - $imgsvr = 0; -} - -//성격 랜덤시 -if (!in_array($character, GameConst::$availablePersonality)) { - $character = Util::choiceRandom(GameConst::$availablePersonality); -} -//상성 랜덤 -$affinity = rand() % 150 + 1; - -########## 회원정보 테이블에 입력값을 등록한다. ########## -$db->insert('general', [ - 'owner' => $userID, - 'name' => $name, - 'owner_name' => $member['name'], - 'picture' => $face, - 'imgsvr' => $imgsvr, - 'nation' => 0, - 'city' => $city, - 'troop' => 0, - 'affinity' => $affinity, - 'leadership' => $leadership, - 'strength' => $strength, - 'intel' => $intel, - 'experience' => $experience, - 'dedication' => 0, - 'gold' => GameConst::$defaultGold, - 'rice' => GameConst::$defaultRice, - 'crew' => 0, - 'train' => 0, - 'atmos' => 0, - 'officer_level' => 0, - 'turntime' => $turntime, - 'killturn' => 6, - 'lastconnect' => $now, - 'lastrefresh' => $now, - 'crewtype' => GameUnitConst::DEFAULT_CREWTYPE, - 'makelimit' => 0, - 'age' => $age, - 'startage' => $age, - 'personal' => $character, - 'specage' => $specage, - 'special' => $special, - 'specage2' => $specage2, - 'special2' => $special2 -]); -$generalID = $db->insertId(); -$turnRows = []; -foreach (Util::range(GameConst::$maxTurn) as $turnIdx) { - $turnRows[] = [ - 'general_id' => $generalID, - 'turn_idx' => $turnIdx, - 'action' => '휴식', - 'arg' => null, - 'brief' => '휴식' - ]; -} -$db->insert('general_turn', $turnRows); - -$rank_data = []; -foreach (array_keys(General::RANK_COLUMN) as $rankColumn) { - $rank_data[] = [ - 'general_id' => $generalID, - 'nation_id' => 0, - 'type' => $rankColumn, - 'value' => 0 - ]; -} -$db->insert('rank_data', $rank_data); -$db->insert('betting', [ - 'general_id' => $generalID, -]); -$cityname = CityConst::byID($city)->name; - -$me = [ - 'no' => $generalID -]; - -$log = []; -$mylog = []; - -$logger = new ActionLogger($generalID, 0, $gameStor->year, $gameStor->month); - -$josaRa = JosaUtil::pick($name, '라'); -$speicalText = getGeneralSpecialWarName($special2); -if ($genius) { - - $logger->pushGlobalActionLog("{$cityname}에서 {$name}{$josaRa}는 기재가 천하에 이름을 알립니다."); - $logger->pushGlobalActionLog("{$speicalText} 특기를 가진 천재의 등장으로 온 천하가 떠들썩합니다."); - $logger->pushGlobalHistoryLog("【천재】{$cityname}에 천재가 등장했습니다."); -} else { - $logger->pushGlobalActionLog("{$cityname}에서 {$name}{$josaRa}는 호걸이 천하에 이름을 알립니다."); -} - -$logger->pushGeneralHistoryLog("{$name}, {$cityname}에서 큰 뜻을 품다."); -$logger->pushGeneralActionLog("삼국지 모의전투 PHP의 세계에 오신 것을 환영합니다 ^o^", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("처음 하시는 경우에는 도움말을 참고하시고,", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("문의사항이 있으시면 게시판에 글을 남겨주시면 되겠네요~", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("부디 즐거운 삼모전 되시길 바랍니다 ^^", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("통솔 $pleadership 무력 $pstrength 지력 $pintel 의 보너스를 받으셨습니다.", ActionLogger::PLAIN); -$logger->pushGeneralActionLog("연령은 $age세로 시작합니다.", ActionLogger::PLAIN); - -if ($genius) { - $logger->pushGeneralActionLog("축하합니다! 천재로 태어나 처음부터 {$speicalText} 특기를 가지게 됩니다!", ActionLogger::PLAIN); - $logger->pushGeneralHistoryLog("{$speicalText} 특기를 가진 천재로 탄생."); -} - -$logger->flush(); - -pushAdminLog(["가입 : {$userID} // {$name} // {$generalID}" . getenv("REMOTE_ADDR")]); - -$rootDB->insert('member_log', [ - 'member_no' => $userID, - 'date' => TimeUtil::now(), - 'action_type' => 'make_general', - 'action' => Json::encode([ - 'server' => DB::prefix(), - 'type' => 'general', - 'generalID' => $generalID, - 'generalName' => $name - ]) -]); - -Json::die([ - 'result'=>true, - 'reason'=>'success' -]); \ No newline at end of file diff --git a/hwe/func_converter.php b/hwe/func_converter.php index 7c696083..9508b13a 100644 --- a/hwe/func_converter.php +++ b/hwe/func_converter.php @@ -1,4 +1,4 @@ -args); + $v + ->rule('required', [ + 'name', + 'leadership', + 'strength', + 'intel', + 'pic', + 'character', + ]) + ->rule('integer', [ + 'leadership', + 'strength', + 'intel', + 'inheritTurntime', + ]) + ->rule('boolean', [ + 'pic' + ]) + ->rule('stringWidthBetween', 'name', 1, 18) + ->rule('min', [ + 'leadership', + 'strength', + 'intel' + ], GameConst::$defaultStatMin) + ->rule('max', [ + 'leadership', + 'strength', + 'intel' + ], GameConst::$defaultStatMax) + ->rule('in', 'character', array_merge(GameConst::$availablePersonality, ['Random'])) + ->rule('in', 'inheritSpecial', GameConst::$availableSpecialWar) + ->rule('min', 'inheritTurntime', 0) + ->rule('in', 'inheritCity', array_keys(CityConst::all())) + ->rule('integerArray', 'inheritBonusStat'); + + if (!$v->validate()) { + return $v->errorStr(); + } + return null; + } + + public function getRequiredSessionMode(): int + { + return static::REQ_LOGIN | static::REQ_READ_ONLY; + } + + public function launch(?Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag) + { + if($session === null){ + throw "invalid session"; + } + + $userID = $session->userID; + + $name = $this->args['name']; + $name = htmlspecialchars($name); + $name = StringUtil::removeSpecialCharacter($name); + $name = WebUtil::htmlPurify($name); + $name = StringUtil::textStrip($name); + $pic = $this->args['pic']; + $character = $this->args['character']; + + $leadership = $this->args['leadership']; + $strength = $this->args['strength']; + $intel = $this->args['intel']; + + $inheritSpecial = $this->args['inheritSpecial']??null; + $inheritTurntime =$this->args['inheritTurntime']??null; + $inheritCity = $this->args['inheritCity']??null; + $inheritBonusStat = $this->args['inheritBonusStat']??null; + + $rootDB = RootDB::db(); + //회원 테이블에서 정보확인 + $member = $rootDB->queryFirstRow('SELECT `no`, id, picture, grade, `name`, imgsvr FROM member WHERE no=%i', $userID); + + if (!$member) { + return "잘못된 접근입니다!!!"; + } + + $db = DB::db(); + $gameStor = KVStorage::getStorage($db, 'game_env'); + $gameStor->cacheValues(['year', 'month', 'maxgeneral', 'scenario', 'show_img_level', 'turnterm', 'turntime', 'genius', 'npcmode']); + ########## 동일 정보 존재여부 확인. ########## + + $gencount = $db->queryFirstField('SELECT count(`no`) FROM general WHERE npc<2'); + $oldGeneral = $db->queryFirstField('SELECT `no` FROM general WHERE `owner`=%i', $userID); + $oldName = $db->queryFirstField('SELECT `no` FROM general WHERE `name`=%s', $name); + + if ($oldGeneral) { + return "이미 등록하셨습니다!"; + } + if ($oldName) { + return "이미 있는 장수입니다. 다른 이름으로 등록해 주세요!"; + } + if ($gameStor->maxgeneral <= $gencount) { + return "더이상 등록할 수 없습니다!"; + } + if ($name == '') { + return "이름이 짧습니다. 다시 가입해주세요!"; + } + if (mb_strwidth($name) > 18) { + return "이름이 유효하지 않습니다. 다시 가입해주세요!"; + } + if ($leadership + $strength + $intel > GameConst::$defaultStatTotal) { + return "능력치가 " . GameConst::$defaultStatTotal . "을 넘어섰습니다. 다시 가입해주세요!"; + } + + if ($inheritBonusStat) { + if (count($inheritBonusStat) != 3) { + return "보너스 능력치가 잘못 지정되었습니다. 다시 가입해주세요!"; + } + $sum = array_sum($inheritBonusStat); + if ($sum < 3 || $sum > 5) { + return "보너스 능력치 합이 잘못 지정되었습니다. 다시 가입해주세요!"; + } + foreach ($inheritBonusStat as $stat) { + if ($stat < 0) { + return "보너스 능력치가 음수입니다. 다시 가입해주세요!"; + } + } + } + + $admin = $gameStor->getValues(['scenario', 'turnterm', 'turntime', 'show_img_level', 'startyear', 'year']); + + $inheritTotalPoint = resetInheritanceUser($userID); + $inheritRequiredPoint = 0; + + if ($inheritCity !== null) { + $inheritRequiredPoint += GameConst::$inheritBornCityPoint; + } + if ($inheritBonusStat !== null) { + $inheritRequiredPoint += GameConst::$inheritBornMaxBonusStat; + } + if ($inheritSpecial !== null) { + $inheritRequiredPoint += GameConst::$inheritBornSpecialPoint; + } + if ($inheritTurntime !== null) { + $inheritRequiredPoint += GameConst::$inheritBornTurntimePoint; + } + + if ($inheritTotalPoint < $inheritRequiredPoint) { + return "유산 포인트가 부족합니다. 다시 가입해주세요!"; + } + + if ($inheritSpecial !== null && $gameStor->genius == 0) { + return "이미 천재가 모두 나타났습니다. 다시 가입해주세요!"; + } + + if ($inheritCity !== null && !key_exists($inheritCity, CityConst::all())) { + return "도시가 잘못 지정되었습니다. 다시 가입해주세요!"; + } + + if ($inheritSpecial) { + $genius = true; + } else { + // 현재 1% + $genius = Util::randBool(0.01); + } + + if ($genius && $gameStor->genius > 0) { + $gameStor->genius = $gameStor->genius - 1; + } else { + $genius = false; + } + + if ($inheritCity !== null) { + $city = $inheritCity; + } else { + // 공백지에서만 태어나게 + $city = $db->queryFirstField("select city from city where level>=5 and level<=6 and nation=0 order by rand() limit 0,1"); + if (!$city) { + $city = $db->queryFirstField("select city from city where level>=5 and level<=6 order by rand() limit 0,1"); + } + } + + if ($inheritBonusStat) { + [$pleadership, $pstrength, $pintel] = $inheritBonusStat; + } else { + $pleadership = 0; + $pstrength = 0; + $pintel = 0; + foreach (Util::range(Util::randRangeInt(3, 5)) as $statIdx) { + switch (Util::choiceRandomUsingWeight([$leadership, $strength, $intel])) { + case 0: + $pleadership++; + break; + case 1: + $pstrength++; + break; + case 2: + $pintel++; + break; + } + } + } + + $leadership = $leadership + $pleadership; + $strength = $strength + $pstrength; + $intel = $intel + $pintel; + + $relYear = Util::valueFit($admin['year'] - $admin['startyear'], 0); + + $age = 20 + ($pleadership + $pstrength + $pintel) * 2 - (mt_rand(0, 1)); + // 아직 남았고 천재등록상태이면 특기 부여 + if ($genius) { + $specage2 = $age; + if ($inheritSpecial) { + $special2 = $inheritSpecial; + } else { + $special2 = SpecialityHelper::pickSpecialWar([ + 'leadership' => $leadership, + 'strength' => $strength, + 'intel' => $intel, + 'dex1' => 0, + 'dex2' => 0, + 'dex3' => 0, + 'dex4' => 0, + 'dex5' => 0 + ]); + } + } else { + $specage2 = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 6 - $relYear / 2), 3) + $age; + $special2 = GameConst::$defaultSpecialWar; + } + //내특 + $specage = Util::valueFit(Util::round((GameConst::$retirementYear - $age) / 12 - $relYear / 2), 3) + $age; + $special = GameConst::$defaultSpecialDomestic; + + if ($admin['scenario'] >= 1000) { + $specage2 = $age + 3; + $specage = $age + 3; + } + + if ($relYear < 3) { + $experience = 0; + } else { + $expGenCount = $db->queryFirstField('SELECT count(*) FROM general WHERE nation != 0 AND npc < 4'); + $targetGenOrder = Util::round($expGenCount * 0.2); + $experience = $db->queryFirstField( + 'SELECT experience FROM general WHERE nation != 0 AND npc < 4 ORDER BY experience ASC LIMIT %i, 1', + $targetGenOrder - 1 + ); + $experience *= 0.8; + } + + if ($inheritTurntime === null) { + $inheritTurntime = $inheritTurntime % ($gameStor->turnterm * 60); + $inheritTurntime += Util::randRangeInt(0, 999999) / 1000000; + $turntime = cutTurn($admin['turntime'], $admin['turnterm']); + $turntime = TimeUtil::nowAddSeconds($inheritTurntime, true); + } else { + $turntime = getRandTurn($admin['turnterm'], new \DateTimeImmutable($admin['turntime'])); + } + + + $now = TimeUtil::now(true); + if ($now >= $turntime) { + $turntime = addTurn($turntime, $admin['turnterm']); + } + + //특회 전콘 + if ($admin['show_img_level'] >= 1 && $member['grade'] >= 1 && $member['picture'] != "" && $pic) { + $face = $member['picture']; + $imgsvr = $member['imgsvr']; + } else { + $face = "default.jpg"; + $imgsvr = 0; + } + + //성격 랜덤시 + if (!in_array($character, GameConst::$availablePersonality)) { + $character = Util::choiceRandom(GameConst::$availablePersonality); + } + //상성 랜덤 + $affinity = rand() % 150 + 1; + + ########## 회원정보 테이블에 입력값을 등록한다. ########## + $db->insert('general', [ + 'owner' => $userID, + 'name' => $name, + 'owner_name' => $member['name'], + 'picture' => $face, + 'imgsvr' => $imgsvr, + 'nation' => 0, + 'city' => $city, + 'troop' => 0, + 'affinity' => $affinity, + 'leadership' => $leadership, + 'strength' => $strength, + 'intel' => $intel, + 'experience' => $experience, + 'dedication' => 0, + 'gold' => GameConst::$defaultGold, + 'rice' => GameConst::$defaultRice, + 'crew' => 0, + 'train' => 0, + 'atmos' => 0, + 'officer_level' => 0, + 'turntime' => $turntime, + 'killturn' => 6, + 'lastconnect' => $now, + 'lastrefresh' => $now, + 'crewtype' => GameUnitConst::DEFAULT_CREWTYPE, + 'makelimit' => 0, + 'age' => $age, + 'startage' => $age, + 'personal' => $character, + 'specage' => $specage, + 'special' => $special, + 'specage2' => $specage2, + 'special2' => $special2 + ]); + $generalID = $db->insertId(); + $turnRows = []; + foreach (Util::range(GameConst::$maxTurn) as $turnIdx) { + $turnRows[] = [ + 'general_id' => $generalID, + 'turn_idx' => $turnIdx, + 'action' => '휴식', + 'arg' => null, + 'brief' => '휴식' + ]; + } + $db->insert('general_turn', $turnRows); + + $rank_data = []; + foreach (array_keys(General::RANK_COLUMN) as $rankColumn) { + $rank_data[] = [ + 'general_id' => $generalID, + 'nation_id' => 0, + 'type' => $rankColumn, + 'value' => 0 + ]; + } + $db->insert('rank_data', $rank_data); + $db->insert('betting', [ + 'general_id' => $generalID, + ]); + $cityname = CityConst::byID($city)->name; + + $me = [ + 'no' => $generalID + ]; + + $log = []; + $mylog = []; + + $logger = new ActionLogger($generalID, 0, $gameStor->year, $gameStor->month); + + $josaRa = JosaUtil::pick($name, '라'); + $speicalText = getGeneralSpecialWarName($special2); + if ($genius) { + + $logger->pushGlobalActionLog("{$cityname}에서 {$name}{$josaRa}는 기재가 천하에 이름을 알립니다."); + $logger->pushGlobalActionLog("{$speicalText} 특기를 가진 천재의 등장으로 온 천하가 떠들썩합니다."); + $logger->pushGlobalHistoryLog("【천재】{$cityname}에 천재가 등장했습니다."); + } else { + $logger->pushGlobalActionLog("{$cityname}에서 {$name}{$josaRa}는 호걸이 천하에 이름을 알립니다."); + } + + $logger->pushGeneralHistoryLog("{$name}, {$cityname}에서 큰 뜻을 품다."); + $logger->pushGeneralActionLog("삼국지 모의전투 PHP의 세계에 오신 것을 환영합니다 ^o^", ActionLogger::PLAIN); + $logger->pushGeneralActionLog("처음 하시는 경우에는 도움말을 참고하시고,", ActionLogger::PLAIN); + $logger->pushGeneralActionLog("문의사항이 있으시면 게시판에 글을 남겨주시면 되겠네요~", ActionLogger::PLAIN); + $logger->pushGeneralActionLog("부디 즐거운 삼모전 되시길 바랍니다 ^^", ActionLogger::PLAIN); + $logger->pushGeneralActionLog("통솔 $pleadership 무력 $pstrength 지력 $pintel 의 보너스를 받으셨습니다.", ActionLogger::PLAIN); + $logger->pushGeneralActionLog("연령은 $age세로 시작합니다.", ActionLogger::PLAIN); + + if ($genius) { + $logger->pushGeneralActionLog("축하합니다! 천재로 태어나 처음부터 {$speicalText} 특기를 가지게 됩니다!", ActionLogger::PLAIN); + $logger->pushGeneralHistoryLog("{$speicalText} 특기를 가진 천재로 탄생."); + } + + $logger->flush(); + + pushAdminLog(["가입 : {$userID} // {$name} // {$generalID}" . getenv("REMOTE_ADDR")]); + + $rootDB->insert('member_log', [ + 'member_no' => $userID, + 'date' => TimeUtil::now(), + 'action_type' => 'make_general', + 'action' => Json::encode([ + 'server' => DB::prefix(), + 'type' => 'general', + 'generalID' => $generalID, + 'generalName' => $name + ]) + ]); + + return null; + } +} diff --git a/hwe/sammo/BaseAPI.php b/hwe/sammo/BaseAPI.php new file mode 100644 index 00000000..32f6d512 --- /dev/null +++ b/hwe/sammo/BaseAPI.php @@ -0,0 +1,26 @@ +args = $args; + } + abstract public function getRequiredSessionMode(): int; + abstract function validateArgs(): ?string; + + /** @return null|string|array */ + abstract function launch(?Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag); + + public function tryCache():?string{ + return null; + } +} diff --git a/src/sammo/Json.php b/src/sammo/Json.php index db85f442..28a879ce 100644 --- a/src/sammo/Json.php +++ b/src/sammo/Json.php @@ -54,6 +54,7 @@ class Json die(Json::encode($value, $flag)); } + /** @return never */ public static function dieWithReason(string $reason){ static::die([ 'result'=>false, diff --git a/src/sammo/TimeUtil.php b/src/sammo/TimeUtil.php index 46881e14..e451c35b 100644 --- a/src/sammo/TimeUtil.php +++ b/src/sammo/TimeUtil.php @@ -1,6 +1,9 @@ format('Y-m-d'); } - public static function now(bool $withFraction=false):string + public static function now(bool $withFraction = false): string { $obj = new \DateTime(); - if(!$withFraction){ + if (!$withFraction) { return $obj->format('Y-m-d H:i:s'); } return $obj->format('Y-m-d H:i:s.u'); } - public static function nowAddDays($day, bool $withFraction=false):string + public static function nowAddDays($day, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($day * 3600 * 24)); - if(!$withFraction){ + if (!$withFraction) { return $obj->format('Y-m-d H:i:s'); } return $obj->format('Y-m-d H:i:s.u'); } - public static function nowAddHours($hour, bool $withFraction=false):string + public static function nowAddHours($hour, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($hour * 3600)); - if(!$withFraction){ + if (!$withFraction) { return $obj->format('Y-m-d H:i:s'); } return $obj->format('Y-m-d H:i:s.u'); } - public static function nowAddMinutes($minute, bool $withFraction=false):string + public static function nowAddMinutes($minute, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($minute * 60)); - if(!$withFraction){ + if (!$withFraction) { return $obj->format('Y-m-d H:i:s'); } return $obj->format('Y-m-d H:i:s.u'); } - public static function nowAddSeconds($second, bool $withFraction=false):string + public static function nowAddSeconds($second, bool $withFraction = false): string { $obj = new \DateTime(); $obj->add(static::secondsToDateInterval($second)); - if(!$withFraction){ + if (!$withFraction) { return $obj->format('Y-m-d H:i:s'); } return $obj->format('Y-m-d H:i:s.u'); } - public static function secondsToDateTime(float $fullSeconds, bool $isDateTimeImmutable=false): \DateTimeInterface{ + public static function secondsToDateTime(float $fullSeconds, bool $isDateTimeImmutable = false, bool $isUTC = false): \DateTimeInterface + { $seconds = floor($fullSeconds); $fraction = $fullSeconds - $seconds; @@ -139,70 +143,73 @@ class TimeUtil $interval->s = $seconds; $interval->f = $fraction; - if($isDateTimeImmutable){ - $dateTime = new \DateTimeImmutable("@0"); + if ($isDateTimeImmutable) { + $dateTime = new \DateTimeImmutable("@0", $isUTC ? new \DateTimeZone("UTC") : null); return $dateTime->add($interval); } - $dateTime = new \DateTime("@0"); + $dateTime = new \DateTime("@0", $isUTC ? new \DateTimeZone("UTC") : null); $dateTime->add($interval); return $dateTime; } - public static function secondsToDateInterval(float $fullSeconds): \DateInterval{ + public static function secondsToDateInterval(float $fullSeconds): \DateInterval + { $d0 = new \DateTime("@0"); return $d0->diff(static::secondsToDateTime($fullSeconds, true)); } - public static function DateTimeToSeconds(\DateTimeInterface $dateTime): float{ - $d0 = new \DateTimeImmutable("@0"); + public static function DateTimeToSeconds(\DateTimeInterface $dateTime, bool $isUTC = false): float + { + $d0 = new \DateTimeImmutable("@0", $isUTC ? new \DateTimeZone("UTC") : null); return static::DateIntervalToSeconds($d0->diff($dateTime)); } - public static function DateIntervalToSeconds(\DateInterval $interval): float{ - if($interval->days !== FALSE){ + public static function DateIntervalToSeconds(\DateInterval $interval): float + { + if ($interval->days !== FALSE) { $days = $interval->days; - } - else{ - if($interval->y != 0){ + } else { + if ($interval->y != 0) { throw new \InvalidArgumentException('Year argument conversion is not supported'); } - if($interval->m != 0){ + if ($interval->m != 0) { throw new \InvalidArgumentException('Month argument conversion is not supported'); } $days = $interval->d; } - + $hours = $days * 24 + $interval->h; $minutes = $hours * 60 + $interval->i; $seconds = $minutes * 60 + $interval->s + $interval->f; - + return $seconds; } /** * $baseYear, $baseMonth 부터 $afterMonth 개월 이내인지. $afterMonth 포함. - * + * */ - public static function IsRangeMonth(int $baseYear, int $baseMonth, int $afterMonth, int $askYear, int $askMonth):bool{ - if($baseMonth < 1 || $baseMonth > 12){ + public static function IsRangeMonth(int $baseYear, int $baseMonth, int $afterMonth, int $askYear, int $askMonth): bool + { + if ($baseMonth < 1 || $baseMonth > 12) { throw new \InvalidArgumentException('개월이 올바르지 않음'); } - if($askMonth < 1 || $askMonth > 12){ + if ($askMonth < 1 || $askMonth > 12) { throw new \InvalidArgumentException('개월이 올바르지 않음'); } $minMonth = $baseYear * 12 + $baseMonth; - if($afterMonth < 0){ + if ($afterMonth < 0) { $maxMonth = $minMonth; $minMonth = $maxMonth - $afterMonth; } $maxMonth = $minMonth + $afterMonth; $askMonth = $askYear * 12 + $askMonth; - if($askMonth < $minMonth || $maxMonth < $askMonth){ + if ($askMonth < $minMonth || $maxMonth < $askMonth) { return false; } return true;