up
This commit is contained in:
+39
-10
@@ -13,7 +13,9 @@ import type {
|
||||
TimerState,
|
||||
ScreenStep,
|
||||
} from '../src/types/screen.js'
|
||||
import { parsePlan } from './screen-plan.js'
|
||||
import { timerLabels, validQR } from '../src/utils/presentation.js'
|
||||
import { parseTeams } from './teams.js'
|
||||
import { parsePlan, parseTimerType } from './screen-plan.js'
|
||||
import { parseResults } from './results.js'
|
||||
import type { LocalPackage } from './package-store.js'
|
||||
|
||||
@@ -36,10 +38,12 @@ export function parseCommand(value: unknown): Command {
|
||||
else if (
|
||||
c.action === 'mode' &&
|
||||
Number.isInteger(c.mode) &&
|
||||
number(c.mode, 1, 8) &&
|
||||
[1, 2, 4, 6, 7, 8].includes(c.mode)
|
||||
number(c.mode, 1, 10) &&
|
||||
[1, 2, 4, 6, 7, 8, 9, 10].includes(c.mode)
|
||||
)
|
||||
intent = { action: 'mode', mode: c.mode as ScreenMode }
|
||||
else if (c.action === 'qr' && typeof c.qrUrl === 'string' && typeof c.text === 'string' && validQR(c.qrUrl, c.text))
|
||||
intent = { action: 'qr', qrUrl: c.qrUrl, text: c.text }
|
||||
else if (c.action === 'step' && Number.isSafeInteger(c.index) && number(c.index, 0))
|
||||
intent = { action: 'step', index: c.index }
|
||||
else if (
|
||||
@@ -58,8 +62,9 @@ export function parseCommand(value: unknown): Command {
|
||||
)
|
||||
intent = {
|
||||
action: 'timer-set',
|
||||
label: c.label.trim() || 'Перерыв',
|
||||
label: c.label.trim() || timerLabels[parseTimerType(c.timerType)],
|
||||
durationSeconds: c.durationSeconds,
|
||||
timerType: parseTimerType(c.timerType),
|
||||
}
|
||||
else if (
|
||||
typeof c.action === 'string' &&
|
||||
@@ -178,6 +183,7 @@ export class Controller {
|
||||
scene: { revision: 0, mode: 1, stepIndex: null, text: '', status: 'idle', error: '' },
|
||||
timer: initialTimer(),
|
||||
results: null,
|
||||
teams: null,
|
||||
channels: { main: initialChannel(), music: initialChannel() },
|
||||
samples: [],
|
||||
}
|
||||
@@ -301,6 +307,7 @@ export class Controller {
|
||||
this.state.timer = initialTimer()
|
||||
this.timerDeadline = null
|
||||
this.state.results = null
|
||||
this.state.teams = null
|
||||
this.state.channels = {
|
||||
main: { ...initialChannel(), source: catalog.media[0] ?? null },
|
||||
music: initialChannel(),
|
||||
@@ -372,11 +379,12 @@ export class Controller {
|
||||
this.broadcast()
|
||||
}
|
||||
}
|
||||
private configureTimer(label: string, seconds: number) {
|
||||
private configureTimer(label: string, seconds: number, timerType = 0) {
|
||||
this.timerDeadline = null
|
||||
this.state.timer = {
|
||||
revision: this.state.timer.revision + 1,
|
||||
label,
|
||||
timerType: parseTimerType(timerType),
|
||||
durationMs: seconds * 1000,
|
||||
remainingMs: seconds * 1000,
|
||||
status: 'stopped',
|
||||
@@ -436,10 +444,17 @@ export class Controller {
|
||||
markStep(index: number) {
|
||||
const step = this.state.catalog.steps[index]
|
||||
const scene = this.state.scene
|
||||
if (!step || step.mode !== scene.mode || (step.mode === 8 && step.text !== scene.text)) return
|
||||
if (
|
||||
!step ||
|
||||
step.mode !== scene.mode ||
|
||||
([8, 9].includes(step.mode) && step.text !== scene.text) ||
|
||||
(step.mode === 9 && step.qrUrl !== scene.qrUrl)
|
||||
)
|
||||
return
|
||||
if (
|
||||
step.mode === 7 &&
|
||||
(step.timerLabel !== this.state.timer.label ||
|
||||
((step.timerType ?? 0) !== (this.state.timer.timerType ?? 0) ||
|
||||
step.timerLabel !== this.state.timer.label ||
|
||||
step.timerDurationSeconds * 1000 !== this.state.timer.durationMs)
|
||||
)
|
||||
return
|
||||
@@ -447,6 +462,15 @@ export class Controller {
|
||||
scene.stepIndex = index
|
||||
this.broadcast()
|
||||
}
|
||||
setTeams(value: unknown) {
|
||||
const key = this.state.catalog.key
|
||||
if (value !== null && !key) throw new Error('Сначала выберите пакет игры')
|
||||
const snapshot = value === null ? null : parseTeams(value, key!)
|
||||
const changed = !isDeepStrictEqual(this.state.teams?.teams, snapshot?.teams)
|
||||
this.state.teams = snapshot
|
||||
if (changed && this.state.scene.mode === 10) this.invalidateScene()
|
||||
this.broadcast()
|
||||
}
|
||||
setResults(value: unknown) {
|
||||
const key = this.state.catalog.key
|
||||
if (value !== null && !key) throw new Error('Сначала выберите пакет игры')
|
||||
@@ -487,6 +511,10 @@ export class Controller {
|
||||
case 'mode':
|
||||
this.mode(command.mode)
|
||||
return true
|
||||
case 'qr':
|
||||
this.state.scene.qrUrl = command.qrUrl
|
||||
this.mode(9, null, command.text)
|
||||
return true
|
||||
case 'text':
|
||||
this.mode(8, null, command.text)
|
||||
return true
|
||||
@@ -494,12 +522,13 @@ export class Controller {
|
||||
const step = this.state.catalog.steps[command.index]
|
||||
if (!step) throw new Error('Шаг плана не найден')
|
||||
if (step.mode === 7)
|
||||
this.configureTimer(step.timerLabel || 'Перерыв', step.timerDurationSeconds)
|
||||
this.configureTimer(step.timerLabel || timerLabels[step.timerType ?? 0], step.timerDurationSeconds, step.timerType)
|
||||
this.state.scene.qrUrl = step.qrUrl ?? ''
|
||||
this.mode(step.mode, command.index, step.text)
|
||||
return true
|
||||
}
|
||||
case 'timer-set':
|
||||
this.configureTimer(command.label, command.durationSeconds)
|
||||
this.configureTimer(command.label, command.durationSeconds, command.timerType)
|
||||
this.mode(7)
|
||||
return true
|
||||
case 'timer-start':
|
||||
@@ -509,7 +538,7 @@ export class Controller {
|
||||
this.updateTimer()
|
||||
const t = this.state.timer
|
||||
if (command.action === 'timer-reset') {
|
||||
this.configureTimer(t.label, t.durationMs / 1000)
|
||||
this.configureTimer(t.label, t.durationMs / 1000, t.timerType)
|
||||
return true
|
||||
}
|
||||
if (command.action === 'timer-pause') {
|
||||
|
||||
Reference in New Issue
Block a user