This commit is contained in:
2026-04-28 19:36:39 +08:00
parent a9febe7678
commit f0471a4f8d
206 changed files with 18456 additions and 10133 deletions

View File

@@ -3,6 +3,7 @@ import type {
PuzzleBoardSnapshot,
PuzzleCellPosition,
PuzzleGridSize,
PuzzleLeaderboardEntry,
PuzzleMergedGroupState,
PuzzlePieceState,
PuzzleRunSnapshot,
@@ -10,6 +11,8 @@ import type {
} from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
import type { PuzzleWorkSummary } from '../../../packages/shared/src/contracts/puzzleWorkSummary';
const LOCAL_PUZZLE_RUN_ID_PREFIX = 'local-puzzle-run-';
function resolvePuzzleGridSize(clearedLevelCount: number): PuzzleGridSize {
return clearedLevelCount >= 3 ? 4 : 3;
}
@@ -399,6 +402,20 @@ function buildLocalNextProfileId(entryProfileId: string, levelIndex: number) {
return `${entryProfileId}::local-level-${levelIndex}`;
}
function buildLocalLeaderboardEntries(
nickname: string,
elapsedMs: number,
): PuzzleLeaderboardEntry[] {
return [
{
rank: 1,
nickname,
elapsedMs,
isCurrentPlayer: true,
},
];
}
// 第一版单机兜底没有后端推荐池时,才沿用当前作品图片生成可推进的临时关卡名。
function buildLocalLevelName(previousLevelName: string, levelIndex: number) {
return `${previousLevelName.replace(/ · 第 \d+ 关$/, '')} · 第 ${levelIndex}`;
@@ -447,7 +464,7 @@ function buildFallbackLocalLevel(run: PuzzleRunSnapshot): PuzzleRunSnapshot {
export function startLocalPuzzleRun(item: PuzzleWorkSummary): PuzzleRunSnapshot {
const gridSize = resolvePuzzleGridSize(0);
const runId = `local-puzzle-run-${item.profileId}-${Date.now()}`;
const runId = `${LOCAL_PUZZLE_RUN_ID_PREFIX}${item.profileId}-${Date.now()}`;
const startedAtMs = Date.now();
return {
runId,
@@ -658,3 +675,45 @@ export function dragLocalPuzzlePiece(
export function advanceLocalPuzzleLevel(run: PuzzleRunSnapshot): PuzzleRunSnapshot {
return buildFallbackLocalLevel(run);
}
/**
* 判断当前拼图运行态是否为前端本地兜底 run。
* 这类 run 没有后端持久化记录,不能再调用依赖真实 runId 的排行榜接口。
*/
export function isLocalPuzzleRun(run: PuzzleRunSnapshot | null | undefined) {
return Boolean(run?.runId?.startsWith(LOCAL_PUZZLE_RUN_ID_PREFIX));
}
/**
* 本地拼图 run 的排行榜兜底。
* 当前版本只写入当前玩家成绩避免结算阶段继续请求后端导致“run 不存在”。
*/
export function submitLocalPuzzleLeaderboard(
run: PuzzleRunSnapshot,
nickname: string,
): PuzzleRunSnapshot {
const currentLevel = run.currentLevel;
if (
!currentLevel ||
currentLevel.status !== 'cleared' ||
currentLevel.elapsedMs === null
) {
return run;
}
if ((currentLevel.leaderboardEntries ?? []).length > 0) {
return run;
}
const leaderboardEntries = buildLocalLeaderboardEntries(
nickname,
currentLevel.elapsedMs,
);
return {
...run,
leaderboardEntries,
currentLevel: {
...currentLevel,
leaderboardEntries,
},
};
}