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:
parent
eed07e4bb0
commit
2946bc81e4
5 changed files with 140 additions and 61 deletions
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
49
fftcg/code.py
Normal 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
|
|
@ -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}")
|
||||
|
|
Loading…
Reference in a new issue