Add endpoint for deck candidates
This commit is contained in:
parent
ee68b1e10c
commit
7f1735f200
3 changed files with 79 additions and 0 deletions
|
@ -594,3 +594,57 @@ async def collection_stats(db: psycopg.AsyncCursor) -> typing.Optional[dict]:
|
|||
"""
|
||||
)
|
||||
return await db.fetchone()
|
||||
|
||||
|
||||
async def deck_candidates(
|
||||
db: psycopg.AsyncCursor, deck_id: int
|
||||
) -> typing.List[tutor.models.CardCopy]:
|
||||
db.row_factory = psycopg.rows.dict_row
|
||||
await db.execute(
|
||||
"""
|
||||
SELECT cards.*, copies.*
|
||||
FROM deck_list
|
||||
JOIN cards USING(oracle_id)
|
||||
JOIN copies USING (scryfall_id)
|
||||
JOIN sets USING(set_code)
|
||||
WHERE deck_id = %(deck_id)s AND type_line not like 'Basic Land%%'
|
||||
ORDER BY CASE WHEN rarity >= 'rare'::rarity THEN 0 ELSE 1 END -- Is it in a binder?
|
||||
, CASE WHEN LENGTH(color_identity) > 1 THEN 0 ELSE 1 END -- Sort gold cards before mono-colored
|
||||
, color_identity
|
||||
, CASE WHEN rarity > 'rare'::rarity THEN 0 ELSE 1 END -- Mythics are separated from rares in binders
|
||||
, release_date ASC, set_code -- Older cards are better organized in boxes
|
||||
, cards.name
|
||||
""",
|
||||
{"deck_id": deck_id},
|
||||
)
|
||||
rows = await db.fetchall()
|
||||
return [
|
||||
tutor.models.CardCopy(
|
||||
card=tutor.models.Card(
|
||||
scryfall_id=row["scryfall_id"],
|
||||
oracle_id=row["oracle_id"],
|
||||
name=row["name"],
|
||||
set_code=row["set_code"],
|
||||
set_name=row["set_name"],
|
||||
collector_number=row["collector_number"],
|
||||
rarity=tutor.models.Rarity.from_string(row["rarity"]),
|
||||
color_identity=tutor.models.Color.from_string(row["color_identity"]),
|
||||
cmc=row["cmc"],
|
||||
mana_cost=row["mana_cost"],
|
||||
type_line=row["type_line"],
|
||||
release_date=datetime.date.fromisoformat(row["release_date"]),
|
||||
games=set(),
|
||||
legalities={},
|
||||
edhrec_rank=row["edhrec_rank"],
|
||||
oracle_text=row["oracle_text"],
|
||||
price_usd=convert_price(row["price_usd"]),
|
||||
price_usd_foil=convert_price(row["price_usd_foil"]),
|
||||
price_eur=convert_price(row["price_eur"]),
|
||||
price_eur_foil=convert_price(row["price_eur_foil"]),
|
||||
price_tix=convert_price(row["price_tix"]),
|
||||
),
|
||||
foil=row["isFoil"] if row["isFoil"] is not None else False,
|
||||
collection=row["collection"] or "Default",
|
||||
)
|
||||
for row in rows
|
||||
]
|
||||
|
|
|
@ -371,6 +371,16 @@ class DeckHandler(RequestHandler):
|
|||
self.set_status(204)
|
||||
|
||||
|
||||
class DeckCandidatesHandler(OpenAPIRequestHandler, RequestHandler):
|
||||
async def get(self, deck_id: int) -> None:
|
||||
self.set_header("Content-Type", "application/json")
|
||||
self.set_header("Access-Control-Allow-Origin", "*")
|
||||
async with self.pool.connection() as conn:
|
||||
async with conn.cursor() as cursor:
|
||||
candidates = await tutor.database.deck_candidates(cursor, deck_id)
|
||||
self.write(json.dumps(candidates, cls=JSONEncoder))
|
||||
|
||||
|
||||
class TemplateHandler(RequestHandler):
|
||||
def initialize(
|
||||
self,
|
||||
|
@ -429,6 +439,7 @@ class Application(tornado.web.Application):
|
|||
(r"/api/collection", CollectionHandler),
|
||||
(r"/api/decks", DecksHandler),
|
||||
(r"/api/decks/([1-9][0-9]*)", DeckHandler),
|
||||
(r"/api/decks/([1-9][0-9]*)/candidates", DeckCandidatesHandler),
|
||||
]
|
||||
if static_path := settings.get("static"):
|
||||
paths.extend(
|
||||
|
|
|
@ -285,6 +285,20 @@ paths:
|
|||
responses:
|
||||
'204':
|
||||
description: Deck deleted
|
||||
/api/decks/{deck_id}/candidates:
|
||||
get:
|
||||
summary: Find cards in collection
|
||||
tags:
|
||||
- Decks
|
||||
responses:
|
||||
'200':
|
||||
description: Cards
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/copy'
|
||||
components:
|
||||
schemas:
|
||||
uuid: &uuid
|
||||
|
|
Loading…
Reference in a new issue