fix(games): put Infinity Nikki's America and Europe servers on their own clocks

Infinity Nikki resets at 04:00 on America UTC-7 and Europe UTC+2, not the
regional default, so the app rolled the day 2h early for American readers
and 1h late for European ones. Source: Game-Time-Master.

Re-labels the game-day of some already-logged ticks for those readers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-13 12:38:29 +02:00
1 parent 72fe6b618b
commit 32e252e381
3 files changed
+35 -6

No files matched your search

+6 -1
View File
@@ -81,7 +81,12 @@ export const GAMES: Record<GameId, GameMeta> = {
// and `america` already resolves to -5, so Europe is the only real override.
endfield: { id: "endfield", name: "Arknights: Endfield", short: "Endfield", hue: "#E8635A" , studio: "Hypergryph", dailyTasks: "Daily missions", resetOffsets: { europe: -5 } },
nte: { id: "nte", name: "Neverness to Everness", short: "NTE", hue: "#C77DFF" , studio: "Hotta Studio", dailyTasks: "Daily tasks" },
nikki: { id: "nikki", name: "Infinity Nikki", short: "Nikki", hue: "#F27BB0" , studio: "Infold Games", dailyTasks: "Daily tasks, Vital Energy" },
// Infinity Nikki resets at 04:00 server time on three servers, and two of them
// are not on the regional default: America runs UTC-7 and Europe UTC+2, per
// Game-Time-Master (github.com/cicerakes/Game-Time-Master). The Fandom wiki's
// Daily Wishes page agrees, and America's is fixed rather than Pacific — the
// December 2024 maintenance was still announced in UTC-7.
nikki: { id: "nikki", name: "Infinity Nikki", short: "Nikki", hue: "#F27BB0" , studio: "Infold Games", dailyTasks: "Daily tasks, Vital Energy", resetOffsets: { america: -7, europe: 2 } },
// No `resetOffsets`: nothing in the source states a server map that differs
// from the regional default, and an offset invented here would move real
// readers' day keys. Add one only against evidence — see games.ts § resetOffsets.
+7 -5
View File
@@ -1734,8 +1734,9 @@ describe("Infinity Nikki wiki (the fourth Fandom template)", () => {
// The row is dated "August 15, 2026 04:00 - August 22, 2026 03:59" and the
// clock is discarded, so `endsAt` is the 00:00Z placeholder. Retiring the
// row on that placeholder drops it nine hours before `clockFor` calls it
// over for an American reader — the reader watches the deadline they were
// counting down to vanish on its last day, which is a silent drop.
// over for an American reader — eleven, now that America is known to run
// UTC-7 — and the reader watches the deadline they were counting down to
// vanish on its last day, which is a silent drop.
const html = await Bun.file(`${fixture}.html`).text();
const at = (now: string) =>
nikki
@@ -1748,9 +1749,10 @@ describe("Infinity Nikki wiki (the fourth Fandom template)", () => {
.some((e) => e.title === "Inspiration Burst");
expect(at("2026-08-22T01:00:00.000Z")).toBe(true);
// 04:00 on the last server to roll, UTC-5. Past that it is over everywhere.
expect(at("2026-08-22T08:59:00.000Z")).toBe(true);
expect(at("2026-08-22T09:01:00.000Z")).toBe(false);
// 04:00 on the last server to roll, America's UTC-7. Past that it is over
// everywhere.
expect(at("2026-08-22T10:59:00.000Z")).toBe(true);
expect(at("2026-08-22T11:01:00.000Z")).toBe(false);
});
test("takes the printed date at day precision and drops the clock", async () => {
+22
View File
@@ -494,3 +494,25 @@ describe("catchUpDays", () => {
expect(catchUpDays(NOW, "europe", "genshin", null)).toHaveLength(CATCH_UP_DAYS);
});
});
describe("reset clocks, per server, as Game-Time-Master states them", () => {
// Each row is one game's server for one of our regions: the UTC instant its
// day rolls on, and the server's own UTC offset — the day key has to read as
// the server's calendar date, because a day-precision boundary resolves
// through it (time.ts § boundaryMs). Source for every row:
// github.com/cicerakes/Game-Time-Master, game-data.js.
const ROWS: [game: string, region: "asia" | "america" | "europe", utc: string, offset: number][] = [
["nikki", "asia", "20:00", 8],
["nikki", "america", "11:00", -7],
["nikki", "europe", "02:00", 2],
];
for (const [game, region, utc, offset] of ROWS) {
test(`${game} ${region} rolls at ${utc} UTC`, () => {
const reset = nextResetMs(at("2026-10-13T00:30:00Z"), region, game);
expect(new Date(reset).toISOString().slice(11, 16)).toBe(utc);
const serverDate = new Date(reset + offset * HOUR).toISOString().slice(0, 10);
expect(dayKey(reset, region, game)).toBe(serverDate);
});
}
});