feat: let the reader mark an event as repeating daily
Dailiness was read off the source's wording alone, which is wrong in both directions: a grind that resets every day but whose page never prints "daily" got no checklist, and a banner whose blurb mentions "daily login rewards" got one nobody could dismiss. The reader's answer now wins. The control sits exactly where the checklist goes — the one place the answer visibly matters — so marking an event and ticking today off are the same gesture in the same place. An override is stored only when it disagrees with detection. Recording agreement would freeze today's guess into the reader's own data, so a later parser improvement could never reach that event. Marked events also join today's dailies at the top of the page, beside the per-game chores: at 23:50 a login campaign and a commission run are the same job, and ticking one should not mean opening a sheet to find its checklist. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6177633abc
commit
7f384eb9db
@@ -2,11 +2,13 @@ import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
dailiesId,
|
||||
dailyDays,
|
||||
dailyOverride,
|
||||
dailySummary,
|
||||
dayKey,
|
||||
isDaily,
|
||||
msUntilReset,
|
||||
nextResetMs,
|
||||
resolveDaily,
|
||||
streakOf,
|
||||
} from "../src/shared/daily.ts";
|
||||
import { DAY, HOUR } from "../src/shared/time.ts";
|
||||
@@ -56,6 +58,50 @@ describe("isDaily", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolveDaily", () => {
|
||||
const detected = { type: "login" as const, title: "Daily Check-In", summary: null };
|
||||
const plain = { type: "story" as const, title: "Chapter Three", summary: null };
|
||||
|
||||
test("detection stands until the reader says otherwise", () => {
|
||||
expect(resolveDaily(detected, undefined)).toBe(true);
|
||||
expect(resolveDaily(plain, undefined)).toBe(false);
|
||||
});
|
||||
|
||||
test("the reader can mark an event the source never called daily", () => {
|
||||
// The case this exists for: a grind whose page never prints the word, but
|
||||
// which the player knows resets every day.
|
||||
expect(resolveDaily(plain, true)).toBe(true);
|
||||
});
|
||||
|
||||
test("the reader can unmark a false positive", () => {
|
||||
// A banner whose blurb happens to mention "daily login rewards" should not
|
||||
// be stuck with a twenty-box checklist the reader cannot dismiss.
|
||||
expect(resolveDaily(detected, false)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("dailyOverride", () => {
|
||||
test("agreeing with detection records nothing", () => {
|
||||
// Storing "yes" on an event already detected as daily would freeze today's
|
||||
// guess into the reader's data, so a later parser fix could never reach it.
|
||||
expect(dailyOverride(true, true)).toBeUndefined();
|
||||
expect(dailyOverride(false, false)).toBeUndefined();
|
||||
});
|
||||
|
||||
test("disagreeing with detection records the disagreement", () => {
|
||||
expect(dailyOverride(true, false)).toBe(true);
|
||||
expect(dailyOverride(false, true)).toBe(false);
|
||||
});
|
||||
|
||||
test("round-trips: overriding then changing back leaves no trace", () => {
|
||||
const detectedDaily = false;
|
||||
const on = dailyOverride(true, detectedDaily);
|
||||
expect(resolveDaily({ type: "story", title: "x", summary: null }, on)).toBe(true);
|
||||
const off = dailyOverride(false, detectedDaily);
|
||||
expect(off).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("dayKey", () => {
|
||||
test("the game day rolls at 04:00 server time, not midnight", () => {
|
||||
// Asia is UTC+8, so its 04:00 reset is 20:00 UTC the day before. Someone
|
||||
|
||||
Reference in New Issue
Block a user