mirror of
https://github.com/ldericher/fftcgtool
synced 2025-01-15 15:02:59 +00:00
Cleanup
This commit is contained in:
parent
ac5d05da49
commit
a78a3ad04a
4 changed files with 76 additions and 50 deletions
|
@ -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")
|
||||
|
|
33
fftcg/grid.py
Normal file
33
fftcg/grid.py
Normal file
|
@ -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)
|
|
@ -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
|
||||
|
|
4
main.py
4
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.")
|
||||
|
|
Loading…
Reference in a new issue