Pure function that derives canonical (name, year) identity from a scoring_events row, stripping trailing 4-digit years from the name or falling back to eventDate. Used by the Phase 2 backfill to group per-window events into canonical tournaments.
57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
/**
|
|
* Pure function(s) for extracting canonical tournament identity
|
|
* (name + year) from a `scoring_events` row.
|
|
*
|
|
* Used by the Phase 2 backfill to group per-window events into
|
|
* canonical `tournaments` rows.
|
|
*/
|
|
|
|
export interface ScoringEventInput {
|
|
name: string;
|
|
eventDate: string | null;
|
|
eventType: string;
|
|
}
|
|
|
|
export interface TournamentIdentity {
|
|
/** Tournament name with any trailing 4-digit year stripped. */
|
|
name: string;
|
|
year: number;
|
|
}
|
|
|
|
const TRAILING_YEAR_RE = / (\d{4})$/;
|
|
|
|
/**
|
|
* Extracts the canonical `(name, year)` identity for a tournament
|
|
* from a scoring event.
|
|
*
|
|
* Resolution order for year:
|
|
* 1. A trailing 4-digit year on the event name (e.g. "Wimbledon 2026").
|
|
* The year is stripped from the returned name.
|
|
* 2. The first 4 characters of `eventDate` (format `YYYY-MM-DD`).
|
|
*
|
|
* Throws if neither source supplies a year.
|
|
*/
|
|
export function extractTournamentIdentity(
|
|
ev: ScoringEventInput,
|
|
): TournamentIdentity {
|
|
const trimmedName = ev.name.trim();
|
|
const match = trimmedName.match(TRAILING_YEAR_RE);
|
|
|
|
if (match) {
|
|
const yearFromName = Number(match[1]);
|
|
const nameWithoutYear = trimmedName.slice(0, match.index).trim();
|
|
return { name: nameWithoutYear, year: yearFromName };
|
|
}
|
|
|
|
if (ev.eventDate) {
|
|
const yearStr = ev.eventDate.slice(0, 4);
|
|
const yearFromDate = Number(yearStr);
|
|
if (Number.isFinite(yearFromDate) && yearStr.length === 4) {
|
|
return { name: trimmedName, year: yearFromDate };
|
|
}
|
|
}
|
|
|
|
throw new Error(
|
|
`cannot determine year for scoring event "${ev.name}" (eventDate=${ev.eventDate ?? "null"})`,
|
|
);
|
|
}
|