feat(routines): a routine can reset with its game's version

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-22 17:14:00 +02:00
1 parent 34ebc401c7
commit b3a84757a1
11 files changed
+135 -21

No files matched your search

+5 -4
View File
@@ -12,7 +12,7 @@ import { isCustomGameId, type DisplayEvent, type LaneId } from "../../shared/cus
import type { GameMeta } from "../../shared/games.ts";
import type { GameId, Region } from "../../shared/schema.ts";
import { goalCount, goalLabel, type GoalStatus } from "../../shared/goal.ts";
import { addDays, periodOf, type Period } from "../../shared/period.ts";
import { addDays, cadenceOf, periodOf, type Period } from "../../shared/period.ts";
import type { TaskShape } from "../../shared/task.ts";
import { asOfLabel } from "../../shared/routines.ts";
import { AmountEditor } from "./AmountEditor.tsx";
@@ -206,8 +206,9 @@ export function dailyGroups(
...(clock === undefined ? {} : { clock }),
notBefore: null,
goal: taskStatusFor(task),
cadence: task.period.unit,
period: task.period,
cadence: cadenceOf(task.period),
// A version has no period before it to catch up on (spec 2026-10-22).
period: task.period.unit === "version" ? undefined : task.period,
unit: task.measure.kind === "amount" ? task.measure.unit : undefined,
});
}
@@ -228,7 +229,7 @@ export function tasksShown<T extends Pick<StripTask, "period">>(
): T[] {
const on = { week: shown.weekly, month: shown.monthly, cycle: shown.cycle } as const;
// A reader's own daily sits with the standing dailies, not these strips.
return tasks.filter((t) => t.period.unit !== "day" && on[t.period.unit]);
return tasks.filter((t) => t.period.unit !== "day" && on[cadenceOf(t.period) as keyof typeof on]);
}
/**
@@ -23,6 +23,9 @@ import {
} from "../../../shared/routines.ts";
import { asOfLabel, TaskSchema, type Task } from "../../../shared/task.ts";
import { periodOf, type Period } from "../../../shared/period.ts";
import { versionCaption, versionWindow } from "../../../shared/versions.ts";
const capitalise = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);
import { AmountTarget } from "../../../shared/goal.ts";
import {
DAY,
@@ -376,13 +379,21 @@ function Library({
const rows = rowsOf(id),
first = rows[0]!,
def = builtins.find((b) => b.id === id);
const version =
def?.period.unit === "version"
? versionWindow(def.game, now)
: undefined;
const line = def
? [
scheduleWords(
def.period,
first.clock.resetHour,
first.clock.resetMinute,
),
def.period.unit === "version"
? version
? capitalise(versionCaption(version, now))
: "Resets with the version"
: scheduleWords(
def.period,
first.clock.resetHour,
first.clock.resetMinute,
),
measureWords(def),
`${sourceLabel(def.source)}, checked ${asOfLabel(def.checked)}`,
]
@@ -22,6 +22,7 @@ import { actionMeta } from "../../state/reader/actions.ts";
import { useGameMeta } from "../../state/gameMeta.tsx";
import { DAY, formatRemaining, resetShiftMs } from "../../../shared/time.ts";
import { periodOf } from "../../../shared/period.ts";
import { versionWindow } from "../../../shared/versions.ts";
import { routinesFor } from "../../../shared/routines.ts";
import { canStep, snapDayWidth, stepDayWidth } from "../../state/zoom.ts";
import { orderGames } from "../../state/gameOrder.ts";
@@ -47,7 +48,12 @@ export const onTimeline = (r: RoutineRow) =>
export function routinePeriod(row: RoutineRow, now: number) {
const key = readerDayKey(now, row.clock),
task = row.task ?? routinesFor(row.game).find((r) => r.id === row.id);
const period = task
if (task?.period.unit === "version") {
// Drawn to the recorded end, else to the estimate: a picture, not a reset.
const w = versionWindow(row.game, now);
if (w) return { start: w.start, end: w.end ?? w.estimate ?? now + DAY };
}
const period = task && task.period.unit !== "version"
? periodOf(task.period, key)
: { start: key, days: [key] };
const shift = resetShiftMs(row.clock.region, row.game, row.clock);
+2 -1
View File
@@ -7,6 +7,7 @@ import { metaFor } from "../../../shared/games.ts";
import { routinesFor, offered } from "../../../shared/routines.ts";
import { type Task, TaskSchema, taskStatus } from "../../../shared/task.ts";
import { readableAmounts } from "../useAmounts.ts";
import { cadenceOf } from "../../../shared/period.ts";
import {
resolveReaderClock,
readerDayKey,
@@ -121,7 +122,7 @@ export function routineRows(
accountId,
game: account.game,
title: task.title,
cadence: task.period.unit,
cadence: cadenceOf(task.period),
status: taskStatus({
task,
region: account.region,