scripts: add extractTournamentIdentity helper for backfill
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.
This commit is contained in:
parent
7168c85ae2
commit
85bca8bb77
2 changed files with 101 additions and 0 deletions
44
scripts/backfill/__tests__/match-tournament.test.ts
Normal file
44
scripts/backfill/__tests__/match-tournament.test.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { extractTournamentIdentity } from "../match-tournament";
|
||||||
|
|
||||||
|
describe("extractTournamentIdentity", () => {
|
||||||
|
it("uses eventDate year when the name has no trailing year", () => {
|
||||||
|
const identity = extractTournamentIdentity({
|
||||||
|
name: "Masters Tournament",
|
||||||
|
eventDate: "2026-04-09",
|
||||||
|
eventType: "tournament",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(identity).toEqual({ name: "Masters Tournament", year: 2026 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("derives the year from eventDate for a simple tournament name", () => {
|
||||||
|
const identity = extractTournamentIdentity({
|
||||||
|
name: "Wimbledon",
|
||||||
|
eventDate: "2026-07-01",
|
||||||
|
eventType: "tournament",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(identity).toEqual({ name: "Wimbledon", year: 2026 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("strips a trailing year from the name and uses it as the canonical year", () => {
|
||||||
|
const identity = extractTournamentIdentity({
|
||||||
|
name: "Wimbledon 2026",
|
||||||
|
eventDate: "2026-07-01",
|
||||||
|
eventType: "tournament",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(identity).toEqual({ name: "Wimbledon", year: 2026 });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws when neither the name nor eventDate supply a year", () => {
|
||||||
|
expect(() =>
|
||||||
|
extractTournamentIdentity({
|
||||||
|
name: "Wimbledon",
|
||||||
|
eventDate: null,
|
||||||
|
eventType: "tournament",
|
||||||
|
}),
|
||||||
|
).toThrow(/cannot determine year/);
|
||||||
|
});
|
||||||
|
});
|
||||||
57
scripts/backfill/match-tournament.ts
Normal file
57
scripts/backfill/match-tournament.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* 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"})`,
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue