Initial commit
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from api.models import Aspect, Hero, Item
|
||||
|
||||
# Add data directory to path for imports
|
||||
sys.path.insert(0, str(Path(settings.BASE_DIR) / "data"))
|
||||
from facets import HERO_FACETS
|
||||
|
||||
|
||||
def _strip_comments(text: str) -> str:
|
||||
"""Remove single-line and block comments from TypeScript data."""
|
||||
text = re.sub(r"/\*.*?\*/", "", text, flags=re.S)
|
||||
lines = []
|
||||
for line in text.splitlines():
|
||||
stripped = line.strip()
|
||||
if stripped.startswith("//"):
|
||||
continue
|
||||
lines.append(line)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def _extract_objects(text: str, require_primary: bool = False):
|
||||
cleaned = _strip_comments(text)
|
||||
objects = []
|
||||
|
||||
for match in re.finditer(r"\{[^}]*\}", cleaned):
|
||||
chunk = match.group(0)
|
||||
entry = {}
|
||||
id_match = re.search(r"['\"]?id['\"]?\s*:\s*(['\"])(.*?)\1", chunk)
|
||||
name_match = re.search(r"['\"]?name['\"]?\s*:\s*(['\"])(.*?)\1", chunk)
|
||||
if not (id_match and name_match):
|
||||
continue
|
||||
entry["slug"] = id_match.group(2)
|
||||
entry["name"] = name_match.group(2)
|
||||
|
||||
if require_primary:
|
||||
primary_match = re.search(r"['\"]?primary['\"]?\s*:\s*(['\"])(.*?)\1", chunk)
|
||||
if not primary_match:
|
||||
continue
|
||||
entry["primary"] = primary_match.group(2)
|
||||
|
||||
if len(entry) == (3 if require_primary else 2):
|
||||
objects.append(entry)
|
||||
|
||||
return objects
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Load heroes, items and facets from data files into the database."
|
||||
|
||||
def handle(self, *args, **options):
|
||||
base_dir = Path(settings.BASE_DIR)
|
||||
heroes_path = base_dir / "data" / "heroes.ts"
|
||||
items_path = base_dir / "data" / "items.ts"
|
||||
|
||||
if not heroes_path.exists() or not items_path.exists():
|
||||
raise CommandError("Missing data files in the ./data directory.")
|
||||
|
||||
heroes = _extract_objects(heroes_path.read_text(encoding="utf-8"), require_primary=True)
|
||||
items = _extract_objects(items_path.read_text(encoding="utf-8"), require_primary=False)
|
||||
|
||||
if not heroes:
|
||||
raise CommandError("Failed to parse heroes.ts")
|
||||
if not items:
|
||||
raise CommandError("Failed to parse items.ts")
|
||||
|
||||
hero_created = item_created = aspect_created = 0
|
||||
|
||||
for hero in heroes:
|
||||
hero_obj, created = Hero.objects.update_or_create(
|
||||
name=hero["name"],
|
||||
defaults={
|
||||
"primary": hero["primary"],
|
||||
},
|
||||
)
|
||||
hero_created += int(created)
|
||||
|
||||
# Load facets for this hero
|
||||
facets = HERO_FACETS.get(hero["name"], [])
|
||||
for facet_name in facets:
|
||||
_, facet_created = Aspect.objects.update_or_create(
|
||||
hero=hero_obj,
|
||||
name=facet_name,
|
||||
)
|
||||
aspect_created += int(facet_created)
|
||||
|
||||
for item in items:
|
||||
_, created = Item.objects.update_or_create(
|
||||
name=item["name"],
|
||||
)
|
||||
item_created += int(created)
|
||||
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f"Loaded {len(heroes)} heroes ({hero_created} new), "
|
||||
f"{len(items)} items ({item_created} new), "
|
||||
f"and {aspect_created} new facets."
|
||||
)
|
||||
)
|
||||
Reference in New Issue
Block a user