Skip to content

Instantly share code, notes, and snippets.

@fernandezmm
Created November 12, 2025 02:32
Show Gist options
  • Save fernandezmm/bdece61f5c02d780dd9272e70552107e to your computer and use it in GitHub Desktop.
Save fernandezmm/bdece61f5c02d780dd9272e70552107e to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculadora de Resultados - Grupo A</title>
<style>
/* Reseteo básico y configuración de fuentes */
body, html {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #ffffff;
color: #333;
box-sizing: border-box; /* Asegura que el padding no afecte el ancho */
}
*, *:before, *:after {
box-sizing: inherit;
}
.tabla-container {
width: 100%;
max-width: 800px; /* Ancho máximo para legibilidad */
margin: 1rem auto;
overflow-x: auto; /* Permite scroll horizontal en móviles si la tabla es muy ancha */
border: 1px solid #ddd;
border-radius: 8px;
}
table {
width: 100%;
border-collapse: collapse; /* Bordes limpios */
text-align: left;
}
th, td {
padding: 12px 15px;
border-bottom: 1px solid #ddd;
text-align: center; /* Centrar números */
}
/* Estilo de la cabecera */
thead th {
background-color: #f4f4f4;
color: #555;
font-weight: 600;
letter-spacing: 0.5px;
text-transform: uppercase;
font-size: 12px;
}
/* Estilo de las filas del cuerpo */
tbody tr:nth-child(even) {
background-color: #f9f9f9; /* Rayado tipo cebra */
}
tbody tr:hover {
background-color: #f0f0f0; /* Resaltado al pasar el ratón */
}
/* Alineación de la columna del equipo */
.col-equipo {
text-align: left;
font-weight: 600;
width: 40%; /* Dar más espacio al nombre */
}
.col-equipo.bandera {
margin-right: 10px;
font-size: 1.2rem;
vertical-align: middle;
}
/* Columna de Puntos (Pts) resaltada */
.col-pts {
font-weight: 700;
color: #000;
}
/* Ocultar columnas menos críticas en pantallas pequeñas */
@media (max-width: 600px) {
.col-opcional {
display: none; /* Oculta G, E, P, GF, GC */
}
th, td {
padding: 10px 8px;
font-size: 14px;
}
.col-equipo {
width: 50%; /* Más espacio en móviles */
}
}
</style>
</head>
<body>
<div class="tabla-container">
<table>
<thead>
<tr>
<th class="col-equipo">Equipo</th>
<th>PJ</th>
<th class="col-opcional">G</th>
<th class="col-opcional">E</th>
<th class="col-opcional">P</th>
<th class="col-opcional">GF</th>
<th class="col-opcional">GC</th>
<th>DG</th>
<th class="col-pts">Pts</th>
</tr>
</thead>
<tbody id="tabla-grupo-a-cuerpo">
<tr>
<td colspan="9" style="text-align: center; padding: 20px;">Cargando...</td>
</tr>
</tbody>
</table>
</div>
<script>
// --- 1. ESTRUCTURA DE DATOS (EL MOTOR) ---
// Aquí es donde se actualizan los resultados.
// Solo modifique los números en 'pj', 'g', 'e', 'p', 'gf', 'gc'.
// 'puntos' y 'dg' se calculan automáticamente.
const datosEquipos =;
// ---------------------------------------------
// --- 2. LÓGICA DE CÁLCULO (EL CEREBRO) ---
/**
* Calcula los datos derivados (Puntos y Diferencia de Goles)
* para cada equipo.
*/
function calcularEstadoDerivado(equipos) {
return equipos.map(equipo => {
// Regla de negocio: 3 puntos por victoria, 1 por empate.
const puntos = (equipo.g * 3) + (equipo.e * 1);
// Diferencia de goles
const dg = equipo.gf - equipo.gc;
// Devuelve un *nuevo* objeto con los datos calculados
return {
...equipo, // Copia todas las propiedades originales
puntos: puntos, // Añade la propiedad calculada
dg: dg // Añade la propiedad calculada
};
});
}
/**
* Ordena la lista de equipos según las reglas de desempate.
* 1. Más Puntos
* 2. Mejor Diferencia de Goles (DG)
* 3. Más Goles a Favor (GF)
*/
function ordenarEquipos(equipos) {
// Se usa el método sort() de Array.
// Compara dos equipos ('a' y 'b') a la vez.
return equipos.sort((a, b) => {
// 1. Criterio de Puntos
if (a.puntos!== b.puntos) {
return b.puntos - a.puntos; // Mayor puntuación primero
}
// 2. Criterio de Diferencia de Goles (si los puntos son iguales)
if (a.dg!== b.dg) {
return b.dg - a.dg; // Mayor DG primero
}
// 3. Criterio de Goles a Favor (si los puntos y DG son iguales)
if (a.gf!== b.gf) {
return b.gf - a.gf; // Mayor GF primero
}
// 4. (Opcional) Criterio alfabético si todo es igual
return a.nombre.localeCompare(b.nombre);
});
}
/**
* Renderiza la tabla en el DOM (la inserta en el HTML).
*/
function renderizarTabla(equipos) {
// Encuentra el 'cuerpo' de la tabla en el HTML usando su ID.
// Este ID es el "contrato" entre el HTML y el JavaScript.
const cuerpoTabla = document.getElementById('tabla-grupo-a-cuerpo');
// Limpiar el contenido existente (ej. el mensaje "Cargando...")
cuerpoTabla.innerHTML = '';
// Generar una fila (<tr>) por cada equipo
equipos.forEach(equipo => {
// Usamos "template literals" (comillas invertidas) para construir el HTML
const filaHtml = `
<tr>
<td class="col-equipo">
<span class="bandera">${equipo.bandera}</span>
${equipo.nombre}
</td>
<td>${equipo.pj}</td>
<td class="col-opcional">${equipo.g}</td>
<td class="col-opcional">${equipo.e}</td>
<td class="col-opcional">${equipo.p}</td>
<td class="col-opcional">${equipo.gf}</td>
<td class="col-opcional">${equipo.gc}</td>
<td>${equipo.dg > 0? '+' : ''}${equipo.dg}</td>
<td class="col-pts">${equipo.puntos}</td>
</tr>
`;
// Insertar la fila recién creada al final de la tabla
cuerpoTabla.insertAdjacentHTML('beforeend', filaHtml);
});
}
// --- 3. EJECUCIÓN ---
// Se asegura de que el script se ejecute solo después de que
// todo el HTML se haya cargado.
document.addEventListener('DOMContentLoaded', () => {
const equiposConCalculos = calcularEstadoDerivado(datosEquipos);
const equiposOrdenados = ordenarEquipos(equiposConCalculos);
renderizarTabla(equiposOrdenados);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment