Files
evening_detective_screen/electron/screen-plan.ts
T
2026-10-19 02:34:50 +07:00

86 lines
2.7 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: number
try {
mode = integer(
typeof step.mode === 'string' && step.mode.startsWith('SCREEN_MODE_')
? modes.indexOf(step.mode.slice(12))
: step.mode,
1,
8,
`${field}.mode`,
)
} catch {
throw new ResponseFieldError(
`${field}.mode`,
'режим экрана 1–8 или enum ScreenMode',
step.mode,
'Некорректный режим экрана',
)
}
let content = text(step.text ?? '', `${field}.text`).trim()
if (mode === 3 || mode === 5) {
content = mode === 3 ? 'Успехов' : 'Спасибо за игру!'
mode = 8
}
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: mode as ScreenMode,
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',
),
}
}