Maratón de desarrollo: Nacionline 2020

Gran parte de mi tiempo libre de las últimas dos semanas lo he invertido en un proyecto que me ha hecho una ilusión tremenda: La web de resultados del campeonato nacional de speedcubing 2020. En esta publicación explicacaré algunas curiosidades técnicas que han surgido y aprovecharé para escribir un poco acerca de una de mis aficiones.

Speedcubing y la WCA

Para entrar en contexto, ¿qué es el speedcubing? Es un deporte que consiste en resolver el cubo de rubik y otros puzzles s¡m¡lares en la menor cantidad de tiempo. Hay una serie de categorías oficiales en las que puedes participar en campeonatos alrededor de todo el mundo, entre ellas, las de resolver los puzzles más populares; 3x3x3, 4x4x4… pero también las hay especiales, como «a ciegas», «mínimos movimientos» o «una mano».

Todas las competiciones a las que una persona asiste (y todos los tiempos que ha obtenido en las mismas) se guardan en una base de datos global, gestionada por la World Cube Association. Por lo que todos los tiempos oficiales están centralizados en una sola página y puedes ser consciente de tu mejora, tu ránking y los mejores tiempos filtrados nacional, continental y mundialmente. Gracias a esta página puedo ponerle una fecha exacta a la edad con la que comencé esta afición; los 11 años, cuando competí por primera vez. Si os entra curiosidad, mi perfil es este.

El Nacionline 2020

Debido a la situación actual, se han suspendido muchos eventos de speedcubing y, entre ellos, el campeonato nacional. Por lo que la AES ha decidido organizar el torneo de forma no presencial.

El reglamento de la WCA no contempla esta posibilidad, por lo que los tiempos no pueden ser oficiales a nivel mundial, sin embargo a nivel nacional, se consideran campeones de 2020 igualmente a los ganadores.

La comunidad cubera es muy austera y es conocida por ser muy colaborativa, pasional y es capaz de organizar grandes cosas sin un gran presupuesto. En esta ocasión he sentido que podía aportar mi parte a la comunidad y ¿qué sé hacer mejor que automatizar procesos? Hace dos semanas ofrecí a la organización la posibilidad de rehacer la web de resultados (hasta el momento funcionando sorprendentemente bien a base de Google Sheets) y añadirle algunas funcionalidades extra.

Una decisión con una desventaja

El primer desafío al que me he enfrentado es la redundancia en los datos que se me presentaban, por ejemplo:

Para calcular la posición de un participante en la clasificación, «tan solo» necesito conocer la puntuación de todos los competidores y ordenadas. A su vez, estas puntuaciones se calculan en base a sus tiempos de todas las jornadas…

De modo que con «tan solo» los datos de los tiempos, se pueden conocer el resto de datos (medias, puntuaciones, posiciones…).

De modo que al final, con unas pocas columnas, la información realmente está ahí, y el resto de datos pueden calcularse con unos datos primitivos (costosamente, pero se puede) de modo que almacenar el dato sería redundante, y atentaría contra el principio de la normalización en bases de datos y el sentido común a la hora de diseñar un sistema.

Mis tiempos en la categoría 3×3.

El problema:

Calcular todos estos datos cada vez que se leyeran estos datos «primitivos» sería bastante costoso, ¡tan solo imagina lo que se necesita para calcular una posición de las que aparecen en la tabla superior! Necesitas calcular las posiciones de todos los competidores de esa misma categoría en base a otros datos también calculados, ordenarlos, filtrar descalificaciones…

Hacer eso en cada llamada es absurdo, y más si hablamos de mostrarlos en una web a la que van a acceder los usuarios a trompicones. No tiene sentido calcular 50 veces por segundo unos datos que van a variar una vez a la semana. Sin embargo este enfoque nos asegura que la consistencia de la base de datos jamás pueda romperse, de modo que es el buen camino, solo hay que encontrar una forma de calcular estos datos con cabeza…

Una desventaja subsanable

Mi primera idea para evitar cálculos innecesarios fue añadir las columnas en la tabla, pero haciendo que los datos se autocalculasen con un trigger desencadenado por los INSERT o UPDATE que los afectasen directamente. De este modo podría leer las posiciones de los participantes en una categoría directamente de una columna, que solo se recalcularía cada vez que se añadiese un nuevo tiempo a ese ránking. ¿Suena bien, cierto? Sí, es una buena idea, pero no es tan sencilla de implementar en la práctica y menos si generas la base de datos con hibernate y quieres que esa creación dependa exclusivamente de las entidades de JPA.

La solución:

Guardando información ya procesada para reutilizarla

La solución final que adopté no me puede haber dejado más satisfecho, pues con ella, la responsabilidad de la lógica recae exclusivamente en el backend de la aplicación, y la base de datos permanece intacta, generada por las entidades, y sin datos calculables (y por tanto, redundantes). Esta solución es cachear los resultados de los cálculos. Y Spring te lo pone realmente fácil con este tema.

De este modo, tan solo cuando se introduzca un nuevo tiempo en la base de datos, y un competidor adelante a otro. y por ende todos las posiciones en el ránking cambien, tan solo se tiene que limpiar esa caché, y todo se recalcula una sola vez (la siguiente vez que se necesite), para todos los apartados de la web que usen esos datos. Y lo mejor de todo es que al no estar la «posicion» como una columna en la base de datos, la información nunca será inconsistente ni habrá que actualizar el resto de filas al bajar todos un puesto (ya que les han adelantado).

La mejora ha sido significativa: En los participantes con más categorías y competiciones participadas la carga de una página de participante ha bajado de alrededor de 400 ms a tan solo 15 ms. (Excepto el primer acceso desde la limpieza de la caché, por supuesto).

Un buen resultado

A pesar de que mi resultado en el campeonato no ha sido tan bueno como me esperaba, estoy muy orgulloso de esta web y planeo seguir ampliándola (¡la AES ha decidido crear torneos mensuales con esta web!), el proyecto es enorme y hay mil cosas por hacer. Insisto en que echéis un vistazo a sus distintos apartados y naveguéis un poco, y, por supuesto, sed críticos, estoy completamente abierto a feedback. ¡Un saludo y suerte con los tiempos a todos!

Sé el primero en comentar

Deja un comentario

Tu dirección de correo electrónico no será publicada.