GET /api/v2/refractor/cards: add evaluated_only filter to exclude zero-value cards
#174
Labels
No Label
ai-changes-requested
ai-failed
ai-merged
ai-pr-opened
ai-reviewed
ai-reviewing
ai-reviewing
ai-working
bug
enhancement
evolution
performance
phase-0
phase-1a
phase-1b
phase-1c
phase-1d
security
tech-debt
todo
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: cal/paper-dynasty-database#174
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
GET /api/v2/refractor/cards?team_id=31currently returns allRefractorCardStaterows for a team — including cards that havecurrent_value = 0and have never been evaluated against season stats. For team 31 this produces 2753 results when only ~14 cards have meaningful data.This happens because
RefractorCardStaterows are created eagerly (one row per card when it enters a roster), butcurrent_valueonly becomes non-zero afterevaluate_card()runs for that player. Cards that have never appeared in a game will havecurrent_value = 0.0andlast_evaluated_at = NULL.The
/refractor statusDiscord command fetches this endpoint for every invocation and pages through the full result set. At 2753 rows with most being zero-value placeholders, the command is fetching and paginating over data that is meaningless to display.Design Recommendation
Add an
evaluated_onlyquery parameter (defaultTrue)Default to
True— the bot never needs to see unevaluated cards, and the admin/pipeline use case for seeing all rows is rare. AFalseopt-in is easier to reason about than aTrueopt-in.Filter predicate
The cleanest signal for "has been evaluated" is
last_evaluated_at IS NOT NULL, notcurrent_value > 0.Rationale:
current_value = 0.0withlast_evaluated_atpopulated. Filtering oncurrent_value > 0would silently drop that card.last_evaluated_at IS NOT NULLprecisely tracks the state transition "this card has gone through at least one evaluation cycle" — which is the actual question the bot needs answered.In Peewee this is a one-line addition to the existing query:
No schema change required
This is a pure query-layer filter. No migration, no new index needed (the
teamindex already covers the base query; the additional predicate adds negligible cost over a small evaluated set).Edge Cases
current_valuelast_evaluated_atlast_evaluated_atfilter, not value)Discord Bot Impact
The bot sends
evaluated_onlyimplicitly via default behavior — no bot-side changes are needed if we default toTrue. The bot's existing params (card_type,tier,season,progress,limit,offset) all compose cleanly with this new filter.Implementation Notes
database/app/routers_v2/refractor.py,list_card_states()function (~line 103)evaluated_only: bool = Query(default=True)to the function signaturequery = query.where(RefractorCardState.last_evaluated_at.is_null(False))whenevaluated_only=Trueevaluated_only=Falsepath (ensures unevaluated cards appear when explicitly requested)PR #175 opened: #175
Added
evaluated_only: bool = Query(default=True)tolist_card_states(). When true (default), appliesWHERE last_evaluated_at IS NOT NULL— filters out the ~2739 placeholder rows created at pack-open time. Bot behaviour is unchanged (gets the filtered view by default); passevaluated_only=falsefor admin/pipeline access to all rows. No migration needed.