548db78ca7
Adds/updates documentation, assets and implementation for Match3D and puzzle image generation workflows. Key changes: decision logs and pitfalls updated to prefer VectorEngine Gemini for Match3D material sheets and to require edits (multipart) for 1:1 container reference images; guidance added for when to use APIMart vs VectorEngine. .env.example clarified APIMart/Responses config. Many new public assets and PPT visuals added. Code changes across frontend and backend: updated shared contracts, server-rs match3d/puzzle/image-generation handlers, VectorEngine/OpenAI image generation clients, and multiple React components/tests to handle UI/background/container image signing, edits workflow, and puzzle UI background resolution. Added src/services/puzzle-runtime/puzzleUiBackgroundSource.ts and related test updates. Includes notes about multipart HTTP/1.1 requirement and test/verification commands in docs.
144 lines
3.3 KiB
TypeScript
144 lines
3.3 KiB
TypeScript
import type { CreationAudioAsset } from './creationAudio';
|
|
|
|
export type PuzzleGridSize = 3 | 4 | 5 | 6 | 7;
|
|
|
|
export interface PuzzleCellPosition {
|
|
row: number;
|
|
col: number;
|
|
}
|
|
|
|
export interface PuzzlePieceState {
|
|
pieceId: string;
|
|
correctRow: number;
|
|
correctCol: number;
|
|
currentRow: number;
|
|
currentCol: number;
|
|
mergedGroupId: string | null;
|
|
}
|
|
|
|
export interface PuzzleMergedGroupState {
|
|
groupId: string;
|
|
pieceIds: string[];
|
|
occupiedCells: PuzzleCellPosition[];
|
|
}
|
|
|
|
export interface PuzzleLeaderboardEntry {
|
|
rank: number;
|
|
nickname: string;
|
|
elapsedMs: number;
|
|
visibleTags?: string[];
|
|
isCurrentPlayer?: boolean;
|
|
}
|
|
|
|
export type PuzzleRuntimeLevelStatus = 'playing' | 'cleared' | 'failed';
|
|
|
|
export type PuzzleRuntimePropKind =
|
|
| 'hint'
|
|
| 'reference'
|
|
| 'freezeTime'
|
|
| 'extendTime';
|
|
|
|
export interface PuzzleBoardSnapshot {
|
|
rows: number;
|
|
cols: number;
|
|
pieces: PuzzlePieceState[];
|
|
mergedGroups: PuzzleMergedGroupState[];
|
|
selectedPieceId: string | null;
|
|
allTilesResolved: boolean;
|
|
}
|
|
|
|
export interface PuzzleRuntimeLevelSnapshot {
|
|
runId: string;
|
|
levelIndex: number;
|
|
levelId: string | null;
|
|
gridSize: PuzzleGridSize;
|
|
profileId: string;
|
|
levelName: string;
|
|
authorDisplayName: string;
|
|
themeTags: string[];
|
|
coverImageSrc: string | null;
|
|
uiBackgroundImageSrc?: string | null;
|
|
uiBackgroundImageObjectKey?: string | null;
|
|
backgroundMusic?: CreationAudioAsset | null;
|
|
board: PuzzleBoardSnapshot;
|
|
status: PuzzleRuntimeLevelStatus;
|
|
startedAtMs: number;
|
|
clearedAtMs: number | null;
|
|
elapsedMs: number | null;
|
|
timeLimitMs: number;
|
|
remainingMs: number;
|
|
pausedAccumulatedMs: number;
|
|
pauseStartedAtMs: number | null;
|
|
freezeAccumulatedMs: number;
|
|
freezeStartedAtMs: number | null;
|
|
freezeUntilMs: number | null;
|
|
leaderboardEntries: PuzzleLeaderboardEntry[];
|
|
}
|
|
|
|
export type PuzzleNextLevelMode = 'sameWork' | 'similarWorks' | 'none';
|
|
|
|
export interface PuzzleRecommendedNextWork {
|
|
profileId: string;
|
|
levelName: string;
|
|
authorDisplayName: string;
|
|
themeTags: string[];
|
|
coverImageSrc: string | null;
|
|
similarityScore: number;
|
|
}
|
|
|
|
export interface PuzzleRunSnapshot {
|
|
runId: string;
|
|
entryProfileId: string;
|
|
clearedLevelCount: number;
|
|
currentLevelIndex: number;
|
|
currentGridSize: PuzzleGridSize;
|
|
playedProfileIds: string[];
|
|
previousLevelTags: string[];
|
|
currentLevel: PuzzleRuntimeLevelSnapshot | null;
|
|
recommendedNextProfileId: string | null;
|
|
nextLevelMode?: PuzzleNextLevelMode;
|
|
nextLevelProfileId?: string | null;
|
|
nextLevelId?: string | null;
|
|
recommendedNextWorks?: PuzzleRecommendedNextWork[];
|
|
leaderboardEntries: PuzzleLeaderboardEntry[];
|
|
}
|
|
|
|
export interface StartPuzzleRunRequest {
|
|
profileId: string;
|
|
levelId?: string | null;
|
|
}
|
|
|
|
export interface PuzzleRunResponse {
|
|
run: PuzzleRunSnapshot;
|
|
}
|
|
|
|
export interface SubmitPuzzleLeaderboardRequest {
|
|
profileId: string;
|
|
gridSize: PuzzleGridSize;
|
|
elapsedMs: number;
|
|
nickname: string;
|
|
}
|
|
|
|
export interface SwapPuzzlePiecesRequest {
|
|
firstPieceId: string;
|
|
secondPieceId: string;
|
|
}
|
|
|
|
export interface DragPuzzlePieceRequest {
|
|
pieceId: string;
|
|
targetRow: number;
|
|
targetCol: number;
|
|
}
|
|
|
|
export interface AdvancePuzzleNextLevelRequest {
|
|
targetProfileId?: string | null;
|
|
}
|
|
|
|
export interface UsePuzzleRuntimePropRequest {
|
|
propKind: PuzzleRuntimePropKind;
|
|
}
|
|
|
|
export interface UpdatePuzzleRuntimePauseRequest {
|
|
paused: boolean;
|
|
}
|