1
0
Fork 0
mirror of https://github.com/ldericher/fftcgtool synced 2025-01-15 15:02:59 +00:00

multilanguage support (breaks upload prompt)

This commit is contained in:
Jörn-Michael Miehe 2021-09-01 19:01:53 +02:00
parent 77bc884eb6
commit 6ae0e00c2c
7 changed files with 81 additions and 70 deletions

View file

@ -1,5 +1,6 @@
import logging import logging
import os import os
from dataclasses import replace
from PIL import Image from PIL import Image
@ -14,8 +15,8 @@ class Book:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# sort cards by element, then alphabetically # sort cards by element, then alphabetically
cards.sort(key=lambda x: x.name) # cards.sort(key=lambda x: x[""].name)
cards.sort(key=lambda x: "Multi" if len(x.elements) > 1 else x.elements[0]) # cards.sort(key=lambda x: "Multi" if len(x.elements) > 1 else x.elements[0])
# all card face URLs # all card face URLs
urls = [ urls = [
@ -35,6 +36,8 @@ class Book:
for page_num, (page_images, page_cards) in enumerate(zip( for page_num, (page_images, page_cards) in enumerate(zip(
chunks(GRID.capacity, images), chunks(GRID.capacity, cards) chunks(GRID.capacity, images), chunks(GRID.capacity, cards)
)): )):
file_name = f"{cards.file_name}_{page_num}.jpg"
# create book page Image # create book page Image
page_image = Image.new("RGB", GRID * RESOLUTION) page_image = Image.new("RGB", GRID * RESOLUTION)
logger.info(f"New image: {page_image.size[0]}x{page_image.size[1]}") logger.info(f"New image: {page_image.size[0]}x{page_image.size[1]}")
@ -49,10 +52,11 @@ class Book:
# set card indices # set card indices
for i, card in enumerate(page_cards): for i, card in enumerate(page_cards):
card.index = i card.index = i
card[language] = replace(card[language], face=file_name)
# save page # save page
self.__pages.append({ self.__pages.append({
"file_name": f"{cards.file_name}_{page_num}.jpg", "file_name": file_name,
"image": page_image, "image": page_image,
"cards": page_cards, "cards": page_cards,
}) })
@ -65,13 +69,3 @@ class Book:
for page in self.__pages: for page in self.__pages:
page["file_name"] = os.path.join(IMAGES_DIR_NAME, page["file_name"]) page["file_name"] = os.path.join(IMAGES_DIR_NAME, page["file_name"])
page["image"].save(page["file_name"]) page["image"].save(page["file_name"])
# ask for upload
for page in self.__pages:
face_url = input(f"Upload '{page['file_name']}' and paste URL: ")
if not face_url:
face_url = f"file://{os.path.abspath(page['file_name'])}"
for card in page["cards"]:
card.face_url = face_url

View file

@ -1,12 +1,20 @@
from __future__ import annotations from __future__ import annotations
import re import re
from dataclasses import dataclass
from .code import Code from .code import Code
from .language import Language from .language import Language
from .utils import encircle_symbol from .utils import encircle_symbol
@dataclass(frozen=True)
class CardContent:
name: str
text: str
face: str
class Card: class Card:
__ELEMENTS_JAP = [ __ELEMENTS_JAP = [
"", "", "", "", "", "", "", "" "", "", "", "", "", "", "", ""
@ -21,23 +29,19 @@ class Card:
for elem_j, elem_e in zip(__ELEMENTS_JAP, __ELEMENTS_ENG) for elem_j, elem_e in zip(__ELEMENTS_JAP, __ELEMENTS_ENG)
} }
def __init__(self, code: Code, elements: list[str], name: str, text: str, face_url: str = "", index: int = 0): def __init__(self, code: Code, elements: list[str], content: dict[Language, CardContent], index: int = 0):
self.__code = code self.__code: Code = code
self.__elements = elements self.__elements: list[str] = elements
self.__name = name self.__content: dict[Language, CardContent] = content
self.__text = text
self.__face_url = face_url
self.__index = index self.__index = index
@classmethod @classmethod
def from_square_api_data(cls, data: dict[str, any], language: Language) -> Card: def from_square_api_data(cls, data: dict[str, any]) -> Card:
if not data: if not data:
return cls( return cls(
code=Code(""), code=Code(""),
elements=[], elements=[],
name="", content={},
text="",
) )
else: else:
@ -69,47 +73,48 @@ class Card:
# place line breaks # place line breaks
return re.sub(r"\s*\[\[br]]\s*", "\n\n", text, flags=re.IGNORECASE | re.UNICODE) return re.sub(r"\s*\[\[br]]\s*", "\n\n", text, flags=re.IGNORECASE | re.UNICODE)
content = {
language: CardContent(load_name(language), load_text(language), "")
for language in Language.all_api_langs()
}
return cls( return cls(
code=Code(data["Code"]), code=Code(data["Code"]),
elements=[ elements=[
Card.__ELEMENTS_MAP[element] Card.__ELEMENTS_MAP[element]
for element in data["Element"].split("/") for element in data["Element"].split("/")
], ],
name=load_name(language), content=content,
text=load_text(language),
) )
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Card(code={self.code!r}, name={self.name!r}, face_url={self.face_url!r})" return f"Card(code={self.code!r}, content={self.__content!r})"
def __str__(self) -> str: def __str__(self) -> str:
return f"'{self.__name}' ({'/'.join(self.__elements)}, {self.code})" if self.__content:
return f"'{self[''].name}' ({'/'.join(self.__elements)}, {self.code})"
def __getitem__(self, item: Language | str) -> CardContent:
if isinstance(item, Language):
return self.__content[item]
else:
return self.__content[Language(item)]
def __setitem__(self, key: Language | str, value: CardContent) -> None:
if isinstance(key, Language):
self.__content[key] = value
else:
self.__content[Language(key)] = value
# 6-048C # 6-048C
@property @property
def code(self) -> Code: def code(self) -> Code:
return self.__code return self.__code
@property
def name(self) -> str:
return self.__name
@property
def text(self) -> str:
return self.__text
@property @property
def elements(self) -> list[str]: def elements(self) -> list[str]:
return self.__elements return self.__elements
@property
def face_url(self) -> str:
return self.__face_url
@face_url.setter
def face_url(self, face_url: str) -> None:
self.__face_url = face_url
@property @property
def index(self) -> int: def index(self) -> int:
return self.__index return self.__index

View file

@ -30,6 +30,9 @@ class Code:
object.__setattr__(self, "serial", serial) object.__setattr__(self, "serial", serial)
object.__setattr__(self, "rarity", rarity) object.__setattr__(self, "rarity", rarity)
def __str__(self) -> str:
return self.long
@property @property
def short(self) -> str: def short(self) -> str:
return f"{self.opus}-{self.serial:03}" return f"{self.opus}-{self.serial:03}"

View file

@ -35,3 +35,10 @@ class Language:
return "" return ""
else: else:
return "_EN" return "_EN"
@classmethod
def all_api_langs(cls) -> set[Language]:
return set([
cls(short)
for short in ["de", "en", "es", "fr", "it", "ja"]
])

View file

@ -49,15 +49,17 @@ class Opus(Cards):
# get cards from square api # get cards from square api
req = requests.post(Opus.__SQUARE_API_URL, json=params) req = requests.post(Opus.__SQUARE_API_URL, json=params)
super().__init__(name, [ cards = [
Card.from_square_api_data(card_data, language) Card.from_square_api_data(card_data)
for card_data in req.json()["cards"] for card_data in req.json()["cards"]
]) ]
# remove reprints # remove reprints
for card in self: super().__init__(name, [
if not card.code.opus == self.__number: card
self.remove(card) for card in cards
if card.code.opus == self.__number
])
# sort cards by opus, then serial # sort cards by opus, then serial
self.sort(key=lambda x: x.code.serial) self.sort(key=lambda x: x.code.serial)

View file

@ -8,6 +8,7 @@ import requests
from .carddb import CardDB from .carddb import CardDB
from .cards import Cards from .cards import Cards
from .code import Code from .code import Code
from .language import Language
from .utils import CARD_BACK_URL, DECKS_DIR_NAME from .utils import CARD_BACK_URL, DECKS_DIR_NAME
@ -23,18 +24,6 @@ class TTSDeck(Cards):
for code in codes for code in codes
]) ])
# unique face urls used
unique_face_urls = set([
card.face_url
for card in self
])
# lookup for indices of urls
self.__url_indices = {
url: i + 1
for i, url in enumerate(unique_face_urls)
}
__FFDECKS_API_URL = "https://ffdecks.com/api/deck" __FFDECKS_API_URL = "https://ffdecks.com/api/deck"
@classmethod @classmethod
@ -49,8 +38,19 @@ class TTSDeck(Cards):
return cls(codes, name, description) return cls(codes, name, description)
@property def tts_object(self, language: Language) -> dict[str, any]:
def tts_object(self) -> dict[str, any]: # unique face urls used
unique_faces = set([
card[language].face
for card in self
])
# lookup for indices of urls
url_indices = {
url: i + 1
for i, url in enumerate(unique_faces)
}
# build the "CustomDeck" dictionary # build the "CustomDeck" dictionary
custom_deck = { custom_deck = {
str(i): { str(i): {
@ -58,7 +58,7 @@ class TTSDeck(Cards):
"NumHeight": "7", "NumHeight": "7",
"FaceURL": url, "FaceURL": url,
"BackURL": CARD_BACK_URL, "BackURL": CARD_BACK_URL,
} for url, i in self.__url_indices.items() } for url, i in url_indices.items()
} }
# values both in main deck and each contained card # values both in main deck and each contained card
@ -81,9 +81,9 @@ class TTSDeck(Cards):
# cards contained in deck # cards contained in deck
contained_objects = [ contained_objects = [
{ {
"Nickname": card.name, "Nickname": card[language].name,
"Description": card.text, "Description": card[language].text,
"CardID": 100 * self.__url_indices[card.face_url] + card.index, "CardID": 100 * url_indices[card[language].face] + card.index,
"Name": "Card", "Name": "Card",
"Hands": True, "Hands": True,
@ -112,11 +112,11 @@ class TTSDeck(Cards):
} | common_dict } | common_dict
]} ]}
def save(self) -> None: def save(self, language: Language) -> None:
# only save if the deck contains cards # only save if the deck contains cards
if self: if self:
if not os.path.exists(DECKS_DIR_NAME): if not os.path.exists(DECKS_DIR_NAME):
os.mkdir(DECKS_DIR_NAME) os.mkdir(DECKS_DIR_NAME)
with open(os.path.join(DECKS_DIR_NAME, f"{self.file_name}.json"), "w") as file: with open(os.path.join(DECKS_DIR_NAME, f"{self.file_name}.json"), "w") as file:
json.dump(self.tts_object, file, indent=2) json.dump(self.tts_object(language), file, indent=2)

View file

@ -143,7 +143,7 @@ def main() -> None:
# call function based on args # call function based on args
for deck in args.func(args): for deck in args.func(args):
deck.save() deck.save(args.language)
# bye # bye
print("Done. Put the generated JSON files in your 'Saved Objects' Folder.") print("Done. Put the generated JSON files in your 'Saved Objects' Folder.")