X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=resources%2Fjs%2Fpages%2FGuessingGameMonitor.js;fp=resources%2Fjs%2Fpages%2FGuessingGameMonitor.js;h=bf2922be5f59848eccf00bd1489b21c8241ef734;hb=167f986f468014e00d82fa2df8193f6be8dca19d;hp=0000000000000000000000000000000000000000;hpb=c7eaba38c74b617fbd03da196e4131e662311cc9;p=alttp.git diff --git a/resources/js/pages/GuessingGameMonitor.js b/resources/js/pages/GuessingGameMonitor.js new file mode 100644 index 0000000..bf2922b --- /dev/null +++ b/resources/js/pages/GuessingGameMonitor.js @@ -0,0 +1,194 @@ +import axios from 'axios'; +import moment from 'moment'; +import React from 'react'; +import { Container } from 'react-bootstrap'; +import { Helmet } from 'react-helmet'; +import { useParams } from 'react-router-dom'; + +import { + hasActiveGuessing, + isAcceptingGuesses, + patchGuess, + patchWinner, +} from '../helpers/Channel'; +import ErrorBoundary from '../components/common/ErrorBoundary'; +import Icon from '../components/common/Icon'; +import Slider from '../components/common/Slider'; + +export const Component = () => { + const [channel, setChannel] = React.useState({}); + const [guesses, setGuesses] = React.useState([]); + const [winnerExpiry, setWinnerExpiry] = React.useState(moment().subtract(15, 'second')); + const [winners, setWinners] = React.useState([]); + + const params = useParams(); + const { key } = params; + + React.useEffect(() => { + if (!key) return; + axios.get(`/api/guessing-game-monitor/${key}`) + .then(res => { + setChannel(res.data.channel); + res.data.guesses.forEach(g => { + setGuesses(gs => patchGuess(gs, g)); + }); + res.data.winners.forEach(w => { + setWinners(ws => patchGuess(ws, w)); + }); + }); + window.Echo.channel(`ChannelKey.${key}`) + .listen('.GuessingGuessCreated', (e) => { + setGuesses(gs => patchGuess(gs, e.model)); + }) + .listen('.GuessingWinnerCreated', (e) => { + setWinners(ws => patchWinner(ws, e.model)); + }) + .listen('.ChannelUpdated', (e) => { + setChannel(c => ({ ...c, ...e.model })); + }); + return () => { + window.Echo.leave(`ChannelKey.${key}`); + }; + }, [key]); + + React.useEffect(() => { + if (isAcceptingGuesses(channel)) { + setGuesses(gs => gs.filter(g => g.created_at >= channel.guessing_start)); + setWinners([]); + } + }, [channel]); + + React.useEffect(() => { + const interval = setInterval(() => { + setWinnerExpiry(moment().subtract(15, 'second')); + }, 1000); + return () => { + clearInterval(interval); + }; + }, []); + + const guessingStats = React.useMemo(() => { + const stats = { + counts: [], + lastWin: null, + max: 0, + wins: [], + winners: [], + }; + for (let i = 0; i < 22; ++i) { + stats.counts.push(0); + stats.wins.push(false); + } + const seen = []; + guesses.forEach(guess => { + if (seen[guess.uid]) { + --stats.counts[parseInt(seen[guess.uid].guess, 10) - 1]; + } + ++stats.counts[parseInt(guess.guess, 10) - 1]; + seen[guess.uid] = guess; + }); + winners.forEach(winner => { + if (winner.score) { + stats.wins[parseInt(winner.guess, 10) - 1] = true; + stats.winners.push(winner.uname); + } + if (!stats.lastWin || stats.lastWin < winner.created_at) { + stats.lastWin = winner.created_at; + } + }); + for (let i = 0; i < 22; ++i) { + if (stats.counts[i] > stats.max) { + stats.max = stats.counts[i]; + } + } + return stats; + }, [guesses, winners]); + + const getNumberHeight = React.useCallback((number) => { + if (!guessingStats || !guessingStats.max) return 3; + if (!number) return 3; + return Math.max(0.05, number / guessingStats.max) * 100; + }, [guessingStats]); + + const getStatClass = React.useCallback((index) => { + const names = ['guessing-stat']; + if (guessingStats.wins[index]) { + names.push('has-won'); + } + return names.join(' '); + }, [guessingStats]); + + const showOpen = React.useMemo(() => { + return isAcceptingGuesses(channel); + }, [channel]); + + const showClosed = React.useMemo(() => { + return hasActiveGuessing(channel) && !isAcceptingGuesses(channel); + }, [channel]); + + const showWinners = React.useMemo(() => { + return !hasActiveGuessing(channel) && ( + guessingStats?.lastWin && + moment(guessingStats.lastWin).isAfter(winnerExpiry)); + }, [channel, guessingStats, winnerExpiry]); + + return + + Guessing Game + + + {showOpen || showClosed || showWinners ? +
+ {showOpen ? +
+ +
+ + GT Big Key Guessing Game + Zahlen von 1 bis 22 in den Chat! + +
+ +
+ : null} + {showClosed ? +
+
+ Anmeldung geschlossen +
+
+ : null} + {showWinners ? +
+
+ {guessingStats.winners.length ? + + Herzlichen Glückwunsch! + {guessingStats.winners.map(winner => + {winner} + )} + + : + 'Leider keiner richtig' + } +
+
+ : null} +
+ {guessingStats.counts.map((number, index) => +
+
+
+
+
{index + 1}
+
+ )} +
+
+ : null} + + ; +};