Session 46: Grade card intel + name normalization + pitchers (2122 tests)
Three focused P1 fixes on the Session-45 snapshot model.
- Grade card intel ROOT CAUSE: gameLogService is NBA/WNBA-only (offline Python),
so MLB props never got l5_avg/l20_avg and buildIntelFields returned {}. Wired
MLB game logs into featureCache.gameLogFeatures via mlbStatsAdapter.getPlayerStats
(pure mlbGameLogFeatures + MLB stat_type->field map). buildIntelFields gained
playerStats/projection fallbacks for partial intel.
- Player name normalization: src/utils/playerName.js (+ web/src/lib copy):
normalizeName -> {display,key}. Strips periods, de-dots suffix, accent-folds
the key. Applied in snapshotService grouping, slateAdapter grade index +
player-strip merge (variants collapse, longest name shown), and
playerIntelService. "A.J. Ewing"/"AJ Ewing" + "Jazz Chisholm"/"Jr." now merge.
- MLB starting pitchers: new GET /api/schedule/:sport/pitchers (probablePitchers
service wrapping mlbStatsAdapter.getScheduleWithPitchers + best-effort ERA).
Slate fetches it, builds a team->pitcher map (full name + mascot match),
attaches pitchers to MLB GameCardData. + Next proxy.
Backend 2100 -> 2122 tests (+22), 176 suites. Web build clean (exit 0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
const { classify } = require('./archetypeService');
|
||||
const { normalizeName, nameKey } = require('../utils/playerName');
|
||||
|
||||
const toNum = (v) => {
|
||||
const n = parseFloat(v);
|
||||
@@ -31,14 +32,18 @@ const fmt3 = (v) => {
|
||||
function sanitizePlayerName(raw) {
|
||||
let decoded = String(raw == null ? '' : raw);
|
||||
try { decoded = decodeURIComponent(decoded); } catch { /* malformed % — use raw */ }
|
||||
return decoded
|
||||
const cleaned = decoded
|
||||
.replace(/[^\p{L}\p{N}\s.'-]/gu, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.slice(0, 60);
|
||||
// Session 46 — normalize periods/suffix for display ("A.J. Ewing" → "AJ Ewing").
|
||||
return normalizeName(cleaned).display;
|
||||
}
|
||||
|
||||
const normName = (n) => String(n == null ? '' : n).toLowerCase().replace(/[^a-z0-9]/g, '');
|
||||
// Session 46 — match by the normalized name key so name variants resolve to the
|
||||
// same player (snapshot grades, profile lookups).
|
||||
const normName = (n) => nameKey(n);
|
||||
|
||||
async function loadPlayerGrades(sport, name, cacheGetFn) {
|
||||
const env = await cacheGetFn(`grades:${sport}`);
|
||||
|
||||
Reference in New Issue
Block a user