Files
Genarrative/src/services/puzzle-runtime/puzzleRuntimeClient.ts

144 lines
3.3 KiB
TypeScript

import type {
DragPuzzlePieceRequest,
PuzzleRunResponse,
StartPuzzleRunRequest,
SubmitPuzzleLeaderboardRequest,
SwapPuzzlePiecesRequest,
} from '../../../packages/shared/src/contracts/puzzleRuntimeSession';
import { type ApiRetryOptions, requestJson } from '../apiClient';
const PUZZLE_RUNTIME_API_BASE = '/api/runtime/puzzle/runs';
const PUZZLE_RUNTIME_READ_RETRY: ApiRetryOptions = {
maxRetries: 1,
baseDelayMs: 120,
maxDelayMs: 360,
};
const PUZZLE_RUNTIME_WRITE_RETRY: ApiRetryOptions = {
maxRetries: 1,
baseDelayMs: 120,
maxDelayMs: 360,
retryUnsafeMethods: true,
};
/**
* 从某个已发布拼图作品开始一次 run。
*/
export async function startPuzzleRun(payload: StartPuzzleRunRequest) {
return requestJson<PuzzleRunResponse>(
PUZZLE_RUNTIME_API_BASE,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
},
'启动拼图玩法失败',
{
retry: PUZZLE_RUNTIME_WRITE_RETRY,
},
);
}
/**
* 读取拼图运行态快照。
*/
export async function getPuzzleRun(runId: string) {
return requestJson<PuzzleRunResponse>(
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}`,
{
method: 'GET',
},
'读取拼图运行快照失败',
{
retry: PUZZLE_RUNTIME_READ_RETRY,
},
);
}
/**
* 提交两块交换请求。
*/
export async function swapPuzzlePieces(
runId: string,
payload: SwapPuzzlePiecesRequest,
) {
return requestJson<PuzzleRunResponse>(
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/swap`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
},
'交换拼图块失败',
{
retry: PUZZLE_RUNTIME_WRITE_RETRY,
},
);
}
/**
* 提交单块或合并块拖动请求。
*/
export async function dragPuzzlePieceOrGroup(
runId: string,
payload: DragPuzzlePieceRequest,
) {
return requestJson<PuzzleRunResponse>(
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/drag`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
},
'拖动拼图块失败',
{
retry: PUZZLE_RUNTIME_WRITE_RETRY,
},
);
}
/**
* 进入推荐出的下一关。
*/
export async function advancePuzzleNextLevel(runId: string) {
return requestJson<PuzzleRunResponse>(
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/next-level`,
{
method: 'POST',
},
'进入下一关失败',
{
retry: PUZZLE_RUNTIME_WRITE_RETRY,
},
);
}
/**
* 提交通关成绩并读取真实排行榜。
*/
export async function submitPuzzleLeaderboard(
runId: string,
payload: SubmitPuzzleLeaderboardRequest,
) {
return requestJson<PuzzleRunResponse>(
`${PUZZLE_RUNTIME_API_BASE}/${encodeURIComponent(runId)}/leaderboard`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
},
'提交拼图排行榜失败',
{
retry: PUZZLE_RUNTIME_WRITE_RETRY,
},
);
}
export const puzzleRuntimeClient = {
advanceNextLevel: advancePuzzleNextLevel,
drag: dragPuzzlePieceOrGroup,
getRun: getPuzzleRun,
submitLeaderboard: submitPuzzleLeaderboard,
startRun: startPuzzleRun,
swap: swapPuzzlePieces,
};