1
0
Fork 0
mirror of https://github.com/ldericher/fftcgtool synced 2025-01-15 15:02:59 +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 .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, chunks, grid_paste
class Book:
@ -19,7 +19,7 @@ class Book:
# all card face 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
]
# card back URL
@ -32,17 +32,19 @@ class Book:
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
page_image = Image.new("RGB", GRID * RESOLUTION)
logger.info(f"New image: {page_image.size[0]}x{page_image.size[1]}")
# paste card faces onto page
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
GRID.paste(page_image, GRID.capacity, back_image)
grid_paste(page_image, GRID.capacity, back_image)
# set card indices
for i, card in enumerate(page_cards):

View file

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

View file

@ -1,9 +1,5 @@
from __future__ import annotations
from PIL import Image
_Point = tuple[int, int]
class Grid(tuple[int, int]):
def __mul__(self, other: Grid) -> Grid:
@ -21,16 +17,3 @@ class Grid(tuple[int, int]):
def capacity(self):
# capacity of grid (reserve last space for card back)
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 dataclasses import dataclass, InitVar, field
@dataclass(frozen=True)
class Language:
def __init__(self, language: str):
language = language.lower()
short: str = field(init=False)
short_init: InitVar[str] = field(default="")
def __post_init__(self, short_init: str):
short_init = short_init.lower()
# supported languages
if language in ["de", "es", "fr", "ja", "it"]:
self.__short = language
if short_init in ["de", "es", "fr", "ja", "it"]:
object.__setattr__(self, "short", short_init)
else:
# everything else is english
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)
object.__setattr__(self, "short", "en")
@property
def image_suffix(self):
# supported languages for face URLs
if self.__short in ["de", "es", "fr", "it"]:
return self.__short
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":
if self.short in ["de", "es", "fr", "it"]:
return f"_{self.short.upper()}"
elif self.short == "ja":
return ""
else:
return "_EN"

View file

@ -17,17 +17,17 @@ class Opus(Cards):
params: dict[str, any]
if opus_id.isnumeric():
name = f"Opus {opus_id} ({language})"
name = f"Opus {opus_id} ({language.short})"
self.__number = opus_id
params = {"set": [f"Opus {roman.toRoman(int(opus_id)).upper()}"]}
elif opus_id == "chaos":
name = f"Boss Deck Chaos ({language})"
name = f"Boss Deck Chaos ({language.short})"
self.__number = "B"
params = {"set": ["Boss Deck Chaos"]}
elif opus_id == "promo":
name = f"Promo ({language})"
name = f"Promo ({language.short})"
self.__number = "PR"
params = {"rarity": ["pr"]}

View file

@ -1,3 +1,5 @@
from PIL import Image
from .grid import Grid
# constants
@ -33,3 +35,18 @@ def encircle_symbol(symbol: str, negative: bool):
symbol_num = ord(symbol) - ord(base_symbols[0])
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)