added stream pre-game page
parent
6b850db777
commit
2ff4ae934a
@ -0,0 +1,227 @@
|
||||
<script>
|
||||
import mqtt from "mqtt";
|
||||
|
||||
let div_id;
|
||||
|
||||
|
||||
/** @type {string[]} */
|
||||
|
||||
let red_teams = [];
|
||||
let blue_teams = [];
|
||||
let field_matches = [];
|
||||
|
||||
|
||||
let latest_start_time = 0;
|
||||
let active_field = 0;
|
||||
let offset = 0;
|
||||
|
||||
|
||||
let event_name = "Mecha Mayhem 2024";
|
||||
let match_name = "No Match";
|
||||
let match_name_show = "No Match";
|
||||
/** @type {string[]} */
|
||||
let teams_red = [];
|
||||
/** @type {string[]} */
|
||||
let teams_blue = [];
|
||||
|
||||
/** @type {undefined | Date} */
|
||||
let timer_end = undefined;
|
||||
/** @type {undefined | ReturnType<typeof setInterval>} */
|
||||
let timer_next_tick = undefined;
|
||||
let timer = "Next Match";
|
||||
|
||||
/** @type {string} */
|
||||
let display_state = "init";
|
||||
|
||||
/** @type {string} */
|
||||
let display_class = "side-display";
|
||||
|
||||
const client = mqtt.connect("ws://metznet.ca:8883");
|
||||
|
||||
function stop_timer() {
|
||||
if(timer_next_tick === undefined) {
|
||||
} else {
|
||||
clearInterval(timer_next_tick);
|
||||
timer_next_tick = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function tick_timer() {
|
||||
if(timer_end === undefined) {
|
||||
stop_timer();
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
const time_diff = timer_end.getTime() - now.getTime() + offset;
|
||||
if (time_diff <= 0) {
|
||||
timer = "0:00";
|
||||
stop_timer();
|
||||
} else {
|
||||
const seconds_total = Math.ceil(time_diff/ 1000);
|
||||
const minutes = Math.floor(seconds_total / 60);
|
||||
const seconds = seconds_total - (minutes * 60);
|
||||
timer = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
}
|
||||
|
||||
client.on("message", (topic, message) => {
|
||||
/** @type {RegExp} */
|
||||
let field_metadata_topic = /^field\/\d+\/(\d+)$/;
|
||||
/** @type {RegExp} */
|
||||
let field_state_topic = /^field\/\d+\/(\d+)\/state$/;
|
||||
|
||||
let topic_str = topic.toString();
|
||||
let message_str = message.toString();
|
||||
let field_state_match = field_state_topic.exec(topic_str);
|
||||
let field_metadata_match = field_metadata_topic.exec(topic_str);
|
||||
|
||||
console.log(`${topic_str} - ${message_str}`);
|
||||
|
||||
if (field_state_match) {
|
||||
console.log("here")
|
||||
let [_, field] = field_state_match;
|
||||
const state_obj = JSON.parse(message_str);
|
||||
if (state_obj.state != "Scheduled") { return; }
|
||||
if (state_obj.start <= latest_start_time) { return; }
|
||||
|
||||
latest_start_time = parseFloat(state_obj.start);
|
||||
active_field = parseInt(field);
|
||||
console.log(`${latest_start_time}`);
|
||||
console.log(`active field: ${active_field}`);
|
||||
|
||||
let field_obj = field_matches[active_field];
|
||||
red_teams = [field_obj.red_teams[0], field_obj.red_teams[1]];
|
||||
blue_teams = [field_obj.blue_teams[0], field_obj.blue_teams[1]];
|
||||
}
|
||||
else if (field_metadata_match) {
|
||||
let [_, field] = field_metadata_match;
|
||||
const field_obj = JSON.parse(message_str);
|
||||
|
||||
field_matches[parseInt(field)] = field_obj;
|
||||
if(field == active_field) {
|
||||
red_teams = [field_obj.red_teams[0], field_obj.red_teams[1]];
|
||||
blue_teams = [field_obj.blue_teams[0], field_obj.blue_teams[1]];
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log(`${topic_str} not defined`);
|
||||
}
|
||||
|
||||
|
||||
// switch(topic_str){
|
||||
// case "time":
|
||||
// let local = Date.now();
|
||||
// let server = JSON.parse(message_str) * 1000;
|
||||
// offset = local - server;
|
||||
// console.log(`NEW offset: ${local} - ${server} = ${offset}`);
|
||||
// break;
|
||||
// case field_metadata_topic:
|
||||
// const field_obj = JSON.parse(message_str);
|
||||
// teams_red = [field_obj.red_teams[0], field_obj.red_teams[1]];
|
||||
// teams_blue = [field_obj.blue_teams[0], field_obj.blue_teams[1]];
|
||||
// let num = field_obj.tuple.match_num;
|
||||
// let round = field_obj.tuple.round;
|
||||
// match_name = `${round} ${num}`;
|
||||
// break;
|
||||
// case field_state_topic:
|
||||
// stop_timer();
|
||||
|
||||
// const state_obj = JSON.parse(message_str);
|
||||
// const start_ms = state_obj.start * 1000;
|
||||
// console.log(`Start_ms: ${start_ms}`);
|
||||
// switch(state_obj.state) {
|
||||
// case "Scheduled":
|
||||
// timer = match_name;
|
||||
// match_name_show = "Next Match";
|
||||
// if (state_obj.start > latest_start_time) {
|
||||
// latest_start_time = state_obj.start;
|
||||
// active_field = parseFloat(topic_str.split("/")[2]);
|
||||
// console.log(`${latest_start_time}`);
|
||||
// console.log(`${active_field}`);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// console.log(`Unhandled topic ${topic_str}`)
|
||||
// }
|
||||
});
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
onMount(() => {
|
||||
const search_params = new URLSearchParams(window.location.search);
|
||||
div_id = search_params.get("division");
|
||||
if (div_id === null) {
|
||||
div_id = "default";
|
||||
}
|
||||
// field_metadata_topic = `field/${div_id}/+`;
|
||||
// field_state_topic = `field/${div_id}/+/state`;
|
||||
|
||||
client.on("connect", () => {
|
||||
console.log("connected to mqtt");
|
||||
|
||||
client.subscribe(`field/${div_id}/#`, (err) => {
|
||||
if (err) {
|
||||
console.log("failed to subscribe to field metadata")
|
||||
console.log(err);
|
||||
} else {
|
||||
console.log(`subscribed`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div class="img-grid">
|
||||
{#each Object.entries(red_teams) as [index, team]}
|
||||
<div class="item">
|
||||
<video autoplay loop muted playsinline src="./{team}.mp4" alt="video {team}"></video>
|
||||
<div class="text">{team}</div>
|
||||
</div>
|
||||
{/each}
|
||||
{#each Object.entries(blue_teams) as [index, team]}
|
||||
<div class="item">
|
||||
<video autoplay loop muted playsinline src="./{team}.mp4" alt="video {team}"></video>
|
||||
<div class="text">{team}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap');
|
||||
|
||||
.img-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, lfr);
|
||||
grid-template-rows: repeat(2, lfr);
|
||||
gap: 20px;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
margin: auto;
|
||||
background-color: #2ae400;
|
||||
font-family: 'Bebas Neue';
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue