1
This commit is contained in:
@@ -14,6 +14,7 @@ import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/p
|
||||
|
||||
const LOCAL_PUZZLE_RUN_ID_PREFIX = 'local-puzzle-run-';
|
||||
const PUZZLE_FREEZE_TIME_DURATION_MS = 10_000;
|
||||
const PUZZLE_EXTEND_TIME_DURATION_MS = 60_000;
|
||||
const PUZZLE_LEVEL_TIME_LIMIT_MS_BY_GRID_SIZE: Record<PuzzleGridSize, number> = {
|
||||
3: 180_000,
|
||||
4: 300_000,
|
||||
@@ -499,6 +500,10 @@ function applyNextBoard(
|
||||
},
|
||||
leaderboardEntries: justCleared ? [] : run.leaderboardEntries,
|
||||
recommendedNextProfileId: run.recommendedNextProfileId,
|
||||
nextLevelMode: run.nextLevelMode ?? 'none',
|
||||
nextLevelProfileId: run.nextLevelProfileId ?? null,
|
||||
nextLevelId: run.nextLevelId ?? null,
|
||||
recommendedNextWorks: run.recommendedNextWorks ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -551,6 +556,7 @@ function buildFallbackLocalLevel(run: PuzzleRunSnapshot): PuzzleRunSnapshot {
|
||||
...currentLevel,
|
||||
runId: run.runId,
|
||||
levelIndex: nextLevelIndex,
|
||||
levelId: null,
|
||||
gridSize,
|
||||
profileId: nextProfileId,
|
||||
levelName: buildLocalLevelName(currentLevel.levelName, nextLevelIndex),
|
||||
@@ -563,6 +569,10 @@ function buildFallbackLocalLevel(run: PuzzleRunSnapshot): PuzzleRunSnapshot {
|
||||
leaderboardEntries: [],
|
||||
},
|
||||
recommendedNextProfileId: null,
|
||||
nextLevelMode: 'none',
|
||||
nextLevelProfileId: null,
|
||||
nextLevelId: null,
|
||||
recommendedNextWorks: [],
|
||||
leaderboardEntries: [],
|
||||
};
|
||||
}
|
||||
@@ -571,6 +581,10 @@ export function startLocalPuzzleRun(item: PuzzleWorkSummary): PuzzleRunSnapshot
|
||||
const gridSize = resolvePuzzleGridSize(0);
|
||||
const runId = `${LOCAL_PUZZLE_RUN_ID_PREFIX}${item.profileId}-${Date.now()}`;
|
||||
const startedAtMs = Date.now();
|
||||
const firstLevel = item.levels?.[0] ?? null;
|
||||
const firstLevelName = firstLevel?.levelName || item.levelName;
|
||||
const firstCoverImageSrc = firstLevel?.coverImageSrc ?? item.coverImageSrc;
|
||||
const secondLevel = item.levels?.[1] ?? null;
|
||||
return {
|
||||
runId,
|
||||
entryProfileId: item.profileId,
|
||||
@@ -582,12 +596,13 @@ export function startLocalPuzzleRun(item: PuzzleWorkSummary): PuzzleRunSnapshot
|
||||
currentLevel: {
|
||||
runId,
|
||||
levelIndex: 1,
|
||||
levelId: firstLevel?.levelId ?? null,
|
||||
gridSize,
|
||||
profileId: item.profileId,
|
||||
levelName: item.levelName,
|
||||
levelName: firstLevelName,
|
||||
authorDisplayName: item.authorDisplayName,
|
||||
themeTags: item.themeTags,
|
||||
coverImageSrc: item.coverImageSrc,
|
||||
coverImageSrc: firstCoverImageSrc,
|
||||
board: buildInitialBoard(gridSize, runId, item.profileId, 1),
|
||||
status: 'playing',
|
||||
startedAtMs,
|
||||
@@ -597,6 +612,10 @@ export function startLocalPuzzleRun(item: PuzzleWorkSummary): PuzzleRunSnapshot
|
||||
leaderboardEntries: [],
|
||||
},
|
||||
recommendedNextProfileId: null,
|
||||
nextLevelMode: secondLevel ? 'sameWork' : 'none',
|
||||
nextLevelProfileId: secondLevel ? item.profileId : null,
|
||||
nextLevelId: secondLevel?.levelId ?? null,
|
||||
recommendedNextWorks: [],
|
||||
leaderboardEntries: [],
|
||||
};
|
||||
}
|
||||
@@ -784,6 +803,37 @@ export function advanceLocalPuzzleLevel(run: PuzzleRunSnapshot): PuzzleRunSnapsh
|
||||
return buildFallbackLocalLevel(run);
|
||||
}
|
||||
|
||||
export function restartLocalPuzzleLevel(run: PuzzleRunSnapshot): PuzzleRunSnapshot {
|
||||
const currentLevel = run.currentLevel;
|
||||
if (!currentLevel) {
|
||||
return run;
|
||||
}
|
||||
|
||||
const runId = `${LOCAL_PUZZLE_RUN_ID_PREFIX}${currentLevel.profileId}-${Date.now()}`;
|
||||
const startedAtMs = Date.now();
|
||||
return {
|
||||
...run,
|
||||
runId,
|
||||
leaderboardEntries: [],
|
||||
currentLevel: {
|
||||
...currentLevel,
|
||||
runId,
|
||||
board: buildInitialBoard(
|
||||
currentLevel.gridSize,
|
||||
runId,
|
||||
currentLevel.profileId,
|
||||
currentLevel.levelIndex,
|
||||
),
|
||||
status: 'playing',
|
||||
startedAtMs,
|
||||
clearedAtMs: null,
|
||||
elapsedMs: null,
|
||||
...buildLevelTimerFields(currentLevel.gridSize),
|
||||
leaderboardEntries: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前拼图运行态是否为前端本地兜底 run。
|
||||
* 这类 run 没有后端持久化记录,不能再调用依赖真实 runId 的排行榜接口。
|
||||
@@ -877,3 +927,34 @@ export function applyLocalPuzzleFreezeTime(
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function extendLocalPuzzleTime(run: PuzzleRunSnapshot): PuzzleRunSnapshot {
|
||||
const timedRun = withResolvedTimer(run);
|
||||
const currentLevel = timedRun.currentLevel;
|
||||
if (!currentLevel || currentLevel.status !== 'failed') {
|
||||
return timedRun;
|
||||
}
|
||||
|
||||
const nowMs = Date.now();
|
||||
const consumedBeforeExtend = Math.max(
|
||||
0,
|
||||
currentLevel.timeLimitMs - PUZZLE_EXTEND_TIME_DURATION_MS,
|
||||
);
|
||||
|
||||
return {
|
||||
...timedRun,
|
||||
currentLevel: {
|
||||
...currentLevel,
|
||||
status: 'playing',
|
||||
startedAtMs: nowMs - consumedBeforeExtend,
|
||||
clearedAtMs: null,
|
||||
elapsedMs: null,
|
||||
remainingMs: PUZZLE_EXTEND_TIME_DURATION_MS,
|
||||
pausedAccumulatedMs: 0,
|
||||
pauseStartedAtMs: null,
|
||||
freezeAccumulatedMs: 0,
|
||||
freezeStartedAtMs: null,
|
||||
freezeUntilMs: null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user