diff --git a/tutor/database.py b/tutor/database.py index 1ba3318..4b7e520 100644 --- a/tutor/database.py +++ b/tutor/database.py @@ -171,6 +171,19 @@ async def advanced_search( if criterion.operator == tutor.search.Operator.gte: constraints.append(f"cards.rarity >= %({param})s::rarity") params[param] = criterion.rarity.value + if isinstance(criterion, tutor.search.PriceUSD): + if criterion.operator == tutor.search.Operator.gte: + constraints.append( + f'(("copies"."isFoil" AND cards.price_usd_foil >= %({param})s)' + f'OR (NOT "copies"."isFoil" AND cards.price_usd >= %({param})s))' + ) + params[param] = criterion.price + if criterion.operator == tutor.search.Operator.lte: + constraints.append( + f'(("copies"."isFoil" AND cards.price_usd_foil <= %({param})s)' + f'OR (NOT "copies"."isFoil" AND cards.price_usd <= %({param})s))' + ) + params[param] = criterion.price if isinstance(criterion, tutor.search.Oracle): constraints.append(f"cards.oracle_text ILIKE %({param})s") params[param] = f"%{criterion.text}%" diff --git a/tutor/search.py b/tutor/search.py index d623dcc..fd021a4 100644 --- a/tutor/search.py +++ b/tutor/search.py @@ -44,6 +44,11 @@ class Oracle(Criterion): text: parsy.string +@dataclasses.dataclass +class PriceUSD(Criterion): + price: parsy.string + + @dataclasses.dataclass class Collection(Criterion): text: parsy.string @@ -180,6 +185,12 @@ collection = parsy.seq( text=string_literal, ).combine_dict(Collection) +price_usd = parsy.seq( + _keyword=lstring_from("usd"), + operator=gte | lte, + price=string_literal, +).combine_dict(PriceUSD) + exact_name = parsy.seq(_prefix=lstring_from("!"), text=string_literal).combine_dict( functools.partial(Name, operator=Operator.matches) @@ -188,7 +199,9 @@ partial_name = parsy.seq(text=string_literal).combine_dict(Name) name = exact_name | partial_name -criterion = colors | expansion | rarity | type_line | oracle | collection | name +criterion = ( + colors | expansion | rarity | type_line | oracle | collection | price_usd | name +) padding = parsy.regex(r"\s*") search = padding >> (criterion << padding).many().map(Search)