const STORAGE_KEY = 'turnierplaner_data';
const ROTATION_STATE_KEY = 'turnierplaner_rotation';
const SCORES_KEY = 'turnierplaner_scores';
let timerInterval = null;
let timerSeconds = 0;
let isRunning = false;
let allTeams = [];
let fieldCount = 0; // Anzahl der physischen Felder (jedes Feld hat 2 Feldhälften)
let rotationState = {};
let matchScores = {}; // { "league:fieldNum": {team1Score, team2Score}, ... }
document.addEventListener('DOMContentLoaded', () => {
loadTournamentData();
setupTimerInput();
loadMatchScores();
});
function loadTournamentData() {
const stored = localStorage.getItem(STORAGE_KEY);
if (!stored) {
console.warn('Keine Turnierdaten gefunden');
return;
}
const data = JSON.parse(stored);
allTeams = data;
fieldCount = parseInt(data.fieldCount) || 0;
// Lade oder initialisiere Rotations-State
loadRotationState(data);
// Populate fields mit aktuellem State
displayCurrentRound();
}
function loadRotationState(data) {
const stored = localStorage.getItem(ROTATION_STATE_KEY);
if (stored) {
rotationState = JSON.parse(stored);
} else {
// Initialisiere mit Startzustand
rotationState = {
bundesliga: {
round: 0,
teamOrder: data.bundesliga.map((t, i) => i)
},
champions: {
round: 0,
teamOrder: data.champions.map((t, i) => i)
}
};
saveRotationState();
}
}
function saveRotationState() {
localStorage.setItem(ROTATION_STATE_KEY, JSON.stringify(rotationState));
}
function displayCurrentRound() {
displayLeagueRound('bundesliga', allTeams.bundesliga);
displayLeagueRound('champions', allTeams.champions);
}
function displayLeagueRound(league, teams) {
// Jedes Feld hat 2 Feldhälften, also maximal fieldCount * 2 Teams können gleichzeitig spielen
const maxPlayingTeams = fieldCount * 2;
const playingTeamsCount = Math.min(teams.length, maxPlayingTeams);
const fieldsPerLeague = Math.ceil(playingTeamsCount / 2); // Anzahl Felder für diese Liga
const state = rotationState[league];
// Bestimme Offset für Feldnummern - Champions League beginnt nach Bundesliga
let fieldNumberOffset = 0;
if (league === 'champions') {
const bundesligaPlayingTeams = Math.min(allTeams.bundesliga.length, fieldCount * 2);
fieldNumberOffset = Math.ceil(bundesligaPlayingTeams / 2);
}
// Aktualisiere Felder basierend auf teamOrder
const container = document.getElementById(`${league}-fields`);
container.innerHTML = '';
for (let i = 0; i < fieldsPerLeague; i++) {
// Info-Box für Feldnummer (nur Label)
const fieldInfoBox = document.createElement('div');
fieldInfoBox.className = 'field-info-box';
const fieldNum = fieldNumberOffset + i + 1;
fieldInfoBox.innerHTML = `
Feld ${fieldNum}:
`;
container.appendChild(fieldInfoBox);
// Team 1 (mittlere Spalte) mit Score-Input
const team1Index = state.teamOrder[i * 2];
const team1 = teams[team1Index] || {};
const fieldCard1 = document.createElement('div');
fieldCard1.className = 'field-card';
const scoreKey = getScoreKey(league, fieldNum);
const existingScore = matchScores[scoreKey] || { team1Score: '', team2Score: '' };
fieldCard1.innerHTML = `
`;
fieldCard1.id = `score-${league}-${fieldNum}-t1-card`;
container.appendChild(fieldCard1);
// Team 2 (rechte Spalte) mit Score-Input
const team2Index = state.teamOrder[i * 2 + 1];
const team2 = teams[team2Index] || {};
const fieldCard2 = document.createElement('div');
fieldCard2.className = 'field-card';
fieldCard2.innerHTML = `
`;
container.appendChild(fieldCard2);
}
// Aktualisiere wartende Teams
updateWaitingTeams(league, teams, fieldsPerLeague, state.teamOrder);
}
function updateWaitingTeams(league, teams, fieldsPerLeague, teamOrder) {
const container = document.getElementById(`${league}-waiting`);
container.innerHTML = '';
// Anzahl der spielenden Teams = fieldsPerLeague * 2 (2 Teams pro Feld)
const playingTeamsCount = fieldsPerLeague * 2;
const waitingIndices = teamOrder.slice(playingTeamsCount);
if (waitingIndices.length === 0) {
container.innerHTML = 'Alle Teams spielen
';
} else {
waitingIndices.forEach(teamIndex => {
const team = teams[teamIndex];
const badge = document.createElement('div');
badge.className = 'waiting-team-badge';
badge.textContent = team.name;
badge.title = `${team.club || ''} - ${team.motto || ''}`;
container.appendChild(badge);
});
}
}
function populateFields(league, teams, fieldCount) {
const container = document.getElementById(`${league}-fields`);
const totalFields = parseInt(fieldCount);
const fieldsPerLeague = Math.ceil(totalFields / 2);
container.innerHTML = '';
for (let i = 1; i <= fieldsPerLeague; i++) {
const fieldCard = document.createElement('div');
fieldCard.className = 'field-card';
// Zuweisung von Teams zu Feldern (Round-Robin)
const teamIndex = (i - 1) % teams.length;
const team = teams[teamIndex] || {};
fieldCard.innerHTML = `
Feld ${i}
${team.name || '-'}
`;
fieldCard.setAttribute('data-field', i);
fieldCard.setAttribute('data-league', league);
fieldCard.setAttribute('data-team', team.name || '');
container.appendChild(fieldCard);
}
}
function populateWaitingTeams(league, teams, fieldCount) {
const container = document.getElementById(`${league}-waiting`);
const totalFields = parseInt(fieldCount);
const fieldsPerLeague = Math.ceil(totalFields / 2);
container.innerHTML = '';
// Teams die auf Feldern spielen
const playingTeamIndices = new Set();
for (let i = 0; i < fieldsPerLeague; i++) {
playingTeamIndices.add(i % teams.length);
}
// Wartende Teams sind alle Teams, die nicht gerade spielen
const waitingTeams = teams.filter((team, index) => !playingTeamIndices.has(index));
if (waitingTeams.length === 0) {
container.innerHTML = 'Alle Teams spielen
';
} else {
waitingTeams.forEach(team => {
const badge = document.createElement('div');
badge.className = 'waiting-team-badge';
badge.textContent = team.name;
badge.title = `${team.club || ''} - ${team.motto || ''}`;
container.appendChild(badge);
});
}
}
// Timer Functions
function setupTimerInput() {
const timerInput = document.getElementById('timerInput');
timerInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
const value = timerInput.value.trim();
if (value) {
parseAndSetTimer(value);
timerInput.value = '';
timerInput.blur(); // Remove focus after input
}
}
});
}
function parseAndSetTimer(timeStr) {
let seconds = 0;
if (timeStr.includes(':')) {
// Parse MM:SS format
const parts = timeStr.split(':');
if (parts.length === 2) {
const minutes = parseInt(parts[0]) || 0;
seconds = parseInt(parts[1]) || 0;
seconds = minutes * 60 + seconds;
}
} else {
// Parse as just seconds
seconds = parseInt(timeStr) || 0;
}
if (seconds > 0) {
// Stop current timer if running
if (isRunning) {
pauseTimer();
}
timerSeconds = seconds;
updateTimerDisplay();
// Start timer automatically
startTimer();
}
}
function toggleTimer() {
if (isRunning) {
pauseTimer();
} else {
startTimer();
}
}
function startTimer() {
if (isRunning) return;
isRunning = true;
const btn = document.getElementById('timerBtn');
btn.textContent = 'Pause';
timerInterval = setInterval(() => {
if (timerSeconds > 0) {
timerSeconds--;
updateTimerDisplay();
} else {
pauseTimer();
}
}, 1000);
}
function pauseTimer() {
if (!isRunning) return;
isRunning = false;
const btn = document.getElementById('timerBtn');
btn.textContent = 'Start';
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
}
function updateTimerDisplay() {
const minutes = Math.floor(timerSeconds / 60);
const seconds = timerSeconds % 60;
const display = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
document.getElementById('timerDisplay').textContent = display;
}
// Modal Functions
function openPointsModal() {
document.getElementById('pointsModal').style.display = 'block';
}
function closePointsModal() {
document.getElementById('pointsModal').style.display = 'none';
}
function openResultsModal() {
document.getElementById('resultsModal').style.display = 'block';
}
function closeResultsModal() {
document.getElementById('resultsModal').style.display = 'none';
}
function savePoints(event) {
event.preventDefault();
const field = document.getElementById('pointsField').value;
const team = document.getElementById('pointsTeam').value;
const points = document.getElementById('pointsValue').value;
if (!field || !points) {
alert('Bitte alle Felder ausfüllen');
return;
}
// TODO: Punkte speichern (z.B. in localStorage oder an Server)
console.log('Punkte gespeichert:', { field, team, points });
alert(`✅ Punkte für ${team} gespeichert!`);
// Reset form
document.getElementById('pointsField').value = '';
document.getElementById('pointsTeam').value = '';
document.getElementById('pointsValue').value = '';
closePointsModal();
}
function saveResults(event) {
event.preventDefault();
const field = document.getElementById('resultsField').value;
const team = document.getElementById('resultsTeam').value;
const sets = document.getElementById('resultsSets').value;
const opponent = document.getElementById('resultsOpponent').value;
if (!field || !sets) {
alert('Bitte alle Pflichtfelder ausfüllen');
return;
}
// TODO: Ergebnisse speichern (z.B. in localStorage oder an Server)
console.log('Ergebnis gespeichert:', { field, team, sets, opponent });
alert(`✅ Ergebnis für ${team} gespeichert!`);
// Reset form
document.getElementById('resultsField').value = '';
document.getElementById('resultsTeam').value = '';
document.getElementById('resultsSets').value = '';
document.getElementById('resultsOpponent').value = '';
closeResultsModal();
}
// Close modal when clicking outside
window.addEventListener('click', (event) => {
const pointsModal = document.getElementById('pointsModal');
const resultsModal = document.getElementById('resultsModal');
if (event.target === pointsModal) {
closePointsModal();
}
if (event.target === resultsModal) {
closeResultsModal();
}
});
function goBack() {
// Stop timer before navigating
if (isRunning) {
pauseTimer();
}
window.location.href = 'index.html';
}
// Rotation Logic
function nextRound() {
// Inkrementiere Runden-Nummer
rotationState.bundesliga.round++;
rotationState.champions.round++;
// Leere die Scores für die neue Runde
matchScores = {};
saveMatchScores();
rotateLeague('bundesliga', allTeams.bundesliga);
rotateLeague('champions', allTeams.champions);
saveRotationState();
displayCurrentRound();
console.log('Nächste Runde!', rotationState);
}
function rotateLeague(league, teams) {
// Jedes Feld hat 2 Feldhälften - maximale spielende Teams = fieldCount * 2
const maxPlayingTeams = fieldCount * 2;
const playingTeamsCount = Math.min(teams.length, maxPlayingTeams);
const state = rotationState[league];
const totalTeams = teams.length;
const waitingCount = totalTeams - playingTeamsCount;
// Fall 1: Keine wartenden Teams (Anzahl Teams = fieldCount * 2)
// Team 1 bleibt stehen, alle anderen rotieren um 1 Position weiter
if (waitingCount === 0) {
// [0, 1, 2, 3, 4, 5] -> [0, 2, 3, 4, 5, 1]
// Team an Index 0 bleibt, Team an Index 1 geht ans Ende, Rest rückt auf
if (state.teamOrder.length > 1) {
const secondTeam = state.teamOrder.splice(1, 1)[0];
state.teamOrder.push(secondTeam);
}
console.log(`${league} Fall 1: Team ${teams[state.teamOrder[0]].name} bleibt stehen, andere rotieren`);
}
// Fall 2: Genau 1 wartendes Team (Anzahl Teams = fieldCount * 2 + 1)
// Alle rotieren um 1 Position, wartendes Team kommt aufs Randfeld
else if (waitingCount === 1) {
// [0, 1, 2, 3, 4, 5, 6(wartend)] -> [1, 2, 3, 4, 5, 6, 0]
// Einfach erstes Team ans Ende verschieben
const first = state.teamOrder.shift();
state.teamOrder.push(first);
console.log(`${league} Fall 2: Team ${teams[first].name} geht warten, Team ${teams[state.teamOrder[playingTeamsCount - 1]].name} kommt ins Spiel`);
}
// Fall 3: Mehrere wartende Teams (Anzahl Teams > fieldCount * 2 + 1)
// Alle wartenden sollen spielen, max 1 Runde Pause
else {
// [0, 1, 2, 3(spielend), 4, 5, 6, 7(wartend)] -> [4, 5, 6, 7(jetzt spielend), 0, 1, 2, 3(jetzt wartend)]
// Wartende Teams kommen nach vorne, spielende Teams gehen warten
const playingTeams = state.teamOrder.slice(0, playingTeamsCount);
const waitingTeams = state.teamOrder.slice(playingTeamsCount);
state.teamOrder = [...waitingTeams, ...playingTeams];
console.log(`${league} Fall 3: Wartende Teams spielen jetzt, spielende Teams warten`);
}
}
// ===== SCORE & PUNKTE-SYSTEM =====
function loadMatchScores() {
const stored = localStorage.getItem(SCORES_KEY);
if (stored) {
matchScores = JSON.parse(stored);
} else {
matchScores = {};
}
}
function saveMatchScores() {
localStorage.setItem(SCORES_KEY, JSON.stringify(matchScores));
}
function getScoreKey(league, fieldNum) {
return `${league}:${fieldNum}`;
}
function updateMatchScore(league, fieldNum, team1Score, team2Score) {
const key = getScoreKey(league, fieldNum);
matchScores[key] = {
round: rotationState[league].round,
team1Score: parseInt(team1Score) || 0,
team2Score: parseInt(team2Score) || 0
};
saveMatchScores();
}
function calculatePoints(team1Score, team2Score) {
// Berechnet Punkte für Team 1 und Team 2 basierend auf Spielstand
const diff = Math.abs(team1Score - team2Score);
if (team1Score > team2Score) {
// Team 1 gewinnt
return {
team1Points: diff + 2,
team2Points: -diff
};
} else if (team2Score > team1Score) {
// Team 2 gewinnt
return {
team1Points: -diff,
team2Points: diff + 2
};
} else {
// Unentschieden
return {
team1Points: 0,
team2Points: 0
};
}
}
function getTeamPointsHistory() {
// Erstellt eine Punkte-Historie für alle Teams in beiden Ligen
const history = {
bundesliga: {},
champions: {}
};
// Initialisiere leere Arrays für jedes Team
allTeams.bundesliga.forEach((team, idx) => {
history.bundesliga[idx] = [];
});
allTeams.champions.forEach((team, idx) => {
history.champions[idx] = [];
});
// Gehe durch alle gespeicherten Scores
Object.keys(matchScores).forEach(key => {
const [league, fieldNum] = key.split(':');
const score = matchScores[key];
const fieldNumInt = parseInt(fieldNum);
const state = rotationState[league];
const teamsInLeague = league === 'bundesliga' ? allTeams.bundesliga : allTeams.champions;
// Berechne fieldsPerLeague basierend auf fieldCount
const maxPlayingTeams = fieldCount * 2;
const playingTeamsCount = Math.min(teamsInLeague.length, maxPlayingTeams);
const fieldsPerLeague = Math.ceil(playingTeamsCount / 2);
// Bestimme Offset für Feldnummern
const bundesligaPlayingTeams = Math.min(allTeams.bundesliga.length, fieldCount * 2);
const bundesligaFields = Math.ceil(bundesligaPlayingTeams / 2);
const fieldOffset = league === 'bundesliga' ? 0 : bundesligaFields;
const i = fieldNumInt - fieldOffset - 1;
if (i >= 0 && i < fieldsPerLeague && state && state.teamOrder) {
const team1Index = state.teamOrder[i * 2];
const team2Index = state.teamOrder[i * 2 + 1];
if (team1Index !== undefined && team2Index !== undefined) {
const points = calculatePoints(score.team1Score, score.team2Score);
if (!history[league][team1Index][score.round]) {
history[league][team1Index][score.round] = 0;
}
if (!history[league][team2Index][score.round]) {
history[league][team2Index][score.round] = 0;
}
history[league][team1Index][score.round] = points.team1Points;
history[league][team2Index][score.round] = points.team2Points;
}
}
});
return history;
}
// ===== MODAL FUNCTIONS =====
function openPointsModal() {
const history = getTeamPointsHistory();
const content = document.getElementById('pointsDisplayContent');
content.innerHTML = '';
// Bundesliga
if (allTeams.bundesliga.length > 0) {
content.appendChild(createLeaguePointsSection('bundesliga', 'Bundesliga', allTeams.bundesliga, history.bundesliga));
}
// Champions League
if (allTeams.champions.length > 0) {
content.appendChild(createLeaguePointsSection('champions', 'Champions League', allTeams.champions, history.champions));
}
document.getElementById('pointsModal').style.display = 'block';
}
function createLeaguePointsSection(leagueId, leagueName, teams, history) {
const section = document.createElement('div');
section.className = 'league-points-section';
// Header
const header = document.createElement('div');
header.className = 'league-points-header';
header.innerHTML = leagueName;
section.appendChild(header);
// Table
const table = document.createElement('table');
table.className = 'points-table';
// Berechne maximale Runde
let maxRound = 0;
Object.keys(history).forEach(teamId => {
if (history[teamId] && history[teamId].length) {
maxRound = Math.max(maxRound, history[teamId].length - 1);
}
});
// Header Row
const headerRow = document.createElement('tr');
headerRow.innerHTML = 'Team | ';
for (let r = 0; r <= maxRound; r++) {
const th = document.createElement('th');
th.innerHTML = `Runde ${r + 1}`;
headerRow.appendChild(th);
}
const totalTh = document.createElement('th');
totalTh.innerHTML = 'Gesamt';
headerRow.appendChild(totalTh);
table.appendChild(headerRow);
// Team Rows
teams.forEach((team, teamIdx) => {
const row = document.createElement('tr');
// Team Name
const nameCell = document.createElement('td');
nameCell.style.textAlign = 'left';
nameCell.style.fontWeight = '500';
nameCell.innerHTML = team.name;
row.appendChild(nameCell);
// Points per round
let totalPoints = 0;
const teamHistory = history[teamIdx] || [];
for (let r = 0; r <= maxRound; r++) {
const cell = document.createElement('td');
const points = teamHistory[r] !== undefined ? teamHistory[r] : '-';
if (points !== '-') {
totalPoints += points;
const pointsDiv = document.createElement('div');
pointsDiv.className = 'points-value';
if (points > 0) {
pointsDiv.classList.add('positive');
pointsDiv.innerHTML = `+${points}`;
} else if (points < 0) {
pointsDiv.classList.add('negative');
pointsDiv.innerHTML = `${points}`;
} else {
pointsDiv.classList.add('neutral');
pointsDiv.innerHTML = '0';
}
cell.appendChild(pointsDiv);
} else {
cell.innerHTML = '-';
}
row.appendChild(cell);
}
// Total Points
const totalCell = document.createElement('td');
const totalDiv = document.createElement('div');
totalDiv.className = 'points-value points-total';
totalDiv.innerHTML = totalPoints > 0 ? `+${totalPoints}` : `${totalPoints}`;
totalCell.appendChild(totalDiv);
row.appendChild(totalCell);
table.appendChild(row);
});
section.appendChild(table);
return section;
}
function closePointsModal() {
document.getElementById('pointsModal').style.display = 'none';
}
function openScoreboard() {
const history = getTeamPointsHistory();
const content = document.getElementById('scoreboardContent');
content.innerHTML = '';
// Erstelle Daten für beide Ligen mit Gesamtpunkten
const leaguesData = [
{ id: 'bundesliga', name: 'Bundesliga', teams: allTeams.bundesliga, history: history.bundesliga },
{ id: 'champions', name: 'Champions League', teams: allTeams.champions, history: history.champions }
];
leaguesData.forEach(league => {
if (league.teams.length > 0) {
// Berechne Gesamtpunkte für jedes Team
const teamScores = league.teams.map((team, idx) => {
const teamHistory = league.history[idx] || [];
const totalPoints = teamHistory.reduce((sum, pts) => sum + (pts || 0), 0);
return { idx, name: team.name, points: totalPoints };
});
// Sortiere absteigend nach Punkten
teamScores.sort((a, b) => b.points - a.points);
// Erstelle die Liga-Section
const section = document.createElement('div');
section.className = 'scoreboard-league';
const header = document.createElement('div');
header.className = 'scoreboard-league-header';
header.innerHTML = league.name;
section.appendChild(header);
const list = document.createElement('ul');
list.className = 'scoreboard-list';
teamScores.forEach((score, rank) => {
const item = document.createElement('li');
item.className = 'scoreboard-item';
const rankDiv = document.createElement('div');
rankDiv.className = 'scoreboard-rank';
rankDiv.innerHTML = `${rank + 1}.`;
item.appendChild(rankDiv);
const nameDiv = document.createElement('div');
nameDiv.className = 'scoreboard-team-name';
nameDiv.innerHTML = score.name;
item.appendChild(nameDiv);
const pointsDiv = document.createElement('div');
pointsDiv.className = 'scoreboard-points';
if (score.points > 0) {
pointsDiv.classList.add('positive');
pointsDiv.innerHTML = `+${score.points}`;
} else if (score.points < 0) {
pointsDiv.classList.add('negative');
pointsDiv.innerHTML = `${score.points}`;
} else {
pointsDiv.innerHTML = '0';
}
item.appendChild(pointsDiv);
list.appendChild(item);
});
section.appendChild(list);
content.appendChild(section);
}
});
document.getElementById('scoreboardModal').style.display = 'block';
}
function closeScoreboard() {
document.getElementById('scoreboardModal').style.display = 'none';
}
function confirmReset() {
document.getElementById('resetConfirmModal').style.display = 'block';
}
function closeResetConfirm() {
document.getElementById('resetConfirmModal').style.display = 'none';
}
function performReset() {
// Lade die Rohdaten (Teams, Feldanzahl)
const stored = localStorage.getItem(STORAGE_KEY);
if (!stored) return;
const data = JSON.parse(stored);
// Setze Rotationsstates zurück auf Anfangszustand
rotationState = {
bundesliga: {
round: 0,
teamOrder: data.bundesliga.map((t, i) => i)
},
champions: {
round: 0,
teamOrder: data.champions.map((t, i) => i)
}
};
// Leere alle Scores
matchScores = {};
// Speichere zurückgesetzte States
saveRotationState();
saveMatchScores();
// Aktualisiere die UI
displayCurrentRound();
// Schließe das Modal
closeResetConfirm();
alert('✅ Turnier wurde zurückgesetzt! Alle Runden und Scores wurden gelöscht.');
}
function openResultsModal() {
document.getElementById('resultsModal').style.display = 'block';
}
function closeResultsModal() {
document.getElementById('resultsModal').style.display = 'none';
}