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

dataclass decorator for code and language, remove clutter from grid

This commit is contained in:
Jörn-Michael Miehe 2021-08-25 16:13:07 +02:00
parent 9c6b784c18
commit 77bc884eb6
6 changed files with 64 additions and 89 deletions

View file

@ -6,7 +6,7 @@ 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 .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, chunks, grid_paste
class Book: class Book:
@ -19,7 +19,7 @@ class Book:
# all card face URLs # all card face URLs
urls = [ urls = [
("https://fftcg.cdn.sewest.net/images/cards/full/{}_{}.jpg", str(card.code), language.image_suffix) ("https://fftcg.cdn.sewest.net/images/cards/full/{}_{}.jpg", card.code.long, language.image_suffix)
for card in cards for card in cards
] ]
# card back URL # card back URL
@ -32,17 +32,19 @@ class Book:
self.__pages = [] self.__pages = []
for page_num, (page_images, page_cards) in enumerate(zip(GRID.chunks(images), GRID.chunks(cards))): for page_num, (page_images, page_cards) in enumerate(zip(
chunks(GRID.capacity, images), chunks(GRID.capacity, cards)
)):
# 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]}")
# paste card faces onto page # paste card faces onto page
for i, image in enumerate(page_images): for i, image in enumerate(page_images):
GRID.paste(page_image, i, image) grid_paste(page_image, i, image)
# paste card back in last position # paste card back in last position
GRID.paste(page_image, GRID.capacity, back_image) grid_paste(page_image, GRID.capacity, back_image)
# set card indices # set card indices
for i, card in enumerate(page_cards): for i, card in enumerate(page_cards):

View file

@ -1,60 +1,39 @@
from __future__ import annotations from __future__ import annotations
import re import re
from dataclasses import dataclass, InitVar, field
@dataclass(frozen=True)
class Code: class Code:
__RE_NUM = re.compile(r"([0-9]+)-([0-9]+)([CRHLS]?)") opus: str = field(init=False)
__RE_PROMO = re.compile(r"(PR)-([0-9]+)") serial: int = field(init=False)
__RE_BOSS = re.compile(r"(B)-([0-9]+)") rarity: str = field(init=False, compare=False)
code_init: InitVar[str] = field(default="")
def __init__(self, code: str): __RE = re.compile(r"([1-9][0-9]*|PR|B)-([0-9]+)([CRHLS]?)", flags=re.UNICODE)
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"): def __post_init__(self, code_init: str):
# card code starts with "PR" match = Code.__RE.match(code_init)
self.__opus, self.__serial = \
Code.__RE_PROMO.match(code).groups()
self.__rarity = ""
elif code.startswith("B"): if match is not None:
# card code starts with "B" groups = match.groups()
self.__opus, self.__serial = \ opus, serial, rarity = \
Code.__RE_BOSS.match(code).groups() groups[0], int(groups[1]), groups[2]
self.__rarity = ""
else: else:
# card code not recognized # card code not recognized
self.__opus, self.__serial, self.__rarity = \ opus, serial, rarity = \
"?", "???", "?" "?", 0, "?"
def __str__(self) -> str: object.__setattr__(self, "opus", opus)
return f"{self.__opus}-{self.__serial}{self.__rarity}" object.__setattr__(self, "serial", serial)
object.__setattr__(self, "rarity", rarity)
def __repr__(self) -> str:
return f"Code({str(self)!r})"
def __hash__(self) -> hash:
return hash(self.short)
def __eq__(self, other: Code):
return self.short == other.short
@property @property
def short(self) -> str: def short(self) -> str:
return f"{self.__opus}-{self.__serial}" return f"{self.opus}-{self.serial:03}"
@property @property
def opus(self) -> str: def long(self) -> str:
return self.__opus return f"{self.short}{self.rarity}"
@property
def serial(self) -> int:
return int(self.__serial)
@property
def rarity(self) -> str:
return self.__rarity

View file

@ -1,9 +1,5 @@
from __future__ import annotations from __future__ import annotations
from PIL import Image
_Point = tuple[int, int]
class Grid(tuple[int, int]): class Grid(tuple[int, int]):
def __mul__(self, other: Grid) -> Grid: def __mul__(self, other: Grid) -> Grid:
@ -21,16 +17,3 @@ class Grid(tuple[int, int]):
def capacity(self): def capacity(self):
# capacity of grid (reserve last space for card back) # capacity of grid (reserve last space for card back)
return self.x * self.y - 1 return self.x * self.y - 1
def chunks(self, whole: list) -> list:
# while there are elements
while whole:
# get a chunk
yield whole[:self.capacity]
# remove that chunk
whole = whole[self.capacity:]
def paste(self, page: Image.Image, index: int, card: Image.Image) -> None:
w, h = card.size
position = (index % self.x) * w, (index // self.x) * h
page.paste(card, position)

View file

@ -1,43 +1,37 @@
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass, InitVar, field
@dataclass(frozen=True)
class Language: class Language:
def __init__(self, language: str): short: str = field(init=False)
language = language.lower() short_init: InitVar[str] = field(default="")
def __post_init__(self, short_init: str):
short_init = short_init.lower()
# supported languages # supported languages
if language in ["de", "es", "fr", "ja", "it"]: if short_init in ["de", "es", "fr", "ja", "it"]:
self.__short = language object.__setattr__(self, "short", short_init)
else: else:
# everything else is english # everything else is english
self.__short = "en" object.__setattr__(self, "short", "en")
def __repr__(self):
return f"Language({self.__short!r})"
def __str__(self):
return self.__short
def __hash__(self) -> hash:
return hash(str(self))
def __eq__(self, other: Language):
return str(self) == str(other)
@property @property
def image_suffix(self): def image_suffix(self):
# supported languages for face URLs # supported languages for face URLs
if self.__short in ["de", "es", "fr", "it"]: if self.short in ["de", "es", "fr", "it"]:
return self.__short return self.short
else: else:
return "eg" return "eg"
@property @property
def key_suffix(self): def key_suffix(self):
# supported languages for Square API # supported languages for Square API
if self.__short in ["de", "es", "fr", "it"]: if self.short in ["de", "es", "fr", "it"]:
return f"_{self.__short.upper()}" return f"_{self.short.upper()}"
elif self.__short == "ja": elif self.short == "ja":
return "" return ""
else: else:
return "_EN" return "_EN"

View file

@ -17,17 +17,17 @@ class Opus(Cards):
params: dict[str, any] params: dict[str, any]
if opus_id.isnumeric(): if opus_id.isnumeric():
name = f"Opus {opus_id} ({language})" name = f"Opus {opus_id} ({language.short})"
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 = f"Boss Deck Chaos ({language})" name = f"Boss Deck Chaos ({language.short})"
self.__number = "B" self.__number = "B"
params = {"set": ["Boss Deck Chaos"]} params = {"set": ["Boss Deck Chaos"]}
elif opus_id == "promo": elif opus_id == "promo":
name = f"Promo ({language})" name = f"Promo ({language.short})"
self.__number = "PR" self.__number = "PR"
params = {"rarity": ["pr"]} params = {"rarity": ["pr"]}

View file

@ -1,3 +1,5 @@
from PIL import Image
from .grid import Grid from .grid import Grid
# constants # constants
@ -33,3 +35,18 @@ def encircle_symbol(symbol: str, negative: bool):
symbol_num = ord(symbol) - ord(base_symbols[0]) symbol_num = ord(symbol) - ord(base_symbols[0])
return chr(ord(base_symbols[1]) + symbol_num) return chr(ord(base_symbols[1]) + symbol_num)
def chunks(chunk_size: int, whole: list):
# while there are elements
while whole:
# get a chunk
yield whole[:chunk_size]
# remove that chunk
whole = whole[chunk_size:]
def grid_paste(page: Image.Image, index: int, card: Image.Image) -> None:
w, h = card.size
position = (index % GRID.x) * w, (index // GRID.x) * h
page.paste(card, position)