Files
evening_detective_screen/electron/screen-plan.ts
T
2026-10-18 04:51:12 +07:00

82 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { ResponseFieldError } from './request-error.js'
import type { ScreenMode, ScreenPlan } from '../src/types/screen.js'
import { integer, object, text } from './remote-state.js'
const modes = [
'UNSPECIFIED',
'COVER',
'INTRO',
'INTRO_DONE',
'CONCLUSION',
'CONCLUSION_DONE',
'RESULTS',
'TIMER',
'TEXT',
]
export function parsePlan(value: unknown): ScreenPlan {
const plan = value == null ? {} : object(value, 'plan')
const list = plan.steps ?? []
if (!Array.isArray(list))
throw new ResponseFieldError('plan.steps', 'массив', list, 'Некорректные шаги плана')
const steps = list.map((value, index) => {
const field = `plan.steps[${index}]`
const step = object(value, field)
let mode: ScreenMode
try {
mode = integer(
typeof step.mode === 'string' && step.mode.startsWith('SCREEN_MODE_')
? modes.indexOf(step.mode.slice(12))
: step.mode,
1,
8,
`${field}.mode`,
) as ScreenMode
} catch {
throw new ResponseFieldError(
`${field}.mode`,
'режим экрана 1–8 или enum ScreenMode',
step.mode,
'Некорректный режим экрана',
)
}
const content = text(step.text ?? '', `${field}.text`).trim()
const label = text(step.timerLabel ?? '', `${field}.timerLabel`).trim()
const seconds = integer(
step.timerDurationSeconds ?? 0,
0,
86400,
`${field}.timerDurationSeconds`,
)
if (mode === 8 && (!content || Buffer.byteLength(content) > 10000))
throw new ResponseFieldError(
`${field}.text`,
'строка от 1 до 10000 байт',
step.text,
'Текст шага должен содержать от 1 до 10000 байт',
)
if (mode === 7 && (!seconds || Buffer.byteLength(label) > 200))
throw new ResponseFieldError(
!seconds ? `${field}.timerDurationSeconds` : `${field}.timerLabel`,
!seconds ? 'число от 1 до 86400' : 'строка до 200 байт',
!seconds ? step.timerDurationSeconds : step.timerLabel,
'Укажите таймер от 1 до 86400 секунд и подпись до 200 байт',
)
return {
mode,
text: content,
timerLabel: mode === 7 ? label || 'Перерыв' : label,
timerDurationSeconds: seconds,
}
})
return {
steps,
currentStep: integer(
plan.currentStep ?? 0,
0,
Math.max(0, steps.length - 1),
'plan.currentStep',
),
}
}