nvj-turnierplaner2/src/context/TournamentContext.tsx
2026-01-23 11:30:15 +01:00

191 lines
5.0 KiB
TypeScript

import React, { createContext, useContext, useState, ReactNode, useMemo } from 'react';
import { Team, Round, TeamScore, Match, MatchResult } from '@/types/tournament';
import { generateMatches, createNextRoundMatches } from '@/utils/tournamentUtils';
interface TournamentContextType {
teams: Team[];
fieldCount: number;
rounds: Round[];
currentRound: Round | null;
addTeam: (team: Omit<Team, 'id'>) => void;
removeTeam: (id: string) => void;
setFieldCount: (count: number) => void;
resetTournament: () => void;
startNewRound: () => void;
updateMatchResult: (matchId: string, scoreA: number, scoreB: number) => void;
completeCurrentRound: () => void;
getTeamScores: (league: 'bundesliga' | 'champions') => TeamScore[];
}
const TournamentContext = createContext<TournamentContextType | undefined>(undefined);
export const TournamentProvider = ({ children }: { children: ReactNode }) => {
const [teams, setTeams] = useState<Team[]>([]);
const [fieldCount, setFieldCountState] = useState<number>(4);
const [rounds, setRounds] = useState<Round[]>([]);
const currentRound = useMemo(() => {
return rounds.find((r) => !r.completed) || null;
}, [rounds]);
const addTeam = (team: Omit<Team, 'id'>) => {
const newTeam: Team = {
...team,
id: crypto.randomUUID(),
};
setTeams((prev) => [...prev, newTeam]);
};
const removeTeam = (id: string) => {
setTeams((prev) => prev.filter((team) => team.id !== id));
};
const setFieldCount = (count: number) => {
setFieldCountState(Math.max(1, count));
};
const resetTournament = () => {
setTeams([]);
setFieldCountState(4);
setRounds([]);
};
const startNewRound = () => {
if (currentRound && !currentRound.completed) return;
let state;
if (rounds.length === 0) {
// First round: initial random generation
state = generateMatches(teams, fieldCount);
} else {
// Subsequent rounds: rotation system
const lastRound = rounds[rounds.length - 1];
state = createNextRoundMatches(lastRound, fieldCount);
}
const allMatches = [...state.bundesligaMatches, ...state.championsMatches];
const newRound: Round = {
id: crypto.randomUUID(),
roundNumber: rounds.length + 1,
matches: allMatches,
bundesligaWaiting: state.bundesligaWaiting,
championsWaiting: state.championsWaiting,
completed: false,
};
setRounds((prev) => [...prev, newRound]);
};
const updateMatchResult = (matchId: string, scoreA: number, scoreB: number) => {
const diff = Math.abs(scoreB - scoreA);
let pointsA: number;
let pointsB: number;
if (scoreA > scoreB) {
// Team A gewinnt
pointsA = diff + 2;
pointsB = -diff;
} else {
// Team B gewinnt
pointsA = -diff;
pointsB = diff + 2;
}
const result: MatchResult = {
scoreA,
scoreB,
pointsA,
pointsB,
};
setRounds((prev) =>
prev.map((round) => ({
...round,
matches: round.matches.map((match) =>
match.id === matchId ? { ...match, result } : match
),
}))
);
};
const completeCurrentRound = () => {
if (!currentRound) return;
// Check if all matches have results
const allMatchesHaveResults = currentRound.matches.every((m) => m.result);
if (!allMatchesHaveResults) return;
setRounds((prev) =>
prev.map((round) =>
round.id === currentRound.id ? { ...round, completed: true } : round
)
);
};
const getTeamScores = (league: 'bundesliga' | 'champions'): TeamScore[] => {
const leagueTeams = teams.filter((t) => t.league === league);
return leagueTeams.map((team) => {
const pointsHistory: number[] = [];
let totalPoints = 0;
let matchesPlayed = 0;
rounds.forEach((round) => {
let roundPoints = 0;
round.matches.forEach((match) => {
if (match.result) {
if (match.teamA.id === team.id) {
roundPoints += match.result.pointsA;
matchesPlayed++;
} else if (match.teamB.id === team.id) {
roundPoints += match.result.pointsB;
matchesPlayed++;
}
}
});
pointsHistory.push(roundPoints);
totalPoints += roundPoints;
});
return {
team,
totalPoints,
pointsHistory,
matchesPlayed,
};
}).sort((a, b) => b.totalPoints - a.totalPoints);
};
return (
<TournamentContext.Provider
value={{
teams,
fieldCount,
rounds,
currentRound,
addTeam,
removeTeam,
setFieldCount,
resetTournament,
startNewRound,
updateMatchResult,
completeCurrentRound,
getTeamScores,
}}
>
{children}
</TournamentContext.Provider>
);
};
export const useTournament = () => {
const context = useContext(TournamentContext);
if (!context) {
throw new Error('useTournament must be used within a TournamentProvider');
}
return context;
};