OpenAthlete
AGPLv3 기반 지구력 훈련 플랫폼—EU 호스팅, 투명한 로직, 자체 호스팅·전체 내보내기 지원
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Minutos jugados y posibles bajas de la Liga Universitaria de Deportes (Uruguay), sacados de las
planillas oficiales. Sigue Mayores (A a G), Sub 20 (A a C), Reserva (A a D), Pre Senior (A a E),
Más 40 (A a C), Sub 18 y Sub 16, con todas sus etapas: primera rueda, título y ascenso, permanencia o
copas. Sub 18 y Sub 16 no tienen divisionales (series, segunda rueda y copas): se analizan como un solo
bloque, así cada equipo conserva su historia de las series, y la web muestra una divisional por copa (Oro,
Plata, Bronce, Competencia, Confraternidad, Amistad) con sus equipos y todos sus partidos de la temporada
(VISTAS en categorias.mjs, partirEnCopas() en analizar.mjs).
Página: https://planilla-lud.github.io/
Tema "pizarra", el mismo de la página de presentación: vestuario de noche, pizarra táctica y tiza.
Fondo verde pizarra (siempre oscuro), texto color tiza y un solo acento amarillo marcador, usado poco
(botón principal, sección activa, Mi equipo). Los estados van en tiza de color (rojo = nivel alto,
naranja = medio) y las barras de minutos son trazos de tiza. Tipografía Big Shoulders Display (títulos y
cifras, en mayúscula), Instrument Sans (texto) e IBM Plex Mono (etiquetas chicas, como una planilla).
La portada tiene una cancha de tiza de fondo y toda la página una capa fija de grano. Aparición suave al
hacer scroll (se apaga si el teléfono pide reducir movimiento).
Todos los colores, radios, sombras y espacios son variables al principio del <style> de index.html.
En el celular hay barra de navegación abajo (Inicio, Bajas, Partidos, Tabla y Más) y la divisional se
elige desde el botón del encabezado. En la compu las secciones van en una fila arriba. og.png es la
imagen que aparece al compartir el link por WhatsApp.
supabase/contador.sql y
la web usa la clave pública, que solo puede llamar a esas funciones. Solo cuenta en la página publicada;
?nocontar en la dirección hace que ese navegador no cuente más (para no inflar con tus propias visitas).En Bajas, cada partido tiene un botón para compartir las bajas por WhatsApp (o con el menú de compartir del celular), y otro para mandar toda la fecha.
Son pistas sacadas de las planillas, no partes médicos: un titular que no juega puede estar lesionado, de viaje o de exámenes. Las suspensiones se confirman en Fallos y Penas de la Liga (se publican los jueves a las 21 h).
La página se instala como app ("Agregar a pantalla de inicio" en el iPhone desde Safari, o "Instalar app"
en Chrome de Android): manifest.webmanifest y los íconos y pantallas de arranque de app/. Los genera
herramientas/portada.py con el mismo diseño de la página.
Anda sin señal (en la cancha): sw.js guarda la página y lo último que se vio de cada divisional. Con
señal va primero a buscar lo nuevo; si en 4 segundos no llegó, muestra lo guardado. Sin conexión, un aviso
arriba dice de cuándo son esos datos. No toca Supabase ni el servidor en vivo, que van directo.
scripts/detalle.mjs baja la planilla de cada partido jugado a planillas/<categoria>/<ID>.json
desde la API de la Liga (resultados/api.php?action=...&id=<ID>) y el fixture de los próximos
partidos. Solo baja lo que falta; un partido se vuelve a bajar durante 4 días por si la Liga
corrige la planilla. Con REBAJAR=1 baja todo de nuevo.scripts/sanciones.mjs baja las sanciones de la temporada del buscador de Fallos y Penas
(ligauniversitaria.org.uy/fallosypenas/api.php) a planillas/_sanciones/<categoria>.json.
Cada sanción trae carné, serie y número de partido, así que se cruza con las planillas.scripts/analizar.mjs revisa cada planilla, calcula minutos (con reingresos) y alertas, y escribe
data/<categoria>.json, que es lo que lee index.html. Al final llama a scripts/picantes.mjs, que arma
data/posiciones.json (la tabla completa de cada grupo que muestra la sección Tabla, sacada de la tabla oficial de la Liga:
posiciones/api.php?action=cargarPosiciones) y data/picantes.json (los partidos más picantes de todas
las divisionales, para la portada). Se puede correr solo con node scripts/picantes.mjs.
La tabla oficial importa: incluye los partidos que da el Tribunal, los W.O. y los formatos especiales
(copa de plata, Reserva D). Si la Liga no responde, se calcula como el reglamento (art. 3): en la segunda
etapa cada equipo conserva lo de la primera rueda (puntos, goles y partidos jugados).scripts/categorias.mjs define qué categorías y divisionales se siguen y qué series tiene cada una
(códigos de ligauniversitaria.org.uy/config/config.json y de las páginas de estadísticas de la Liga).
Para sumar una divisional alcanza con agregar una línea ahí: la web la muestra sola.
scripts/comun.mjs tiene la temporada y los nombres cortos.clubDe() en analizar.mjs los junta, con una lista de alias para los casos raros.data/mayores-a.json, data/reserva-d.json, ...) y
data/indice.json lista las disponibles. data/clubes.json tiene el resumen por club para "Mi equipo".SOLO=mayores-b,reserva-a (solo esas divisionales),
REBAJAR=1 (bajar todo de nuevo), MAX_MIN=60 (cortar la bajada a los 60 minutos y seguir en la próxima)..github/workflows/actualizar.yml) corre todo solo el domingo a las 18:35, de lunes
a jueves a las 20:35 y el jueves a las 22:35, después de que salen los fallos (hora de Montevideo). Además,
sábados y domingos se fija cada una hora, de 14:05 a 03:05, si hay partidos jugados sin cargar
(): si hay, baja solo esos; si no, termina enseguida. De lunes a viernes hace lo mismo
cada 2 horas, de 8:05 a 0:05, porque la Liga sube las planillas del finde a cualquier hora de la semana. Así lo del sábado (Reserva,
Sub 20...) entra el mismo sábado de noche, apenas la Liga lo publica. También se puede correr a mano:
Actions > "Actualizar planillas y bajas" > Run workflow.medirAciertos() en analizar.mjs rearma cada partido de la temporada (desde el 4.º de cada equipo) con lo
que se sabía antes: las planillas anteriores y las sanciones publicadas hasta ese día, con las fechas que
llevaba cumplidas. Calcula el once probable y las alertas, y los compara con la planilla real. Escribe
data/aciertos.json: titulares acertados por partido (total, por categoría, divisional y equipo), arquero,
y para cada tipo de alerta cuántos marcados no fueron titulares o no jugaron, contra la referencia de los
titulares sin alerta. La referencia del once es repetir el del partido anterior.
Con esa medición se ajustaron los pesos del once ([1, .5, .3, .2, .1] para los últimos 5 partidos; antes
[1, .8, .65, .5, .4] empataba con repetir el once anterior) y se vio que una suspensión de otra categoría
que no dice "todas las categorías" la cumple 3 de cada 4 veces: es duda, no baja segura. Para probar otros
pesos sin tocar el código: AJUSTE='{"W":[1,.6,.4,.3,.2]}' node scripts/analizar.mjs.
Los arqueros fallan más de lo que parece (alrededor de 3 de cada 4): casi siempre porque el equipo rota arqueros, no porque se identifique mal.
La planilla no trae posiciones. El arquero se deduce (arqueros() en analizar.mjs): arranca con la 1 o
la 12 en al menos 6 de cada 10 partidos que es titular (y 2 como mínimo), casi nunca sale reemplazado antes
del 80' y no hace goles. Se identifica en unos 190 de los 230 equipos; en el resto nadie usa la 1 o la 12
de forma fija y la web lo aclara. El once probable lleva siempre un solo arquero (el más reciente).
EnContra no indica gol en contra. Un gol en contra viene con el carné de un jugador rival.La Liga publica cuántas fechas le dieron a cada uno (F:2 = 2 fechas). Las cumplidas se cuentan con los
partidos que jugó su equipo, en la divisional de la expulsión, después de ese partido. Es aproximado: si
la Liga cuenta partidos de otra categoría, puede variar.
Dos reglas para no dejar suspensiones colgadas:
Cambiar TEMPORADA e INICIO_TEMPORADA en scripts/comun.mjs (y los códigos de serie en categorias.mjs si cambian).
Un chat con IA gratis para preguntar por cualquier equipo o jugador. scripts/chat.mjs arma data/chat.json
(resumen de cada equipo e índice de jugadores) después de cada análisis. worker/ es el servidor en Cloudflare:
busca en ese resumen lo que menciona la pregunta (worker/src/buscar.js) y se lo pasa a la IA, que solo contesta
con eso. Usa Workers AI (cuota diaria gratis de Cloudflare) y, si se acaba, Gemini o Groq cuando hay claves.
.github/workflows/chat.yml lo publica con los secretos CLOUDFLARE_API_TOKEN y CLOUDFLARE_ACCOUNT_ID y
escribe su dirección en chat-config.json; la página muestra el botón solo si ese archivo existe.
scripts/faltan.mjs