feat(daily-task): 返回周任务倒计时时间
This commit is contained in:
parent
6c35c7506d
commit
04ed8d700f
|
|
@ -30,6 +30,8 @@ export type DailyWeeklyTaskData = {
|
||||||
version: 2;
|
version: 2;
|
||||||
dayKey: string;
|
dayKey: string;
|
||||||
weekKey: string;
|
weekKey: string;
|
||||||
|
weekEndsAt: number;
|
||||||
|
serverNow: number;
|
||||||
dailyTasks: DailyTask[];
|
dailyTasks: DailyTask[];
|
||||||
weeklyStars: number;
|
weeklyStars: number;
|
||||||
weeklyRewards: WeeklyReward[];
|
weeklyRewards: WeeklyReward[];
|
||||||
|
|
@ -128,4 +130,3 @@ export const WEEKLY_REWARDS: WeeklyReward[] = [
|
||||||
{ rewardId: "weekly_105", target: 105, state: 0, rewards: [{ type: "infinite_health", count: 3600 }, { type: "hammer", count: 1 }] },
|
{ rewardId: "weekly_105", target: 105, state: 0, rewards: [{ type: "infinite_health", count: 3600 }, { type: "hammer", count: 1 }] },
|
||||||
{ rewardId: "weekly_140", target: 140, state: 0, rewards: [{ type: "infinite_rocket", count: 900 }, { type: "infinite_hourglass", count: 900 }, { type: "coin", count: 1500 }] },
|
{ rewardId: "weekly_140", target: 140, state: 0, rewards: [{ type: "infinite_rocket", count: 900 }, { type: "infinite_hourglass", count: 900 }, { type: "coin", count: 1500 }] },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,11 @@ export function getWeekKey(nowMs = Date.now()): string {
|
||||||
return new Date(shifted.getTime() - (day - 1) * DAY_MS).toISOString().slice(0, 10);
|
return new Date(shifted.getTime() - (day - 1) * DAY_MS).toISOString().slice(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getWeekEndsAt(nowMs = Date.now()): number {
|
||||||
|
const weekKey = getWeekKey(nowMs);
|
||||||
|
return Date.parse(`${weekKey}T00:00:00+08:00`) + 7 * DAY_MS;
|
||||||
|
}
|
||||||
|
|
||||||
function hash(input: string): number {
|
function hash(input: string): number {
|
||||||
let value = 2166136261;
|
let value = 2166136261;
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
|
|
@ -56,6 +61,7 @@ export function refreshTaskData(
|
||||||
): { data: DailyWeeklyTaskData; changed: boolean } {
|
): { data: DailyWeeklyTaskData; changed: boolean } {
|
||||||
const dayKey = getDayKey(nowMs);
|
const dayKey = getDayKey(nowMs);
|
||||||
const weekKey = getWeekKey(nowMs);
|
const weekKey = getWeekKey(nowMs);
|
||||||
|
const weekEndsAt = getWeekEndsAt(nowMs);
|
||||||
const parsed = typeof stored === "string" ? safeParse(stored) : stored;
|
const parsed = typeof stored === "string" ? safeParse(stored) : stored;
|
||||||
const valid = parsed && (parsed as DailyWeeklyTaskData).version === 2
|
const valid = parsed && (parsed as DailyWeeklyTaskData).version === 2
|
||||||
&& Array.isArray((parsed as DailyWeeklyTaskData).dailyTasks)
|
&& Array.isArray((parsed as DailyWeeklyTaskData).dailyTasks)
|
||||||
|
|
@ -66,9 +72,12 @@ export function refreshTaskData(
|
||||||
const newDay = !old || old.dayKey !== dayKey;
|
const newDay = !old || old.dayKey !== dayKey;
|
||||||
|
|
||||||
if (!newDay && !newWeek) {
|
if (!newDay && !newWeek) {
|
||||||
|
const changed = old.weekEndsAt !== weekEndsAt;
|
||||||
|
old.weekEndsAt = weekEndsAt;
|
||||||
|
old.serverNow = nowMs;
|
||||||
applyLocks(old.dailyTasks);
|
applyLocks(old.dailyTasks);
|
||||||
applyWeeklyStates(old);
|
applyWeeklyStates(old);
|
||||||
return { data: old, changed: false };
|
return { data: old, changed };
|
||||||
}
|
}
|
||||||
|
|
||||||
const previousTaskIds = old ? old.dailyTasks.map(task => task.taskId) : [];
|
const previousTaskIds = old ? old.dailyTasks.map(task => task.taskId) : [];
|
||||||
|
|
@ -76,6 +85,8 @@ export function refreshTaskData(
|
||||||
version: 2,
|
version: 2,
|
||||||
dayKey,
|
dayKey,
|
||||||
weekKey,
|
weekKey,
|
||||||
|
weekEndsAt,
|
||||||
|
serverNow: nowMs,
|
||||||
dailyTasks: selectDailyTasks(uid, dayKey, Math.max(1, level), previousTaskIds),
|
dailyTasks: selectDailyTasks(uid, dayKey, Math.max(1, level), previousTaskIds),
|
||||||
weeklyStars: newWeek ? 0 : Number(old?.weeklyStars) || 0,
|
weeklyStars: newWeek ? 0 : Number(old?.weeklyStars) || 0,
|
||||||
weeklyRewards: newWeek
|
weeklyRewards: newWeek
|
||||||
|
|
@ -141,4 +152,3 @@ function applyWeeklyStates(data: DailyWeeklyTaskData): void {
|
||||||
function safeParse(value: string): unknown {
|
function safeParse(value: string): unknown {
|
||||||
try { return JSON.parse(value); } catch (_) { return null; }
|
try { return JSON.parse(value); } catch (_) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,23 @@ registerHooks({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const { getDayKey, getWeekKey, refreshTaskData, mergeClientProgress, claimDaily, claimWeekly } = await import(serviceUrl);
|
const { getDayKey, getWeekKey, getWeekEndsAt, refreshTaskData, mergeClientProgress, claimDaily, claimWeekly } = await import(serviceUrl);
|
||||||
|
|
||||||
test("uses Shanghai natural day and Monday week keys", () => {
|
test("uses Shanghai natural day and Monday week keys", () => {
|
||||||
assert.equal(getDayKey(Date.parse("2026-09-06T15:59:59Z")), "2026-09-06");
|
assert.equal(getDayKey(Date.parse("2026-09-06T15:59:59Z")), "2026-09-06");
|
||||||
assert.equal(getDayKey(Date.parse("2026-09-06T16:00:00Z")), "2026-09-07");
|
assert.equal(getDayKey(Date.parse("2026-09-06T16:00:00Z")), "2026-09-07");
|
||||||
assert.equal(getWeekKey(Date.parse("2026-09-06T16:00:00Z")), "2026-09-07");
|
assert.equal(getWeekKey(Date.parse("2026-09-06T16:00:00Z")), "2026-09-07");
|
||||||
|
assert.equal(getWeekEndsAt(Date.parse("2026-09-06T16:00:00Z")), Date.parse("2026-09-14T00:00:00+08:00"));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("returns current server time and refreshes it on repeated reads", () => {
|
||||||
|
const firstNow = Date.parse("2026-09-07T04:00:00Z");
|
||||||
|
const secondNow = firstNow + 5000;
|
||||||
|
const first = refreshTaskData(null, "user-time", 20, firstNow).data;
|
||||||
|
const second = refreshTaskData(JSON.stringify(first), "user-time", 20, secondNow);
|
||||||
|
assert.equal(second.changed, false);
|
||||||
|
assert.equal(second.data.serverNow, secondNow);
|
||||||
|
assert.equal(second.data.weekEndsAt, Date.parse("2026-09-14T00:00:00+08:00"));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("migrates legacy tasks into five v2 stages totaling twenty stars", () => {
|
test("migrates legacy tasks into five v2 stages totaling twenty stars", () => {
|
||||||
|
|
@ -77,4 +88,3 @@ test("daily reset preserves stars while weekly reset clears them", () => {
|
||||||
assert.equal(monday.weeklyStars, 0);
|
assert.equal(monday.weeklyStars, 0);
|
||||||
assert.ok(monday.weeklyRewards.every(reward => reward.state === 0));
|
assert.ok(monday.weeklyRewards.every(reward => reward.state === 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user