Redesign scoreboard

This commit is contained in:
Joey Yakimowich-Payne 2026-01-14 01:55:49 -07:00
commit fc270d437f
No known key found for this signature in database
GPG key ID: 6BFE655FA5ABD1E1
4 changed files with 231 additions and 90 deletions

View file

@ -1,7 +1,7 @@
import { useState, useEffect, useRef, useCallback } from 'react';
import { Quiz, Player, GameState, GameRole, NetworkMessage, AnswerOption, Question, GenerateQuizOptions, ProcessedDocument, GameConfig, DEFAULT_GAME_CONFIG } from '../types';
import { Quiz, Player, GameState, GameRole, NetworkMessage, AnswerOption, Question, GenerateQuizOptions, ProcessedDocument, GameConfig, DEFAULT_GAME_CONFIG, PointsBreakdown } from '../types';
import { generateQuiz } from '../services/geminiService';
import { QUESTION_TIME, QUESTION_TIME_MS, PLAYER_COLORS, calculatePoints, getPlayerRank } from '../constants';
import { QUESTION_TIME, QUESTION_TIME_MS, PLAYER_COLORS, calculatePointsWithBreakdown, getPlayerRank } from '../constants';
import { Peer, DataConnection } from 'peerjs';
const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:3001';
@ -158,8 +158,10 @@ export const useGame = () => {
id: 'host',
name: 'Host',
score: 0,
previousScore: 0,
streak: 0,
lastAnswerCorrect: null,
pointsBreakdown: null,
isBot: false,
avatarSeed: Math.random(),
color: PLAYER_COLORS[0]
@ -197,8 +199,10 @@ export const useGame = () => {
id: conn.peer,
name: data.payload.name,
score: 0,
previousScore: 0,
streak: 0,
lastAnswerCorrect: null,
pointsBreakdown: null,
isBot: false,
avatarSeed: Math.random(),
color: PLAYER_COLORS[colorIndex]
@ -224,7 +228,7 @@ export const useGame = () => {
const newStreak = isCorrect ? currentPlayer.streak + 1 : 0;
const playerRank = getPlayerRank(playerId, playersRef.current);
const points = calculatePoints({
const breakdown = calculatePointsWithBreakdown({
isCorrect,
timeLeftMs: timeLeftRef.current,
questionTimeMs: QUESTION_TIME_MS,
@ -233,14 +237,14 @@ export const useGame = () => {
isFirstCorrect,
config: gameConfigRef.current,
});
const newScore = Math.max(0, currentPlayer.score + points);
const newScore = Math.max(0, currentPlayer.score + breakdown.total);
setPlayers(prev => prev.map(p => {
if (p.id !== playerId) return p;
return { ...p, score: newScore, streak: newStreak, lastAnswerCorrect: isCorrect };
return { ...p, score: newScore, previousScore: p.score, streak: newStreak, lastAnswerCorrect: isCorrect, pointsBreakdown: breakdown };
}));
conn.send({ type: 'RESULT', payload: { isCorrect, scoreAdded: points, newScore } });
conn.send({ type: 'RESULT', payload: { isCorrect, scoreAdded: breakdown.total, newScore, breakdown } });
}
};
@ -284,7 +288,7 @@ export const useGame = () => {
setSelectedOption(null);
setTimeLeft(QUESTION_TIME_MS);
setFirstCorrectPlayerId(null);
setPlayers(prev => prev.map(p => ({ ...p, lastAnswerCorrect: null })));
setPlayers(prev => prev.map(p => ({ ...p, lastAnswerCorrect: null, pointsBreakdown: null })));
const currentQuiz = quizRef.current;
const currentIndex = currentQuestionIndexRef.current;
@ -469,7 +473,7 @@ export const useGame = () => {
const playerRank = getPlayerRank('host', playersRef.current);
const points = calculatePoints({
const breakdown = calculatePointsWithBreakdown({
isCorrect,
timeLeftMs: timeLeftRef.current,
questionTimeMs: QUESTION_TIME_MS,
@ -479,14 +483,14 @@ export const useGame = () => {
config: gameConfigRef.current,
});
setLastPointsEarned(points);
const newScore = Math.max(0, (hostPlayer?.score || 0) + points);
setLastPointsEarned(breakdown.total);
const newScore = Math.max(0, (hostPlayer?.score || 0) + breakdown.total);
setCurrentPlayerScore(newScore);
setCurrentStreak(newStreak);
setPlayers(prev => prev.map(p => {
if (p.id !== 'host') return p;
return { ...p, score: newScore, streak: newStreak, lastAnswerCorrect: isCorrect };
return { ...p, score: newScore, previousScore: p.score, streak: newStreak, lastAnswerCorrect: isCorrect, pointsBreakdown: breakdown };
}));
} else {
const option = arg as AnswerOption;