From a78a3ad04a6ae76b45dcfc3a7a2535f35eba99ac Mon Sep 17 00:00:00 2001 From: LDericher <40151420+ldericher@users.noreply.github.com> Date: Mon, 9 Aug 2021 14:03:45 +0200 Subject: [PATCH] Cleanup --- fftcg/book.py | 64 ++++++++++++++++++++------------------------------- fftcg/grid.py | 33 ++++++++++++++++++++++++++ fftcg/opus.py | 25 ++++++++++++-------- main.py | 4 ++-- 4 files changed, 76 insertions(+), 50 deletions(-) create mode 100644 fftcg/grid.py diff --git a/fftcg/book.py b/fftcg/book.py index 163e4d6..96cd592 100644 --- a/fftcg/book.py +++ b/fftcg/book.py @@ -3,70 +3,56 @@ import logging from PIL import Image from .cards import Cards +from .grid import Grid from .imageloader import ImageLoader -def chunks(whole: list[any], chunk_size) -> list: - # while there are elements - while whole: - # get a chunk - yield whole[:chunk_size] - # remove that chunk - whole = whole[chunk_size:] - - class Book: - # Card faces by Square API - __FACE_URL = "https://fftcg.cdn.sewest.net/images/cards/full/{}_{}.jpg" - - # Card back image by Aurik - __BACK_URL = "http://cloud-3.steamusercontent.com/ugc/948455238665576576/85063172B8C340602E8D6C783A457122F53F7843/" - def __init__(self, cards: Cards, grid: tuple[int, int], resolution: tuple[int, int], language: str, num_threads: int): logger = logging.getLogger(__name__) + # transform grid into Grid + grid = Grid(grid) + # sort cards by element, then alphabetically cards.sort(key=lambda x: x.name) cards.sort(key=lambda x: "Multi" if len(x.elements) > 1 else x.elements[0]) # all card face URLs - urls = [Book.__FACE_URL.format(card.code, language) for card in cards] - # card back URL - urls.append(Book.__BACK_URL) + urls = [f"https://fftcg.cdn.sewest.net/images/cards/full/{card.code}_{language}.jpg" for card in cards] + # card back URL (image by Aurik) + urls.append( + "http://cloud-3.steamusercontent.com/ugc/948455238665576576/85063172B8C340602E8D6C783A457122F53F7843/" + ) - # multithreaded download + # multi-threaded download images = ImageLoader.load(urls, resolution, language, num_threads) # card back Image back_image = images.pop(-1) - # shorthands - # rows and columns per sheet - r, c = grid - # capacity of grid (reserve last space for card back) - grid_capacity = r * c - 1 - # width, height per card - w, h = resolution - - def paste_card(index: int, card: Image) -> None: - x, y = (index % c) * w, (index // c) * h - page.paste(card, (x, y)) - self.__pages = [] - for images in chunks(images, grid_capacity): + for page_images, page_cards in zip(grid.chunks(images), grid.chunks(cards)): # create book page Image - page = Image.new("RGB", (c * w, r * h)) - logger.info(f"New image: {page.size[0]}x{page.size[1]}") + 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(images): - paste_card(i, image) + for i, image in enumerate(page_images): + grid.paste(page_image, i, image) # paste card back in last position - paste_card(c * r - 1, back_image) + grid.paste(page_image, grid.capacity, back_image) - self.__pages.append(page) + # save page + self.__pages.append({ + "image": page_image, + "cards": page_cards, + }) + + def __getitem__(self, index: int) -> Image.Image: + return self.__pages[index]["image"] def save(self, filename: str) -> None: for i, page in enumerate(self.__pages): - page.save(filename.format(i)) + page["image"].save(f"{filename}_{i}.jpg") diff --git a/fftcg/grid.py b/fftcg/grid.py new file mode 100644 index 0000000..9e660a6 --- /dev/null +++ b/fftcg/grid.py @@ -0,0 +1,33 @@ +from PIL import Image + + +class Grid(tuple[int, int]): + def __mul__(self, other): + other = Grid(other) + return Grid((self.x * other.x, self.y * other.y)) + + @property + def x(self): + return self[0] + + @property + def y(self): + return self[1] + + @property + 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) diff --git a/fftcg/opus.py b/fftcg/opus.py index 2c9aeda..3bd4f81 100644 --- a/fftcg/opus.py +++ b/fftcg/opus.py @@ -10,25 +10,28 @@ class Opus(Cards): logger = logging.getLogger(__name__) if opus_id.isnumeric(): - roman_opus_id = roman.toRoman(int(opus_id)) - params = {"set": [f"Opus {roman_opus_id.upper()}"]} + self.__name = f"Opus {roman.toRoman(int(opus_id)).upper()}" self.__number = opus_id - self.__name = f"opus_{opus_id}" + self.__filename = f"opus_{opus_id}" + params = {"set": [self.__name]} elif opus_id == "chaos": - params = {"set": ["Boss Deck Chaos"]} + self.__name = "Boss Deck Chaos" self.__number = "B" - self.__name = "boss_deck_chaos" + self.__filename = "boss_deck_chaos" + params = {"set": [self.__name]} elif opus_id == "promo": - params = {"rarity": ["pr"]} + self.__name = "Promo" self.__number = "PR" - self.__name = "promo" + self.__filename = "promo" + params = {"rarity": ["pr"]} else: - params = {"set": ["?"]} - self.__number = "?" self.__name = "?" + self.__number = "?" + self.__filename = "?" + params = {"set": "?"} super().__init__(params) @@ -51,3 +54,7 @@ class Opus(Cards): @property def number(self) -> str: return self.__number + + @property + def filename(self) -> str: + return self.__filename diff --git a/main.py b/main.py index bd95bd7..33c258c 100755 --- a/main.py +++ b/main.py @@ -6,7 +6,7 @@ import os import fftcg # constants -GRID = 7, 10 # default in TTsim: 7 rows, 10 columns +GRID = 10, 7 # default in TTsim: 10 columns, 7 rows RESOLUTION = 429, 600 # default in TTsim: 480x670 pixels per card @@ -45,7 +45,7 @@ def main() -> None: # main program opus = fftcg.Opus(args.opus_id) book = fftcg.Book(opus, GRID, RESOLUTION, "eg", args.num_threads) - book.save(f"{opus.name}_{{}}.jpg") + book.save(opus.filename) # bye logging.info("Done. Put the generated JSON files in your 'Saved Objects' Folder.")