mirror of
https://github.com/ldericher/fftcgtool
synced 2025-01-15 15:02:59 +00:00
Crude multilang support
This commit is contained in:
parent
0b142c394f
commit
c7938c9f0d
6 changed files with 80 additions and 31 deletions
|
@ -1,6 +1,7 @@
|
||||||
from .book import Book
|
from .book import Book
|
||||||
from .carddb import CardDB
|
from .carddb import CardDB
|
||||||
|
from .language import Language
|
||||||
from .opus import Opus
|
from .opus import Opus
|
||||||
from .ttsdeck import TTSDeck
|
from .ttsdeck import TTSDeck
|
||||||
|
|
||||||
__all__ = ["Book", "CardDB", "Opus", "TTSDeck"]
|
__all__ = ["Book", "CardDB", "Language", "Opus", "TTSDeck"]
|
||||||
|
|
|
@ -5,11 +5,12 @@ from PIL import Image
|
||||||
|
|
||||||
from .cards import Cards
|
from .cards import Cards
|
||||||
from .imageloader import ImageLoader
|
from .imageloader import ImageLoader
|
||||||
|
from .language import Language
|
||||||
from .utils import GRID, RESOLUTION, CARD_BACK_URL, IMAGES_DIR_NAME
|
from .utils import GRID, RESOLUTION, CARD_BACK_URL, IMAGES_DIR_NAME
|
||||||
|
|
||||||
|
|
||||||
class Book:
|
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__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# sort cards by element, then alphabetically
|
# sort cards by element, then alphabetically
|
||||||
|
@ -18,7 +19,7 @@ class Book:
|
||||||
|
|
||||||
# all card face URLs
|
# all card face URLs
|
||||||
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
|
for card in cards
|
||||||
]
|
]
|
||||||
# card back URL
|
# card back URL
|
||||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import annotations
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from .code import Code
|
from .code import Code
|
||||||
|
from .language import Language
|
||||||
from .utils import encircle_symbol
|
from .utils import encircle_symbol
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ class Card:
|
||||||
self.__index = index
|
self.__index = index
|
||||||
|
|
||||||
@classmethod
|
@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:
|
if not data:
|
||||||
return cls(
|
return cls(
|
||||||
code=Code(""),
|
code=Code(""),
|
||||||
|
@ -46,8 +47,9 @@ class Card:
|
||||||
def sub_elements(match: re.Match):
|
def sub_elements(match: re.Match):
|
||||||
return encircle_symbol(Card.__ELEMENTS_MAP[match.group(1)], False)
|
return encircle_symbol(Card.__ELEMENTS_MAP[match.group(1)], False)
|
||||||
|
|
||||||
|
def load_text(language: Language) -> str:
|
||||||
# load text
|
# load text
|
||||||
text = str(data[f"Text_{language}"])
|
text = str(data[f"Text{language.key_suffix}"])
|
||||||
# place "S" symbols
|
# place "S" symbols
|
||||||
text = text.replace("《S》", encircle_symbol("S", False))
|
text = text.replace("《S》", encircle_symbol("S", False))
|
||||||
# place other letter and numerical cost symbols
|
# place other letter and numerical cost symbols
|
||||||
|
@ -59,9 +61,10 @@ class Card:
|
||||||
# replace formatting hints with brackets
|
# replace formatting hints with brackets
|
||||||
text = re.sub(r"\[\[[a-z]]]([^\[]*?)\s*\[\[/]]\s*", r"[\1] ", text, flags=re.IGNORECASE | re.UNICODE)
|
text = re.sub(r"\[\[[a-z]]]([^\[]*?)\s*\[\[/]]\s*", r"[\1] ", text, flags=re.IGNORECASE | re.UNICODE)
|
||||||
# place EX-BURST markers
|
# place EX-BURST markers
|
||||||
text = re.sub(r"\[\[ex]]\s*EX BURST\s*\[\[/]]\s*", r"[EX BURST] ", text, flags=re.IGNORECASE | re.UNICODE)
|
text = re.sub(r"\[\[ex]]\s*EX BURST\s*\[\[/]]\s*", r"[EX BURST] ", text,
|
||||||
|
flags=re.IGNORECASE | re.UNICODE)
|
||||||
# place line breaks
|
# place line breaks
|
||||||
text = 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)
|
||||||
|
|
||||||
return cls(
|
return cls(
|
||||||
code=Code(data["Code"]),
|
code=Code(data["Code"]),
|
||||||
|
@ -69,8 +72,8 @@ class Card:
|
||||||
Card.__ELEMENTS_MAP[element]
|
Card.__ELEMENTS_MAP[element]
|
||||||
for element in data["Element"].split("/")
|
for element in data["Element"].split("/")
|
||||||
],
|
],
|
||||||
name=data[f"Name_{language}"],
|
name=data[f"Name{language.key_suffix}"],
|
||||||
text=text,
|
text=load_text(language),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
|
|
35
fftcg/language.py
Normal file
35
fftcg/language.py
Normal file
|
@ -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"
|
||||||
|
|
|
@ -5,28 +5,29 @@ import roman
|
||||||
|
|
||||||
from .card import Card
|
from .card import Card
|
||||||
from .cards import Cards
|
from .cards import Cards
|
||||||
|
from .language import Language
|
||||||
from .ttsdeck import TTSDeck
|
from .ttsdeck import TTSDeck
|
||||||
|
|
||||||
|
|
||||||
class Opus(Cards):
|
class Opus(Cards):
|
||||||
__SQUARE_API_URL = "https://fftcg.square-enix-games.com/de/get-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__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
params: dict[str, any]
|
params: dict[str, any]
|
||||||
if opus_id.isnumeric():
|
if opus_id.isnumeric():
|
||||||
name = f"Opus {opus_id}"
|
name = f"Opus {opus_id} ({language})"
|
||||||
self.__number = opus_id
|
self.__number = opus_id
|
||||||
params = {"set": [f"Opus {roman.toRoman(int(opus_id)).upper()}"]}
|
params = {"set": [f"Opus {roman.toRoman(int(opus_id)).upper()}"]}
|
||||||
|
|
||||||
elif opus_id == "chaos":
|
elif opus_id == "chaos":
|
||||||
name = "Boss Deck Chaos"
|
name = f"Boss Deck Chaos ({language})"
|
||||||
self.__number = "B"
|
self.__number = "B"
|
||||||
params = {"set": [name]}
|
params = {"set": ["Boss Deck Chaos"]}
|
||||||
|
|
||||||
elif opus_id == "promo":
|
elif opus_id == "promo":
|
||||||
name = "Promo"
|
name = f"Promo ({language})"
|
||||||
self.__number = "PR"
|
self.__number = "PR"
|
||||||
params = {"rarity": ["pr"]}
|
params = {"rarity": ["pr"]}
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ 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, [
|
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"]
|
for card_data in req.json()["cards"]
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ class Opus(Cards):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def elemental_decks(self) -> list[TTSDeck]:
|
def elemental_decks(self) -> list[TTSDeck]:
|
||||||
if self.name in ["Promo", "Boss Deck Chaos"]:
|
if self.number in ["PR", "B"]:
|
||||||
return [TTSDeck(
|
return [TTSDeck(
|
||||||
[
|
[
|
||||||
card.code
|
card.code
|
||||||
|
|
12
main.py
12
main.py
|
@ -11,8 +11,8 @@ OUT_DIR_NAME = "out" # name of output directory
|
||||||
|
|
||||||
def opus_decks(args: argparse.Namespace) -> list[fftcg.TTSDeck]:
|
def opus_decks(args: argparse.Namespace) -> list[fftcg.TTSDeck]:
|
||||||
# import an opus
|
# import an opus
|
||||||
opus = fftcg.Opus(args.opus_id)
|
opus = fftcg.Opus(args.opus_id, args.language)
|
||||||
book = fftcg.Book(opus, "eg", args.num_requests)
|
book = fftcg.Book(opus, args.language, args.num_requests)
|
||||||
book.save()
|
book.save()
|
||||||
|
|
||||||
# load the current carddb
|
# load the current carddb
|
||||||
|
@ -42,6 +42,14 @@ def main() -> None:
|
||||||
description="Imports FFTCG cards for TT-Sim.",
|
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(
|
subparsers = parser.add_subparsers(
|
||||||
description="Import either an Opus to extend the mod, or import a deck to play right away.",
|
description="Import either an Opus to extend the mod, or import a deck to play right away.",
|
||||||
dest="subcommand",
|
dest="subcommand",
|
||||||
|
|
Loading…
Reference in a new issue