diff --git a/fftcg/book.py b/fftcg/book.py index 583bf78..f7dfdae 100644 --- a/fftcg/book.py +++ b/fftcg/book.py @@ -5,7 +5,7 @@ from PIL import Image from .cards import Cards from .imageloader import ImageLoader -from .utils import GRID, RESOLUTION, BOOK_YML_NAME +from .utils import GRID, RESOLUTION, BOOK_YML_NAME, CARD_BACK_URL class Book: @@ -18,10 +18,8 @@ class Book: # all card face URLs urls = [f"https://fftcg.cdn.sewest.net/images/cards/full/{card.code}_{language}.jpg" for card in cards] - # card back URL (image by Aurik) - urls.append( - "http://cloud-3.steamusercontent.com/ugc/948455238665576576/85063172B8C340602E8D6C783A457122F53F7843/" - ) + # card back URL + urls.append(CARD_BACK_URL) # multi-threaded download images = ImageLoader.load(urls, language, num_threads) diff --git a/fftcg/card.py b/fftcg/card.py index ea8b014..04edd83 100644 --- a/fftcg/card.py +++ b/fftcg/card.py @@ -1,6 +1,5 @@ from __future__ import annotations -import json import re import yaml @@ -23,8 +22,6 @@ class Card(yaml.YAMLObject): "闇": "Darkness" } - __ELEMENTS = "".join(__ELEMENTS_MAP.keys()) - def __init__(self, code, elements, name, text): self.__code = code self.__elements = elements @@ -55,15 +52,15 @@ class Card(yaml.YAMLObject): # place other letter and numerical cost symbols text = re.sub(r"《([a-z0-9])》", sub_encircle, text, flags=re.IGNORECASE) # place elemental cost symbols - text = re.sub(rf"《([{Card.__ELEMENTS}])》", sub_elements, text, flags=re.IGNORECASE) + text = re.sub(rf"《([{''.join(Card.__ELEMENTS_MAP.keys())}])》", sub_elements, text, flags=re.IGNORECASE) # 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) + text = re.sub(r"\[\[[a-z]]]([^\[]*?)\s*\[\[/]]\s*", r"[\1] ", text, flags=re.IGNORECASE) # place EX-BURST markers - text = re.sub(r"\[\[ex\]\]\s*EX BURST\s*\[\[/\]\]\s*", r"[EX BURST] ", text, flags=re.IGNORECASE) + text = re.sub(r"\[\[ex]]\s*EX BURST\s*\[\[/]]\s*", r"[EX BURST] ", text, flags=re.IGNORECASE) # place line breaks - text = re.sub(r"\s*\[\[br\]\]\s*", "\n\n", text, flags=re.IGNORECASE) + text = re.sub(r"\s*\[\[br]]\s*", "\n\n", text, flags=re.IGNORECASE) return cls( code=Code(data["Code"]), @@ -75,9 +72,6 @@ class Card(yaml.YAMLObject): def __str__(self) -> str: return f"'{self.__name}' ({'/'.join(self.__elements)}, {self.code})" - def to_json(self) -> str: - return json.dumps(self, default=lambda o: o.__dict__) - # 6-048C @property def code(self) -> Code: diff --git a/fftcg/cards.py b/fftcg/cards.py index 3cc1162..eb4c27e 100644 --- a/fftcg/cards.py +++ b/fftcg/cards.py @@ -6,6 +6,22 @@ from .card import Card class Cards(list[Card]): __API_URL = "https://fftcg.square-enix-games.com/de/get-cards" + def __init__(self, name): + super().__init__() + + self.__name = name + + def __str__(self) -> str: + return f"[{', '.join(str(card) for card in self)}]" + + @property + def name(self) -> str: + return self.__name + + @property + def file_name(self) -> str: + return self.name.lower().replace(" ", "_") + def _load(self, params: dict[str, any]): # required params: # text @@ -20,6 +36,3 @@ class Cards(list[Card]): req = requests.post(Cards.__API_URL, json=params) self.clear() self.extend([Card.from_data(card_data, "EN") for card_data in req.json()["cards"]]) - - def __str__(self) -> str: - return "\n".join(str(card) for card in self) diff --git a/fftcg/opus.py b/fftcg/opus.py index 6f3cd76..1cdaf0f 100644 --- a/fftcg/opus.py +++ b/fftcg/opus.py @@ -8,34 +8,31 @@ from .ttsdeck import TTSDeck class Opus(Cards): def __init__(self, opus_id: str): - super().__init__() logger = logging.getLogger(__name__) if opus_id.isnumeric(): - self.__name = f"Opus {roman.toRoman(int(opus_id)).upper()}" + name = f"Opus {opus_id}" self.__number = opus_id - self.__filename = f"opus_{opus_id}" - params = {"set": [self.__name]} + params = {"set": [f"Opus {roman.toRoman(int(opus_id)).upper()}"]} elif opus_id == "chaos": - self.__name = "Boss Deck Chaos" + name = "Boss Deck Chaos" self.__number = "B" - self.__filename = "boss_deck_chaos" - params = {"set": [self.__name]} + params = {"set": [name]} elif opus_id == "promo": - self.__name = "Promo" + name = "Promo" self.__number = "PR" - self.__filename = "promo" params = {"rarity": ["pr"]} else: - self.__name = "?" + name = "?" self.__number = "?" self.__filename = "?" params = {"set": "?"} + super().__init__(name) self._load(params) # remove reprints @@ -50,25 +47,21 @@ class Opus(Cards): for card in self: logger.info(f"imported card {card}") - @property - def name(self) -> str: - return self.__name - @property def number(self) -> str: return self.__number - @property - def filename(self) -> str: - return self.__filename - @property def elemental_decks(self) -> list[TTSDeck]: if self.name in ["Promo", "Boss Deck Chaos"]: - return [TTSDeck([ - card.code - for card in self - ])] + return [TTSDeck( + [ + card.code + for card in self + ], + f"{self.name}", + f"All {self.name} Cards in elemental, then alphabetical order" + )] else: def element_filter(element: str): @@ -76,17 +69,21 @@ class Opus(Cards): # simple cases: create lambdas for base elemental decks base_elements = ["Fire", "Ice", "Wind", "Earth", "Lightning", "Water"] - filters = [element_filter(elem) for elem in base_elements] + filters = {elem: element_filter(elem) for elem in base_elements} - filters += [ + filters |= { # light/darkness elemental deck - lambda card: card.elements == ["Light"] or card.elements == ["Darkness"], + "Light/Darkness": lambda card: card.elements == ["Light"] or card.elements == ["Darkness"], # multi element deck - lambda card: len(card.elements) > 1, - ] + "Multi": lambda card: len(card.elements) > 1, + } - return [TTSDeck([ - card.code - for card in self - if f(card) - ]) for f in filters] + return [TTSDeck( + [ + card.code + for card in self + if f(card) + ], + f"{self.name} {elem}", + f"All {self.name} Cards with {elem} element in alphabetical order" + ) for elem, f in filters.items()] diff --git a/fftcg/ttsdeck.py b/fftcg/ttsdeck.py index ba85350..eef0897 100644 --- a/fftcg/ttsdeck.py +++ b/fftcg/ttsdeck.py @@ -2,13 +2,17 @@ import json from .carddb import CardDB from .code import Code +from .utils import CARD_BACK_URL class TTSDeck(list[dict[str, any]]): - def __init__(self, codes: list[Code]): + def __init__(self, codes: list[Code], name: str, description: str): carddb = CardDB.get() super().__init__([carddb[code] for code in codes]) + self.__name = name + self.__description = description + def __str__(self) -> str: face_urls = list(set([entry["file"] for entry in self])) @@ -17,7 +21,7 @@ class TTSDeck(list[dict[str, any]]): "NumWidth": "10", "NumHeight": "7", "FaceURL": url, - "BackURL": "http://cloud-3.steamusercontent.com/ugc/948455238665576576/85063172B8C340602E8D6C783A457122F53F7843/", + "BackURL": CARD_BACK_URL, } for i, url in enumerate(face_urls) } @@ -63,8 +67,8 @@ class TTSDeck(list[dict[str, any]]): jsondict = {"ObjectStates": [ { "Name": "Deck", - "Nickname": "TODO Deck Name", - "Description": "TODO Deck Description", + "Nickname": self.__name, + "Description": self.__description, "Hands": False, "SidewaysCard": False, @@ -76,3 +80,6 @@ class TTSDeck(list[dict[str, any]]): ]} return json.dumps(jsondict, indent=2) + + def save(self, file_name: str) -> None: + pass diff --git a/fftcg/utils.py b/fftcg/utils.py index 6024bf9..a21f1df 100644 --- a/fftcg/utils.py +++ b/fftcg/utils.py @@ -4,6 +4,8 @@ from .grid import Grid GRID = Grid((10, 7)) # default in TTsim: 10 columns, 7 rows RESOLUTION = Grid((429, 600)) # default in TTsim: 480x670 pixels per card BOOK_YML_NAME = "book.yml" +# card back URL (image by Aurik) +CARD_BACK_URL = "http://cloud-3.steamusercontent.com/ugc/948455238665576576/85063172B8C340602E8D6C783A457122F53F7843/" # functions diff --git a/main.py b/main.py index 1586f95..11ede61 100755 --- a/main.py +++ b/main.py @@ -41,12 +41,13 @@ def main() -> None: # main program opus = fftcg.Opus(args.opus_id) book = fftcg.Book(opus, "eg", args.num_threads) - book.save(opus.filename) + book.save(opus.file_name) - # create elemental decks for opus + # load the current carddb carddb = fftcg.CardDB.get() carddb.load() + # create elemental decks for opus for deck in opus.elemental_decks: print(deck)