This Val tracks Apex Manager market listings to find "hidden gems": players who displayed BELOW A- potential on the market but actually retired with A- or higher potential (i.e., fog hid their true quality)[cite: 1]. This is strictly a data collection and comparison pipeline with a web dashboard, entirely separate from notification/alert Vals[cite: 1].
The Gem Rule (db.ts)
is_gem = isBelowAMinus(marketPotential) && !isBelowAMinus(retiredPotential)[cite: 1, 4]
CRITICAL: Always compare LETTER GRADES (estimatedRank / estimatedPotential), never the numeric trueRating or potentialRating[cite: 1]. The game's numeric ratings do not map to a reliable letter grade scale (e.g., a potential rating of 1986 might retire as a C/B, not an A)[cite: 1]. The authoritative "true" grade is the revealed letter grade on the retired card at 100% confidence[cite: 1].
Fog Semantics
fogConfidence (API) = INTEL[cite: 1]. Displayed "Fog %" = 100 - (fogConfidence * 100)[cite: 3]. High intel (low fog) = well-scouted; low intel (high fog) = obscured/lottery[cite: 1].
listings: Snapshot of every market listing (keyed by auction_id)[cite: 1]. Captures the first-seen state (est rank/potential, intel, fog, salary, full player_json)[cite: 1, 3]. Upserted every run[cite: 1]. left_at is set when a listing stops appearing in the active auctions API[cite: 1, 3].retired: Resolved players[cite: 1]. Compares market display vs. retired revealed grade (retired_rank / retired_potential)[cite: 1]. Stores market age/salary snapshot + true numeric ratings + is_gem flag + card_url[cite: 1, 2].player_checks: Dedupe and backoff tracking table (checked every 10 minutes) so we don't spam the API for unresolved players[cite: 1, 2].collect.ts (*/15 mins): Snapshots all /api/auctions listings[cite: 1]. Inserts new listings and updates left_at for expired auctions[cite: 3].check.ts (Hourly): Looks at listings that left the market >=1h ago[cite: 1]. Fetches /api/players/{id}[cite: 1]. If retired, calculates gem status and moves to retired table[cite: 1, 2]. If still active, backs off and checks again later[cite: 1].site.ts: The main frontend UI and API router[cite: 9]. Serves a rich HTML/JS dashboard at the root (/) with tabs for Live Market, Retired Players, and Advanced Analytics charts[cite: 6, 9]. Serves JSON endpoints at /api/stats, /api/live, /api/retired, and /api/analytics[cite: 9].report.ts: Spreadsheet export router[cite: 1, 7]. Serves raw JSON and CSVs (e.g., /csv for gems, /csv/listings for active market)[cite: 1, 7]. Designed to be ingested directly by Google Sheets using the IMPORTDATA() function[cite: 1].main.ts: A utility script to initialize the DB schema and print current table row counts[cite: 1, 5].APEX_TOKEN: The bearer token required to authenticate against the Apex Manager API[cite: 1]. All scripts will fail if this is missing or expired[cite: 1, 2, 3].