Wave 6: Combat Intelligence Layer (honest free v1)
Net-new MMA/UFC vertical — fight-card discovery, tale-of-the-tape,
style-blend archetypes, ML + round-total odds, and a style-edge VERDICT
(a MODEL read, explicitly NOT a settled grade). Built to
specs/combat-intelligence.md.
Backend:
- combatAdapter: ESPN MMA scoreboard (date-pinned, free JSON) -> fight
cards + tale-of-tape (record/weight class/rounds/ESPN athlete id);
defensive parse (null on unknown shape, never throws); injectable
fetchImpl + cache; pure normalizeCombatOdds (odds-api h2h/totals ->
ML + round total, allow-listed books, best price). Number(null) guard.
- archetypeService: 6 pinned combat styles in a SEPARATE COMBAT_ARCHETYPES
registry (FINISHER collides with soccer + its green trips the signal-
green gate); classify('mma') blends range/tempo/outcome, honest-empty on
thin data (no forced fallback); styleMatchup() honest verdict.
- oddsService: SPORT_KEYS.mma + MMA_MARKETS=['h2h','totals'] + SPORT_MARKETS
(no spreads suffix). oddsNormalizer MARKET_MAP h2h/totals.
- config/sports.js + web mirror: mma.active=true (collectData stays false;
NOT in the graded-props pipeline SPORT_CONFIG or snapshot/settle loop).
- routes/combat.js: GET /api/combat/:date + GET /api/fight/:id (public,
cached, honest empty off-card) + Next proxies.
Frontend:
- FightCard: two-fighter tale-of-the-tape (initials monogram — no photos),
GRAPPLER/STRIKER blend bars, discipline pedigree tags, shared
ArchetypeBadge (sport="mma", unicode glyphs), CENTER VERDICT, ML +
round-total real; method/round/KO = honest "data-limited", never
fabricated. Self-hides on a non-two-fighter bout.
- /fight/[id] page (server wrapper + client), EmptyState off-season.
- MMA SportBadge token (#D4AF37); archetypes.js sport-aware resolution.
DEFERRED (per spec, NOT built): matchup-GRADE engine, method/round/props
board, combat settlement, ufcstats scraping.
Tests: +3 suites (31 tests) — combat archetype cross-file color/glyph
match, classify blends, styleMatchup honesty, adapter defensive parse +
odds normalize, FightCard honesty grep; extended oddsNormalizer +
sportMarkets. Full suite 253/253 green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -83,6 +83,16 @@ const MARKET_MAP = {
|
||||
// are shared with soccer/NBA — sport context discriminates downstream.
|
||||
player_shots_on_goal: 'shots_on_goal',
|
||||
goalie_saves: 'saves',
|
||||
|
||||
// MMA / UFC (Wave 6 — combat intelligence). Game-level markets, NOT player
|
||||
// props: h2h = moneyline (per fighter), totals = round total (over/under).
|
||||
// Mapped here so combat odds don't silently normalize to zero when wired
|
||||
// through the odds-api path (same silent-failure class as the MLB/NHL gaps).
|
||||
// The combat surface parses these via combatAdapter.normalizeCombatOdds —
|
||||
// normalizeProps (this file) is player-prop-shaped and skips them, which is
|
||||
// correct: MMA carries no per-player point props on the free feed.
|
||||
h2h: 'moneyline',
|
||||
totals: 'round_total',
|
||||
};
|
||||
|
||||
function normalizeProps(eventsWithOdds) {
|
||||
|
||||
Reference in New Issue
Block a user