Session 7j: Soccer intelligence - 9 leagues, 11 signals, 6 traps, poller, prefetch, 131 new tests (1173 total)

This commit is contained in:
Kev
2026-06-10 14:50:13 -04:00
parent b9084408bf
commit ad5ea8d5a8
28 changed files with 3175 additions and 49 deletions
+25 -1
View File
@@ -4,7 +4,29 @@ const { normalizeProps, extractSpreads, MARKET_MAP } = require('../utils/oddsNor
const ODDS_API_BASE = 'https://api.the-odds-api.com/v4/sports';
const CACHE_TTL = 900; // 15 minutes in seconds
const SPORT_KEYS = { nba: 'basketball_nba', ncaab: 'basketball_ncaab' };
// Sport identifiers consumed by getOdds → mapped to the odds-api.com
// sport key. Soccer leagues are listed individually so the route layer
// can fetch per-league without changing the upstream contract. Only
// fetched on user demand (on-demand cache with 15-min TTL); leagues
// nobody queries don't consume odds-api quota.
const SPORT_KEYS = {
nba: 'basketball_nba',
ncaab: 'basketball_ncaab',
// Soccer (Session 7j) — odds-api sport keys verified against
// https://the-odds-api.com/sports-odds-data/sports-apis.html
soccer_wc: 'soccer_fifa_world_cup',
soccer_epl: 'soccer_epl',
soccer_laliga: 'soccer_spain_la_liga',
soccer_bundesliga: 'soccer_germany_bundesliga',
soccer_seriea: 'soccer_italy_serie_a',
soccer_ligue1: 'soccer_france_ligue_one',
soccer_ucl: 'soccer_uefa_champs_league',
soccer_mls: 'soccer_usa_mls',
soccer_ligamx: 'soccer_mexico_ligamx',
};
const SOCCER_SPORT_KEYS = Object.freeze(
Object.keys(SPORT_KEYS).filter((k) => k.startsWith('soccer_'))
);
const ALL_MARKETS = Object.keys(MARKET_MAP).join(',') + ',spreads';
const BOOKMAKERS = 'draftkings,fanduel,betmgm,caesars,fanatics,bet365,hardrockbet,pointsbet,betrivers';
@@ -201,6 +223,8 @@ module.exports = {
fetchEventsFromApi,
fetchEventOddsFromApi,
getCacheKey,
SPORT_KEYS,
SOCCER_SPORT_KEYS,
getQuotaKey,
updateQuota,
getQuotaRemaining,