feat(routines): Genshin's weekly and monthly built-ins
Weekly Bosses, Battle Pass weekly EXP, Reputation Bounties and Requests, the Realm Depot, Paimon's Bargains (Intertwined Fates), Spiral Abyss and Imaginarium Theater, each from a dated wiki page and confirmed in game by the owner. Records the one exception to "a page states it": a figure the owner confirmed in game says so in its note, with the day, and a test holds it. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
f322061c88
commit
af6a02cb34
@@ -62,6 +62,8 @@ export interface GameMeta {
|
||||
}
|
||||
|
||||
export const GAMES: Record<GameId, GameMeta> = {
|
||||
// EU reset at 04:00 UTC+1 confirmed in game by the owner on 2026-10-16: the
|
||||
// Trounce Domains menu reads "every Monday 4AM GMT+1".
|
||||
genshin: { id: "genshin", name: "Genshin Impact", short: "Genshin", hue: "#4EA8DE" , studio: "HoYoverse", dailyTasks: "Commissions, resin" },
|
||||
hsr: { id: "hsr", name: "Honkai: Star Rail", short: "Star Rail", hue: "#7B8CFF" , studio: "HoYoverse", dailyTasks: "Daily training, Trailblaze Power" },
|
||||
zzz: { id: "zzz", name: "Zenless Zone Zero", short: "ZZZ", hue: "#F2A03D" , studio: "HoYoverse", dailyTasks: "Daily missions, battery" },
|
||||
|
||||
@@ -14,6 +14,11 @@ import { MeasureSchema, type TaskShape } from "./task.ts";
|
||||
* then visibly ten months old rather than presented as current. Nothing here is
|
||||
* inferred; add one only when a page states it.
|
||||
*
|
||||
* The one exception is a figure the repository owner confirmed in the game
|
||||
* when no page states it (owner, 2026-10-14). It still links the best page
|
||||
* there is, and its `note` says `Confirmed in game, YYYY-MM-DD.` so the reader
|
||||
* can tell which figure is ours rather than the page's.
|
||||
*
|
||||
* Off unless the reader says yes — for every game (`prefs.showRoutines`) or for
|
||||
* one (`prefs.routineGames`, `prefs.routinesOff`; see `perGame.ts`). Its id is in
|
||||
* the reserved `routine:` space, and its ticks and numbers are stored under that
|
||||
@@ -37,6 +42,102 @@ export const RoutineSchema = z.object({
|
||||
export type Routine = z.infer<typeof RoutineSchema> & TaskShape;
|
||||
|
||||
export const ROUTINES: readonly Routine[] = [
|
||||
// Genshin Impact. Every weekly item rolls with the Monday reset, which each
|
||||
// page states for itself; the monthly two name their own day.
|
||||
{
|
||||
id: "routine:genshin:weekly-bosses",
|
||||
game: "genshin",
|
||||
title: "Weekly Bosses",
|
||||
period: { unit: "week", startsOn: 1 },
|
||||
// The three discounted claims; a fourth costs full resin.
|
||||
measure: { kind: "amount", target: 3, unit: "runs" },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Weekly_Boss",
|
||||
asOf: "2026-08-21",
|
||||
checked: "2026-10-14",
|
||||
note: "Trounce Domains: three runs at half the Resin. Confirmed in game, 2026-10-16.",
|
||||
},
|
||||
{
|
||||
id: "routine:genshin:battle-pass-exp",
|
||||
game: "genshin",
|
||||
title: "Battle Pass weekly EXP",
|
||||
period: { unit: "week", startsOn: 1 },
|
||||
measure: { kind: "amount", target: 10000, unit: "EXP" },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Battle_Pass",
|
||||
asOf: "2026-01-08",
|
||||
checked: "2026-10-14",
|
||||
note: "The cap on EXP from daily and weekly missions. Confirmed in game, 2026-10-14.",
|
||||
},
|
||||
{
|
||||
id: "routine:genshin:bounties",
|
||||
game: "genshin",
|
||||
title: "Reputation Bounties",
|
||||
period: { unit: "week", startsOn: 1 },
|
||||
measure: { kind: "amount", target: 3, unit: "bounties" },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Bounties",
|
||||
asOf: "2026-06-13",
|
||||
checked: "2026-10-14",
|
||||
note: "Counted apart from Reputation Requests. Confirmed in game, 2026-10-16.",
|
||||
},
|
||||
{
|
||||
id: "routine:genshin:requests",
|
||||
game: "genshin",
|
||||
title: "Reputation Requests",
|
||||
period: { unit: "week", startsOn: 1 },
|
||||
measure: { kind: "amount", target: 3, unit: "requests" },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Request",
|
||||
asOf: "2026-06-13",
|
||||
checked: "2026-10-14",
|
||||
note: "Three across all nations, not three each; apart from Bounties. Confirmed in game, 2026-10-16.",
|
||||
},
|
||||
{
|
||||
id: "routine:genshin:realm-depot",
|
||||
game: "genshin",
|
||||
title: "Realm Depot: Realm Treasures",
|
||||
// The page says weekly and names no day; Monday is the owner's in-game
|
||||
// restock timer. No one target either, so it is ticked once a week.
|
||||
period: { unit: "week", startsOn: 1 },
|
||||
measure: { kind: "days", required: 1 },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Serenitea_Pot/Realm_Depot",
|
||||
asOf: "2026-10-12",
|
||||
checked: "2026-10-16",
|
||||
note: "Bought with Realm Currency; the whole stock costs 13,100. The wiki says weekly; the Monday is ours. Confirmed in game, 2026-10-16.",
|
||||
},
|
||||
{
|
||||
id: "routine:genshin:paimons-bargains",
|
||||
game: "genshin",
|
||||
title: "Paimon's Bargains: Intertwined Fates",
|
||||
period: { unit: "month", startsOn: 1 },
|
||||
measure: { kind: "amount", target: 5, unit: "fates" },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Paimon%27s_Bargains",
|
||||
asOf: "2026-08-23",
|
||||
checked: "2026-10-14",
|
||||
note: "Bought with Masterless Stardust. Confirmed in game, 2026-10-16.",
|
||||
},
|
||||
{
|
||||
id: "routine:genshin:spiral-abyss",
|
||||
game: "genshin",
|
||||
title: "Spiral Abyss",
|
||||
// The page names the reset and no target, so it is ticked once a cycle.
|
||||
period: { unit: "month", startsOn: 16 },
|
||||
measure: { kind: "days", required: 1 },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Spiral_Abyss",
|
||||
asOf: "2026-08-29",
|
||||
checked: "2026-10-14",
|
||||
note: "Confirmed in game, 2026-10-16.",
|
||||
},
|
||||
{
|
||||
id: "routine:genshin:imaginarium-theater",
|
||||
game: "genshin",
|
||||
title: "Imaginarium Theater",
|
||||
period: { unit: "month", startsOn: 1 },
|
||||
measure: { kind: "days", required: 1 },
|
||||
source: "https://genshin-impact.fandom.com/wiki/Imaginarium_Theater",
|
||||
asOf: "2026-09-01",
|
||||
checked: "2026-10-14",
|
||||
note: "Confirmed in game, 2026-10-16.",
|
||||
},
|
||||
|
||||
// Zenless Zone Zero.
|
||||
{
|
||||
id: "routine:zzz:ridu-weekly",
|
||||
game: "zzz",
|
||||
@@ -48,6 +149,8 @@ export const ROUTINES: readonly Routine[] = [
|
||||
asOf: "2025-12-02",
|
||||
checked: "2026-10-13",
|
||||
},
|
||||
|
||||
// Arknights: Endfield.
|
||||
{
|
||||
id: "routine:endfield:weekly-routine",
|
||||
game: "endfield",
|
||||
|
||||
@@ -325,7 +325,8 @@ describe("Controls: built-in weekly and monthly tasks", () => {
|
||||
});
|
||||
|
||||
test("no switch when no game on the list has any", () => {
|
||||
expect(render(PREFS)).not.toContain("built-in weekly and monthly tasks");
|
||||
// Arknights and Blue Archive have none.
|
||||
expect(render(PREFS, 0, ["arknights", "ba"])).not.toContain("built-in weekly and monthly tasks");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+24
-4
@@ -33,6 +33,15 @@ describe("ROUTINES", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("a figure confirmed in game says so, with the day", () => {
|
||||
// The one exception to "a page states it" (routines.ts): the reader must
|
||||
// be able to tell our figure from the page's.
|
||||
for (const r of ROUTINES) {
|
||||
if (r.note?.toLowerCase().includes("in game") !== true) continue;
|
||||
expect(r.note).toMatch(/Confirmed in game, \d{4}-\d{2}-\d{2}\./);
|
||||
}
|
||||
});
|
||||
|
||||
test("a routine without a source is refused", () => {
|
||||
const { source: _s, ...bare } = ROUTINES[0]!;
|
||||
expect(RoutineSchema.safeParse(bare).success).toBe(false);
|
||||
@@ -44,7 +53,16 @@ describe("ROUTINES", () => {
|
||||
const shape = (game: string): unknown[] =>
|
||||
routinesFor(game).map((r) => [r.title, r.period, r.measure]);
|
||||
const week = { unit: "week" as const, startsOn: 1 };
|
||||
expect(shape("genshin")).toEqual([]);
|
||||
expect(shape("genshin")).toEqual([
|
||||
["Weekly Bosses", week, { kind: "amount", target: 3, unit: "runs" }],
|
||||
["Battle Pass weekly EXP", week, { kind: "amount", target: 10000, unit: "EXP" }],
|
||||
["Reputation Bounties", week, { kind: "amount", target: 3, unit: "bounties" }],
|
||||
["Reputation Requests", week, { kind: "amount", target: 3, unit: "requests" }],
|
||||
["Realm Depot: Realm Treasures", week, { kind: "days", required: 1 }],
|
||||
["Paimon's Bargains: Intertwined Fates", { unit: "month", startsOn: 1 }, { kind: "amount", target: 5, unit: "fates" }],
|
||||
["Spiral Abyss", { unit: "month", startsOn: 16 }, { kind: "days", required: 1 }],
|
||||
["Imaginarium Theater", { unit: "month", startsOn: 1 }, { kind: "days", required: 1 }],
|
||||
]);
|
||||
expect(shape("hsr")).toEqual([]);
|
||||
expect(shape("zzz")).toEqual([
|
||||
["Ridu Weekly", week, { kind: "amount", target: 1300, unit: "points" }],
|
||||
@@ -131,10 +149,12 @@ describe("a reader's answers from before the global switch carry over", () => {
|
||||
describe("which game to ask about", () => {
|
||||
const off = { all: false };
|
||||
test("the first game on screen with built-ins, not asked and not on", () => {
|
||||
expect(routineToAsk(["genshin", "zzz", "endfield"], off, undefined, false)).toBe("zzz");
|
||||
expect(routineToAsk(["genshin", "zzz", "endfield"], off, ["zzz"], false)).toBe("endfield");
|
||||
// Arknights has none, so the first game asked about is the next one.
|
||||
expect(routineToAsk(["arknights", "zzz", "endfield"], off, undefined, false)).toBe("zzz");
|
||||
expect(routineToAsk(["arknights", "zzz", "endfield"], off, ["zzz"], false)).toBe("endfield");
|
||||
expect(routineToAsk(["zzz"], { all: false, on: ["zzz"] }, undefined, false)).toBeNull();
|
||||
expect(routineToAsk(["genshin"], off, undefined, false)).toBeNull();
|
||||
expect(routineToAsk(["arknights"], off, undefined, false)).toBeNull();
|
||||
expect(routineToAsk(["genshin"], off, undefined, false)).toBe("genshin");
|
||||
});
|
||||
|
||||
test("never once the reader has answered the global switch", () => {
|
||||
|
||||
Reference in New Issue
Block a user