feat(p5x): track Persona 5: The Phantom X
Adds the game and its Game8 events page, the second of the games named in
the release thread. `parseAdjacentFullRange` reads the shape this page
uses: two full dates divided by an `<hr>` rather than a dash, so a
tag-stripping reader sees only whitespace between them. It is anchored at
both ends and needs a year on each half, because without that "August 12,
2026 Day 3 rewards" reads "Day 3" as an end.
Three of the four live rows publish. "Take Your Heart" ends 30 days after
each player makes an account, so it has no calendar date and no honest
place on a calendar. "Login Campaigns" names two candidate ends
("July 16/30, 2026") — it keeps its real start and takes no end, and the
leftover is not shown as a summary either, since a date the parser
refused to trust must not reappear dressed as information.
The page lists each live event twice: once in a bare Event|Duration table
and again under its own heading with Start Date / End Date rows and a
paragraph of prose. The second copy corroborates the dates, so deduping
now fills a missing summary from the copy it drops. Dates are still taken
wholesale from the better-dated copy and never blended.
Verified by re-extracting the page independently of the parser: 4 rows,
3 events, the fourth correctly skipped.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
67951e81b4
commit
d8b539bce1
@@ -147,6 +147,37 @@ export function parseShortSlashRange(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* "July 30, 2026 August 13, 2026" → both instants.
|
||||
*
|
||||
* Game8 separates the two halves of a duration cell with `<hr>` rather than a
|
||||
* dash on some templates, and a tag-stripping reader sees only whitespace
|
||||
* between them. Both anchors and both years are required: without the anchors
|
||||
* this would happily read "August 12, 2026 Day 3 rewards" as a range, and a
|
||||
* bare "Month D" second half could belong to any year.
|
||||
*/
|
||||
export function parseAdjacentFullRange(
|
||||
input: string,
|
||||
): { start: ParsedInstant; end: ParsedInstant } | null {
|
||||
const re =
|
||||
/^\s*([A-Za-z]+)\.?\s+(\d{1,2}),\s*(\d{4})\s+([A-Za-z]+)\.?\s+(\d{1,2}),\s*(\d{4})\s*$/;
|
||||
const m = re.exec(input);
|
||||
if (!m) return null;
|
||||
|
||||
const startMonth = monthNumber(m[1] ?? "");
|
||||
const endMonth = monthNumber(m[4] ?? "");
|
||||
if (startMonth === null || endMonth === null) return null;
|
||||
|
||||
const startIso = iso(Number(m[3]), startMonth, Number(m[2]));
|
||||
const endIso = iso(Number(m[6]), endMonth, Number(m[5]));
|
||||
if (startIso === null || endIso === null) return null;
|
||||
|
||||
return {
|
||||
start: { iso: startIso, precision: "day" },
|
||||
end: { iso: endIso, precision: "day" },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* "Start: January 24, 2025 End: Permanent" → the start, and whatever the end
|
||||
* half turns out to be.
|
||||
|
||||
Reference in New Issue
Block a user