Record the Honkai Impact 3rd source and what its dates are worth
SOURCES.md § 13 declined this game's only known source partly because every boundary was a week bucket, and we have now built a different source with that same objection standing. Leaving that contradiction unwritten is how a later pass rediscovers the trade the expensive way, so § 14 records the decision itself: the conduct evidence, which three of § 13's four objections arustats answers, which one it does not, and that any source stating a date per event retires it. § 13 is marked superseded rather than rewritten — its verdict on marisaimpact.com still stands and was not re-tested. AGENTS.md gets the same warning where a parser author will hit it, because the estimate is not visible from the code: the numbers look like every other day-precision date in the project. Also corrects the counts this game made false — nine parsers, twenty sources, nineteen games. The "stopped working at eighteen" passages are left alone: they date the settings-panel redesign, and bumping them would falsify the history rather than update a count. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c272d9e93d
commit
7864ba6241
@@ -37,8 +37,8 @@ A web app that aggregates live and upcoming events across popular gacha games, p
|
|||||||
calendar, sorts them by end date or by what the reader is partway through, tracks day-by-day
|
calendar, sorts them by end date or by what the reader is partway through, tracks day-by-day
|
||||||
progress on events that repeat daily, and lets a user mark events completed.
|
progress on events that repeat daily, and lets a user mark events completed.
|
||||||
|
|
||||||
**Status: working app, refreshing itself on a schedule.** Schema, eight parsers, nineteen sources across
|
**Status: working app, refreshing itself on a schedule.** Schema, nine parsers, twenty sources across
|
||||||
eighteen games, the full interface, offline support, a static server, a Docker image and CI all exist and
|
nineteen games, the full interface, offline support, a static server, a Docker image and CI all exist and
|
||||||
are tested. The refresh runner (`bun run refresh`) fetches, caches raw snapshots and rebuilds the
|
are tested. The refresh runner (`bun run refresh`) fetches, caches raw snapshots and rebuilds the
|
||||||
feed; `.github/workflows/refresh.yml` runs it twice a day and commits only when a page actually
|
feed; `.github/workflows/refresh.yml` runs it twice a day and commits only when a page actually
|
||||||
changed. The SQLite layer and the review queue are still specified in `docs/` but not built, so the
|
changed. The SQLite layer and the review queue are still specified in `docs/` but not built, so the
|
||||||
@@ -144,7 +144,7 @@ src/client/ React app, service worker, manifest
|
|||||||
theme.ts — dark or light, and what a game hue reads as on each
|
theme.ts — dark or light, and what a game hue reads as on each
|
||||||
scripts/ build-feed.ts, build-static.ts, parse-fixture.ts (offline), refresh-sources.ts (fetches)
|
scripts/ build-feed.ts, build-static.ts, parse-fixture.ts (offline), refresh-sources.ts (fetches)
|
||||||
serve.ts static server + /api/health
|
serve.ts static server + /api/health
|
||||||
test/ 831 tests
|
test/ 898 tests
|
||||||
fixtures/<game>/ raw HTML + .expected.json per source — pinned, kept forever
|
fixtures/<game>/ raw HTML + .expected.json per source — pinned, kept forever
|
||||||
snapshots/ current page per source, rewritten by refresh — see its README
|
snapshots/ current page per source, rewritten by refresh — see its README
|
||||||
```
|
```
|
||||||
@@ -196,10 +196,13 @@ These come from how gacha games actually schedule things, and they cause most bu
|
|||||||
year, month, or end. `readColumnTable` drops a row it cannot date. An omitted event is a
|
year, month, or end. `readColumnTable` drops a row it cannot date. An omitted event is a
|
||||||
recoverable disappointment; a confidently wrong date is the failure this product exists to prevent.
|
recoverable disappointment; a confidently wrong date is the failure this product exists to prevent.
|
||||||
- **Parsers are keyed by site, not game.** One `game8` parser serves nine sources and `fandom` four;
|
- **Parsers are keyed by site, not game.** One `game8` parser serves nine sources and `fandom` four;
|
||||||
`wikigg`, `akwiki`, `bawiki`, `holodoriwiki`, `iopwiki` and `stellasorawiki` serve one each — the first two share a host family
|
`wikigg`, `akwiki`, `bawiki`, `holodoriwiki`, `iopwiki`, `stellasorawiki` and `arustats` serve one
|
||||||
and have entirely different templates, and the last two are both Miraheze wikis whose page
|
each — `wikigg` and `akwiki` share a host family and have entirely different templates, and
|
||||||
templates have nothing in common. Adding a source for a known site is one `SOURCES` entry; a new
|
`bawiki`, `holodoriwiki` and `stellasorawiki` are all Miraheze wikis whose page templates have
|
||||||
site is a parser module.
|
nothing in common. `arustats` is the odd one out and the only parser here that does not read
|
||||||
|
markup at all: that site server-renders its schedule into a Next.js `__NEXT_DATA__` blob, so the
|
||||||
|
parser reads JSON and the rendered grid is ignored. Adding a source for a known site is one
|
||||||
|
`SOURCES` entry; a new site is a parser module.
|
||||||
- **A source may publish more than one region's schedule.** Arknights' wiki lists CN and Global on
|
- **A source may publish more than one region's schedule.** Arknights' wiki lists CN and Global on
|
||||||
every row, five months apart. Publish the one our readers are on and skip the row that lacks it —
|
every row, five months apart. Publish the one our readers are on and skip the row that lacks it —
|
||||||
a CN date on a Global calendar is a confidently wrong date, not a near miss.
|
a CN date on a Global calendar is a confidently wrong date, not a near miss.
|
||||||
@@ -309,11 +312,11 @@ Sources are community wikis. Treat them as a guest would:
|
|||||||
the obligation. What makes it defensible is what it does *not* change: conditional headers still go
|
the obligation. What makes it defensible is what it does *not* change: conditional headers still go
|
||||||
out, so a page that has not moved costs the host a `304` rather than a re-serve, and per-host
|
out, so a page that has not moved costs the host a `304` rather than a re-serve, and per-host
|
||||||
spacing, robots, the one-request-per-source rule and the no-retry rule all still apply. Prefer it
|
spacing, robots, the one-request-per-source rule and the no-retry rule all still apply. Prefer it
|
||||||
with `--only`: forcing nineteen sources to re-ask a question they answered an hour ago is the
|
with `--only`: forcing twenty sources to re-ask a question they answered an hour ago is the
|
||||||
behaviour this bullet exists to prevent, whatever flag authorised it. The run names every source it
|
behaviour this bullet exists to prevent, whatever flag authorised it. The run names every source it
|
||||||
asked early, and a run that was due anyway is never reported as forced.
|
asked early, and a run that was due anyway is never reported as forced.
|
||||||
- **Space requests to one host**, honouring its `Crawl-delay` and defaulting to 2s. Nine of the
|
- **Space requests to one host**, honouring its `Crawl-delay` and defaulting to 2s. Nine of the
|
||||||
nineteen sources are game8.co pages, so the per-source floor alone still permits one cycle to arrive
|
twenty sources are game8.co pages, so the per-source floor alone still permits one cycle to arrive
|
||||||
as nine back-to-back requests to a single site — which is the shape an edge network throttles, and
|
as nine back-to-back requests to a single site — which is the shape an edge network throttles, and
|
||||||
what a burst looks like from the far end regardless of our intent.
|
what a burst looks like from the far end regardless of our intent.
|
||||||
- Send `If-None-Match` / `If-Modified-Since`; treat `304` as "skip, unchanged".
|
- Send `If-None-Match` / `If-Modified-Since`; treat `304` as "skip, unchanged".
|
||||||
@@ -365,6 +368,7 @@ re-litigated each pass:
|
|||||||
| `guardian-tales.fandom.com` | **Declined.** Parses fine and contains no 2026 date at all — newest dated entry is 2025. The `bluearchive.fandom.com` failure again: parses cleanly to nothing live |
|
| `guardian-tales.fandom.com` | **Declined.** Parses fine and contains no 2026 date at all — newest dated entry is 2025. The `bluearchive.fandom.com` failure again: parses cleanly to nothing live |
|
||||||
| `blhx.fandom.com`, `azurlane-archive.fandom.com` | **Declined.** The two Fandom alternatives to the declined koumakan wiki are dead archives — `Event_Calendar` stops in **2021**, and the archive wiki's headings have nothing under them. Azur Lane still has no source |
|
| `blhx.fandom.com`, `azurlane-archive.fandom.com` | **Declined.** The two Fandom alternatives to the declined koumakan wiki are dead archives — `Event_Calendar` stops in **2021**, and the archive wiki's headings have nothing under them. Azur Lane still has no source |
|
||||||
| Aether Gazer | **Do not build.** The developer confirmed no further content updates after 23 July 2026, with store listings removed 17 October 2026. The wiki dates nothing anyway — `Event_Guide_List` is an image gallery. A lane that will be empty by winter |
|
| Aether Gazer | **Do not build.** The developer confirmed no further content updates after 23 July 2026, with store listings removed 17 October 2026. The wiki dates nothing anyway — `Event_Guide_List` is an image gallery. A lane that will be empty by winter |
|
||||||
|
| `arustats.com` (Honkai Impact 3rd) | **Built** (2026-08-27), and the only source here that publishes **estimated** dates — see § Honkai Impact 3rd below before touching it. `robots.txt` is `Allow: /` for `*` with `/hi3/*` and `/en-us/*` named explicitly, no `Disallow`, no `Content-Signal`, `Crawl-delay: 1`. Solves the per-version URL problem `marisaimpact` failed: `/en-us/hi3/timeline` answers `307` to the live version |
|
||||||
| `marisaimpact.com` (Honkai Impact 3rd) | **Declined** (2026-08-19). Conduct is clear — its `robots.txt` is comments only, with no directive and no `Content-Signal`, and the page answers our own `User-Agent` with a `200`. The data is the problem: the schedule is a grid of week columns headed `Estimated date for Regional Servers` under a page that says `Based on CN server`, it states **no year anywhere**, and it lives at a per-version URL — `/calendar89` is v8.9 and expires on 20 August, with no stable route to the current one. `docs/SOURCES.md` § 13 |
|
| `marisaimpact.com` (Honkai Impact 3rd) | **Declined** (2026-08-19). Conduct is clear — its `robots.txt` is comments only, with no directive and no `Content-Signal`, and the page answers our own `User-Agent` with a `200`. The data is the problem: the schedule is a grid of week columns headed `Estimated date for Regional Servers` under a page that says `Based on CN server`, it states **no year anywhere**, and it lives at a per-version URL — `/calendar89` is v8.9 and expires on 20 August, with no stable route to the current one. `docs/SOURCES.md` § 13 |
|
||||||
| game8.co hubs for Black Beacon, Brawl Stars, Destiny: Rising, Diablo Immortal, Epic Seven, Fire Emblem Shadows, Gundam UC Engage, Mongil: Star Dive, Pokémon Champions, Pokémon UNITE, Tower of Fantasy | **Declined** (2026-08-19). All thirteen hubs in that sweep exist and answer `200`; these eleven have no usable schedule. Six are abandoned wikis whose newest page is 2021–2025 — the Infinity Nikki failure mode, a source that parses perfectly and publishes history. Gundam's calendar prints ends with no starts, so no event ID; Pokémon UNITE is fresh but its template fails `canParse`, which is the check working. Per-game evidence in `docs/SOURCES.md` § 12 |
|
| game8.co hubs for Black Beacon, Brawl Stars, Destiny: Rising, Diablo Immortal, Epic Seven, Fire Emblem Shadows, Gundam UC Engage, Mongil: Star Dive, Pokémon Champions, Pokémon UNITE, Tower of Fantasy | **Declined** (2026-08-19). All thirteen hubs in that sweep exist and answer `200`; these eleven have no usable schedule. Six are abandoned wikis whose newest page is 2021–2025 — the Infinity Nikki failure mode, a source that parses perfectly and publishes history. Gundam's calendar prints ends with no starts, so no event ID; Pokémon UNITE is fresh but its template fails `canParse`, which is the check working. Per-game evidence in `docs/SOURCES.md` § 12 |
|
||||||
| `game8.co/games/MementoMori`, `game8.co/games/fire-emblem-heroes` | **Assessed, not yet built** (2026-08-19) — the two live finds of that sweep, and proposals rather than decisions. MementoMori parses today with no parser change; FEH has the freshest page of any source here and needs a ninth Game8 column shape plus a ruling on the 180-day rule, which one real seven-month banner breaks. See `docs/SOURCES.md` §§ 12a–12b |
|
| `game8.co/games/MementoMori`, `game8.co/games/fire-emblem-heroes` | **Assessed, not yet built** (2026-08-19) — the two live finds of that sweep, and proposals rather than decisions. MementoMori parses today with no parser change; FEH has the freshest page of any source here and needs a ninth Game8 column shape plus a ruling on the 180-day rule, which one real seven-month banner breaks. See `docs/SOURCES.md` §§ 12a–12b |
|
||||||
@@ -740,6 +744,47 @@ Stella Sora takes no `resetOffsets` either, and for the opposite reason to most:
|
|||||||
outright, and the offset is `-07:00` — US Pacific, which shifts by an hour twice a year. That is the
|
outright, and the offset is `-07:00` — US Pacific, which shifts by an hour twice a year. That is the
|
||||||
Fate/Grand Order problem arriving through a source that looks like it answered the question.
|
Fate/Grand Order problem arriving through a source that looks like it answered the question.
|
||||||
|
|
||||||
|
**Honkai Impact 3rd: the one source here whose dates are estimates, and the only one whose URL
|
||||||
|
tracks itself.** `arustats.com` publishes a per-version timeline, and both halves of that sentence
|
||||||
|
matter.
|
||||||
|
|
||||||
|
- **The URL is version-less on purpose, and must stay that way.**
|
||||||
|
`/en-us/hi3/timeline` answers `307` to the live version — `/en-us/hi3/timeline/9.0` today — so the
|
||||||
|
site names its own current version server-side and the runner's `redirect: "follow"` lands on it.
|
||||||
|
That is the stable route `docs/SOURCES.md` § 13 recorded `marisaimpact.com` as lacking, and it is
|
||||||
|
why this game needs no scheduled URL edit. **Pinning `/9.0` in `SOURCES` would publish a finished
|
||||||
|
schedule as current the day 9.1 ships** — § 11's stale-source failure on a six-week clock. A test
|
||||||
|
asserts the registered URL carries no version.
|
||||||
|
- **Every boundary it publishes is an estimate, which nothing else here does.** The page schedules by
|
||||||
|
*week bucket*: an event is a bar spanning whole week columns, no event states a date of its own,
|
||||||
|
and the header over the grid reads `GLB/SEA` / `ESTIMATED WEEK`. So a start or end from this source
|
||||||
|
is the edge of a bucket the site estimated, not a date anybody announced. That is a weaker claim
|
||||||
|
than the day-precision reading Game8 and Infinity Nikki get, where the page did print a date per
|
||||||
|
event and we only declined to invent a time of day for it.
|
||||||
|
- **It was built with that cost named, not overlooked.** `docs/SOURCES.md` § 13 declined
|
||||||
|
`marisaimpact.com` on this exact ground; § 14 records the decision to take the trade here anyway
|
||||||
|
(repository owner, 2026-08-27) and what would retire it. `ESTIMATE_CONFIDENCE` (0.4, in
|
||||||
|
`parsers/arustats.ts`) is what carries the fact into the data, well below the 0.85–0.95 a
|
||||||
|
date-stating source earns — so a real Honkai Impact 3rd source outranks this one on `mergeEvents`
|
||||||
|
automatically, with nobody having to remember to remove it. **Do not raise that number** without
|
||||||
|
re-opening the decision.
|
||||||
|
- **Nothing on screen says "estimated" yet.** `confidence` is not read anywhere in `src/client/`, so
|
||||||
|
the reader currently sees this lane exactly as they see a wiki-sourced one. That is a known gap
|
||||||
|
rather than an oversight: saying so in the UI needs a schema field or a client change, which
|
||||||
|
§ Adding a game source calls a design question rather than adapter work. If this source stays,
|
||||||
|
that gap is the thing to close next.
|
||||||
|
- **Two shapes to know.** `startsAt` is half of every event ID, so an estimated start the site
|
||||||
|
revises moves IDs and orphans completion marks — a hazard the wiki sources do not carry. And
|
||||||
|
`endWeek` is *exclusive* and runs one past the grid to mean "to the end of the version"; an index
|
||||||
|
further out than that is skipped rather than clamped, because pinning an unreadable bar to the
|
||||||
|
version's edge would be inventing the boundary.
|
||||||
|
|
||||||
|
Also unlike everything else here, this parser reads no markup: the site is Next.js and
|
||||||
|
server-renders the schedule into `__NEXT_DATA__`, so the parser reads that JSON and ignores the
|
||||||
|
grid. `canParse` asserts the blob, the week array and its dates, so a redesign fails the source
|
||||||
|
rather than emptying the lane. The host sends neither `ETag` nor `Last-Modified`, so conditional
|
||||||
|
requests buy nothing and the 6h floor is the only thing sparing it — do not lower it here.
|
||||||
|
|
||||||
`scripts/refresh-sources.ts` enforces all of the above in code — the 6h floor (except under the
|
`scripts/refresh-sources.ts` enforces all of the above in code — the 6h floor (except under the
|
||||||
opt-in `--force` above), one request, no retries, conditional headers, per-host spacing, robots
|
opt-in `--force` above), one request, no retries, conditional headers, per-host spacing, robots
|
||||||
(failing closed when `robots.txt` cannot be read, except under the opt-in `--assume-robots-on-403`
|
(failing closed when `robots.txt` cannot be read, except under the opt-in `--assume-robots-on-403`
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
export const GameId = z.enum([
|
export const GameId = z.enum([
|
||||||
"genshin", "hsr", "zzz", "wuwa", "arknights", "endfield", "nte", "nikki", "p5x", "r1999",
|
"genshin", "hsr", "zzz", "wuwa", "arknights", "endfield", "nte", "nikki", "p5x", "r1999",
|
||||||
"ba", "fgo", "holodori", "gfl2", "stellasora", "czn", "uma", "nikke",
|
"ba", "fgo", "holodori", "gfl2", "stellasora", "czn", "uma", "nikke", "hi3",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const EventType = z.enum([
|
export const EventType = z.enum([
|
||||||
|
|||||||
@@ -56,11 +56,18 @@ Consequences worth internalising:
|
|||||||
| `holodoriwiki` | holodori.wiki's rendered `/wiki/Events` — `Current Events` and `Past Events` wikitables over `Event \| Type \| Start Date \| End Date` | hololive Dreams |
|
| `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 |
|
| `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 |
|
| `stellasorawiki` | stellasora.miraheze.org's front-page `Current Banners` module — `<time datetime>` pairs inside `stellasora-home-banner` blocks | Stella Sora |
|
||||||
|
| `arustats` | arustats.com's Next.js `__NEXT_DATA__` blob — a per-version week grid, with events carrying `startWeek`/`endWeek` **integers** rather than dates. **Estimated boundaries** — see AGENTS.md § Honkai Impact 3rd | Honkai Impact 3rd |
|
||||||
|
|
||||||
`wikigg` is the better shape by a distance: it emits ISO timestamps with one timer per server
|
`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
|
region, so its events carry exact precision and real `regionEnds`. Prefer a source like that over a
|
||||||
prose wiki when both exist, and give it a higher `priority`.
|
prose wiki when both exist, and give it a higher `priority`.
|
||||||
|
|
||||||
|
`arustats` is the outlier on precision rather than on markup, and it is the only source in the
|
||||||
|
project that does not publish a date per event: its page schedules by week bucket and labels the grid
|
||||||
|
`ESTIMATED WEEK`, so every boundary it emits is an estimate. It carries `confidence: 0.4` for that
|
||||||
|
reason, against the 0.85–0.95 everything else earns, which is also what makes `mergeEvents` prefer
|
||||||
|
any real source that replaces it. Read AGENTS.md § Honkai Impact 3rd before changing it.
|
||||||
|
|
||||||
`fandom` is the only parser whose body is not HTML: it reads an `action=parse` JSON envelope and
|
`fandom` is the only parser whose body is not HTML: it reads an `action=parse` JSON envelope and
|
||||||
takes the rendered wikitext out of `parse.text`. That is not a preference — the rendered page is
|
takes the rendered wikitext out of `parse.text`. That is not a preference — the rendered page is
|
||||||
behind a Cloudflare challenge and the API is the surface the wiki's `robots.txt` allows, so the
|
behind a Cloudflare challenge and the API is the surface the wiki's `robots.txt` allows, so the
|
||||||
|
|||||||
+2
-2
@@ -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`
|
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
|
metadata, and a source registration. That is the test of whether the data model is right, and it has
|
||||||
held: the eighteen games here have cost the event schema nothing. Per-game *metadata* does occasionally
|
held: the nineteen 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
|
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.
|
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
|
`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
|
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
|
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 eighteen games share a stack — so each bar
|
event a bar is, and hue alone cannot answer that once nineteen 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
|
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
|
title both keeps the title: a chopped game name reads as a broken word, and the hue and the tooltip
|
||||||
still answer it.
|
still answer it.
|
||||||
|
|||||||
+68
-1
@@ -58,6 +58,7 @@ Two things this method cannot tell you, and both matter:
|
|||||||
| Punishing: Gray Raven, Guardian Tales, Aether Gazer | Declined — see §§ 6, 7, 9 |
|
| Punishing: Gray Raven, Guardian Tales, Aether Gazer | Declined — see §§ 6, 7, 9 |
|
||||||
| Infinity Nikki | **Rebuilt** (2026-08-19) on `infinity-nikki.fandom.com` at day precision, replacing a Game8 page stale since August 2025 — see § 11 |
|
| Infinity Nikki | **Rebuilt** (2026-08-19) on `infinity-nikki.fandom.com` at day precision, replacing a Game8 page stale since August 2025 — see § 11 |
|
||||||
| Silver Palace | Unreleased |
|
| Silver Palace | Unreleased |
|
||||||
|
| Honkai Impact 3rd | **Built** (2026-08-27) on `arustats.com`, and the only lane here whose dates are **estimates** — see § 14 |
|
||||||
|
|
||||||
## Summary of findings
|
## Summary of findings
|
||||||
|
|
||||||
@@ -467,7 +468,7 @@ table.
|
|||||||
|
|
||||||
**One cost applies to both builds and should be in the commit message, not discovered later.** Both
|
**One cost applies to both builds and should be in the commit message, not discovered later.** Both
|
||||||
candidates are game8.co, which does not answer the Actions runner (`AGENTS.md` § Scraping conduct).
|
candidates are game8.co, which does not answer the Actions runner (`AGENTS.md` § Scraping conduct).
|
||||||
Nine of the nineteen sources are game8 pages today, now that Infinity Nikki has moved to Fandom
|
Nine of the twenty sources are game8 pages today, now that Infinity Nikki has moved to Fandom
|
||||||
(§ 11); these would make ten and eleven. Each is a lane fixture-backed in CI from day one and only
|
(§ 11); these would make ten and eleven. Each is a lane fixture-backed in CI from day one and only
|
||||||
ever as fresh as someone's last manual `bun run refresh`, and one more request to a single host every
|
ever as fresh as someone's last manual `bun run refresh`, and one more request to a single host every
|
||||||
cycle — the per-host arithmetic § Scraping conduct already calls uncomfortable.
|
cycle — the per-host arithmetic § Scraping conduct already calls uncomfortable.
|
||||||
@@ -674,6 +675,72 @@ an estimate over the CN one — plus a stable URL for the current version, or an
|
|||||||
Any two of the three still leaves the other. No alternative HI3 source was looked for in this pass, so
|
Any two of the three still leaves the other. No alternative HI3 source was looked for in this pass, so
|
||||||
the game is unsourced rather than declined outright.
|
the game is unsourced rather than declined outright.
|
||||||
|
|
||||||
|
**Superseded 2026-08-27.** The alternative this section did not look for exists — `arustats.com`,
|
||||||
|
§ 14 below — and it answers three of the four objections above. `marisaimpact.com` itself stays
|
||||||
|
declined on all four; nothing here has been re-tested and this verdict is not the live one for the
|
||||||
|
game.
|
||||||
|
|
||||||
|
## 14. Honkai Impact 3rd — BUILT 2026-08-27, on estimated week buckets, by decision
|
||||||
|
|
||||||
|
**Source:** `https://www.arustats.com/en-us/hi3/timeline` — AruStats' per-version timeline. Assessed
|
||||||
|
on request as an alternative to the `marisaimpact.com` page § 13 declined, and built with one of
|
||||||
|
§ 13's four objections still standing.
|
||||||
|
|
||||||
|
**Conduct is clean, and better than most things here.** `robots.txt` is `User-agent: *` / `Allow: /`
|
||||||
|
with `/hi3/*` and `/en-us/*` named explicitly, no `Disallow` anywhere, no `Content-Signal` header and
|
||||||
|
none of the named AI-crawler blocks; `Crawl-delay: 1`, far below our 6h floor. Verified through the
|
||||||
|
real `RobotsCache` and the runner's own User-Agent rather than `curl` — `robots.txt ok`,
|
||||||
|
`crawlDelayMs: 1000` — per AGENTS.md § Fandom on why the instrument matters. The page carries its own
|
||||||
|
"not affiliated with miHoYo" attribution line, and the host advertises a sitemap.
|
||||||
|
|
||||||
|
**Three of § 13's four objections are answered:**
|
||||||
|
|
||||||
|
| § 13 objection | Here |
|
||||||
|
|---|---|
|
||||||
|
| Dates are CN estimates redrawn for regions | The grid is headed `GLB/SEA` — our readers' server, not a CN schedule with an estimate over it |
|
||||||
|
| No year appears anywhere | `scheduleDates` states full dates with years — `2026-8-20`, `2026-10-22` |
|
||||||
|
| The URL is per-version with no stable route | **`/en-us/hi3/timeline` answers `307` to the live version.** The site names its own current version server-side; the runner follows it and no URL ever needs editing |
|
||||||
|
| The unit is a week column, not an event boundary | **Still true.** Unchanged, and it is the whole cost below |
|
||||||
|
|
||||||
|
**The objection that stands.** No event on the page states a date. Events are bars carrying
|
||||||
|
`startWeek` / `endWeek` *integers* into a nine-column week grid, and the header over that grid reads
|
||||||
|
`ESTIMATED WEEK`. So every boundary this source publishes is the edge of a bucket the site estimated.
|
||||||
|
That is weaker than the day-precision reading Game8 and Infinity Nikki get — there the page printed a
|
||||||
|
date per event and we declined only to invent a time of day for it — and § 13 declined
|
||||||
|
`marisaimpact.com` on exactly this ground.
|
||||||
|
|
||||||
|
**It was built anyway, and that is a decision rather than an oversight** (repository owner,
|
||||||
|
2026-08-27, with the cost stated before the adapter was written). The reasoning: Honkai Impact 3rd
|
||||||
|
had no source at all, this page is otherwise healthy and current, and a lane of approximate
|
||||||
|
six-week windows was judged better than no lane. Be exact about what that buys and what it costs:
|
||||||
|
|
||||||
|
- **What is honest about it.** The week grid's *outer* boundaries are real and independently
|
||||||
|
checkable: v8.9 reads `2026-6-25` → `2026-8-20` and v9.0 picks up at `2026-8-20` → `2026-10-22`,
|
||||||
|
which are the version's actual maintenance dates and chain exactly. Sixteen bars on the page yield
|
||||||
|
sixteen events, so nothing is silently dropped.
|
||||||
|
- **What is not.** Where a banner swaps *inside* a version is the estimated part, and those are most
|
||||||
|
of the boundaries. `startsAt` is also half of every event ID, so a week grid the site revises moves
|
||||||
|
IDs and orphans completion marks — a hazard no wiki source here carries.
|
||||||
|
- **How the fact is carried.** `ESTIMATE_CONFIDENCE` (0.4) on every event, against the 0.85–0.95 a
|
||||||
|
date-stating source earns. `mergeEvents` prefers the higher number, so a real HI3 source outranks
|
||||||
|
this one the moment one is added, with no cleanup step to forget.
|
||||||
|
- **The gap left open.** `confidence` is read nowhere in `src/client/`, so nothing on screen tells a
|
||||||
|
reader this lane is estimated while every other lane is announced. Closing that needs a schema
|
||||||
|
field or a client change — a design question, not adapter work — and it is the obvious next step
|
||||||
|
if this source stays.
|
||||||
|
|
||||||
|
**What would retire it:** any HI3 source that states a date per event. That is a strictly lower bar
|
||||||
|
than § 13's list, and this source outranks nothing — it is the floor, not the ceiling.
|
||||||
|
|
||||||
|
**The markup, so nobody re-derives it.** The site is Next.js and server-renders the whole schedule
|
||||||
|
into `__NEXT_DATA__` (`props.pageProps.timeline`), so `parsers/arustats.ts` reads JSON and ignores the
|
||||||
|
rendered grid entirely — the bars carry their geometry in Tailwind `col-span-N` classes and their
|
||||||
|
offsets in bare spacer `<div>`s, which a DOM reader would have to count positionally. `endWeek` is
|
||||||
|
exclusive and runs one past the grid to mean "to the end of the version". `scheduleBosses` is the
|
||||||
|
only exactly-dated material on the page (Abyss and Memorial Arena openings, three a week) and is
|
||||||
|
deliberately unread: a recurring rotation with no end is not a deadline, and `endsAt: null` on each
|
||||||
|
would render them live-with-unknown-end forever.
|
||||||
|
|
||||||
## What every one of these costs, beyond the source
|
## What every one of these costs, beyond the source
|
||||||
|
|
||||||
Adding a game is never only a `SOURCES` entry:
|
Adding a game is never only a `SOURCES` entry:
|
||||||
|
|||||||
Reference in New Issue
Block a user