'use strict'; /** * probablePitchers — today's MLB probable starters (Session 46). * * The ESPN schedule (`scheduleService`) doesn't carry probable pitchers, so MLB * game cards never showed them. This wraps `mlbStatsAdapter.getScheduleWithPitchers` * (FREE statsapi.mlb.com) and best-effort enriches each starter's season ERA. * Everything is graceful + injectable. `shapePitcherGames` is pure/unit-tested. */ const mlbStats = require('./adapters/mlbStatsAdapter'); /** Map the adapter's schedule shape → a compact { home, away } pitcher record. */ function shapePitcherGames(scheduleGames) { return (scheduleGames || []) .map((g) => ({ home: { team: g.home?.team || null, pitcher: g.home?.probablePitcher?.name || null, pitcherId: g.home?.probablePitcher?.id || null, era: null }, away: { team: g.away?.team || null, pitcher: g.away?.probablePitcher?.name || null, pitcherId: g.away?.probablePitcher?.id || null, era: null }, })) .filter((x) => x.home.pitcher || x.away.pitcher); } async function getProbablePitchers(date, opts = {}) { const adapter = opts.mlbAdapter || mlbStats; let games; try { games = await adapter.getScheduleWithPitchers(date); } catch (e) { console.warn('[probablePitchers] schedule fetch failed:', e.message); return []; } const shaped = shapePitcherGames(games); if (opts.withEra !== false) { const eraLookup = opts.eraLookup || (async (id) => { const s = await adapter.getSeasonAverages(id, undefined, 'pitching').catch(() => null); const era = s && parseFloat(s.era); return Number.isFinite(era) ? era : null; }); await Promise.all( shaped.flatMap((g) => [g.home, g.away]).map(async (side) => { if (side.pitcherId) { try { side.era = await eraLookup(side.pitcherId); } catch { side.era = null; } } }), ); } return shaped; } module.exports = { getProbablePitchers, shapePitcherGames };