1
0
card/python/api/app/services/card_master.py
2025-06-08 06:42:03 +09:00

142 lines
5.0 KiB
Python

"""
Card master data fetcher from external ai.json
"""
import httpx
import json
from typing import Dict, List, Optional
from functools import lru_cache
import logging
logger = logging.getLogger(__name__)
CARD_MASTER_URL = "https://git.syui.ai/ai/ai/raw/branch/main/ai.json"
# Default CP ranges for cards (matching existing gacha.py values)
DEFAULT_CP_RANGES = {
0: (10, 100),
1: (20, 120),
2: (30, 130),
3: (40, 140),
4: (50, 150),
5: (25, 125),
6: (15, 115),
7: (60, 160),
8: (80, 180),
9: (70, 170),
10: (90, 190),
11: (35, 135),
12: (65, 165),
13: (75, 175),
14: (100, 200),
15: (85, 185),
135: (95, 195), # world card
}
class CardMasterService:
def __init__(self):
self._cache = None
self._cache_time = 0
self._cache_duration = 3600 # 1 hour cache
@lru_cache(maxsize=1)
def fetch_card_master_data(self) -> Optional[Dict]:
"""Fetch card master data from external source"""
try:
response = httpx.get(CARD_MASTER_URL, timeout=10.0)
response.raise_for_status()
data = response.json()
return data
except Exception as e:
logger.error(f"Failed to fetch card master data: {e}")
return None
def get_card_info(self) -> Dict[int, Dict]:
"""Get card information in the format expected by gacha service"""
master_data = self.fetch_card_master_data()
if not master_data:
# Fallback to hardcoded data
return self._get_fallback_card_info()
try:
cards = master_data.get("ai", {}).get("card", {}).get("cards", [])
card_info = {}
for card in cards:
card_id = card.get("id")
if card_id is not None:
# Use name from JSON, fallback to English name
name = card.get("name", f"card_{card_id}")
# Get CP range from defaults
cp_range = DEFAULT_CP_RANGES.get(card_id, (50, 150))
card_info[card_id] = {
"name": name,
"base_cp_range": cp_range,
"ja_name": card.get("lang", {}).get("ja", {}).get("name", name),
"description": card.get("lang", {}).get("ja", {}).get("text", "")
}
return card_info
except Exception as e:
logger.error(f"Failed to parse card master data: {e}")
return self._get_fallback_card_info()
def _get_fallback_card_info(self) -> Dict[int, Dict]:
"""Fallback card info if external source fails"""
return {
0: {"name": "ai", "base_cp_range": (10, 100)},
1: {"name": "dream", "base_cp_range": (20, 120)},
2: {"name": "radiance", "base_cp_range": (30, 130)},
3: {"name": "neutron", "base_cp_range": (40, 140)},
4: {"name": "sun", "base_cp_range": (50, 150)},
5: {"name": "night", "base_cp_range": (25, 125)},
6: {"name": "snow", "base_cp_range": (15, 115)},
7: {"name": "thunder", "base_cp_range": (60, 160)},
8: {"name": "ultimate", "base_cp_range": (80, 180)},
9: {"name": "sword", "base_cp_range": (70, 170)},
10: {"name": "destruction", "base_cp_range": (90, 190)},
11: {"name": "earth", "base_cp_range": (35, 135)},
12: {"name": "galaxy", "base_cp_range": (65, 165)},
13: {"name": "create", "base_cp_range": (75, 175)},
14: {"name": "supernova", "base_cp_range": (100, 200)},
15: {"name": "world", "base_cp_range": (85, 185)},
}
def get_all_cards(self) -> List[Dict]:
"""Get all cards with full information"""
master_data = self.fetch_card_master_data()
if not master_data:
return []
try:
cards = master_data.get("ai", {}).get("card", {}).get("cards", [])
result = []
for card in cards:
card_id = card.get("id")
if card_id is not None:
cp_range = DEFAULT_CP_RANGES.get(card_id, (50, 150))
result.append({
"id": card_id,
"name": card.get("name", f"card_{card_id}"),
"ja_name": card.get("lang", {}).get("ja", {}).get("name", ""),
"description": card.get("lang", {}).get("ja", {}).get("text", ""),
"base_cp_min": cp_range[0],
"base_cp_max": cp_range[1]
})
return result
except Exception as e:
logger.error(f"Failed to get all cards: {e}")
return []
# Singleton instance
card_master_service = CardMasterService()