diff --git a/fftcg/__init__.py b/fftcg/__init__.py index aa874c2..fb01815 100644 --- a/fftcg/__init__.py +++ b/fftcg/__init__.py @@ -1,6 +1,7 @@ from .book import Book from .carddb import CardDB +from .language import Language from .opus import Opus from .ttsdeck import TTSDeck -__all__ = ["Book", "CardDB", "Opus", "TTSDeck"] +__all__ = ["Book", "CardDB", "Language", "Opus", "TTSDeck"] diff --git a/fftcg/book.py b/fftcg/book.py index 4f92083..6dc5ba4 100644 --- a/fftcg/book.py +++ b/fftcg/book.py @@ -5,11 +5,12 @@ from PIL import Image from .cards import Cards from .imageloader import ImageLoader +from .language import Language from .utils import GRID, RESOLUTION, CARD_BACK_URL, IMAGES_DIR_NAME class Book: - def __init__(self, cards: Cards, language: str, num_threads: int): + def __init__(self, cards: Cards, language: Language, num_threads: int): logger = logging.getLogger(__name__) # sort cards by element, then alphabetically @@ -18,7 +19,7 @@ class Book: # all card face URLs urls = [ - f"https://fftcg.cdn.sewest.net/images/cards/full/{card.code}_{language}.jpg" + f"https://fftcg.cdn.sewest.net/images/cards/full/{card.code}_{language.image_suffix}.jpg" for card in cards ] # card back URL diff --git a/fftcg/card.py b/fftcg/card.py index 106542b..fbb967d 100644 --- a/fftcg/card.py +++ b/fftcg/card.py @@ -3,6 +3,7 @@ from __future__ import annotations import re from .code import Code +from .language import Language from .utils import encircle_symbol @@ -30,7 +31,7 @@ class Card: self.__index = index @classmethod - def from_square_api_data(cls, data: dict[str, any], language: str) -> Card: + def from_square_api_data(cls, data: dict[str, any], language: Language) -> Card: if not data: return cls( code=Code(""), @@ -46,22 +47,24 @@ class Card: def sub_elements(match: re.Match): return encircle_symbol(Card.__ELEMENTS_MAP[match.group(1)], False) - # load text - text = str(data[f"Text_{language}"]) - # place "S" symbols - text = text.replace("《S》", encircle_symbol("S", False)) - # place other letter and numerical cost symbols - text = re.sub(r"《([\w])》", sub_encircle, text, flags=re.UNICODE) - # place elemental cost symbols - text = re.sub(rf"《([{''.join(Card.__ELEMENTS_JAP)}])》", sub_elements, text, flags=re.UNICODE) - # place dull symbols - text = text.replace("《ダル》", "[⤵]") - # replace formatting hints with brackets - text = re.sub(r"\[\[[a-z]]]([^\[]*?)\s*\[\[/]]\s*", r"[\1] ", text, flags=re.IGNORECASE | re.UNICODE) - # place EX-BURST markers - text = re.sub(r"\[\[ex]]\s*EX BURST\s*\[\[/]]\s*", r"[EX BURST] ", text, flags=re.IGNORECASE | re.UNICODE) - # place line breaks - text = re.sub(r"\s*\[\[br]]\s*", "\n\n", text, flags=re.IGNORECASE | re.UNICODE) + def load_text(language: Language) -> str: + # load text + text = str(data[f"Text{language.key_suffix}"]) + # place "S" symbols + text = text.replace("《S》", encircle_symbol("S", False)) + # place other letter and numerical cost symbols + text = re.sub(r"《([\w])》", sub_encircle, text, flags=re.UNICODE) + # place elemental cost symbols + text = re.sub(rf"《([{''.join(Card.__ELEMENTS_JAP)}])》", sub_elements, text, flags=re.UNICODE) + # place dull symbols + text = text.replace("《ダル》", "[⤵]") + # replace formatting hints with brackets + text = re.sub(r"\[\[[a-z]]]([^\[]*?)\s*\[\[/]]\s*", r"[\1] ", text, flags=re.IGNORECASE | re.UNICODE) + # place EX-BURST markers + text = re.sub(r"\[\[ex]]\s*EX BURST\s*\[\[/]]\s*", r"[EX BURST] ", text, + flags=re.IGNORECASE | re.UNICODE) + # place line breaks + return re.sub(r"\s*\[\[br]]\s*", "\n\n", text, flags=re.IGNORECASE | re.UNICODE) return cls( code=Code(data["Code"]), @@ -69,8 +72,8 @@ class Card: Card.__ELEMENTS_MAP[element] for element in data["Element"].split("/") ], - name=data[f"Name_{language}"], - text=text, + name=data[f"Name{language.key_suffix}"], + text=load_text(language), ) def __repr__(self) -> str: diff --git a/fftcg/language.py b/fftcg/language.py new file mode 100644 index 0000000..ec15b7b --- /dev/null +++ b/fftcg/language.py @@ -0,0 +1,35 @@ +class Language: + def __init__(self, language: str): + language = language.lower() + + # supported languages + if language in ["de", "es", "fr", "ja", "it"]: + self.__short = language + else: + # everything else is english + self.__short = "en" + + def __repr__(self): + return f"Language({self.__short!r})" + + def __str__(self): + return self.__short + + @property + def image_suffix(self): + # supported languages for face URLs + if self.__short in ["de", "es", "fr", "it"]: + return self.__short + else: + return "eg" + + @property + def key_suffix(self): + # supported languages for Square API + if self.__short in ["de", "es", "fr", "it"]: + return f"_{self.__short.upper()}" + elif self.__short == "ja": + return "" + else: + return "_EN" + diff --git a/fftcg/opus.py b/fftcg/opus.py index 627042e..d15828b 100644 --- a/fftcg/opus.py +++ b/fftcg/opus.py @@ -5,28 +5,29 @@ import roman from .card import Card from .cards import Cards +from .language import Language from .ttsdeck import TTSDeck class Opus(Cards): __SQUARE_API_URL = "https://fftcg.square-enix-games.com/de/get-cards" - def __init__(self, opus_id: str): + def __init__(self, opus_id: str, language: Language): logger = logging.getLogger(__name__) params: dict[str, any] if opus_id.isnumeric(): - name = f"Opus {opus_id}" + name = f"Opus {opus_id} ({language})" self.__number = opus_id params = {"set": [f"Opus {roman.toRoman(int(opus_id)).upper()}"]} elif opus_id == "chaos": - name = "Boss Deck Chaos" + name = f"Boss Deck Chaos ({language})" self.__number = "B" - params = {"set": [name]} + params = {"set": ["Boss Deck Chaos"]} elif opus_id == "promo": - name = "Promo" + name = f"Promo ({language})" self.__number = "PR" params = {"rarity": ["pr"]} @@ -49,7 +50,7 @@ class Opus(Cards): # get cards from square api req = requests.post(Opus.__SQUARE_API_URL, json=params) super().__init__(name, [ - Card.from_square_api_data(card_data, "EN") + Card.from_square_api_data(card_data, language) for card_data in req.json()["cards"] ]) @@ -71,7 +72,7 @@ class Opus(Cards): @property def elemental_decks(self) -> list[TTSDeck]: - if self.name in ["Promo", "Boss Deck Chaos"]: + if self.number in ["PR", "B"]: return [TTSDeck( [ card.code diff --git a/main.py b/main.py index bb5e26f..1e453fc 100755 --- a/main.py +++ b/main.py @@ -11,8 +11,8 @@ OUT_DIR_NAME = "out" # name of output directory def opus_decks(args: argparse.Namespace) -> list[fftcg.TTSDeck]: # import an opus - opus = fftcg.Opus(args.opus_id) - book = fftcg.Book(opus, "eg", args.num_requests) + opus = fftcg.Opus(args.opus_id, args.language) + book = fftcg.Book(opus, args.language, args.num_requests) book.save() # load the current carddb @@ -42,6 +42,14 @@ def main() -> None: description="Imports FFTCG cards for TT-Sim.", ) + parser.add_argument( + "-l", "--language", + type=fftcg.Language, + default="en", + metavar="LANGUAGE", + help="lang", + ) + subparsers = parser.add_subparsers( description="Import either an Opus to extend the mod, or import a deck to play right away.", dest="subcommand",