fix: open all daily tasks without sequential locks
This commit is contained in:
parent
ee8c51bf7d
commit
123d4cb1c0
|
|
@ -50,7 +50,7 @@ function selectDailyTasks(uid: string, dayKey: string, level: number, previousTa
|
|||
value: selected.metric === "login" ? 1 : 0,
|
||||
stars,
|
||||
state: selected.metric === "login" ? 1 : 0,
|
||||
locked: slot !== 0,
|
||||
locked: false,
|
||||
rewards: DAILY_REWARDS[stars].map(reward => ({ ...reward })),
|
||||
...(selected.params ? { params: { ...selected.params } } : {}),
|
||||
} as DailyTask;
|
||||
|
|
@ -77,11 +77,12 @@ export function refreshTaskData(
|
|||
const newDay = !old || old.dayKey !== dayKey;
|
||||
|
||||
if (!newDay && !newWeek) {
|
||||
const changed = old.dayEndsAt !== dayEndsAt || old.weekEndsAt !== weekEndsAt;
|
||||
const changed = old.dayEndsAt !== dayEndsAt || old.weekEndsAt !== weekEndsAt
|
||||
|| old.dailyTasks.some(task => task.locked !== false);
|
||||
old.dayEndsAt = dayEndsAt;
|
||||
old.weekEndsAt = weekEndsAt;
|
||||
old.serverNow = nowMs;
|
||||
applyLocks(old.dailyTasks);
|
||||
refreshDailyStates(old.dailyTasks);
|
||||
applyWeeklyStates(old);
|
||||
return { data: old, changed };
|
||||
}
|
||||
|
|
@ -118,18 +119,17 @@ export function mergeClientProgress(data: DailyWeeklyTaskData, submitted: unknow
|
|||
if (Number.isFinite(value)) task.value = Math.max(0, Math.min(task.target, value));
|
||||
if (task.state !== 2) task.state = task.value >= task.target ? 1 : 0;
|
||||
});
|
||||
applyLocks(data.dailyTasks);
|
||||
refreshDailyStates(data.dailyTasks);
|
||||
}
|
||||
|
||||
export function claimDaily(data: DailyWeeklyTaskData, taskId: string) {
|
||||
const task = data.dailyTasks.find(item => item.taskId === taskId);
|
||||
if (!task) return { ok: false, msg: "任务不存在" };
|
||||
if (task.locked) return { ok: false, msg: "请先领取上一阶段奖励" };
|
||||
if (task.state === 2) return { ok: false, msg: "不能重复领取奖励" };
|
||||
if (task.value < task.target || task.state !== 1) return { ok: false, msg: "请先完成任务" };
|
||||
task.state = 2;
|
||||
data.weeklyStars = Math.min(140, data.weeklyStars + task.stars);
|
||||
applyLocks(data.dailyTasks);
|
||||
refreshDailyStates(data.dailyTasks);
|
||||
applyWeeklyStates(data);
|
||||
return { ok: true, rewards: task.rewards };
|
||||
}
|
||||
|
|
@ -143,9 +143,10 @@ export function claimWeekly(data: DailyWeeklyTaskData, rewardId: string) {
|
|||
return { ok: true, rewards: reward.rewards };
|
||||
}
|
||||
|
||||
function applyLocks(tasks: DailyTask[]): void {
|
||||
tasks.forEach((task, index) => {
|
||||
task.locked = index > 0 && tasks[index - 1].state !== 2;
|
||||
function refreshDailyStates(tasks: DailyTask[]): void {
|
||||
tasks.forEach(task => {
|
||||
// 保留字段兼容旧客户端,历史任务在读取时一并开放。
|
||||
task.locked = false;
|
||||
if (task.state !== 2 && task.value >= task.target) task.state = 1;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ test("migrates legacy tasks into five v2 stages totaling twenty stars", () => {
|
|||
assert.equal(result.data.version, 2);
|
||||
assert.equal(result.data.dailyTasks.length, 5);
|
||||
assert.equal(result.data.dailyTasks.reduce((sum, task) => sum + task.stars, 0), 20);
|
||||
assert.deepEqual(result.data.dailyTasks.map(task => task.locked), [false, true, true, true, true]);
|
||||
assert.deepEqual(result.data.dailyTasks.map(task => task.locked), [false, false, false, false, false]);
|
||||
});
|
||||
|
||||
test("keeps the same selection during a day and avoids previous slot tasks next day", () => {
|
||||
|
|
@ -52,17 +52,46 @@ test("keeps the same selection during a day and avoids previous slot tasks next
|
|||
next.dailyTasks.forEach((task, index) => assert.notEqual(task.taskId, first.dailyTasks[index].taskId));
|
||||
});
|
||||
|
||||
test("locked stages accumulate but cannot be claimed before the previous reward", () => {
|
||||
test("all daily tasks accumulate and can be claimed in any order", () => {
|
||||
const data = refreshTaskData(null, "user-3", 20, Date.parse("2026-09-04T04:00:00Z")).data;
|
||||
const submitted = structuredClone(data);
|
||||
submitted.dailyTasks[0].value = submitted.dailyTasks[0].target;
|
||||
submitted.dailyTasks[1].value = submitted.dailyTasks[1].target;
|
||||
submitted.dailyTasks.forEach(task => task.value = task.target);
|
||||
mergeClientProgress(data, submitted);
|
||||
assert.equal(data.dailyTasks[1].state, 1);
|
||||
assert.equal(data.dailyTasks[1].locked, true);
|
||||
assert.equal(claimDaily(data, data.dailyTasks[1].taskId).ok, false);
|
||||
assert.equal(claimDaily(data, data.dailyTasks[0].taskId).ok, true);
|
||||
assert.equal(data.dailyTasks[1].locked, false);
|
||||
assert.ok(data.dailyTasks.every(task => task.state === 1 && !task.locked));
|
||||
for (const task of [...data.dailyTasks].reverse()) {
|
||||
assert.equal(claimDaily(data, task.taskId).ok, true);
|
||||
assert.equal(claimDaily(data, task.taskId).ok, false);
|
||||
}
|
||||
assert.equal(data.weeklyStars, 20);
|
||||
});
|
||||
|
||||
test("opens stored locked tasks immediately without resetting progress or rewards", () => {
|
||||
const now = Date.parse("2026-09-04T04:00:00Z");
|
||||
const stored = refreshTaskData(null, "existing-user", 20, now).data;
|
||||
stored.dailyTasks.forEach((task, index) => task.locked = index > 0);
|
||||
stored.dailyTasks[4].value = stored.dailyTasks[4].target;
|
||||
stored.dailyTasks[4].state = 1;
|
||||
const original = structuredClone(stored);
|
||||
const result = refreshTaskData(JSON.stringify(stored), "existing-user", 20, now);
|
||||
assert.equal(result.changed, true);
|
||||
assert.deepEqual(result.data.dailyTasks, original.dailyTasks.map(task => ({ ...task, locked: false })));
|
||||
assert.deepEqual(result.data.weeklyRewards, original.weeklyRewards);
|
||||
assert.equal(result.data.weeklyStars, original.weeklyStars);
|
||||
assert.equal(refreshTaskData(JSON.stringify(result.data), "existing-user", 20, now).changed, false);
|
||||
assert.equal(claimDaily(result.data, result.data.dailyTasks[4].taskId).ok, true);
|
||||
});
|
||||
|
||||
test("ignores legacy lock flags but still requires completion", () => {
|
||||
const data = refreshTaskData(null, "legacy-flags", 20, Date.parse("2026-09-04T04:00:00Z")).data;
|
||||
const task = data.dailyTasks[4];
|
||||
task.locked = true;
|
||||
task.value = 0;
|
||||
task.state = 0;
|
||||
assert.equal(claimDaily(data, task.taskId).ok, false);
|
||||
task.value = task.target;
|
||||
task.state = 1;
|
||||
assert.equal(claimDaily(data, task.taskId).ok, true);
|
||||
assert.ok(data.dailyTasks.every(item => !item.locked));
|
||||
});
|
||||
|
||||
test("daily claims add stars once and weekly tiers claim independently", () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user