pre-push commit
This commit is contained in:
122
battleflow/storage.py
Normal file
122
battleflow/storage.py
Normal file
@@ -0,0 +1,122 @@
|
||||
from __future__ import annotations
|
||||
import json, os, uuid
|
||||
from typing import List, Dict
|
||||
from flask import current_app
|
||||
from .models import Actor, Preset, PresetGroup, CONDITION_ICON_FILES, CURATED_ICON_SLUGS
|
||||
|
||||
PLACEHOLDER_BG = '#334155'
|
||||
PLACEHOLDER_FG = '#e2e8f0'
|
||||
GAME_ICONS_BASE = 'https://raw.githubusercontent.com/game-icons/icons/master'
|
||||
|
||||
def paths():
|
||||
return dict(
|
||||
STATE=current_app.config["STATE_PATH"],
|
||||
PRESETS=current_app.config["PRESETS_PATH"],
|
||||
GROUPS=current_app.config["PRESET_GROUPS_PATH"],
|
||||
AVATARS=current_app.config["AVATAR_DIR"],
|
||||
ICONS=current_app.config["ICON_DIR"],
|
||||
DATA=current_app.config["DATA_DIR"],
|
||||
)
|
||||
|
||||
def save_state(state) -> None:
|
||||
p = paths()
|
||||
tmp = {
|
||||
'actors': [a.__dict__ for a in state.actors],
|
||||
'turn_idx': state.turn_idx,
|
||||
'round': state.round,
|
||||
'visible': state.visible,
|
||||
'dead_mode': state.dead_mode,
|
||||
}
|
||||
with open(p["STATE"], 'w', encoding='utf-8') as f:
|
||||
json.dump(tmp, f, ensure_ascii=False, indent=2)
|
||||
|
||||
def load_state(state) -> None:
|
||||
p = paths()
|
||||
if not os.path.exists(p["STATE"]):
|
||||
return
|
||||
try:
|
||||
with open(p["STATE"], 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
state.actors = [Actor(**a) for a in data.get('actors', [])]
|
||||
state.turn_idx = int(data.get('turn_idx', 0))
|
||||
state.round = int(data.get('round', 1))
|
||||
state.visible = bool(data.get('visible', True))
|
||||
state.dead_mode = str(data.get('dead_mode', 'normal'))
|
||||
state.normalize()
|
||||
state.touch()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def save_presets(items: List[Preset]) -> None:
|
||||
p = paths()
|
||||
with open(p["PRESETS"], 'w', encoding='utf-8') as f:
|
||||
json.dump([x.__dict__ for x in items], f, ensure_ascii=False, indent=2)
|
||||
|
||||
def load_presets() -> List[Preset]:
|
||||
p = paths()
|
||||
if not os.path.exists(p["PRESETS"]):
|
||||
return []
|
||||
try:
|
||||
with open(p["PRESETS"], 'r', encoding='utf-8') as f:
|
||||
arr = json.load(f)
|
||||
return [Preset(**x) for x in arr]
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
def save_groups(items: List[PresetGroup]) -> None:
|
||||
p = paths()
|
||||
with open(p["GROUPS"], 'w', encoding='utf-8') as f:
|
||||
json.dump([x.__dict__ for x in items], f, ensure_ascii=False, indent=2)
|
||||
|
||||
def load_groups() -> List[PresetGroup]:
|
||||
p = paths()
|
||||
if not os.path.exists(p["GROUPS"]):
|
||||
return []
|
||||
try:
|
||||
with open(p["GROUPS"], 'r', encoding='utf-8') as f:
|
||||
arr = json.load(f)
|
||||
return [PresetGroup(**x) for x in arr]
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
def ensure_default_icons() -> None:
|
||||
p = paths()
|
||||
os.makedirs(p["ICONS"], exist_ok=True)
|
||||
for c, fn in CONDITION_ICON_FILES.items():
|
||||
dest = os.path.join(p["ICONS"], fn)
|
||||
if os.path.exists(dest):
|
||||
continue
|
||||
letter = (c[:1] or '?').upper()
|
||||
svg = f"""<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'>
|
||||
<rect rx='6' width='32' height='32' fill='{PLACEHOLDER_BG}' />
|
||||
<text x='16' y='21' font-family='sans-serif' font-size='16' text-anchor='middle' fill='{PLACEHOLDER_FG}'>{letter}</text>
|
||||
</svg>"""
|
||||
try:
|
||||
with open(dest, 'w', encoding='utf-8') as f:
|
||||
f.write(svg)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def seed_curated_icons(overwrite: bool = True) -> list[dict]:
|
||||
ensure_default_icons()
|
||||
out = []
|
||||
try:
|
||||
from urllib.request import urlopen
|
||||
from urllib.error import URLError, HTTPError
|
||||
p = paths()
|
||||
for cond, (author, slug) in CURATED_ICON_SLUGS.items():
|
||||
dest = os.path.join(p["ICONS"], f'{cond}.svg')
|
||||
url = f"https://raw.githubusercontent.com/game-icons/icons/master/{author}/{slug}.svg"
|
||||
try:
|
||||
with urlopen(url, timeout=10) as r:
|
||||
svg = r.read()
|
||||
if (not os.path.exists(dest)) or overwrite:
|
||||
with open(dest, 'wb') as f:
|
||||
f.write(svg)
|
||||
out.append({'condition': cond, 'status': 'downloaded'})
|
||||
else:
|
||||
out.append({'condition': cond, 'status': 'exists'})
|
||||
except (URLError, HTTPError) as e:
|
||||
out.append({'condition': cond, 'status': f'fallback ({e.__class__.__name__})'})
|
||||
finally:
|
||||
return out
|
||||
Reference in New Issue
Block a user