2026-01-23 18:47:44 +01:00
|
|
|
<template>
|
2026-02-01 13:54:15 +01:00
|
|
|
<v-dialog v-model="dialog" persistent max-width="800" height="500" style="background-color: rgba(0, 0, 0, 0.8);">
|
|
|
|
|
<v-card dark rounded="xl">
|
2026-01-23 18:47:44 +01:00
|
|
|
<v-card-title :style="{ backgroundColor: buzzerColor }" class="headline text-center justify-center">
|
|
|
|
|
<v-icon color="background" dark large left size="70">mdi-alarm-light</v-icon>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-text :style="{ color: buzzerColor }" class="text-style">
|
|
|
|
|
L'équipe {{ buzzerTeam }} a buzzé !
|
|
|
|
|
</v-card-text>
|
|
|
|
|
|
|
|
|
|
<v-card-actions class="justify-center pa-0 ma-0" style="height: 100px; gap: 0;">
|
|
|
|
|
<v-btn
|
|
|
|
|
class="refuse-btn ma-0"
|
|
|
|
|
tile
|
|
|
|
|
rounded="0"
|
|
|
|
|
height="100%"
|
|
|
|
|
width="50%"
|
|
|
|
|
@click="refuse">
|
|
|
|
|
<v-icon left size="40">mdi-close-circle</v-icon>
|
|
|
|
|
<span style="font-size: 20px; padding-left: 10px;">Refuser</span>
|
|
|
|
|
</v-btn>
|
|
|
|
|
<v-btn
|
|
|
|
|
class="validate-btn ma-0"
|
|
|
|
|
tile
|
|
|
|
|
rounded="0"
|
|
|
|
|
height="100%"
|
|
|
|
|
width="50%"
|
2026-02-01 13:54:15 +01:00
|
|
|
:style="{ backgroundColor: buzzerColor }"
|
2026-01-23 18:47:44 +01:00
|
|
|
@click="validate">
|
|
|
|
|
<v-icon left size="40">mdi-check-circle</v-icon>
|
|
|
|
|
<span style="font-size: 20px; padding-left: 10px;">Valider (+1)</span>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-card-actions>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-dialog>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, onMounted } from 'vue';
|
|
|
|
|
import mqtt from 'mqtt';
|
|
|
|
|
import config from '@/config.js';
|
|
|
|
|
import { useTheme } from 'vuetify';
|
|
|
|
|
|
|
|
|
|
const theme = useTheme();
|
|
|
|
|
const dialog = ref(false);
|
|
|
|
|
const buzzerTeam = ref('');
|
|
|
|
|
const buzzerColor = ref('');
|
|
|
|
|
const client = mqtt.connect(config.mqttBrokerUrl);
|
|
|
|
|
|
2026-02-03 19:59:02 +01:00
|
|
|
// Associe les couleurs hex aux noms d'équipe si besoin, ou utilise directement la couleur
|
2026-01-23 18:47:44 +01:00
|
|
|
function getTeamNameFromColor(color) {
|
|
|
|
|
const c = color.toUpperCase();
|
|
|
|
|
const colors = theme.current.value.colors;
|
|
|
|
|
|
|
|
|
|
console.log('Received Color:', c);
|
|
|
|
|
console.log('Comparing against:', colors.RedBuzzer.toUpperCase(), colors.BlueBuzzer.toUpperCase(), colors.YellowBuzzer.toUpperCase(), colors.GreenBuzzer.toUpperCase());
|
|
|
|
|
|
|
|
|
|
if (c === colors.RedBuzzer.toUpperCase()) return 'rouge';
|
|
|
|
|
if (c === colors.BlueBuzzer.toUpperCase()) return 'bleue';
|
|
|
|
|
if (c === colors.YellowBuzzer.toUpperCase()) return 'jaune';
|
|
|
|
|
if (c === colors.GreenBuzzer.toUpperCase()) return 'verte';
|
2026-02-03 19:59:02 +01:00
|
|
|
return color; // Valeur par défaut
|
2026-01-23 18:47:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getTeamKeyFromColor(color) {
|
|
|
|
|
const c = color.toUpperCase();
|
|
|
|
|
const colors = theme.current.value.colors;
|
|
|
|
|
|
|
|
|
|
if (c === colors.RedBuzzer.toUpperCase()) return 'Red';
|
|
|
|
|
if (c === colors.BlueBuzzer.toUpperCase()) return 'Blue';
|
|
|
|
|
if (c === colors.YellowBuzzer.toUpperCase()) return 'Yellow';
|
|
|
|
|
if (c === colors.GreenBuzzer.toUpperCase()) return 'Green';
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
client.on('connect', () => {
|
|
|
|
|
console.log('BuzzerValidation: Connected');
|
|
|
|
|
client.subscribe('vulture/buzzer/status');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
client.on('message', (topic, message) => {
|
|
|
|
|
if (topic === 'vulture/buzzer/status') {
|
|
|
|
|
try {
|
|
|
|
|
const data = JSON.parse(message.toString());
|
|
|
|
|
if (data.status === 'blocked') {
|
|
|
|
|
buzzerColor.value = data.color;
|
|
|
|
|
buzzerTeam.value = getTeamNameFromColor(data.color);
|
|
|
|
|
dialog.value = true;
|
|
|
|
|
} else if (data.status === 'unblocked') {
|
2026-02-03 19:59:02 +01:00
|
|
|
// Optionnel : fermer automatiquement si débloqué depuis ailleurs
|
2026-01-23 18:47:44 +01:00
|
|
|
dialog.value = false;
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Error parsing buzzer status:', e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function unlockBuzzers() {
|
|
|
|
|
client.publish('vulture/buzzer/unlock','0');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validate() {
|
|
|
|
|
const teamKey = getTeamKeyFromColor(buzzerColor.value);
|
|
|
|
|
if (teamKey) {
|
|
|
|
|
const payload = { [teamKey]: "+1" };
|
|
|
|
|
client.publish('game/score/update', JSON.stringify(payload));
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-03 19:59:02 +01:00
|
|
|
// Petit délai avant le déblocage pour que la mise à jour du score soit traitée
|
2026-01-23 18:47:44 +01:00
|
|
|
setTimeout(() => {
|
|
|
|
|
unlockBuzzers();
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
|
|
dialog.value = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function refuse() {
|
|
|
|
|
unlockBuzzers();
|
|
|
|
|
dialog.value = false;
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.headline {
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
.text-style {
|
|
|
|
|
font-size: 45px!important;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
text-align: center;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
2026-02-03 19:59:02 +01:00
|
|
|
height: 100%; /* S'assure que l'élément occupe toute la hauteur du conteneur si possible, ou une hauteur substantielle */
|
2026-01-23 18:47:44 +01:00
|
|
|
}
|
|
|
|
|
.validate-btn {
|
|
|
|
|
color: rgb(var(--v-theme-background),1);
|
|
|
|
|
}
|
|
|
|
|
.refuse-btn {
|
2026-02-01 13:54:15 +01:00
|
|
|
background-color: rgb(var(--v-theme-inactiveButton),1);
|
2026-01-23 18:47:44 +01:00
|
|
|
color: rgb(var(--v-theme-background),1);
|
|
|
|
|
}
|
|
|
|
|
</style>
|