diff --git a/hwe/sammo/API/Global/GetConst.php b/hwe/sammo/API/Global/GetConst.php new file mode 100644 index 00000000..be599f33 --- /dev/null +++ b/hwe/sammo/API/Global/GetConst.php @@ -0,0 +1,306 @@ + $fileModified) { + continue; + } + $lastModified = $fileModified; + } + if ($lastModified === null) { + return null; + } + return $lastModified; + } + + public function getCacheKey(): string + { + if ($this->cacheKey !== null) { + return $this->cacheKey; + } + + if (is_subclass_of('\\sammo\\VersionGit', '\\sammo\VersionGitDynamic')) { + $lastModified = $this->findLastModified(); + if ($lastModified !== null) { + $versionHash = "lt{$lastModified}"; + } else { + $versionHash = VersionGit::getHash(); + } + } else { + $versionHash = VersionGit::getHash(); + } + + $apiVersion = static::CONST_API_VERSION; + $serverID = UniqueConst::$serverID; + + + $cacheKey = "{$apiVersion}_{$serverID}_{$versionHash}"; + $this->cacheKey = $cacheKey; + + return $cacheKey; + } + + public function tryCache(): ?APICacheResult + { + if (is_subclass_of('\\sammo\\VersionGit', '\\sammo\VersionGitDynamic')) { + return new APICacheResult(TimeUtil::secondsToDateTime($this->findLastModified(), true, true)); + } + + return new APICacheResult(null, $this->getCacheKey()); + } + + public function readCache(Cache $cache): null|string|array|int|float|bool + { + $rawJSONCache = $cache->load(static::CACHE_KEY); + if ($rawJSONCache === null) { + return null; + } + $jsonCache = Json::decode($rawJSONCache); + if (!key_exists('cacheKey', $jsonCache)) { + return null; + } + + $jsonCacheKey = $jsonCache['cacheKey']; + if ($jsonCacheKey !== $this->getCacheKey()) { + return null; + } + + return $jsonCache['data'] ?? null; + } + + public function extractObjClassInfo(string $objKey, callable $callerFunction): array + { + /** @var \sammo\iAction */ + $target = $callerFunction($objKey); + if (!($target instanceof \sammo\iAction)) { + throw new \RuntimeException("{$objKey}의 대상이 iAction이 아님"); + } + return [ + 'value' => $objKey, + 'name' => $target->getName(), + 'info' => $target->getInfo(), + ]; + } + + public function extractObjClassInfoFromArray(array $constArray, callable $callerFunction): array + { + $result = []; + foreach ($constArray as $key => $target) { + if (is_string($target)) { + $actionInfo = $this->extractObjClassInfo($target, $callerFunction); + if (is_string($key)) { + $result[$key] = $actionInfo; + } else { + $result[$target] = $actionInfo; + } + continue; + } + if (is_array($target)) { + $result[$key] = $this->extractObjClassInfoFromArray($target, $callerFunction); + continue; + } + if(is_string($key) && is_int($target)){ + //역전된 상황이다. + $result[$key] = $this->extractObjClassInfo($key, $callerFunction); + continue; + } + $result[$key] = $target; + } + return $result; + } + + public function extractObjClassInfoFromGameConst(string $gameConstKey, callable $callerFunction): array + { + $gameConstKeyList = explode(".", $gameConstKey); + $target = (GameConst::${$gameConstKeyList[0]}) ?? []; + foreach(\array_slice($gameConstKeyList, 1) as $gameConstSubKey){ + $target = $target[$gameConstSubKey] ?? []; + } + + if (is_string($target)) { + return $this->extractObjClassInfo($target, $callerFunction); + } + + if (!is_array($target)) { + throw new \RuntimeException("GameConst::{$gameConstKey}의 값이 {$target}임"); + } + + return $this->extractObjClassInfoFromArray($target, $callerFunction); + } + + public function genConstData() + { + $gameConstKeys = [ + 'nationType' => [ + '\sammo\buildNationTypeClass', + ['availableNationType', 'neutralNationType'] + ], + 'specialDomestic' => [ + '\sammo\buildGeneralSpecialDomesticClass', + ['defaultSpecialDomestic', 'availableSpecialDomestic', 'optionalSpecialDomestic'] + ], + 'specialWar' => [ + '\sammo\buildGeneralSpecialWarClass', + ['defaultSpecialWar', 'availableSpecialWar', 'optionalSpecialWar'] + ], + 'personality' => [ + '\sammo\buildPersonalityClass', + ['neutralPersonality', 'availablePersonality', 'optionalPersonality'] + ], + 'item' => [ + '\sammo\buildItemClass', + ['allItems'], + 1 + ], + ]; + //GameConst 중 BaseCommand는 시간 흐름, 장수에 따라 정보가 달라지므로 따로 처리해야함 + + + $iActionInfo = []; + $iActionKeyMap = []; + foreach ($gameConstKeys as $mappedKey => $callerTarget) { + $flatLevel = 0; + if (is_array($callerTarget)) { + $callerFunction = $callerTarget[0]; + $gameConstSubKey = $callerTarget[1]; + if(count($callerTarget) > 2){ + /** @var int */ + $flatLevel = $callerTarget[2]; + } + } else { + $gameConstSubKey = [$mappedKey]; + $callerFunction = $callerTarget; + } + + if (!is_callable($callerFunction)) { + throw new \RuntimeException("{$mappedKey} => {$callerFunction}이 callable이 아님"); + } + + $actionInfo = []; + foreach ($gameConstSubKey as $key) { + $appendInfo = $this->extractObjClassInfoFromGameConst($key, $callerFunction); + $actionInfo = array_merge($actionInfo, $appendInfo); + $iActionKeyMap[$key] = $mappedKey; + } + + if($flatLevel > 0){ + foreach(range(0, $flatLevel - 1) as $tryFlatLevel){ + $actionInfo = array_merge(...array_values($actionInfo)); + } + } + + + $iActionInfo[$mappedKey] = $actionInfo; + } + return [ + 'gameConst' => get_class_vars('\sammo\GameConst'), + 'gameUnitConst' => GameUnitConst::all(), + 'cityConst' => CityConst::all(), + 'cityConstMap' => [ + 'region' => CityConst::$regionMap, + 'level' => CityConst::$levelMap, + ], + 'iActionInfo' => $iActionInfo, + 'iActionKeyMap' => $iActionKeyMap, + ]; + } + + public function launch(Session $session, ?DateTimeInterface $modifiedSince, ?string $reqEtag) + { + $cacheDir = $this->rootPath . '/data/file_cache'; + + if (!prepareDir($cacheDir)) { + throw new RuntimeException('cache 폴더 없음'); + } + $storage = new \Nette\Caching\Storages\FileStorage($cacheDir); + $cache = new Cache($storage); + + + $constCache = $this->readCache($cache); + if ($constCache !== null) { + return [ + 'result' => true, + 'cacheKey' => $this->getCacheKey(), + 'data' => $constCache, + ]; + } + + $constCache = $this->genConstData(); + $cache->save(static::CACHE_KEY, Json::encode([ + 'cacheKey' => $this->getCacheKey(), + 'data' => $constCache + ])); + + return [ + 'result' => true, + 'cacheKey' => $this->getCacheKey(), + 'data' => $constCache, + ]; + } +}