Finer granularity points
This commit is contained in:
parent
3a22b42492
commit
a7e37024f5
3 changed files with 16 additions and 17 deletions
|
|
@ -27,9 +27,9 @@ export const GameScreen: React.FC<GameScreenProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const isClient = role === 'CLIENT';
|
const isClient = role === 'CLIENT';
|
||||||
const displayOptions = question?.options || [];
|
const displayOptions = question?.options || [];
|
||||||
|
const timeLeftSeconds = Math.ceil(timeLeft / 1000);
|
||||||
|
|
||||||
// Timer styling logic
|
const isUrgent = timeLeftSeconds <= 5 && timeLeftSeconds > 0;
|
||||||
const isUrgent = timeLeft < 5 && timeLeft > 0;
|
|
||||||
const timerBorderColor = isUrgent ? 'border-red-500' : 'border-white';
|
const timerBorderColor = isUrgent ? 'border-red-500' : 'border-white';
|
||||||
const timerTextColor = isUrgent ? 'text-red-500' : 'text-theme-primary';
|
const timerTextColor = isUrgent ? 'text-red-500' : 'text-theme-primary';
|
||||||
const timerAnimation = isUrgent ? 'animate-ping' : '';
|
const timerAnimation = isUrgent ? 'animate-ping' : '';
|
||||||
|
|
@ -45,9 +45,9 @@ export const GameScreen: React.FC<GameScreenProps> = ({
|
||||||
{/* Whimsical Timer */}
|
{/* Whimsical Timer */}
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="absolute inset-0 bg-white/20 rounded-full blur-xl animate-pulse"></div>
|
<div className="absolute inset-0 bg-white/20 rounded-full blur-xl animate-pulse"></div>
|
||||||
<div className={`bg-white ${timerTextColor} rounded-full w-20 h-20 flex items-center justify-center text-4xl font-black shadow-[0_6px_0_rgba(0,0,0,0.2)] border-4 ${timerBorderColor} ${timerAnimation} relative z-10 transition-colors duration-300`}>
|
<div className={`bg-white ${timerTextColor} rounded-full w-20 h-20 flex items-center justify-center text-4xl font-black shadow-[0_6px_0_rgba(0,0,0,0.2)] border-4 ${timerBorderColor} ${timerAnimation} relative z-10 transition-colors duration-300`}>
|
||||||
{timeLeft}
|
{timeLeftSeconds}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white/20 backdrop-blur-md px-6 py-2 rounded-2xl font-black text-xl shadow-sm border-2 border-white/10">
|
<div className="bg-white/20 backdrop-blur-md px-6 py-2 rounded-2xl font-black text-xl shadow-sm border-2 border-white/10">
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export const BOT_NAMES = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export const QUESTION_TIME = 20; // seconds
|
export const QUESTION_TIME = 20; // seconds
|
||||||
|
export const QUESTION_TIME_MS = 20000; // milliseconds
|
||||||
export const POINTS_PER_QUESTION = 1000;
|
export const POINTS_PER_QUESTION = 1000;
|
||||||
|
|
||||||
export const PLAYER_COLORS = [
|
export const PLAYER_COLORS = [
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useState, useEffect, useRef, useCallback } from 'react';
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
import { Quiz, Player, GameState, GameRole, NetworkMessage, AnswerOption, Question } from '../types';
|
import { Quiz, Player, GameState, GameRole, NetworkMessage, AnswerOption, Question } from '../types';
|
||||||
import { generateQuiz } from '../services/geminiService';
|
import { generateQuiz } from '../services/geminiService';
|
||||||
import { POINTS_PER_QUESTION, QUESTION_TIME, PLAYER_COLORS } from '../constants';
|
import { POINTS_PER_QUESTION, QUESTION_TIME, QUESTION_TIME_MS, PLAYER_COLORS } from '../constants';
|
||||||
import { Peer, DataConnection } from 'peerjs';
|
import { Peer, DataConnection } from 'peerjs';
|
||||||
|
|
||||||
export const useGame = () => {
|
export const useGame = () => {
|
||||||
|
|
@ -147,7 +147,7 @@ export const useGame = () => {
|
||||||
|
|
||||||
if (!currentPlayer || currentPlayer.lastAnswerCorrect !== null) return;
|
if (!currentPlayer || currentPlayer.lastAnswerCorrect !== null) return;
|
||||||
|
|
||||||
const points = isCorrect ? Math.round(POINTS_PER_QUESTION * (timeLeftRef.current / QUESTION_TIME)) : 0;
|
const points = isCorrect ? Math.round(POINTS_PER_QUESTION * (timeLeftRef.current / QUESTION_TIME_MS)) : 0;
|
||||||
const newScore = currentPlayer.score + points;
|
const newScore = currentPlayer.score + points;
|
||||||
|
|
||||||
setPlayers(prev => prev.map(p => {
|
setPlayers(prev => prev.map(p => {
|
||||||
|
|
@ -197,16 +197,14 @@ export const useGame = () => {
|
||||||
setHasAnswered(false);
|
setHasAnswered(false);
|
||||||
setLastPointsEarned(null);
|
setLastPointsEarned(null);
|
||||||
setSelectedOption(null);
|
setSelectedOption(null);
|
||||||
setTimeLeft(QUESTION_TIME);
|
setTimeLeft(QUESTION_TIME_MS);
|
||||||
setPlayers(prev => prev.map(p => ({ ...p, lastAnswerCorrect: null })));
|
setPlayers(prev => prev.map(p => ({ ...p, lastAnswerCorrect: null })));
|
||||||
|
|
||||||
// Use refs to get the latest state inside this async callback
|
|
||||||
const currentQuiz = quizRef.current;
|
const currentQuiz = quizRef.current;
|
||||||
const currentIndex = currentQuestionIndexRef.current;
|
const currentIndex = currentQuestionIndexRef.current;
|
||||||
|
|
||||||
if (currentQuiz) {
|
if (currentQuiz) {
|
||||||
const currentQ = currentQuiz.questions[currentIndex];
|
const currentQ = currentQuiz.questions[currentIndex];
|
||||||
// Ensure options exist
|
|
||||||
const options = currentQ.options || [];
|
const options = currentQ.options || [];
|
||||||
const correctOpt = options.find(o => o.isCorrect);
|
const correctOpt = options.find(o => o.isCorrect);
|
||||||
const correctShape = correctOpt?.shape || 'triangle';
|
const correctShape = correctOpt?.shape || 'triangle';
|
||||||
|
|
@ -214,7 +212,7 @@ export const useGame = () => {
|
||||||
|
|
||||||
const optionsForClient = options.map(o => ({
|
const optionsForClient = options.map(o => ({
|
||||||
...o,
|
...o,
|
||||||
isCorrect: false // Masked
|
isCorrect: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
broadcast({
|
broadcast({
|
||||||
|
|
@ -233,10 +231,10 @@ export const useGame = () => {
|
||||||
if (timerRef.current) clearInterval(timerRef.current);
|
if (timerRef.current) clearInterval(timerRef.current);
|
||||||
timerRef.current = setInterval(() => {
|
timerRef.current = setInterval(() => {
|
||||||
setTimeLeft(prev => {
|
setTimeLeft(prev => {
|
||||||
if (prev <= 1) { endQuestion(); return 0; }
|
if (prev <= 100) { endQuestion(); return 0; }
|
||||||
return prev - 1;
|
return prev - 100;
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
const endQuestion = () => {
|
const endQuestion = () => {
|
||||||
|
|
@ -303,7 +301,7 @@ export const useGame = () => {
|
||||||
setLastPointsEarned(null);
|
setLastPointsEarned(null);
|
||||||
setSelectedOption(null);
|
setSelectedOption(null);
|
||||||
setCurrentQuestionIndex(data.payload.currentQuestionIndex);
|
setCurrentQuestionIndex(data.payload.currentQuestionIndex);
|
||||||
setTimeLeft(data.payload.timeLimit);
|
setTimeLeft(data.payload.timeLimit * 1000);
|
||||||
setCurrentCorrectShape(data.payload.correctShape);
|
setCurrentCorrectShape(data.payload.correctShape);
|
||||||
|
|
||||||
setQuiz(prev => {
|
setQuiz(prev => {
|
||||||
|
|
@ -321,7 +319,7 @@ export const useGame = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (timerRef.current) clearInterval(timerRef.current);
|
if (timerRef.current) clearInterval(timerRef.current);
|
||||||
timerRef.current = setInterval(() => setTimeLeft(prev => Math.max(0, prev - 1)), 1000);
|
timerRef.current = setInterval(() => setTimeLeft(prev => Math.max(0, prev - 100)), 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.type === 'RESULT') {
|
if (data.type === 'RESULT') {
|
||||||
|
|
@ -356,7 +354,7 @@ export const useGame = () => {
|
||||||
const option = arg as AnswerOption;
|
const option = arg as AnswerOption;
|
||||||
const isCorrect = option.isCorrect;
|
const isCorrect = option.isCorrect;
|
||||||
setSelectedOption(option);
|
setSelectedOption(option);
|
||||||
const points = isCorrect ? Math.round(POINTS_PER_QUESTION * (timeLeftRef.current / QUESTION_TIME)) : 0;
|
const points = isCorrect ? Math.round(POINTS_PER_QUESTION * (timeLeftRef.current / QUESTION_TIME_MS)) : 0;
|
||||||
setLastPointsEarned(points);
|
setLastPointsEarned(points);
|
||||||
|
|
||||||
const hostPlayer = playersRef.current.find(p => p.id === 'host');
|
const hostPlayer = playersRef.current.find(p => p.id === 'host');
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue