mirror of
https://github.com/ldericher/fftcgtool
synced 2025-01-15 15:02:59 +00:00
ttsdeck import -> ffdecks
This commit is contained in:
parent
8c1313da93
commit
0bfcc92191
4 changed files with 109 additions and 100 deletions
|
@ -1,7 +1,8 @@
|
||||||
from .book import Book
|
from .book import Book
|
||||||
from .carddb import CardDB, RWCardDB
|
from .carddb import CardDB, RWCardDB
|
||||||
|
from .ffdecks import FFDecks
|
||||||
from .language import Language
|
from .language import Language
|
||||||
from .opus import Opus
|
from .opus import Opus
|
||||||
from .ttsdeck import TTSDeck
|
from .ttsdeck import TTSDeck
|
||||||
|
|
||||||
__all__ = ["Book", "CardDB", "RWCardDB", "Language", "Opus", "TTSDeck"]
|
__all__ = ["Book", "CardDB", "RWCardDB", "FFDecks", "Language", "Opus", "TTSDeck"]
|
||||||
|
|
106
fftcgtool/ffdecks.py
Normal file
106
fftcgtool/ffdecks.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
from typing import Iterable, Iterator, Optional
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from .code import Code
|
||||||
|
from .ttsdeck import TTSDeck
|
||||||
|
|
||||||
|
|
||||||
|
class FFDecks(list[TTSDeck]):
|
||||||
|
__FFDECKS_API_URL = "https://ffdecks.com/api/deck"
|
||||||
|
__RE_FFDECKS_ID = re.compile(r"((https?://)?ffdecks\.com(/+api)?/+deck/+)?([0-9]+).*", flags=re.UNICODE)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sanitized_ids(cls, deck_ids: Iterable) -> Iterator[Optional[str]]:
|
||||||
|
matches = (
|
||||||
|
cls.__RE_FFDECKS_ID.match(str(deck_id))
|
||||||
|
for deck_id in deck_ids
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
match.groups()[3]
|
||||||
|
if match is not None
|
||||||
|
else None
|
||||||
|
for match in matches
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, deck_ids: Iterable):
|
||||||
|
super().__init__()
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def by_type(data: dict[str, str | int]) -> int:
|
||||||
|
key_prios = {
|
||||||
|
"Forward": 1,
|
||||||
|
"Summon": 2,
|
||||||
|
"Monster": 3,
|
||||||
|
"Backup": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
return key_prios[data["type"]]
|
||||||
|
except KeyError:
|
||||||
|
return 4
|
||||||
|
|
||||||
|
def by_cost(data: dict[str, str | int]) -> int:
|
||||||
|
return data["cost"]
|
||||||
|
|
||||||
|
for deck_id in self.sanitized_ids(deck_ids):
|
||||||
|
if deck_id is None:
|
||||||
|
logger.error("Malformed Deck ID for FFDecks API!")
|
||||||
|
|
||||||
|
else:
|
||||||
|
# api request
|
||||||
|
res = requests.get(FFDecks.__FFDECKS_API_URL, params={"deck_id": deck_id})
|
||||||
|
|
||||||
|
if not res.ok:
|
||||||
|
logger.error(f"Invalid Deck ID '{deck_id}' for FFDecks API!")
|
||||||
|
|
||||||
|
else:
|
||||||
|
# general metadata
|
||||||
|
name = f"{res.json()['name']}"
|
||||||
|
description = deck_id
|
||||||
|
|
||||||
|
logger.info(f"Importing Deck {name!r}")
|
||||||
|
|
||||||
|
# pre-extract the used data
|
||||||
|
deck_cards = [{
|
||||||
|
"code": card["card"]["serial_number"],
|
||||||
|
"type": card["card"]["type"],
|
||||||
|
"cost": int(card["card"]["cost"]),
|
||||||
|
"count": int(card["quantity"]),
|
||||||
|
} for card in res.json()["cards"]]
|
||||||
|
|
||||||
|
# sort cards by type, then by cost
|
||||||
|
deck_cards.sort(key=by_cost)
|
||||||
|
deck_cards.sort(key=by_type)
|
||||||
|
|
||||||
|
# ffdecks quirk: some full-art promos in database
|
||||||
|
replace_full_arts = {
|
||||||
|
# line format:
|
||||||
|
# full-art-id: normal id,
|
||||||
|
"PR-051": "11-083",
|
||||||
|
"PR-055": "11-062",
|
||||||
|
}
|
||||||
|
|
||||||
|
# replace with normal-art cards
|
||||||
|
for card in deck_cards:
|
||||||
|
try:
|
||||||
|
card["code"] = replace_full_arts[card["code"]]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
codes = [
|
||||||
|
# create list of code objects
|
||||||
|
Code(card["code"])
|
||||||
|
# for each card
|
||||||
|
for card in deck_cards
|
||||||
|
# repeat to meet count
|
||||||
|
for _ in range(card["count"])
|
||||||
|
]
|
||||||
|
|
||||||
|
# create deck object
|
||||||
|
self.append(TTSDeck(codes, name, description, True))
|
|
@ -168,7 +168,7 @@ def ffdecks(deck_ids: list[str]) -> list[fftcgtool.TTSDeck]:
|
||||||
DECK_ID: each of the Decks to import
|
DECK_ID: each of the Decks to import
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return list(fftcgtool.TTSDeck.from_ffdecks_decks(deck_ids))
|
return fftcgtool.FFDecks(deck_ids)
|
||||||
|
|
||||||
|
|
||||||
@main.result_callback()
|
@main.result_callback()
|
||||||
|
|
|
@ -3,10 +3,6 @@ from __future__ import annotations
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
from typing import Optional, Iterable, Iterator
|
|
||||||
|
|
||||||
import requests
|
|
||||||
|
|
||||||
from .carddb import CardDB
|
from .carddb import CardDB
|
||||||
from .cards import Cards
|
from .cards import Cards
|
||||||
|
@ -48,100 +44,6 @@ class TTSDeck(Cards):
|
||||||
def file_name(self) -> str:
|
def file_name(self) -> str:
|
||||||
return f"{super().file_name}.json"
|
return f"{super().file_name}.json"
|
||||||
|
|
||||||
__FFDECKS_API_URL = "https://ffdecks.com/api/deck"
|
|
||||||
__RE_FFDECKS_ID = re.compile(r"((https?://)?ffdecks\.com(/+api)?/+deck/+)?([0-9]+).*", flags=re.UNICODE)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def sanitized_ids(cls, deck_ids: Iterable) -> Iterator[Optional[str]]:
|
|
||||||
matches = (
|
|
||||||
cls.__RE_FFDECKS_ID.match(str(deck_id))
|
|
||||||
for deck_id in deck_ids
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
match.groups()[3]
|
|
||||||
if match is not None
|
|
||||||
else None
|
|
||||||
for match in matches
|
|
||||||
)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_ffdecks_decks(cls, deck_ids: Iterable) -> Iterator[TTSDeck]:
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
def by_type(data: dict[str, str | int]) -> int:
|
|
||||||
key_prios = {
|
|
||||||
"Forward": 1,
|
|
||||||
"Summon": 2,
|
|
||||||
"Monster": 3,
|
|
||||||
"Backup": 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
return key_prios[data["type"]]
|
|
||||||
except KeyError:
|
|
||||||
return 4
|
|
||||||
|
|
||||||
def by_cost(data: dict[str, str | int]) -> int:
|
|
||||||
return data["cost"]
|
|
||||||
|
|
||||||
for deck_id in cls.sanitized_ids(deck_ids):
|
|
||||||
if deck_id is None:
|
|
||||||
logger.error("Malformed Deck ID for FFDecks API!")
|
|
||||||
|
|
||||||
else:
|
|
||||||
# api request
|
|
||||||
res = requests.get(TTSDeck.__FFDECKS_API_URL, params={"deck_id": deck_id})
|
|
||||||
|
|
||||||
if not res.ok:
|
|
||||||
logger.error(f"Invalid Deck ID '{deck_id}' for FFDecks API!")
|
|
||||||
|
|
||||||
else:
|
|
||||||
# general metadata
|
|
||||||
name = f"{res.json()['name']}"
|
|
||||||
description = deck_id
|
|
||||||
|
|
||||||
logger.info(f"Importing Deck {name!r}")
|
|
||||||
|
|
||||||
# pre-extract the used data
|
|
||||||
deck_cards = [{
|
|
||||||
"code": card["card"]["serial_number"],
|
|
||||||
"type": card["card"]["type"],
|
|
||||||
"cost": int(card["card"]["cost"]),
|
|
||||||
"count": int(card["quantity"]),
|
|
||||||
} for card in res.json()["cards"]]
|
|
||||||
|
|
||||||
# sort cards by type, then by cost
|
|
||||||
deck_cards.sort(key=by_cost)
|
|
||||||
deck_cards.sort(key=by_type)
|
|
||||||
|
|
||||||
# ffdecks quirk: some full-art promos in database
|
|
||||||
replace_full_arts = {
|
|
||||||
# line format:
|
|
||||||
# full-art-id: normal id,
|
|
||||||
"PR-051": "11-083",
|
|
||||||
"PR-055": "11-062",
|
|
||||||
}
|
|
||||||
|
|
||||||
# replace with normal-art cards
|
|
||||||
for card in deck_cards:
|
|
||||||
try:
|
|
||||||
card["code"] = replace_full_arts[card["code"]]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
codes = [
|
|
||||||
# create list of code objects
|
|
||||||
Code(card["code"])
|
|
||||||
# for each card
|
|
||||||
for card in deck_cards
|
|
||||||
# repeat to meet count
|
|
||||||
for _ in range(card["count"])
|
|
||||||
]
|
|
||||||
|
|
||||||
# create deck object
|
|
||||||
yield cls(codes, name, description, True)
|
|
||||||
|
|
||||||
def get_tts_object(self, language: Language) -> dict[str, any]:
|
def get_tts_object(self, language: Language) -> dict[str, any]:
|
||||||
carddb = CardDB()
|
carddb = CardDB()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue