diff --git a/tutor/csvimport.py b/tutor/csvimport.py index 2733ff5..fe8f0a1 100644 --- a/tutor/csvimport.py +++ b/tutor/csvimport.py @@ -58,6 +58,7 @@ async def load( card=found[0], foil=is_foil, language=row["Language"] or "English", + collection=row.get("List name") or "Default", ) logging.info((quantity, card)) for i in range(quantity): diff --git a/tutor/database.py b/tutor/database.py index 291e710..082e756 100644 --- a/tutor/database.py +++ b/tutor/database.py @@ -183,14 +183,14 @@ async def advanced_search( ] if sort_by == "price": orderings = [ - "CAST(COALESCE(CASE WHEN \"copies\".\"isFoil\" THEN card_prices.usd_foil ELSE card_prices.usd END, 0) as decimal) DESC", + 'CAST(COALESCE(CASE WHEN "copies"."isFoil" THEN card_prices.usd_foil ELSE card_prices.usd END, 0) as decimal) DESC', *orderings, ] params["last_update_key"] = "last_update" query = " ".join( [ - "SELECT cards.*, card_prices.*", - ", CASE WHEN \"copies\".\"isFoil\" THEN card_prices.usd_foil", + "SELECT cards.*, card_prices.*, copies.*", + ', CASE WHEN "copies"."isFoil" THEN card_prices.usd_foil', " ELSE card_prices.usd END AS usd", "FROM cards", " ".join(joins), @@ -212,26 +212,30 @@ async def advanced_search( return None return [ - tutor.models.Card( - scryfall_id=row["scryfall_id"], - oracle_id=row["oracle_id"], - name=row["name"], - set_code=row["set_code"], - 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"], - 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["usd"]), - price_usd_foil=convert_price(row["usd_foil"]), - price_eur=convert_price(row["eur"]), - price_eur_foil=convert_price(row["eur_foil"]), - price_tix=convert_price(row["tix"]), + 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"], + 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"], + 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["usd"]), + price_usd_foil=convert_price(row["usd_foil"]), + price_eur=convert_price(row["eur"]), + price_eur_foil=convert_price(row["eur_foil"]), + price_tix=convert_price(row["tix"]), + ), + foil=row["isFoil"] if row["isFoil"] is not None else False, + collection=row["collection"] or "Default", ) for row in rows ] @@ -300,12 +304,13 @@ async def store_set(db: psycopg.Cursor, set_code: str, name: str) -> None: async def store_copy(db: psycopg.Cursor, copy: tutor.models.CardCopy) -> None: await db.execute( """ - INSERT INTO copies ("scryfall_id", "isFoil", "condition") - VALUES (%(scryfall_id)s, %(foil)s, %(condition)s) + INSERT INTO copies ("scryfall_id", "isFoil", "collection", "condition") + VALUES (%(scryfall_id)s, %(foil)s, %(collection)s, %(condition)s) """, { "scryfall_id": str(copy.card.scryfall_id), "foil": copy.foil, + "collection": copy.collection, "condition": copy.condition, }, ) diff --git a/tutor/models.py b/tutor/models.py index 7714a6b..746d66a 100644 --- a/tutor/models.py +++ b/tutor/models.py @@ -90,4 +90,5 @@ class CardCopy: card: Card foil: bool language: str = "English" + collection: str = "Default" condition: typing.Optional[str] = None diff --git a/tutor/server.py b/tutor/server.py index 3b93c44..6c0440c 100644 --- a/tutor/server.py +++ b/tutor/server.py @@ -64,7 +64,7 @@ class SearchHandler(tornado.web.RequestHandler): limit = int(self.get_argument("limit", 10)) sort_by = self.get_argument("sort_by", "rarity") search = tutor.search.search.parse(query) - cards = await tutor.database.advanced_search( + copies = await tutor.database.advanced_search( cursor, search, limit=limit + 1, @@ -74,7 +74,7 @@ class SearchHandler(tornado.web.RequestHandler): if in_collection else None, ) - has_more = cards and len(cards) > limit + has_more = copies and len(copies) > limit self.set_header("Content-Type", "application/json") self.set_header("Access-Control-Allow-Origin", "*") links = {} @@ -92,24 +92,26 @@ class SearchHandler(tornado.web.RequestHandler): json.dumps( [ { - "scryfall_id": str(card.scryfall_id), - "name": card.name, - "set_code": card.set_code, - "collector_number": card.collector_number, - "rarity": str(card.rarity), + "scryfall_id": str(copy.card.scryfall_id), + "name": copy.card.name, + "set_code": copy.card.set_code, + "collector_number": copy.card.collector_number, + "rarity": str(copy.card.rarity), "color_identity": tutor.models.Color.to_string( - card.color_identity + copy.card.color_identity ), - "oracle_text": card.oracle_text, + "oracle_text": copy.card.oracle_text, "prices": { - "usd": price(card.price_usd), - "usd_foil": price(card.price_usd_foil), - "eur": price(card.price_eur), - "eur_foil": price(card.price_eur_foil), - "tix": price(card.price_tix), - } + "usd": price(copy.card.price_usd), + "usd_foil": price(copy.card.price_usd_foil), + "eur": price(copy.card.price_eur), + "eur_foil": price(copy.card.price_eur_foil), + "tix": price(copy.card.price_tix), + }, + "foil": copy.foil, + "collection": copy.collection, } - for card in cards[:limit] + for copy in copies[:limit] ] ) ) diff --git a/www/src/App.elm b/www/src/App.elm index 4b00ee2..3ee98c9 100644 --- a/www/src/App.elm +++ b/www/src/App.elm @@ -326,6 +326,9 @@ colors = white = E.rgb255 255 255 255 + offwhite = + E.rgb255 200 200 200 + mythic = E.rgb255 205 55 0 @@ -345,7 +348,9 @@ colors = , sidebar = lighterGrey , selected = darkGrey , hover = grey - , text = white + , title = white + , subtitle = offwhite + , text = offwhite , mythic = mythic , rare = rare , uncommon = uncommon @@ -458,6 +463,7 @@ viewCardBrowser model = , E.padding 2 , Font.family [ Font.typeface "sans" ] , Font.size 10 + , Font.color colors.title ] <| E.text text @@ -514,7 +520,7 @@ viewCardBrowser model = E.el [ E.centerX ] (viewCard { width = 192, height = 272 } card) :: (E.row [ E.spacing 5, E.centerX ] <| List.map priceBadge (prices card)) - :: E.paragraph [ Font.heavy, Font.size 24, Font.center ] [ E.text card.name ] + :: E.paragraph [ Font.heavy, Font.size 24, Font.center, Font.color colors.title ] [ E.text card.name ] :: List.map (\text -> E.paragraph [ Font.size 16 ] [ E.text text ]) (String.lines card.oracleText) @@ -551,7 +557,10 @@ viewCardBrowser model = ] , description = cardModel.name } - , E.el [ E.centerY, E.height E.fill, E.width E.fill, E.clipX ] <| E.text cardModel.name + , E.column [ E.centerY, E.height E.fill, E.width E.fill, E.clipX ] + [ E.el [ Font.color colors.title ] <| E.text cardModel.name + , E.el [ Font.size 16, Font.italic, Font.color colors.subtitle ] <| E.text cardModel.collection + ] , E.column [ E.alignRight, E.height E.fill ] <| setBadge cardModel :: List.map priceBadge (prices cardModel) diff --git a/www/src/Card.elm b/www/src/Card.elm index b7db051..bbcff1a 100644 --- a/www/src/Card.elm +++ b/www/src/Card.elm @@ -20,8 +20,11 @@ type alias Card = , rarity : String , oracleText : String , prices : Prices + , collection : String + , foil : Bool } + decode : Json.Decode.Decoder Card decode = Json.Decode.succeed Card @@ -34,6 +37,8 @@ decode = |> Json.Decode.map (Maybe.withDefault "") ) |> JDP.required "prices" decodePrices + |> JDP.required "collection" Json.Decode.string + |> JDP.required "foil" Json.Decode.bool decodePrices : Json.Decode.Decoder Prices