Files
Genarrative/src/components/platform-entry/platformPuzzleDraftRecoveryModel.ts

155 lines
4.2 KiB
TypeScript

import type { PuzzleDraftLevel } from '../../../packages/shared/src/contracts/puzzleAgentDraft';
import type { PuzzleAgentSessionSnapshot } from '../../../packages/shared/src/contracts/puzzleAgentSession';
function normalizeRecoveryText(value: string | null | undefined) {
return value?.trim() || null;
}
function hasPuzzleAssetReference(
imageSrc: string | null | undefined,
objectKey: string | null | undefined,
) {
return Boolean(normalizeRecoveryText(imageSrc) || normalizeRecoveryText(objectKey));
}
function resolvePrimaryPuzzleLevel(session: PuzzleAgentSessionSnapshot) {
return session.draft?.levels?.[0] ?? null;
}
function resolvePuzzleRecoveryCandidate(
session: PuzzleAgentSessionSnapshot,
primaryLevel: PuzzleDraftLevel | null,
) {
const draft = session.draft;
if (!draft) {
return null;
}
return (
primaryLevel?.candidates.find((candidate) => candidate.selected) ??
primaryLevel?.candidates[0] ??
draft.candidates.find((candidate) => candidate.selected) ??
draft.candidates[0] ??
null
);
}
function resolvePuzzleRecoveryCoverFields(
session: PuzzleAgentSessionSnapshot,
) {
const draft = session.draft;
const primaryLevel = resolvePrimaryPuzzleLevel(session);
const selectedCandidate = resolvePuzzleRecoveryCandidate(
session,
primaryLevel,
);
return {
coverImageSrc:
normalizeRecoveryText(draft?.coverImageSrc) ??
normalizeRecoveryText(primaryLevel?.coverImageSrc) ??
normalizeRecoveryText(selectedCandidate?.imageSrc),
coverAssetId:
normalizeRecoveryText(draft?.coverAssetId) ??
normalizeRecoveryText(primaryLevel?.coverAssetId) ??
normalizeRecoveryText(selectedCandidate?.assetId),
selectedCandidateId:
draft?.selectedCandidateId ??
primaryLevel?.selectedCandidateId ??
selectedCandidate?.candidateId ??
null,
};
}
function hasCompleteGeneratedPuzzleLevelAssets(
level: PuzzleDraftLevel | null,
coverImageSrc: string | null,
) {
return Boolean(
normalizeRecoveryText(coverImageSrc) &&
hasPuzzleAssetReference(
level?.levelSceneImageSrc,
level?.levelSceneImageObjectKey,
) &&
hasPuzzleAssetReference(
level?.uiSpritesheetImageSrc,
level?.uiSpritesheetImageObjectKey,
) &&
hasPuzzleAssetReference(
level?.levelBackgroundImageSrc,
level?.levelBackgroundImageObjectKey,
),
);
}
export function hasRecoverableGeneratedPuzzleDraft(
session: PuzzleAgentSessionSnapshot,
) {
const draft = session.draft;
if (!draft) {
return false;
}
const primaryLevel = resolvePrimaryPuzzleLevel(session);
const { coverImageSrc } = resolvePuzzleRecoveryCoverFields(session);
return hasCompleteGeneratedPuzzleLevelAssets(primaryLevel, coverImageSrc);
}
export function normalizeRecoveredPuzzleDraftSession(
session: PuzzleAgentSessionSnapshot,
): PuzzleAgentSessionSnapshot {
const draft = session.draft;
if (!draft) {
return session;
}
const { coverImageSrc, coverAssetId, selectedCandidateId } =
resolvePuzzleRecoveryCoverFields(session);
const nextLevels = draft.levels?.map((level, index) =>
index === 0
? {
...level,
coverImageSrc: normalizeRecoveryText(level.coverImageSrc)
? level.coverImageSrc
: coverImageSrc,
coverAssetId: normalizeRecoveryText(level.coverAssetId)
? level.coverAssetId
: coverAssetId,
selectedCandidateId:
level.selectedCandidateId ?? selectedCandidateId,
}
: level,
);
const nextSession = {
...session,
draft: {
...draft,
coverImageSrc,
coverAssetId,
selectedCandidateId,
levels: nextLevels,
},
} satisfies PuzzleAgentSessionSnapshot;
const isRecoverable = hasRecoverableGeneratedPuzzleDraft(nextSession);
if (!isRecoverable) {
return nextSession;
}
return {
...nextSession,
draft: {
...nextSession.draft,
generationStatus: 'ready',
levels: nextSession.draft.levels?.map((level, index) =>
index === 0
? {
...level,
generationStatus: 'ready',
}
: level,
),
},
};
}