diff --git a/App.tsx b/App.tsx index f1cb188..cbfe1bf 100644 --- a/App.tsx +++ b/App.tsx @@ -55,7 +55,8 @@ function App() { currentCorrectShape, selectedOption, currentPlayerScore, - currentStreak + currentStreak, + currentPlayerId } = useGame(); const currentQ = quiz?.questions[currentQuestionIndex]; @@ -90,7 +91,7 @@ function App() { {gameState === 'LOBBY' ? ( ) : null} diff --git a/components/Landing.tsx b/components/Landing.tsx index 288dec4..b33a90c 100644 --- a/components/Landing.tsx +++ b/components/Landing.tsx @@ -39,7 +39,7 @@ export const Landing: React.FC = ({ onGenerate, onCreateManual, on -

OpenHoot

+

Kaboot

The AI Quiz Party

diff --git a/components/Scoreboard.tsx b/components/Scoreboard.tsx index c94747c..037bca9 100644 --- a/components/Scoreboard.tsx +++ b/components/Scoreboard.tsx @@ -8,10 +8,15 @@ interface ScoreboardProps { players: Player[]; onNext: () => void; isHost: boolean; + currentPlayerId: string | null; } -export const Scoreboard: React.FC = ({ players, onNext, isHost }) => { - const sortedPlayers = [...players].sort((a, b) => b.score - a.score).slice(0, 5); +export const Scoreboard: React.FC = ({ players, onNext, isHost, currentPlayerId }) => { + const playersWithDisplayName = players.map(p => ({ + ...p, + displayName: p.id === currentPlayerId ? `${p.name} (You)` : p.name + })); + const sortedPlayers = [...playersWithDisplayName].sort((a, b) => b.score - a.score).slice(0, 5); return (
@@ -29,7 +34,7 @@ export const Scoreboard: React.FC = ({ players, onNext, isHost = ({ players, onNext, isHost {sortedPlayers.map((entry, index) => ( ))} diff --git a/constants.ts b/constants.ts index 173b9b7..d0606dc 100644 --- a/constants.ts +++ b/constants.ts @@ -23,3 +23,18 @@ export const BOT_NAMES = [ export const QUESTION_TIME = 20; // seconds export const POINTS_PER_QUESTION = 1000; + +export const PLAYER_COLORS = [ + '#46178f', + '#e21b3c', + '#1368ce', + '#26890c', + '#ffa602', + '#d89e00', + '#0aa3a3', + '#b8008a', + '#6a4c93', + '#ff6b6b', + '#4ecdc4', + '#45b7d1', +]; diff --git a/hooks/useGame.ts b/hooks/useGame.ts index 6dca234..2b9b6ac 100644 --- a/hooks/useGame.ts +++ b/hooks/useGame.ts @@ -1,7 +1,7 @@ import { useState, useEffect, useRef, useCallback } from 'react'; import { Quiz, Player, GameState, GameRole, NetworkMessage, AnswerOption, Question } from '../types'; import { generateQuiz } from '../services/geminiService'; -import { POINTS_PER_QUESTION, QUESTION_TIME } from '../constants'; +import { POINTS_PER_QUESTION, QUESTION_TIME, PLAYER_COLORS } from '../constants'; import { Peer, DataConnection } from 'peerjs'; export const useGame = () => { @@ -19,6 +19,8 @@ export const useGame = () => { const [selectedOption, setSelectedOption] = useState(null); const [currentPlayerScore, setCurrentPlayerScore] = useState(0); const [currentStreak, setCurrentStreak] = useState(0); + const [currentPlayerId, setCurrentPlayerId] = useState(null); + const [currentPlayerName, setCurrentPlayerName] = useState(null); const timerRef = useRef | null>(null); const peerRef = useRef(null); @@ -71,20 +73,23 @@ export const useGame = () => { const pin = generateGamePin(); setGamePin(pin); - const peer = new Peer(`openhoot-${pin}`); + const peer = new Peer(`kaboot-${pin}`); peerRef.current = peer; peer.on('open', (id) => { const hostPlayer: Player = { id: 'host', - name: 'Host (You)', + name: 'Host', score: 0, streak: 0, lastAnswerCorrect: null, isBot: false, - avatarSeed: Math.random() + avatarSeed: Math.random(), + color: PLAYER_COLORS[0] }; setPlayers([hostPlayer]); + setCurrentPlayerId('host'); + setCurrentPlayerName('Host'); setGameState('LOBBY'); }); @@ -103,21 +108,23 @@ export const useGame = () => { const handleHostData = (conn: DataConnection, data: NetworkMessage) => { if (data.type === 'JOIN') { - const newPlayer: Player = { - id: conn.peer, - name: data.payload.name, - score: 0, - streak: 0, - lastAnswerCorrect: null, - isBot: false, - avatarSeed: Math.random() - }; setPlayers(prev => { - if (prev.find(p => p.id === newPlayer.id)) return prev; + if (prev.find(p => p.id === conn.peer)) return prev; + const colorIndex = prev.length % PLAYER_COLORS.length; + const newPlayer: Player = { + id: conn.peer, + name: data.payload.name, + score: 0, + streak: 0, + lastAnswerCorrect: null, + isBot: false, + avatarSeed: Math.random(), + color: PLAYER_COLORS[colorIndex] + }; return [...prev, newPlayer]; }); connectionsRef.current.set(conn.peer, conn); - conn.send({ type: 'WELCOME', payload: { playerId: conn.peer, quizTitle: 'OpenHoot', players: [] } }); + conn.send({ type: 'WELCOME', payload: { playerId: conn.peer, quizTitle: 'Kaboot', players: [] } }); } if (data.type === 'ANSWER') { @@ -247,11 +254,13 @@ export const useGame = () => { setRole('CLIENT'); setError(null); setGamePin(pin); + setCurrentPlayerName(name); const peer = new Peer(); peerRef.current = peer; - peer.on('open', () => { - const conn = peer.connect(`openhoot-${pin}`); + peer.on('open', (id) => { + setCurrentPlayerId(id); + const conn = peer.connect(`kaboot-${pin}`); hostConnectionRef.current = conn; conn.on('open', () => { conn.send({ type: 'JOIN', payload: { name } }); @@ -369,7 +378,7 @@ export const useGame = () => { }, []); return { - role, gameState, quiz, players, currentQuestionIndex, timeLeft, error, gamePin, hasAnswered, lastPointsEarned, currentCorrectShape, selectedOption, currentPlayerScore, currentStreak, + role, gameState, quiz, players, currentQuestionIndex, timeLeft, error, gamePin, hasAnswered, lastPointsEarned, currentCorrectShape, selectedOption, currentPlayerScore, currentStreak, currentPlayerId, startQuizGen, startManualCreation, finalizeManualQuiz, joinGame, startGame: startHostGame, handleAnswer, nextQuestion }; }; \ No newline at end of file diff --git a/index.html b/index.html index 18e90f6..a7ab8b0 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - OpenHoot + Kaboot