[Enhance] World map sub folder

- Make the world maps' folder can have sub folders.
This commit is contained in:
Lost-MSth
2024-06-20 00:13:58 +08:00
parent 64526e3c4b
commit c38208832b
7 changed files with 72 additions and 34 deletions

View File

@@ -82,11 +82,15 @@ class BundleParser:
version_tuple_bundles: 'dict[tuple[str, str], ContentBundle]' = {} version_tuple_bundles: 'dict[tuple[str, str], ContentBundle]' = {}
def __init__(self) -> None: def __init__(self) -> None:
self.parse() if not self.bundles:
self.parse()
def re_init(self) -> None: def re_init(self) -> None:
self.bundles.clear() self.bundles.clear()
self.max_bundle_version.clear() self.max_bundle_version.clear()
self.next_versions.clear()
self.version_tuple_bundles.clear()
self.get_bundles.cache_clear()
self.parse() self.parse()
def parse(self) -> None: def parse(self) -> None:

View File

@@ -1,6 +1,6 @@
from .config_manager import Config from .config_manager import Config
ARCAEA_SERVER_VERSION = 'v2.11.3.13' ARCAEA_SERVER_VERSION = 'v2.11.3.14'
ARCAEA_DATABASE_VERSION = 'v2.11.3.13' ARCAEA_DATABASE_VERSION = 'v2.11.3.13'
ARCAEA_LOG_DATBASE_VERSION = 'v1.1' ARCAEA_LOG_DATBASE_VERSION = 'v1.1'

View File

@@ -16,6 +16,7 @@ from core.sql import (Connect, DatabaseMigrator, LogDatabaseMigrator,
MemoryDatabase) MemoryDatabase)
from core.user import UserRegister from core.user import UserRegister
from core.util import try_rename from core.util import try_rename
from core.world import MapParser
class DatabaseInit: class DatabaseInit:
@@ -326,12 +327,11 @@ class FileChecker:
def check_song_file(self) -> bool: def check_song_file(self) -> bool:
'''检查song有关文件并初始化缓存''' '''检查song有关文件并初始化缓存'''
f = self.check_folder(Config.SONG_FILE_FOLDER_PATH) f = self.check_folder(Config.SONG_FILE_FOLDER_PATH)
self.logger.info("Start to initialize song data...") self.logger.info("Initialize song data...")
try: try:
DownloadList.initialize_cache() DownloadList.initialize_cache()
if not Config.SONG_FILE_HASH_PRE_CALCULATE: if not Config.SONG_FILE_HASH_PRE_CALCULATE:
self.logger.info('Song file hash pre-calculate is disabled.') self.logger.info('Song file hash pre-calculate is disabled.')
self.logger.info('Song data initialization is complete!')
except Exception as e: except Exception as e:
self.logger.error(format_exc()) self.logger.error(format_exc())
self.logger.warning('Song data initialization error!') self.logger.warning('Song data initialization error!')
@@ -341,17 +341,28 @@ class FileChecker:
def check_content_bundle(self) -> bool: def check_content_bundle(self) -> bool:
'''检查 content bundle 有关文件并初始化缓存''' '''检查 content bundle 有关文件并初始化缓存'''
f = self.check_folder(Config.CONTENT_BUNDLE_FOLDER_PATH) f = self.check_folder(Config.CONTENT_BUNDLE_FOLDER_PATH)
self.logger.info("Start to initialize content bundle data...") self.logger.info("Initialize content bundle data...")
try: try:
BundleParser() BundleParser()
self.logger.info('Content bundle data initialization is complete!')
except Exception as e: except Exception as e:
self.logger.error(format_exc()) self.logger.error(format_exc())
self.logger.warning('Content bundle data initialization error!') self.logger.warning('Content bundle data initialization error!')
f = False f = False
return f return f
def check_world_map(self) -> bool:
'''检查 world map 有关文件并初始化缓存'''
f = self.check_folder(Config.WORLD_MAP_FOLDER_PATH)
self.logger.info("Initialize world map data...")
try:
MapParser()
except Exception as e:
self.logger.error(format_exc())
self.logger.warning('World map data initialization error!')
f = False
return f
def check_before_run(self) -> bool: def check_before_run(self) -> bool:
'''运行前检查,返回布尔值''' '''运行前检查,返回布尔值'''
MemoryDatabase() # 初始化内存数据库 MemoryDatabase() # 初始化内存数据库
return self.check_song_file() and self.check_content_bundle() and self.check_update_database() return self.check_song_file() and self.check_content_bundle() and self.check_update_database() and self.check_world_map()

View File

@@ -6,6 +6,7 @@ from .save import SaveData
from .score import Score from .score import Score
from .sql import Connect, Sql from .sql import Connect, Sql
from .user import User from .user import User
from .world import MapParser
class BaseOperation: class BaseOperation:
@@ -88,6 +89,16 @@ class RefreshBundleCache(BaseOperation):
BundleParser().re_init() BundleParser().re_init()
class RefreshWorldMapCache(BaseOperation):
'''
刷新 map 缓存
'''
_name = 'refresh_world_map_cache'
def run(self):
MapParser().re_init()
class SaveUpdateScore(BaseOperation): class SaveUpdateScore(BaseOperation):
''' '''
云存档更新成绩,是覆盖式更新 云存档更新成绩,是覆盖式更新

View File

@@ -437,7 +437,7 @@ class DatabaseMigrator:
def _version_2_11_3_11(self): def _version_2_11_3_11(self):
''' '''
2.11.3.11 版本特殊更新,调整 recent30 表结构 2.11.3.11 版本特殊更新,调整 recent30 表结构
recent30 表从 (user_id: int PK, song_id<index>: text, rating<index>: real, ...) \ recent30 表从 (user_id: int PK, rating<index>: real, song_id<index>: text, ...) \
更改为 (user_id: int PK, r_index: int PK, time_played: int, song_id: text, difficulty: int, score: int, sp, p, n, m, hp, mod, clear_type, rating: real) 更改为 (user_id: int PK, r_index: int PK, time_played: int, song_id: text, difficulty: int, score: int, sp, p, n, m, hp, mod, clear_type, rating: real)
''' '''

View File

@@ -10,34 +10,46 @@ from .error import InputError, MapLocked, NoData
from .item import ItemFactory from .item import ItemFactory
@lru_cache(maxsize=128) class MapParser:
def get_world_name(file_dir: str = Constant.WORLD_MAP_FOLDER_PATH) -> list:
'''获取所有地图名称,返回列表'''
file_list = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if os.path.splitext(file)[1] == '.json':
file_list.append(os.path.splitext(file)[0])
return file_list
map_id_path: 'dict[str, str]' = {}
@lru_cache(maxsize=128) def __init__(self) -> None:
def get_world_info(map_id: str) -> dict: if not self.map_id_path:
'''读取json文件内容返回字典''' self.parse()
world_info = {}
with open(os.path.join(Constant.WORLD_MAP_FOLDER_PATH, f'{map_id}.json'), 'rb') as f:
world_info = load(f)
return world_info def parse(self) -> None:
for root, dirs, files in os.walk(Constant.WORLD_MAP_FOLDER_PATH):
for file in files:
if not file.endswith('.json'):
continue
path = os.path.join(root, file)
self.map_id_path[file[:-5]] = path
def get_world_all(c, user) -> list: def re_init(self) -> None:
''' self.map_id_path.clear()
读取所有地图信息,返回列表 self.get_world_info.cache_clear()
parameter: `user` - `User`类或子类的实例 self.parse()
'''
worlds = get_world_name() @staticmethod
return [UserMap(c, map_id, user) for map_id in worlds] @lru_cache(maxsize=128)
def get_world_info(map_id: str) -> dict:
'''读取json文件内容返回字典'''
world_info = {}
with open(MapParser.map_id_path[map_id], 'rb') as f:
world_info = load(f)
return world_info
@staticmethod
def get_world_all(c, user) -> list:
'''
读取所有地图信息,返回列表
parameter: `user` - `User` 类或子类的实例
`c` - 数据库连接
'''
return [UserMap(c, map_id, user) for map_id in MapParser.map_id_path.keys()]
class Step: class Step:
@@ -208,7 +220,7 @@ class Map:
def select_map_info(self): def select_map_info(self):
'''获取地图信息''' '''获取地图信息'''
self.from_dict(get_world_info(self.map_id)) self.from_dict(MapParser.get_world_info(self.map_id))
class UserMap(Map): class UserMap(Map):

View File

@@ -2,7 +2,7 @@ from flask import Blueprint, request
from core.sql import Connect from core.sql import Connect
from core.user import UserOnline from core.user import UserOnline
from core.world import UserMap, get_world_all from core.world import MapParser, UserMap
from .auth import auth_required from .auth import auth_required
from .func import arc_try, success_return from .func import arc_try, success_return
@@ -20,7 +20,7 @@ def world_all(user_id):
return success_return({ return success_return({
"current_map": user.current_map.map_id, "current_map": user.current_map.map_id,
"user_id": user_id, "user_id": user_id,
"maps": [x.to_dict(has_map_info=True, has_rewards=True) for x in get_world_all(c, user)] "maps": [x.to_dict(has_map_info=True, has_rewards=True) for x in MapParser.get_world_all(c, user)]
}) })