Files
bscscore/src/utils/gameUtils.ts
Frank Schwenk e89ae1039d fix: prevent endlos games from ending immediately on first score
- Change endlos raceTo from 0 to Infinity to prevent automatic completion
- Update NewGame component to handle Infinity values properly
- Add Infinity checks in game completion and winner logic
- Fix game progress calculation for endless games

Fixes issue where selecting 'endlos' mode would end the match
immediately when any player scored their first point.
2025-10-28 16:44:57 +01:00

108 lines
3.1 KiB
TypeScript

import type { Game, StandardGame, EndlosGame } from '../types/game';
/**
* Game utility functions for common operations
*/
export function isEndlosGame(game: Game): game is EndlosGame {
return 'players' in game;
}
export function isStandardGame(game: Game): game is StandardGame {
return !('players' in game);
}
export function formatGameTime(dateString: string): string {
const date = new Date(dateString);
const now = new Date();
const diffInHours = (now.getTime() - date.getTime()) / (1000 * 60 * 60);
if (diffInHours < 1) {
return 'vor wenigen Minuten';
} else if (diffInHours < 24) {
return `vor ${Math.floor(diffInHours)} Stunde${Math.floor(diffInHours) !== 1 ? 'n' : ''}`;
} else if (diffInHours < 168) { // 7 days
const days = Math.floor(diffInHours / 24);
return `vor ${days} Tag${days !== 1 ? 'en' : ''}`;
} else {
return date.toLocaleDateString('de-DE');
}
}
export function getGameDuration(game: Game): string {
const start = new Date(game.createdAt);
const end = new Date(game.updatedAt);
const diffInMinutes = (end.getTime() - start.getTime()) / (1000 * 60);
if (diffInMinutes < 60) {
return `${Math.floor(diffInMinutes)} Min`;
} else {
const hours = Math.floor(diffInMinutes / 60);
const minutes = Math.floor(diffInMinutes % 60);
return `${hours}h ${minutes}m`;
}
}
export function calculateGameProgress(game: Game): number {
// If raceTo is Infinity, progress is always 0 (endless game)
if (game.raceTo === Infinity) return 0;
if (isEndlosGame(game)) {
const maxScore = Math.max(...game.players.map(p => p.score));
return Math.min((maxScore / game.raceTo) * 100, 100);
} else {
const scores = [game.score1, game.score2, game.score3 || 0];
const maxScore = Math.max(...scores);
return Math.min((maxScore / game.raceTo) * 100, 100);
}
}
export function getGameWinner(game: Game): string | null {
if (game.status !== 'completed') return null;
if ('winner' in game && game.winner) {
return game.winner;
}
// If raceTo is Infinity, there's no automatic winner
if (game.raceTo === Infinity) return null;
if (isEndlosGame(game)) {
const winner = game.players.find(player => player.score >= game.raceTo);
return winner?.name || null;
} else {
if (game.score1 >= game.raceTo) return game.player1;
if (game.score2 >= game.raceTo) return game.player2;
if (game.player3 && game.score3 && game.score3 >= game.raceTo) return game.player3;
}
return null;
}
export function getGamePlayers(game: Game): Array<{ name: string; score: number }> {
if (isEndlosGame(game)) {
return game.players.map(player => ({
name: player.name,
score: player.score,
}));
} else {
const players = [
{ name: game.player1, score: game.score1 },
{ name: game.player2, score: game.score2 },
];
if (game.player3) {
players.push({ name: game.player3, score: game.score3 || 0 });
}
return players;
}
}
export function validateGameData(data: any): boolean {
return !!(
data.player1?.trim() &&
data.player2?.trim() &&
data.gameType &&
data.raceTo &&
parseInt(data.raceTo) > 0
);
}