Fix config loading, speed thresholds and block selection; add tests, README, CLAUDE.md
This commit is contained in:
+59
-22
@@ -6,9 +6,16 @@ from enum import Enum
|
||||
import pygame
|
||||
from Serializer import EnumSerializer
|
||||
|
||||
CONFIG_JSON = 'configs/config.json'
|
||||
CONFIG_BLOCKS_JSON = 'configs/blocks.json'
|
||||
CONFIG_ADD_BLOCKS_JSON = 'configs/blocks_ADD.json'
|
||||
# Resolve configs next to the script (or next to the executable when frozen by PyInstaller),
|
||||
# so the game does not depend on the current working directory
|
||||
BASE_DIR = os.path.dirname(sys.executable if getattr(sys, 'frozen', False) else os.path.abspath(__file__))
|
||||
CONFIG_DIR = os.path.join(BASE_DIR, 'configs')
|
||||
|
||||
CONFIG_JSON = os.path.join(CONFIG_DIR, 'config.json')
|
||||
CONFIG_BLOCKS_JSON = os.path.join(CONFIG_DIR, 'blocks.json')
|
||||
CONFIG_ADD_BLOCKS_JSON = os.path.join(CONFIG_DIR, 'blocks_ADD.json')
|
||||
# Default configs ('*_000.json') are used when the local ones above are absent
|
||||
DEFAULT_SUFFIX = '_000'
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@@ -161,36 +168,66 @@ def store_config():
|
||||
es.save_to_file(config_to_save, CONFIG_JSON)
|
||||
|
||||
|
||||
def _config_path(path: str) -> str | None:
|
||||
"""Return the local config path, or its '*_000.json' default if the local one is absent"""
|
||||
if os.path.isfile(path):
|
||||
return path
|
||||
root, ext = os.path.splitext(path)
|
||||
default = root + DEFAULT_SUFFIX + ext
|
||||
return default if os.path.isfile(default) else None
|
||||
|
||||
|
||||
def _fail(message: str):
|
||||
print(f'Config error: {message}')
|
||||
sys.exit(10)
|
||||
|
||||
|
||||
def _read_json(path: str) -> dict:
|
||||
try:
|
||||
with open(path, encoding='utf-8') as fd:
|
||||
return json.load(fd)
|
||||
except (OSError, json.JSONDecodeError) as e:
|
||||
_fail(f'cannot read {path}: {e}')
|
||||
|
||||
|
||||
def load_config():
|
||||
global KEY_CONFIG, COLORS, CONTROLS_TEXT, STORE_WIDTH, BLOCK_SIZE, BLOCK_TYPE, HIGH_SCORE_INC_SPEED
|
||||
es = EnumSerializer
|
||||
|
||||
if not os.path.isfile(CONFIG_JSON) or not os.path.isfile(CONFIG_JSON) :
|
||||
print('No config files was found')
|
||||
sys.exit(10)
|
||||
config_path = _config_path(CONFIG_JSON)
|
||||
blocks_path = _config_path(CONFIG_BLOCKS_JSON)
|
||||
if config_path is None or blocks_path is None:
|
||||
_fail(f'no config files were found in {CONFIG_DIR}')
|
||||
|
||||
config_data = es.load_from_file(CONFIG_JSON)
|
||||
KEY_CONFIG = config_data['CONFIG']['keys']
|
||||
CONTROLS_TEXT = config_data['CONFIG']['controls_text']
|
||||
COLORS = config_data['CONFIG']['colors']
|
||||
STORE_WIDTH = config_data['CONFIG']['store_width']
|
||||
BLOCK_SIZE = config_data['CONFIG']['block_size']
|
||||
HIGH_SCORE_INC_SPEED = True if str(config_data['CONFIG']['high_score_inc_speed']).lower() == 'true' else False
|
||||
_read_json(config_path) # validate JSON syntax with a clear message
|
||||
try:
|
||||
config = es.load_from_file(config_path)['CONFIG']
|
||||
KEY_CONFIG = config['keys']
|
||||
CONTROLS_TEXT = config['controls_text']
|
||||
COLORS = config['colors']
|
||||
STORE_WIDTH = config['store_width']
|
||||
BLOCK_SIZE = config['block_size']
|
||||
except (KeyError, TypeError) as e:
|
||||
_fail(f'missing key {e} in {config_path}')
|
||||
HIGH_SCORE_INC_SPEED = str(config.get('high_score_inc_speed', False)).lower() == 'true'
|
||||
|
||||
with open(CONFIG_BLOCKS_JSON) as block_fd:
|
||||
blocks_data = json.load(block_fd)
|
||||
|
||||
blocks0 = blocks_data['ALL_BLOCKS']['members']
|
||||
try:
|
||||
blocks0 = _read_json(blocks_path)['ALL_BLOCKS']['members']
|
||||
except (KeyError, TypeError) as e:
|
||||
_fail(f'missing key {e} in {blocks_path}')
|
||||
|
||||
blocks1 = {}
|
||||
if os.path.isfile(CONFIG_ADD_BLOCKS_JSON):
|
||||
with open(CONFIG_ADD_BLOCKS_JSON) as block_fd:
|
||||
blocks_data1 = json.load(block_fd)
|
||||
blocks1 = blocks_data1['ADDITIONAL_BLOCKS']['members']
|
||||
add_blocks_path = _config_path(CONFIG_ADD_BLOCKS_JSON)
|
||||
if add_blocks_path is not None:
|
||||
try:
|
||||
blocks1 = _read_json(add_blocks_path)['ADDITIONAL_BLOCKS']['members']
|
||||
except (KeyError, TypeError) as e:
|
||||
_fail(f'missing key {e} in {add_blocks_path}')
|
||||
|
||||
blocks = blocks0 | blocks1
|
||||
if not any(block['min_score'] <= 0 for block in blocks.values()):
|
||||
_fail('at least one block must have min_score 0')
|
||||
BLOCK_TYPE = Enum('BlockType', blocks)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user