buen-sonido / index.html
JairoSC's picture
mejorar pausa posesion, mejorar local visita - Follow Up Deployment
2001ef7 verified
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>App Estad铆sticas F煤tbol</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.history-item:nth-child(even) {
background-color: #f9fafb;
}
.history-item:hover {
background-color: #f3f4f6;
}
</style>
</head>
<body class="bg-gray-50 font-sans">
<div class="container mx-auto p-4 max-w-md">
<h1 class="text-2xl font-bold text-center mb-6 text-gray-800">Estad铆sticas de Partido</h1>
<!-- Selector de equipos -->
<div class="flex justify-between mb-6 bg-white p-4 rounded-lg shadow-sm">
<div class="w-2/5">
<input type="text" id="team-a-name" placeholder="Equipo A" class="w-full p-2 border-b-2 border-blue-500 focus:outline-none text-center font-medium text-blue-600">
</div>
<div class="w-1/5 text-center pt-2 text-gray-500">vs</div>
<div class="w-2/5">
<input type="text" id="team-b-name" placeholder="Equipo B" class="w-full p-2 border-b-2 border-red-500 focus:outline-none text-center font-medium text-red-600">
</div>
</div>
<!-- Temporizador de posesi贸n al estilo UEFA -->
<div class="mb-6 bg-white p-4 rounded-lg shadow-sm">
<h3 class="text-center font-medium text-gray-700 mb-4">Posesi贸n del Bal贸n</h3>
<div class="flex justify-around items-center mb-4">
<div class="text-center">
<div id="team-a-timer" class="text-4xl font-bold mb-2 text-gray-300">00:00</div>
<div class="text-sm font-medium text-blue-600" id="team-a-name-display">LOCAL</div>
</div>
<div class="text-center">
<div class="text-lg font-bold text-gray-500">TOTAL</div>
<div id="total-timer" class="text-2xl font-mono mb-1">00:00</div>
<button onclick="resetTotalTimer()" class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-2 py-1 rounded text-xs">
<i class="fas fa-redo"></i>
</button>
</div>
<div class="text-center">
<div id="team-b-timer" class="text-4xl font-bold mb-2 text-gray-300">00:00</div>
<div class="text-sm font-medium text-red-600" id="team-b-name-display">VISITANTE</div>
</div>
</div>
<div class="flex justify-around">
<button id="team-a-btn" onclick="togglePossession('team-a')" class="bg-blue-500 hover:bg-blue-600 text-white px-6 py-3 rounded-lg text-lg font-bold">
<i class="fas fa-play"></i> LOCAL
</button>
<button id="team-b-btn" onclick="togglePossession('team-b')" class="bg-red-500 hover:bg-red-600 text-white px-6 py-3 rounded-lg text-lg font-bold">
VISITANTE <i class="fas fa-play"></i>
</button>
</div>
<div class="flex justify-center mt-4 gap-4">
<button onclick="resetPossessionTimer()" class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-4 py-2 rounded">
<i class="fas fa-redo"></i> Reiniciar
</button>
<button id="pause-btn" onclick="togglePossessionPause()" class="bg-yellow-500 hover:bg-yellow-600 text-white px-4 py-2 rounded">
<i class="fas fa-pause"></i> Pausar
</button>
</div>
<div class="possession-bar mt-4 relative h-4 w-full bg-gray-200 rounded-full overflow-hidden">
<div id="team-a-possession" class="absolute h-full bg-blue-500 transition-all duration-1000 ease-linear" style="left: 0; width: 50%;"></div>
<div id="team-b-possession" class="absolute h-full bg-red-500 transition-all duration-1000 ease-linear" style="right: 0; width: 50%;"></div>
</div>
<div class="flex justify-between mt-2">
<span id="team-a-possession-percentage" class="font-bold text-blue-600">50%</span>
<span class="text-xs font-medium text-gray-500">POSESI脫N TOTAL</span>
<span id="team-b-possession-percentage" class="font-bold text-red-600">50%</span>
</div>
</div>
<!-- Estad铆sticas -->
<div class="grid grid-cols-2 gap-4 mb-6">
<!-- Tarjetas amarillas -->
<div class="bg-white p-4 rounded-lg shadow-sm">
<h3 class="text-center font-medium text-gray-700 mb-2 flex justify-center items-center">
<i class="fas fa-square text-yellow-400 mr-2"></i> Tarjetas
</h3>
<div class="flex justify-between mb-2">
<span id="team-a-yellow" class="text-2xl font-bold text-blue-600">0</span>
<span id="team-b-yellow" class="text-2xl font-bold text-red-600">0</span>
</div>
<div class="flex justify-between">
<button onclick="changeCard('team-a', 'yellow', 'add')" class="bg-blue-500 hover:bg-blue-600 text-white px-3 py-1 rounded text-sm">
<i class="fas fa-plus"></i>
</button>
<button onclick="changeCard('team-a', 'yellow', 'remove')" class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded text-sm">
<i class="fas fa-minus"></i>
</button>
<button onclick="changeCard('team-b', 'yellow', 'remove')" class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded text-sm">
<i class="fas fa-minus"></i>
</button>
<button onclick="changeCard('team-b', 'yellow', 'add')" class="bg-red-500 hover:bg-red-600 text-white px-3 py-1 rounded text-sm">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
<!-- Corners -->
<div class="bg-white p-4 rounded-lg shadow-sm">
<h3 class="text-center font-medium text-gray-700 mb-2 flex justify-center items-center">
<i class="fas fa-flag mr-2 text-green-500"></i> Corners
</h3>
<div class="flex justify-between mb-2">
<span id="team-a-corners" class="text-2xl font-bold text-blue-600">0</span>
<span id="team-b-corners" class="text-2xl font-bold text-red-600">0</span>
</div>
<div class="flex justify-between">
<button onclick="changeCorner('team-a', 'add')" class="bg-blue-500 hover:bg-blue-600 text-white px-3 py-1 rounded text-sm">
<i class="fas fa-plus"></i>
</button>
<button onclick="changeCorner('team-a', 'remove')" class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded text-sm">
<i class="fas fa-minus"></i>
</button>
<button onclick="changeCorner('team-b', 'remove')" class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-3 py-1 rounded text-sm">
<i class="fas fa-minus"></i>
</button>
<button onclick="changeCorner('team-b', 'add')" class="bg-red-500 hover:bg-red-600 text-white px-3 py-1 rounded text-sm">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
</div>
<!-- Historial -->
<div class="bg-white p-4 rounded-lg shadow-sm mb-4">
<h2 class="text-lg font-semibold text-gray-700 mb-3 flex items-center">
<i class="fas fa-history mr-2 text-gray-500"></i> Historial
</h2>
<div class="max-h-60 overflow-y-auto">
<table class="w-full border-collapse">
<thead class="bg-gray-100">
<tr>
<th class="p-2 text-xs text-left text-gray-600">Minuto</th>
<th class="p-2 text-xs text-left text-gray-600">Evento</th>
<th class="p-2 text-xs text-left text-gray-600">Posesi贸n</th>
</tr>
</thead>
<tbody id="history-list">
<!-- Aqu铆 se agregar谩n los elementos del historial din谩micamente -->
</tbody>
</table>
</div>
</div>
<!-- Bot贸n para a帽adir evento manual -->
<div class="flex justify-between mb-4">
<input type="number" id="minute-input" placeholder="Minuto" class="w-24 p-2 border rounded" min="0">
<select id="event-type" class="p-2 border rounded">
<option value="possession">Cambio posesi贸n</option>
<option value="yellow">Tarjeta amarilla</option>
<option value="corner">Corner</option>
</select>
<select id="event-team" class="p-2 border rounded">
<option value="team-a">Equipo A</option>
<option value="team-b">Equipo B</option>
</select>
<button onclick="addManualEvent()" class="bg-green-500 hover:bg-green-600 text-white px-3 py-1 rounded">
<i class="fas fa-plus"></i>
</button>
</div>
<!-- Reset -->
<button onclick="resetAll()" class="w-full bg-gray-200 hover:bg-gray-300 text-gray-700 py-2 rounded font-medium flex items-center justify-center">
<i class="fas fa-redo mr-2"></i> Reiniciar Todo
</button>
</div>
<script>
// Variables de estado para el temporizador
let isPaused = false;
let possession = {
'team-a': 0,
'team-b': 0
};
let totalTime = 0;
let timerActive = false;
let currentTeam = null;
let startTime = null;
let lastUpdateTime = null;
let possessionIntervalId = null;
let totalIntervalId = null;
let stats = {
'team-a': {
'yellow': 0,
'corners': 0
},
'team-b': {
'yellow': 0,
'corners': 0
}
};
let history = [];
let lastPossessionChange = {
'team-a': 50,
'team-b': 50
};
// Actualizar la UI
function updateUI() {
document.getElementById('team-a-possession-percentage').textContent = `${possession['team-a']}%`;
document.getElementById('team-b-possession-percentage').textContent = `${possession['team-b']}%`;
document.getElementById('team-a-possession').style.width = `${possession['team-a']}%`;
document.getElementById('team-b-possession').style.width = `${possession['team-b']}%`;
document.getElementById('team-a-yellow').textContent = stats['team-a']['yellow'];
document.getElementById('team-b-yellow').textContent = stats['team-b']['yellow'];
document.getElementById('team-a-corners').textContent = stats['team-a']['corners'];
document.getElementById('team-b-corners').textContent = stats['team-b']['corners'];
}
// Cambiar posesi贸n
function changePossession(team, action) {
const step = 5;
let otherTeam = team === 'team-a' ? 'team-b' : 'team-a';
if (action === 'increase' && possession[team] < 100) {
possession[team] += step;
possession[otherTeam] -= step;
} else if (action === 'reduce' && possession[team] > 0) {
possession[team] -= step;
possession[otherTeam] += step;
}
// Guardar el estado antes del cambio para el historial
lastPossessionChange['team-a'] = possession['team-a'];
lastPossessionChange['team-b'] = possession['team-b'];
addHistoryEntry('Posesi贸n cambiada', 'possession');
updateUI();
}
// Reiniciar posesi贸n
function resetPossession() {
possession['team-a'] = 50;
possession['team-b'] = 50;
addHistoryEntry('Posesi贸n reiniciada', 'possession');
updateUI();
}
// Manejar tarjetas amarillas
function changeCard(team, type, action) {
if (action === 'add') {
stats[team][type]++;
} else if (action === 'remove' && stats[team][type] > 0) {
stats[team][type]--;
}
const teamName = document.getElementById(`${team}-name`).value || `Equipo ${team.split('-')[1].toUpperCase()}`;
addHistoryEntry(`Tarjeta amarilla - ${teamName}`, 'yellow');
updateUI();
}
// Manejar corners
function changeCorner(team, action) {
if (action === 'add') {
stats[team]['corners']++;
} else if (action === 'remove' && stats[team]['corners'] > 0) {
stats[team]['corners']--;
}
const teamName = document.getElementById(`${team}-name`).value || `Equipo ${team.split('-')[1].toUpperCase()}`;
addHistoryEntry(`Corner - ${teamName}`, 'corner');
updateUI();
}
// A帽adir entrada al historial
function addHistoryEntry(eventDescription, eventType) {
const now = new Date();
const currentMinute = Math.floor(now.getTime() / 60000) % 90; // Simulando minuto de partido
const entry = {
minute: currentMinute,
description: eventDescription,
type: eventType,
possessionA: possession['team-a'],
possessionB: possession['team-b'],
timestamp: now.toLocaleTimeString()
};
history.unshift(entry); // A帽adir al principio
renderHistory();
// Guardar en localStorage
localStorage.setItem('footballStats', JSON.stringify({
possession,
stats,
history,
teamNames: {
'team-a': document.getElementById('team-a-name').value,
'team-b': document.getElementById('team-b-name').value
}
}));
}
// A帽adir evento manual
function addManualEvent() {
const minute = document.getElementById('minute-input').value || '0';
const eventType = document.getElementById('event-type').value;
const team = document.getElementById('event-team').value;
const teamName = document.getElementById(`${team}-name`).value || `Equipo ${team.split('-')[1].toUpperCase()}`;
let description = '';
switch(eventType) {
case 'possession':
description = `Posesi贸n cambiada manualmente - ${teamName}`;
break;
case 'yellow':
description = `Tarjeta amarilla manual - ${teamName}`;
if (team === 'team-a') stats['team-a']['yellow']++;
else stats['team-b']['yellow']++;
break;
case 'corner':
description = `Corner manual - ${teamName}`;
if (team === 'team-a') stats['team-a']['corners']++;
else stats['team-b']['corners']++;
break;
}
const entry = {
minute: minute,
description: description,
type: eventType,
possessionA: possession['team-a'],
possessionB: possession['team-b'],
timestamp: new Date().toLocaleTimeString()
};
history.unshift(entry);
renderHistory();
updateUI();
// Limpiar inputs
document.getElementById('minute-input').value = '';
}
// Renderizar historial
function renderHistory() {
const historyList = document.getElementById('history-list');
historyList.innerHTML = '';
history.forEach((entry, index) => {
const row = document.createElement('tr');
row.className = `history-item border-t ${index % 2 === 0 ? '' : 'bg-gray-50'}`;
row.innerHTML = `
<td class="p-2 text-sm text-gray-600">${entry.minute}'</td>
<td class="p-2 text-sm ${getEventColor(entry.type)}">${entry.description}</td>
<td class="p-2 text-xs text-gray-500">${entry.possessionA}% - ${entry.possessionB}%</td>
`;
historyList.appendChild(row);
});
}
// Obtener color seg煤n tipo de evento
function getEventColor(type) {
switch(type) {
case 'possession': return 'text-blue-500';
case 'yellow': return 'text-yellow-500';
case 'corner': return 'text-green-500';
case 'pause': return 'text-gray-500';
case 'resume': return 'text-green-500';
default: return 'text-gray-600';
}
}
// Reiniciar todo
function resetAll() {
if (confirm('驴Est谩s seguro de que quieres reiniciar todas las estad铆sticas?')) {
possession = {
'team-a': 50,
'team-b': 50
};
stats = {
'team-a': {
'yellow': 0,
'corners': 0
},
'team-b': {
'yellow': 0,
'corners': 0
}
};
history = [];
document.getElementById('team-a-name').value = '';
document.getElementById('team-b-name').value = '';
updateUI();
renderHistory();
localStorage.removeItem('footballStats');
}
}
// Cargar datos guardados
function loadSavedData() {
const savedData = localStorage.getItem('footballStats');
if (savedData) {
const data = JSON.parse(savedData);
possession = data.possession;
stats = data.stats;
history = data.history || [];
if (data.teamNames) {
document.getElementById('team-a-name').value = data.teamNames['team-a'] || '';
document.getElementById('team-b-name').value = data.teamNames['team-b'] || '';
}
updateUI();
renderHistory();
}
}
// Guardar nombres de equipos al cambiar
document.getElementById('team-a-name').addEventListener('change', saveTeamNames);
document.getElementById('team-b-name').addEventListener('change', saveTeamNames);
function saveTeamNames() {
const savedData = localStorage.getItem('footballStats');
if (savedData) {
const data = JSON.parse(savedData);
data.teamNames = {
'team-a': document.getElementById('team-a-name').value,
'team-b': document.getElementById('team-b-name').value
};
localStorage.setItem('footballStats', JSON.stringify(data));
}
}
// Funciones del temporizador de posesi贸n
function togglePossession(team) {
const now = new Date();
// Si est谩 pausado, no hacer nada
if (isPaused) return;
// Si ya est谩 activo para este equipo, detener
if (timerActive && currentTeam === team) {
stopTimer();
return;
}
// Si hay otro temporizador activo, transferir tiempo
if (timerActive) {
const elapsed = (now - lastUpdateTime) / 1000;
possession[currentTeam] += elapsed;
updateTimers();
}
// Iniciar nuevo temporizador
currentTeam = team;
timerActive = true;
startTime = now;
lastUpdateTime = now;
// Actualizar botones UI
document.getElementById('team-a-btn').disabled = (team === 'team-a');
document.getElementById('team-b-btn').disabled = (team === 'team-b');
// Iniciar intervalos de actualizaci贸n
if (!possessionIntervalId) {
possessionIntervalId = setInterval(updateTimers, 1000);
}
// Iniciar total timer solo si no est谩 corriendo
if (!totalIntervalId) {
totalIntervalId = setInterval(updateTotalTimer, 1000);
totalTime = 0; // Reset total timer when first starting possession
}
addHistoryEntry(`Posesi贸n: ${team === 'team-a' ? 'Local' : 'Visitante'}`, 'possession');
}
// Manejar pausa/reanudaci贸n
function togglePossessionPause() {
const now = new Date();
isPaused = !isPaused;
const pauseBtn = document.getElementById('pause-btn');
if (isPaused) {
if (timerActive) {
// Save elapsed time before pause
const elapsed = (now - lastUpdateTime) / 1000;
possession[currentTeam] += elapsed;
lastUpdateTime = now;
}
pauseBtn.innerHTML = '<i class="fas fa-play"></i> Reanudar';
pauseBtn.classList.remove('bg-yellow-500', 'hover:bg-yellow-600');
pauseBtn.classList.add('bg-green-500', 'hover:bg-green-600');
addHistoryEntry('Posesi贸n pausada (falta)', 'pause');
} else {
if (timerActive) {
// Update lastUpdateTime when resuming to avoid counting paused time
lastUpdateTime = new Date();
}
pauseBtn.innerHTML = '<i class="fas fa-pause"></i> Pausar';
pauseBtn.classList.remove('bg-green-500', 'hover:bg-green-600');
pauseBtn.classList.add('bg-yellow-500', 'hover:bg-yellow-600');
addHistoryEntry('Posesi贸n reanudada', 'resume');
}
}
function stopTimer(stopTotalTimer = false) {
if (!timerActive) return;
clearInterval(possessionIntervalId);
possessionIntervalId = null;
timerActive = false;
// Solo detener el total timer si se especifica
if (stopTotalTimer) {
clearInterval(totalIntervalId);
totalIntervalId = null;
}
const now = new Date();
const elapsed = (now - lastUpdateTime) / 1000;
possession[currentTeam] += elapsed;
// Restablecer botones
document.getElementById('team-a-btn').disabled = false;
document.getElementById('team-b-btn').disabled = false;
updateTimers();
calculatePossessionPercentages();
}
function updateTimers() {
const now = new Date();
if (timerActive && !isPaused) {
const elapsed = (now - lastUpdateTime) / 1000;
possession[currentTeam] += elapsed;
lastUpdateTime = now;
// Actualizar la barra de posesi贸n en tiempo real
calculatePossessionPercentages();
// Agregar entrada al historial cada 30s de posesi贸n
const totalSec = Math.floor(possession[currentTeam]);
if (totalSec % 30 === 0 && totalSec > 0) {
addHistoryEntry(`Posesi贸n continua ${currentTeam === 'team-a' ? 'Local' : 'Visitante'} (${formatTime(totalSec)})`, 'possession');
}
}
// Mostrar todos los tiempos
document.getElementById('team-a-timer').textContent = formatTime(possession['team-a']);
document.getElementById('team-b-timer').textContent = formatTime(possession['team-b']);
function updateTotalTimer() {
totalTime++;
document.getElementById('total-timer').textContent = formatTime(totalTime);
}
// Actualizar porcentajes incluso cuando el temporizador no est谩 activo
if (!timerActive || isPaused) {
calculatePossessionPercentages();
}
}
function resetPossessionTimer() {
stopTimer(true); // Also stop total timer
possession = {
'team-a': 0,
'team-b': 0
};
currentTeam = null;
updateTimers();
calculatePossessionPercentages();
addHistoryEntry('Posesi贸n reiniciada', 'possession');
}
function resetTotalTimer() {
totalTime = 0;
document.getElementById('total-timer').textContent = '00:00';
addHistoryEntry('Temporizador total reiniciado', 'possession');
// Keep timer running if it was running
if (!totalIntervalId && timerActive) {
totalIntervalId = setInterval(updateTotalTimer, 1000);
}
}
function calculatePossessionPercentages() {
const total = possession['team-a'] + possession['team-b'];
// Calcular porcentajes
let teamAPercent, teamBPercent;
if (total === 0) {
teamAPercent = 50;
teamBPercent = 50;
} else {
teamAPercent = Math.max(0, Math.min(100, (possession['team-a'] / total) * 100));
teamBPercent = 100 - teamAPercent;
}
// Actualizar UI con animaci贸n suave
document.getElementById('team-a-possession-percentage').textContent = Math.round(teamAPercent) + '%';
document.getElementById('team-b-possession-percentage').textContent = Math.round(teamBPercent) + '%';
const teamABar = document.getElementById('team-a-possession');
const teamBBar = document.getElementById('team-b-possession');
teamABar.style.width = `${teamAPercent}%`;
teamBBar.style.width = `${teamBPercent}%`;
// Asegurar que las barras no se solapen
if (teamAPercent > 99.5) {
teamABar.style.width = '100%';
teamBBar.style.width = '0%';
} else if (teamBPercent > 99.5) {
teamBBar.style.width = '100%';
teamABar.style.width = '0%';
}
}
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
// Actualizar la UI
function updateUI() {
updateTimers();
calculatePossessionPercentages();
document.getElementById('team-a-yellow').textContent = stats['team-a']['yellow'];
document.getElementById('team-b-yellow').textContent = stats['team-b']['yellow'];
document.getElementById('team-a-corners').textContent = stats['team-a']['corners'];
document.getElementById('team-b-corners').textContent = stats['team-b']['corners'];
// Mostrar nombres de equipos
const teamAName = document.getElementById('team-a-name').value || 'LOCAL';
const teamBName = document.getElementById('team-b-name').value || 'VISITANTE';
document.getElementById('team-a-name-display').textContent = teamAName;
document.getElementById('team-b-name-display').textContent = teamBName;
}
// Inicializar
document.addEventListener('DOMContentLoaded', function() {
loadSavedData();
updateUI();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 馃К <a href="https://enzostvs-deepsite.hf.space?remix=JairoSC/buen-sonido" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>