feat: add Stella Sora, from the wiki's front page rather than its banner list

This wiki publishes the same schedule twice and the fuller surface is the worse
one. /wiki/Banner_List has 55 clean rows with full wall clocks and states no
timezone anywhere on the page; the front page's Current Banners module emits
the same instants as real <time datetime="...-07:00"> elements. The two agree
exactly, which is strong evidence the list is UTC and is still only evidence —
so we read the surface that says what it means and pay four live banners
instead of a full history for it. If an editor ever states the zone on
Banner_List, that page becomes the better source immediately.

Two ways this could have failed silently. The template writes its BEM
underscores as &#95;&#95;, so a selector written against the class name a
browser shows matches nothing at all; and banner names are red links to
?action=edit&redlink=1, which Miraheze's robots.txt disallows, so a href
carrying a query is refused and the page URL stands in.

No resetOffsets, and here the source did state an offset: -07:00, which is US
Pacific and therefore shifts twice a year. That is the Fate/Grand Order gap
arriving through a page that looks like it answered the question.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
Lucas Winther
2026-08-19 03:50:20 +02:00
co-authored by Claude Opus 5
parent 4dff14087f
commit ecbf9c0422
14 changed files with 1286 additions and 13 deletions
+8 -3
View File
@@ -10,7 +10,7 @@ import { z } from "zod";
export const GameId = z.enum([
"genshin", "hsr", "zzz", "wuwa", "arknights", "endfield", "nte", "nikki", "p5x", "r1999",
"ba", "fgo", "holodori", "gfl2",
"ba", "fgo", "holodori", "gfl2", "stellasora",
]);
export const EventType = z.enum([
@@ -310,13 +310,18 @@ logged under the old clock. Get it right at introduction or accept a migration.
Infinity Nikki, P5X and Blue Archive carry **no `resetOffsets`
entry**, so they take the regional default. That is an assumption, not a verified server map — none
of those sources states one. The 2026-08-19 addition below is worth separating out, because it is
silent for a different reason than the usual one:
of those sources states one. Two of the 2026-08-19 additions are worth separating out, because they
are silent for different reasons and neither is the usual one:
- **Girls' Frontline 2** states an exact UTC instant on every boundary, so the data is there and
still settles nothing: its EN events end at 22:59 (33 of them), 08:59 (11) and 02:59 (5). Arknights
and Reverse: 1999 each earned an override from a single boundary the whole page agreed on; three
of them is a patch window, not a reset hour.
- **Stella Sora** states an offset outright — `-07:00` — and that is precisely why it gets no entry.
`-07:00` is US Pacific in summer and `-08:00` in winter, so one fixed number is wrong for half the
year in either direction. This is the Fate/Grand Order gap, arriving through a source that looks
like it answered the question.
Blue Archive is the case where the assumption is most likely wrong and still the right entry: the
game does run one worldwide server, but `bluearchive.wiki` states no time of day and no timezone
+2
View File
@@ -55,6 +55,7 @@ Consequences worth internalising:
| `bawiki` | bluearchive.wiki's rendered `/wiki/Events` — a JP/Global tabber over `Name (EN) \| Start date \| End date \| Notes` wikitables | Blue Archive |
| `holodoriwiki` | holodori.wiki's rendered `/wiki/Events``Current Events` and `Past Events` wikitables over `Event \| Type \| Start Date \| End Date` | hololive Dreams |
| `iopwiki` | iopwiki.com's `gf-table event-period` tables — `Title \| Period (start/end) \| Server \| Type \| Comment`, one table per event and one row per server | Girls' Frontline 2 |
| `stellasorawiki` | stellasora.miraheze.org's front-page `Current Banners` module — `<time datetime>` pairs inside `stellasora-home-banner` blocks | Stella Sora |
`wikigg` is the better shape by a distance: it emits ISO timestamps with one timer per server
region, so its events carry exact precision and real `regionEnds`. Prefer a source like that over a
@@ -142,6 +143,7 @@ All live in `src/ingest/dates.ts`, each returning null rather than inferring any
| `parseIsoDay` | `2026-08-04` (one boundary per column, so nothing to split) | Blue Archive |
| `parseSlashClockZone` | `08/17/2026 8:00PM (JST)` (one boundary per column, 12-hour clock, **named** zone) | hololive Dreams |
| `parseIsoClockRangeUtc` | `2026-08-06 13:00 - 2026-08-26 22:59 (UTC)` (whole range in one cell, **zone required**, nothing converted) | Girls' Frontline 2 |
| `parseIsoOffsetInstant` | `2026-08-03T21:00-07:00` (a machine-readable `<time datetime>` attribute; **offset required**) | Stella Sora |
| `parseOpenRange` | `Jul. 24, 2026 - End of 4.6`, `July 10, 2026 - Permanent` | Star Rail, Wuthering Waves |
**A day-precision result is 00:00Z, and that is a placeholder rather than a time.** Every reader
+2 -2
View File
@@ -59,7 +59,7 @@ have a source — this table is the launch scope, not a roster to keep in sync.
Adding a game must require no change to `GachaEvent` — only a `GameId` entry, its `games.ts`
metadata, and a source registration. That is the test of whether the data model is right, and it has
held: the fourteen games here have cost the event schema nothing. Per-game *metadata* does occasionally
held: the fifteen games here have cost the event schema nothing. Per-game *metadata* does occasionally
grow (Reverse: 1999 needed `resetHourLocal` for a 05:00 reset), which is a different file and moves
no stored key. A game may have several sources; see `docs/INGESTION.md` § Three layers.
@@ -90,7 +90,7 @@ default `"game"` — the board every existing reader already has). Merged, the o
`endingSoonestFirst`, the same comparator behind the list's "Ending soonest" (F2), so the two views
cannot mean different things by the same words and an unannounced end still sorts behind every dated
one rather than claiming a place in the queue. Merged there is also no lane heading to say whose
event a bar is, and hue alone cannot answer that once fourteen games share a stack — so each bar
event a bar is, and hue alone cannot answer that once fifteen games share a stack — so each bar
carries its game's short name, with the full name in its tooltip. A bar too narrow for a tag and a
title both keeps the title: a chopped game name reads as a broken word, and the hue and the tooltip
still answer it.