This commit is contained in:
2026-10-18 04:59:27 +07:00
parent 7a97b9b506
commit f5e645ec00
7 changed files with 267 additions and 51 deletions
+64 -37
View File
@@ -37,6 +37,7 @@ export interface PackageRequest {
server: string
gameId: number
token: string
resources?: { cover: string; background: string; intro: string; conclusion: string }
signal?: AbortSignal
onRequestFailure?: (failure: {
path: string
@@ -149,6 +150,7 @@ export function buildScreenPackage(
server: string,
gameId: number,
responses: { game: unknown; plan: unknown; music: unknown },
resources?: PackageRequest['resources'],
): ScreenPackage {
server = serverURL(server)
id(gameId)
@@ -160,8 +162,8 @@ export function buildScreenPackage(
game.ID,
'API вернул другую игру',
)
const scenario = object(game.scenario, 'game.scenario')
const story = object(scenario.story, 'game.scenario.story')
const scenario = optionalObject(game.scenario, 'game.scenario')
const story = optionalObject(scenario.story, 'game.scenario.story')
const intro = optionalObject(story.introduction, 'game.scenario.story.introduction')
const conclusion = optionalObject(story.conclusion, 'game.scenario.story.conclusion')
const assets = new Map<string, { id: string; url: string }>()
@@ -183,12 +185,20 @@ export function buildScreenPackage(
assets.set(assetId, { id: assetId, url })
return assetId
}
const cover = asset(scenario.image, 'game.scenario.image')
const cover = resources
? asset(resources.cover, 'state.coverImage')
: asset(scenario.image, 'game.scenario.image')
const media = {
cover,
background: asset(story.background, 'game.scenario.story.background') ?? cover,
intro: asset(intro.audio, 'game.scenario.story.introduction.audio'),
conclusion: asset(conclusion.video, 'game.scenario.story.conclusion.video'),
background: resources
? asset(resources.background, 'state.backgroundImage')
: (asset(story.background, 'game.scenario.story.background') ?? cover),
intro: resources
? asset(resources.intro, 'state.introAudio')
: asset(intro.audio, 'game.scenario.story.introduction.audio'),
conclusion: resources
? asset(resources.conclusion, 'state.conclusionVideo')
: asset(conclusion.video, 'game.scenario.story.conclusion.video'),
}
const plan = optionalObject(object(responses.plan, 'planResponse').plan, 'plan')
const steps = list(plan.steps, 'plan.steps').map((value, index) => {
@@ -374,9 +384,10 @@ export async function prepareScreenPackage(
client.GetGameMusic({ gameID: request.gameId }),
])
try {
return buildScreenPackage(server, request.gameId, { game, plan, music })
return buildScreenPackage(server, request.gameId, { game, plan, music }, request.resources)
} catch (error) {
const field = error instanceof ResponseFieldError ? error.field : 'game'
const state = field.startsWith('state.')
const suffix = field.startsWith('plan')
? '/screen-plan'
: field.startsWith('music')
@@ -384,9 +395,15 @@ export async function prepareScreenPackage(
: ''
throw requestErrorContext(
error,
suffix === '/music' ? 'GetGameMusic' : suffix ? 'GetScreenPlan' : 'GetGame',
'GET',
`/api/games/${request.gameId}${suffix}`,
state
? 'GetScreenState'
: suffix === '/music'
? 'GetGameMusic'
: suffix
? 'GetScreenPlan'
: 'GetGame',
state ? 'POST' : 'GET',
state ? '/api/screens/state' : `/api/games/${request.gameId}${suffix}`,
)
}
}
@@ -431,41 +448,51 @@ export function parseScreenPackage(value: unknown): ScreenPackage {
const selectedId = integer(music.selectedPlaylistId)
const selected = selectedId ? playlists.find((playlist) => playlist.ID === selectedId) : undefined
if (selectedId && !selected) throw new Error('Отсутствует выбранный плейлист')
const result = buildScreenPackage(text(data.server), id(game.id), {
game: {
const result = buildScreenPackage(
text(data.server),
id(game.id),
{
game: {
ID: game.id,
name: text(game.name),
scenario: {
image: ref(media.cover),
story: {
background: ref(media.background),
introduction: { audio: ref(media.intro) },
conclusion: { video: ref(media.conclusion) },
game: {
ID: game.id,
name: text(game.name),
scenario: {
image: ref(media.cover),
story: {
background: ref(media.background),
introduction: { audio: ref(media.intro) },
conclusion: { video: ref(media.conclusion) },
},
},
},
},
},
plan: {
plan: {
steps: list(data.steps).map((value) => {
const step = object(value)
return {
mode: step.mode,
text: step.text,
timerLabel: step.timerLabel,
timerDurationSeconds: step.timerDurationSeconds,
}
}),
plan: {
steps: list(data.steps).map((value) => {
const step = object(value)
return {
mode: step.mode,
text: step.text,
timerLabel: step.timerLabel,
timerDurationSeconds: step.timerDurationSeconds,
}
}),
},
},
music: {
scenarioPlaylistId: integer(music.scenarioPlaylistId),
gamePlaylistId: integer(music.gamePlaylistId),
state: { playlist: selected },
playlists,
},
},
music: {
scenarioPlaylistId: integer(music.scenarioPlaylistId),
gamePlaylistId: integer(music.gamePlaylistId),
state: { playlist: selected },
playlists,
{
cover: ref(media.cover),
background: ref(media.background),
intro: ref(media.intro),
conclusion: ref(media.conclusion),
},
})
)
if (result.metadataVersion !== data.metadataVersion || result.assets.length !== assets.size)
throw new Error('Повреждены метаданные пакета')
return result