142 lines
5.0 KiB
Python
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() |