This commit is contained in:
2026-10-27 13:07:24 +07:00
parent 066134f6ef
commit 6e83c014e5
18 changed files with 1445 additions and 174 deletions
+42 -3
View File
@@ -10,6 +10,8 @@ import { parseTimerType } from './screen-plan.js'
import { validQR } from '../src/utils/presentation.js'
import type { TimerType } from '../src/types/screen.js'
import { createHash } from 'node:crypto'
import type { MusicGroup } from '../src/types/screen.js'
import { parsePlaylistGroups, apiGroupEndMode } from './playlist-groups.js'
export const INCOMPLETE_MATERIALS_WARNING = 'Получен неполный список материалов. Подключите экран к игре для уточнения'
@@ -24,7 +26,14 @@ export interface ScreenPackage {
intro: string | null
conclusion: string | null
}
steps: { mode: number; text: string; timerLabel: string; timerDurationSeconds: number; qrUrl?: string; timerType?: TimerType }[]
steps: {
mode: number
text: string
timerLabel: string
timerDurationSeconds: number
qrUrl?: string
timerType?: TimerType
}[]
music: {
scenarioPlaylistId: number | null
gamePlaylistId: number | null
@@ -33,7 +42,8 @@ export interface ScreenPackage {
playlists: {
id: number
name: string
tracks: { id: number; name: string; position: number; assetId: string }[]
groups?: MusicGroup[]
tracks: { id: number; name: string; position: number; groupId?: number; assetId: string }[]
}[]
assets: { id: string; url: string }[]
}
@@ -283,6 +293,7 @@ export function buildScreenPackage(
)
const playlist = entry.value
const field = entry.field
const groups = parsePlaylistGroups(playlist.groups)
const tracks = list(playlist.tracks, `${field}.tracks`)
.map((value, index) => {
const trackField = `${field}.tracks[${index}]`
@@ -299,11 +310,23 @@ export function buildScreenPackage(
id: id(track.ID, `${trackField}.ID`),
name: text(track.name, `${trackField}.name`),
position: integer(track.position, 0, `${trackField}.position`),
...(integer(track.groupId, 0, `${trackField}.groupId`)
? { groupId: integer(track.groupId, 0, `${trackField}.groupId`) }
: {}),
assetId,
}
})
.sort((a, b) => a.position - b.position || a.id - b.id)
return { id: playlistId, name: text(playlist.name, `${field}.name`), tracks }
for (const track of tracks) {
if (track.groupId && !groups.some((group) => group.id === track.groupId))
throw new Error('Группа трека отсутствует в плейлисте')
}
return {
id: playlistId,
name: text(playlist.name, `${field}.name`),
tracks,
...(groups.length ? { groups } : {}),
}
})
const data = {
formatVersion: 1 as const,
@@ -480,12 +503,28 @@ export function parseScreenPackage(value: unknown): ScreenPackage {
return {
ID: id(playlist.id),
name: text(playlist.name),
...(playlist.groups === undefined
? {}
: {
groups: list(playlist.groups).map((value) => {
const group = object(value)
if (!['repeat', 'stop', 'next'].includes(String(group.endMode)))
throw new Error('Некорректный режим группы пакета')
return {
ID: id(group.id),
name: text(group.name),
position: integer(group.position),
endMode: apiGroupEndMode(group.endMode as MusicGroup['endMode']),
}
}),
}),
tracks: list(playlist.tracks).map((value) => {
const track = object(value)
return {
ID: id(track.id),
name: text(track.name),
position: integer(track.position),
...(track.groupId === undefined ? {} : { groupId: integer(track.groupId) }),
filename: ref(track.assetId),
}
}),