Skip to content

Commit

Permalink
change device stream pools to be configured on a screen+rows+cols bas…
Browse files Browse the repository at this point in the history
…is allowing more flexible layouts
  • Loading branch information
swantzter committed Jul 21, 2023
1 parent 4d6183b commit bdcdbf5
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 127 deletions.
58 changes: 58 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@vue/apollo-composable": "^4.0.0-beta.8",
"@vueuse/core": "^10.2.1",
"@vueuse/head": "^1.1.26",
"@vueuse/router": "^10.2.1",
"graphql": "^16.7.1",
"graphql-ws": "^5.14.0",
"unocss": "^0.53.5",
Expand Down
4 changes: 2 additions & 2 deletions src/components/DeviceNotSet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<div
class="font-bold text-8xl absolute top-0 left-2 text-gray-600 dark:text-gray-400"
>
{{ pool }}
{{ pool ?? '' }}
</div>

<p class="text-center">
Expand All @@ -18,7 +18,7 @@
defineProps({
pool: {
type: Number,
required: true
default: undefined
}
})
</script>
4 changes: 2 additions & 2 deletions src/components/SpeedLiveScore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<div
class="font-bold text-8xl absolute top-0 left-2 text-gray-600 dark:text-gray-400"
>
{{ pool }}
{{ pool ?? '' }}
</div>
<div
v-if="entry"
Expand Down Expand Up @@ -52,7 +52,7 @@ import { type ScoreTally, getAbbr } from '../helpers'
const props = defineProps({
pool: {
type: Number,
required: true
default: undefined
},
entry: {
type: Object as PropType<EntryFragment>,
Expand Down
6 changes: 3 additions & 3 deletions src/components/TimingLiveScore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<div
class="font-bold text-8xl absolute top-0 left-2 text-gray-600 dark:text-gray-400"
>
{{ pool }}
{{ pool ?? '' }}
</div>
<div
v-if="entry"
Expand Down Expand Up @@ -51,8 +51,8 @@ import { type ScoreTally, getAbbr } from '../helpers'
const props = defineProps({
pool: {
type: Number,
required: true
type: [Number],
default: undefined
},
entry: {
type: Object as PropType<EntryFragment>,
Expand Down
4 changes: 2 additions & 2 deletions src/components/UnsupportedCompetitionEvent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<div
class="font-bold text-8xl absolute top-0 left-2 text-gray-600 dark:text-gray-400"
>
{{ pool }}
{{ pool ?? '' }}
</div>

<p class="text-center">
Expand All @@ -29,7 +29,7 @@ import { type EntryFragment } from '../graphql/generated'
defineProps({
pool: {
type: Number,
required: true
default: undefined
},
entry: {
type: Object as PropType<EntryFragment>,
Expand Down
14 changes: 9 additions & 5 deletions src/hooks/stream-pools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ export interface ServoPoolBackgroundsConfig {
competitionId?: number
}

export interface ScreenConfig {
rows: number
cols: number
// row:col
pools?: Record<`${number}:${number}`, StreamPool>
}

export interface DeviceStreamSettings {
poolBackgrounds?: ServoPoolBackgroundsConfig
screens?: Record<string, ScreenConfig>
}

const pools = useLocalStorage<StreamPool[]>('rs-device-stream-pools', [])
const settings = useLocalStorage<DeviceStreamSettings>('rs-device-stream-settings', {})

export function useDeviceStreamPools () {
return {
pools,
settings
}
return settings
}
94 changes: 50 additions & 44 deletions src/views/DeviceStreamLive.vue
Original file line number Diff line number Diff line change
@@ -1,39 +1,47 @@
<template>
<div class="grid grid-rows-1 bg-white dark:bg-black">
<main class="grid custom-grid">
<template
v-for="(pool, idx) of pools"
:key="pool.idx"
>
<device-not-set v-if="!pool.deviceId" :pool="pool.label || idx + 1" />
<speed-live-score
v-else-if="tallies[pool.deviceId]?.info == null || tallies[pool.deviceId]?.info?.judgeType === 'S' || tallies[pool.deviceId]?.info?.judgeType === 'Shj'"
:pool="pool.label || idx + 1"
:tally="tallies[pool.deviceId]?.tally"
:device-id="pool.deviceId"
:cols="cols"
:bg-url="poolBgUrl(pool.label || idx + 1)"
/>
<timing-live-score
v-else-if="tallies[pool.deviceId]?.info?.judgeType === 'T'"
:pool="pool.label || idx + 1"
:tally="tallies[pool.deviceId]?.tally"
:device-id="pool.deviceId"
:cols="cols"
:bg-url="poolBgUrl(pool.label || idx + 1)"
/>
<unsupported-competition-event
v-else
:pool="pool.label || idx + 1"
:competition-event-id="pool.deviceId ? tallies[pool.deviceId]?.info?.judgeType ?? '---' : '---'"
/>
<template v-for="row of screen?.rows ?? 0" :key="row">
<template v-for="col of screen?.cols ?? 0" :key="col">
<div v-if="pools[`${row}:${col}`] == null" />
<template v-else>
<device-not-set v-if="!pools[`${row}:${col}`].deviceId" :pool="pools[`${row}:${col}`].label" />
<speed-live-score
v-else-if="tallies[pools[`${row}:${col}`].deviceId!]?.info == null || tallies[pools[`${row}:${col}`].deviceId!]?.info?.judgeType === 'S' || tallies[pools[`${row}:${col}`].deviceId!]?.info?.judgeType === 'Shj'"
:pool="pools[`${row}:${col}`].label"
:tally="tallies[pools[`${row}:${col}`].deviceId!]?.tally"
:device-id="pools[`${row}:${col}`].deviceId"
:cols="cols"
:bg-url="poolBgUrl(pools[`${row}:${col}`].label)"
/>
<timing-live-score
v-else-if="tallies[pools[`${row}:${col}`].deviceId!]?.info?.judgeType === 'T'"
:pool="pools[`${row}:${col}`].label"
:tally="tallies[pools[`${row}:${col}`].deviceId!]?.tally"
:device-id="pools[`${row}:${col}`].deviceId"
:cols="cols"
:bg-url="poolBgUrl(pools[`${row}:${col}`].label)"
/>
<unsupported-competition-event
v-else
:pool="pools[`${row}:${col}`].label"
:competition-event-id="pools[`${row}:${col}`].deviceId ? tallies[pools[`${row}:${col}`].deviceId!]?.info?.judgeType ?? '---' : '---'"
/>
</template>
</template>
</template>
<div v-show="pools.length === 0" class="bg-gray-300 flex items-center justify-center relative">
<div v-if="screen != null && ((screen?.cols ?? 0) === 0 || (screen?.rows ?? 0) === 0)" class="bg-gray-300 dark:bg-gray-800 dark:text-white flex items-center justify-center relative">
<p class="text-center">
No pools configured
</p>
</div>
<div v-if="screen == null" class="bg-gray-300 dark:bg-gray-800 dark:text-white flex items-center justify-center relative">
<p class="text-center">
Screen does not exist, close this display
</p>
</div>
</main>
</div>
</template>
Expand All @@ -44,6 +52,7 @@ import { type DeviceStreamJudgeInfo, type DeviceStreamMarkAddedSubscription, use
import { type ScoreTally, type Mark } from '../helpers'
import { useDeviceStreamPools } from '../hooks/stream-pools'
import { useHead } from '@vueuse/head'
import { useRouteQuery } from '@vueuse/router'
import { useFetch, useTimeoutPoll } from '@vueuse/core'
import DeviceNotSet from '../components/DeviceNotSet.vue'
Expand All @@ -55,23 +64,17 @@ useHead({
title: '📺 Device Stream (Live)'
})
const { pools, settings } = useDeviceStreamPools()
const cols = computed(() => {
const len = pools.value.length
if (len === 0) return 1
else if (len === 1) return 1
else if (len <= 4) return 2
else if (len <= 6) return 3
else if (len <= 8) return 4
else if (len <= 9) return 3
else if (len <= 12) return 6
else return 5
})
const settings = useDeviceStreamPools()
const screenId = useRouteQuery<string>('screen-id')
const screen = computed(() => screenId.value == null ? null : settings.value.screens?.[screenId.value])
const cols = computed(() => screen.value?.rows === 0 ? 1 : screen.value?.cols ?? 1)
const rows = computed(() => screen.value?.cols === 0 ? 1 : screen.value?.rows ?? 1)
const pools = computed(() => screen.value?.pools ?? {})
const tallies = reactive<Record<string, { tally: ScoreTally, lastSequence: number, completed: boolean, info?: DeviceStreamJudgeInfo }>>({})
const deviceIds = computed(() => pools.value.map(p => p.deviceId).filter(id => typeof id === 'string'))
const deviceIds = computed(() => Object.values(pools.value).map(p => p.deviceId).filter(id => typeof id === 'string'))
const markStreamSubscription = useDeviceStreamMarkAddedSubscription({
deviceIds: deviceIds as unknown as string[]
Expand All @@ -98,12 +101,13 @@ function markStreamWatcher (res: DeviceStreamMarkAddedSubscription | null | unde
tallyInfo = {
tally: reactive<ScoreTally>({}),
lastSequence: 0,
completed: false,
...(info != null ? { info } : {})
completed: false
}
tallies[deviceId] = tallyInfo
}
if (info != null) tallyInfo.info = info
if (sequence >= tallyInfo.lastSequence) {
tallyInfo.tally = reactive(tally)
tallyInfo.lastSequence = sequence
Expand All @@ -118,7 +122,8 @@ watch(markStreamSubscriptionAlt.result, markStreamWatcher)
const poolBackgrounds = ref<Array<{ poolLabel: number, bgUrl?: string }>>([])
function poolBgUrl (poolLabel: number) {
function poolBgUrl (poolLabel: number | undefined) {
if (poolLabel == null) return undefined
return poolBackgrounds.value.find(pb => `${pb.poolLabel}` === `${poolLabel}`)?.bgUrl
}
Expand Down Expand Up @@ -180,5 +185,6 @@ watch(() => settings.value.poolBackgrounds, poolBackgrounds => {
<style scoped>
.custom-grid {
grid-template-columns: repeat(v-bind(cols), minmax(0, 1fr));
grid-template-rows: repeat(v-bind(rows), minmax(0, 1fr));
}
</style>
Loading

0 comments on commit bdcdbf5

Please sign in to comment.