Created
November 12, 2025 02:48
-
-
Save fernandezmm/dfe0e4864b076dbb3cca8bebe3c4fee5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Calculadora Grupo A</title> | |
| <style> | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | |
| margin: 20px; | |
| background-color: #f9f9f9; | |
| color: #333; | |
| } | |
| .container { | |
| display: grid; | |
| grid-template-columns: 1fr 2fr; | |
| gap: 30px; | |
| max-width: 1200px; | |
| margin: auto; | |
| } | |
| @media (max-width: 900px) { | |
| .container { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| h2 { | |
| border-bottom: 2px solid #007bff; | |
| padding-bottom: 5px; | |
| color: #007bff; | |
| } | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| background-color: #fff; | |
| } | |
| th, td { | |
| border: 1px solid #ddd; | |
| padding: 10px; | |
| text-align: left; | |
| } | |
| th { | |
| background-color: #f2f2f2; | |
| font-size: 0.9em; | |
| text-transform: uppercase; | |
| } | |
| td:first-child, th:first-child { | |
| text-align: center; | |
| font-weight: bold; | |
| } | |
| tr:nth-child(even) { | |
| background-color: #f9f9f9; | |
| } | |
| .match { | |
| display: grid; | |
| grid-template-columns: 1fr 50px 20px 50px 1fr; | |
| gap: 5px; | |
| align-items: center; | |
| margin-bottom: 12px; | |
| background-color: #fff; | |
| padding: 10px; | |
| border-radius: 5px; | |
| box-shadow: 0 1px 3px rgba(0,0,0,0.08); | |
| } | |
| .match-label { | |
| font-size: 0.95em; | |
| } | |
| .home-label { text-align: right; } | |
| .away-label { text-align: left; } | |
| .match input { | |
| width: 100%; | |
| height: 30px; | |
| text-align: center; | |
| font-size: 1.1em; | |
| font-weight: bold; | |
| border: 1px solid #ccc; | |
| border-radius: 4px; | |
| box-sizing: border-box; /* Importante para que el padding no afecte el width */ | |
| } | |
| .separator { | |
| text-align: center; | |
| font-weight: bold; | |
| color: #888; | |
| } | |
| #calculateBtn { | |
| width: 100%; | |
| padding: 12px; | |
| font-size: 1.2em; | |
| font-weight: bold; | |
| background-color: #28a745; | |
| color: white; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| margin-top: 10px; | |
| transition: background-color 0.2s; | |
| } | |
| #calculateBtn:hover { | |
| background-color: #218838; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div id="matches-simulator"> | |
| <h2>Simular Resultados</h2> | |
| <p>Ingresa los goles de los partidos relevantes del Grupo A.</p> | |
| <div id="matchesContainer"> | |
| </div> | |
| <button id="calculateBtn">Calcular Tabla</button> | |
| </div> | |
| <div id="standings"> | |
| <h2>Tabla de Posiciones</h2> | |
| <div id="standingsContainer"> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // --- 1. DATOS INICIALES (BASADOS EN TU TABLA) --- | |
| // (Tomamos tu tabla como el punto de partida) | |
| const initialData = [ | |
| { pos: 1, name: "Boca Jrs.", pts: 26, pj: 15, g: 7, e: 5, p: 3, gf: 26, gc: 12, dg: 14 }, | |
| { pos: 2, name: "Unión", pts: 24, pj: 15, g: 6, e: 6, p: 3, gf: 20, gc: 13, dg: 7 }, | |
| { pos: 3, name: "Central Córdoba", pts: 23, pj: 15, g: 5, e: 8, p: 2, gf: 16, gc: 10, dg: 6 }, | |
| { pos: 4, name: "Tigre", pts: 22, pj: 15, g: 5, e: 7, p: 3, gf: 14, gc: 11, dg: 3 }, | |
| { pos: 5, name: "Barracas", pts: 22, pj: 15, g: 5, e: 7, p: 3, gf: 18, gc: 16, dg: 2 }, | |
| { pos: 6, name: "Racing", pts: 22, pj: 15, g: 6, e: 4, p: 5, gf: 15, gc: 13, dg: 2 }, | |
| { pos: 7, name: "Argentinos Jrs.", pts: 21, pj: 15, g: 6, e: 3, p: 6, gf: 16, gc: 12, dg: 4 }, | |
| { pos: 8, name: "Estudiantes", pts: 21, pj: 15, g: 6, e: 3, p: 6, gf: 16, gc: 16, dg: 0 }, | |
| { pos: 9, name: "Banfield", pts: 20, pj: 15, g: 6, e: 2, p: 7, gf: 14, gc: 20, dg: -6 }, | |
| { pos: 10, name: "Belgrano", pts: 19, pj: 15, g: 4, e: 7, p: 4, gf: 13, gc: 11, dg: 2 }, | |
| { pos: 11, name: "Defensa", pts: 19, pj: 15, g: 5, e: 4, p: 6, gf: 14, gc: 17, dg: -3 }, | |
| { pos: 12, name: "Huracán", pts: 19, pj: 15, g: 5, e: 4, p: 6, gf: 9, gc: 14, dg: -5 }, | |
| { pos: 13, name: "Aldosivi", pts: 15, pj: 15, g: 4, e: 3, p: 8, gf: 9, gc: 16, dg: -7 }, | |
| { pos: 14, name: "Newell's", pts: 14, pj: 15, g: 3, e: 5, p: 7, gf: 13, gc: 22, dg: -9 }, | |
| { pos: 15, name: "Ind. Rivadavia Mza", pts: 13, pj: 15, g: 2, e: 7, p: 6, gf: 12, gc: 17, dg: -5 } | |
| ]; | |
| // --- 2. PARTIDOS A SIMULAR (FILTRADOS DE TU LISTA) --- | |
| // (Solo los que involucran a equipos del Grupo A) | |
| const matches = [ | |
| { home: "Boca Jrs.", away: "Tigre" }, | |
| { home: "Central Córdoba", away: "Banfield" }, | |
| { home: "Estudiantes", away: "Argentinos Jrs." }, | |
| { home: "Newell's", away: "Racing" }, | |
| { home: "Barracas", away: "Huracán" }, | |
| { home: "Belgrano", away: "Unión" }, | |
| { home: "Defensa", away: "Ind. Rivadavia Mza" }, | |
| { home: "Aldosivi", away: "San Martín SJ" } // "San Martín SJ" no está en la tabla, solo se actualizará Aldosivi. | |
| ]; | |
| // --- 3. FUNCIONES DE LA CALCULADORA --- | |
| /** | |
| * Renderiza la tabla de posiciones en el HTML | |
| */ | |
| function renderStandings(teamData) { | |
| const container = document.getElementById('standingsContainer'); | |
| let html = '<table>'; | |
| html += '<tr><th>Pos.</th><th>Equipo</th><th>PTS</th><th>PJ</th><th>G</th><th>E</th><th>P</th><th>GF</th><th>GC</th><th>DG</th></tr>'; | |
| teamData.forEach(team => { | |
| html += ` | |
| <tr> | |
| <td>${team.pos}</td> | |
| <td>${team.name}</td> | |
| <td><strong>${team.pts}</strong></td> | |
| <td>${team.pj}</td> | |
| <td>${team.g}</td> | |
| <td>${team.e}</td> | |
| <td>${team.p}</td> | |
| <td>${team.gf}</td> | |
| <td>${team.gc}</td> | |
| <td>${team.dg}</td> | |
| </tr> | |
| `; | |
| }); | |
| html += '</table>'; | |
| container.innerHTML = html; | |
| } | |
| /** | |
| * Renderiza los inputs para los partidos | |
| */ | |
| function renderMatches() { | |
| const container = document.getElementById('matchesContainer'); | |
| let html = ''; | |
| matches.forEach((match, index) => { | |
| html += ` | |
| <div class="match"> | |
| <label class="match-label home-label" for="home_${index}">${match.home}</label> | |
| <input type="number" id="home_${index}" min="0" max="99"> | |
| <span class="separator">-</span> | |
| <input type="number" id="away_${index}" min="0" max="99"> | |
| <label class="match-label away-label" for="away_${index}">${match.away}</label> | |
| </div> | |
| `; | |
| }); | |
| container.innerHTML = html; | |
| } | |
| /** | |
| * Calcula los nuevos stats basado en los inputs | |
| */ | |
| function calculateResults() { | |
| // 1. Crea una copia profunda de los datos iniciales para no modificar el original | |
| let calculatedData = JSON.parse(JSON.stringify(initialData)); | |
| // 2. Itera sobre cada partido | |
| matches.forEach((match, index) => { | |
| const homeScoreEl = document.getElementById(`home_${index}`); | |
| const awayScoreEl = document.getElementById(`away_${index}`); | |
| // Si los inputs están vacíos, los trata como 0 | |
| const homeScore = parseInt(homeScoreEl.value || 0); | |
| const awayScore = parseInt(awayScoreEl.value || 0); | |
| // Solo procesa si se ingresó algún valor (o se cambió) | |
| if (homeScoreEl.value !== "" || awayScoreEl.value !== "") { | |
| // 3. Busca los equipos en nuestros datos | |
| let homeTeam = calculatedData.find(t => t.name === match.home); | |
| let awayTeam = calculatedData.find(t => t.name === match.away); // Puede ser undefined (ej: San Martín SJ) | |
| // 4. Actualiza stats del equipo LOCAL (si existe en la tabla) | |
| if (homeTeam) { | |
| homeTeam.pj++; | |
| homeTeam.gf += homeScore; | |
| homeTeam.gc += awayScore; | |
| if (homeScore > awayScore) { // Gana Local | |
| homeTeam.pts += 3; | |
| homeTeam.g++; | |
| } else if (homeScore === awayScore) { // Empate | |
| homeTeam.pts += 1; | |
| homeTeam.e++; | |
| } else { // Pierde Local | |
| homeTeam.p++; | |
| } | |
| } | |
| // 5. Actualiza stats del equipo VISITANTE (si existe en la tabla) | |
| if (awayTeam) { | |
| awayTeam.pj++; | |
| awayTeam.gf += awayScore; | |
| awayTeam.gc += homeScore; | |
| if (awayScore > homeScore) { // Gana Visitante | |
| awayTeam.pts += 3; | |
| awayTeam.g++; | |
| } else if (homeScore === awayScore) { // Empate | |
| awayTeam.pts += 1; | |
| awayTeam.e++; | |
| } else { // Pierde Visitante | |
| awayTeam.p++; | |
| } | |
| } | |
| } | |
| }); | |
| // 6. Recalcula la Diferencia de Gol (DG) para todos | |
| calculatedData.forEach(team => { | |
| team.dg = team.gf - team.gc; | |
| }); | |
| // 7. Ordena la tabla | |
| calculatedData.sort((a, b) => { | |
| if (b.pts !== a.pts) return b.pts - a.pts; // 1. Por Puntos (desc) | |
| if (b.dg !== a.dg) return b.dg - a.dg; // 2. Por Dif. Gol (desc) | |
| if (b.gf !== a.gf) return b.gf - a.gf; // 3. Por Goles a Favor (desc) | |
| return a.name.localeCompare(b.name); // 4. Alfabético (asc) | |
| }); | |
| // 8. Asigna las nuevas posiciones | |
| calculatedData.forEach((team, index) => { | |
| team.pos = index + 1; | |
| }); | |
| // 9. Renderiza la tabla actualizada | |
| renderStandings(calculatedData); | |
| } | |
| // --- 4. INICIALIZACIÓN --- | |
| // Espera a que el DOM esté cargado | |
| document.addEventListener('DOMContentLoaded', () => { | |
| renderMatches(); | |
| renderStandings(initialData); // Muestra la tabla inicial | |
| // Asigna el evento al botón | |
| document.getElementById('calculateBtn').addEventListener('click', calculateResults); | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment