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

inverted book.yml; card text formatting

This commit is contained in:
Jörn-Michael Miehe 2021-08-16 13:17:24 +02:00
parent eed07e4bb0
commit 2946bc81e4
5 changed files with 140 additions and 61 deletions

View file

@ -4,6 +4,7 @@ import yaml
from PIL import Image
from .cards import Cards
from .code import Code
from .grid import Grid
from .imageloader import ImageLoader
@ -55,24 +56,39 @@ class Book:
return self.__pages[index]["image"]
def save(self, filename: str) -> None:
pages: dict[str, dict[str, any]]
book: dict[str, dict[str, any]]
# load pages.yml file
# load book.yml file
try:
with open("pages.yml", "r") as file:
pages = yaml.load(file, Loader=yaml.Loader)
with open("book.yml", "r") as file:
book = yaml.load(file, Loader=yaml.Loader)
except FileNotFoundError:
pages = {}
book = {}
# save book
for i, page in enumerate(self.__pages):
fn = f"{filename}_{i}.jpg"
# save page image
page["image"].save(fn)
# add contents of image
pages[fn] = {}
pages[fn]["cards"] = page["cards"]
# add contents of that image
book[fn] = {"cards": page["cards"]}
# update pages.yml file
with open("pages.yml", "w") as file:
yaml.dump(pages, file, Dumper=yaml.Dumper)
# update book.yml file
with open("book.yml", "w") as file:
yaml.dump(book, file, Dumper=yaml.Dumper)
# invert book
inverse_book: dict[Code, dict[str, any]] = {}
for fn, content in book.items():
inverse_book |= {
str(card.code): {
"card": card,
"file": fn,
"index": i
} for i, card in enumerate(content["cards"])
}
# write inverse_book.yml file
with open("inverse_book.yml", "w") as file:
yaml.dump(inverse_book, file, Dumper=yaml.Dumper)

View file

@ -3,6 +3,32 @@ import re
import yaml
from .code import Code
def encircle_symbol(symbol: str, negative: bool):
symbol = symbol[0].upper()
base_symbols: tuple[str, str] = "", ""
if symbol.isalpha():
if negative:
base_symbols = "A", "🅐"
else:
base_symbols = "A", ""
elif symbol == "0":
if negative:
base_symbols = "0", "🄌"
else:
base_symbols = "0", ""
elif symbol.isnumeric():
if negative:
base_symbols = "1", ""
else:
base_symbols = "1", ""
symbol_num = ord(symbol) - ord(base_symbols[0])
return chr(ord(base_symbols[1]) + symbol_num)
class Card(yaml.YAMLObject):
yaml_tag = u'!Card'
@ -18,10 +44,10 @@ class Card(yaml.YAMLObject):
"": "Darkness"
}
def __init__(self, opus, serial, rarity, elements, name, text):
self.__opus = opus
self.__serial = serial
self.__rarity = rarity
__ELEMENTS = "".join(__ELEMENTS_MAP.keys())
def __init__(self, code, elements, name, text):
self.__code = code
self.__elements = elements
self.__name = name
self.__text = text
@ -30,44 +56,41 @@ class Card(yaml.YAMLObject):
def from_data(cls, data: dict[str, any], language: str):
if not data:
return cls(
opus="0",
serial="000",
rarity="X",
code=Code(""),
elements=[],
name=None,
text=None,
)
else:
if str(data["Code"])[0].isnumeric():
# card code starts with a number
opus, serial, rarity = \
re.match(r"([0-9]+)-([0-9]+)([CRHLS])", data["Code"]).groups()
def sub_encircle(match: re.Match):
return encircle_symbol(match.group(1), True)
elif str(data["Code"]).startswith("PR"):
# card code starts with "PR"
opus, serial = \
re.match(r"(PR)-([0-9]+)", data["Code"]).groups()
rarity = ""
def sub_elements(match: re.Match):
return encircle_symbol(Card.__ELEMENTS_MAP[match.group(1)], True)
elif str(data["Code"]).startswith("B"):
# card code starts with "B"
opus, serial = \
re.match(r"(B)-([0-9]+)", data["Code"]).groups()
rarity = ""
else:
# card code not recognized
opus, serial, rarity = \
"?", "???", "?"
# 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"《([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)
# 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)
# place EX-BURST markers
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)
return cls(
opus=opus,
serial=serial,
rarity=rarity,
code=Code(data["Code"]),
elements=[Card.__ELEMENTS_MAP[element] for element in data["Element"].split("/")],
name=data[f"Name_{language}"],
text=data[f"Text_{language}"],
text=text,
)
def __str__(self) -> str:
@ -78,20 +101,8 @@ class Card(yaml.YAMLObject):
# 6-048C
@property
def code(self) -> str:
return f"{self.__opus}-{self.__serial}{self.__rarity}"
@property
def opus(self) -> str:
return self.__opus
@property
def serial(self) -> int:
return int(self.__serial)
@property
def rarity(self) -> str:
return self.__rarity
def code(self) -> Code:
return self.__code
@property
def name(self) -> str:

View file

@ -6,7 +6,7 @@ from .card import Card
class Cards(list[Card]):
__API_URL = "https://fftcg.square-enix-games.com/de/get-cards"
def __init__(self, params: dict[str, any]):
def _load(self, params: dict[str, any]):
# required params:
# text
# supported params:
@ -18,7 +18,8 @@ class Cards(list[Card]):
params["text"] = ""
req = requests.post(Cards.__API_URL, json=params)
super().__init__([Card.from_data(card_data, "EN") for card_data in req.json()["cards"]])
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)

49
fftcg/code.py Normal file
View file

@ -0,0 +1,49 @@
import re
import yaml
class Code(yaml.YAMLObject):
yaml_tag = u'!Code'
__RE_NUM = re.compile(r"([0-9]+)-([0-9]+)([CRHLS])")
__RE_PROMO = re.compile(r"(PR)-([0-9]+)")
__RE_BOSS = re.compile(r"(B)-([0-9]+)")
def __init__(self, code: str):
if code[0].isnumeric():
# card code starts with a number
self.__opus, self.__serial, self.__rarity = \
Code.__RE_NUM.match(code).groups()
elif code.startswith("PR"):
# card code starts with "PR"
self.__opus, self.__serial = \
Code.__RE_PROMO.match(code).groups()
self.__rarity = ""
elif code.startswith("B"):
# card code starts with "B"
self.__opus, self.__serial = \
Code.__RE_BOSS.match(code).groups()
self.__rarity = ""
else:
# card code not recognized
self.__opus, self.__serial, self.__rarity = \
"?", "???", "?"
def __str__(self) -> str:
return f"{self.__opus}-{self.__serial}{self.__rarity}"
@property
def opus(self) -> str:
return self.__opus
@property
def serial(self) -> int:
return int(self.__serial)
@property
def rarity(self) -> str:
return self.__rarity

View file

@ -7,6 +7,8 @@ from .cards import Cards
class Opus(Cards):
def __init__(self, opus_id: str):
super().__init__()
logger = logging.getLogger(__name__)
if opus_id.isnumeric():
@ -33,16 +35,16 @@ class Opus(Cards):
self.__filename = "?"
params = {"set": "?"}
super().__init__(params)
self._load(params)
# remove reprints
for card in self:
if not card.code.startswith(self.__number + "-"):
if not card.code.opus == self.__number:
self.remove(card)
# sort cards by opus, then serial
self.sort(key=lambda x: x.serial)
self.sort(key=lambda x: x.opus)
self.sort(key=lambda x: x.code.serial)
self.sort(key=lambda x: x.code.opus)
for card in self:
logger.info(f"imported card {card}")