Por si no recuerdan o no están enterados, estoy armando un proyecto llamado LatamQChallenge donde desarrollo múltiples funcionalidades, puedes ver todo mi progreso el siguiente enlace:
Esta ocasión mostraré el análisis de la funcionalidad de Ranking para que los espectadores puedan saber quién va ganando el evento.
Funcionalidad
La funcionalidad consiste en mostrar una tabla de Ranking ordenado por división y winrate; es decir, que siga el orden que conocen todos los jugadores de LOL:
Cada división tiene 4 niveles y para subir de nivel debes ganar 99 LPS, excepto para las 3 últimas divisiones.
Problema
Ya tengo programada la parte donde consulto las estadísticas y las guardo en la base de datos, bastante sencillo.
El problema surge cuando tenga que desplegar los participantes en la tabla por orden; ya que, no es numérico y por lo tanto no tiene un orden, debo buscar la forma de como ordenarlo.
Solución
Primero me percaté que si juntamos la división y el nivel son contiguos, logrando un orden lógico:
TIER | RANK | value |
---|---|---|
NORANK | 0 | |
IRON | IV | 1 |
IRON | III | 2 |
IRON | II | 3 |
IRON | I | 4 |
BRONZE | IV | 5 |
BRONZE | III | 6 |
BRONZE | II | 7 |
BRONZE | I | 8 |
SILVER | IV | 9 |
... | ... | ... |
¿Notaste algún patrón? ¡Sí lo hay!
Si me fijo solo en el salto entre divisiones (tier), los niveles (rank) siempre son 4, por lo tanto puedo simplificarlo del siguiente modo:
TIER | value |
---|---|
NORANK | 0 |
IRON | 1 |
BRONZE | 5 |
SILVER | 9 |
y si omito NORANK siempre es una diferencia de 4, pero luego explicaré porque no lo simplifiqué hasta ese punto. Este seria el tierOffset.
Si resuelvo el valor de cada rank en este contexto, seria restar el valor de las tablas anteriores.
Por ejemplo, si quiero saber cuanto debe ser rank para encontrar BRONZE II, la ecuación seria:
III = BRONZE III - BRONZE
III = 6 - 5
III = 1
Igual lo podrías ver navegando por la tabla, este sería el rankOffset
Hay un detalle adicional, hay unas 3 divisiones finales que se manejan distinto:
TIER | RANK | value |
---|---|---|
... | ... | ... |
MASTER | I | 25 |
GRANDMASTER | I | 25 |
CHALLENGER | I | 25 |
Realmente el salto entre estas divisiones es por LPS y no se reinicia por lo que toma mayor relevancia; es decir:
DIAMOND I a MASTER I con 0 LPS
MASTER I a GRANDMASTER I con 350 LPS
GRANDMASTER I a CHALLENGER I con 500 LPS
(son ejemplos)
Sin contar que debo buscar la forma de que un DIAMOND II con 97 LPS sea mayor a un DIAMOND II con 46 LPS sin dañar la ecuación previa. Para esto me apoyaré de los decimales.
La ecuación resultante fue esta:
(tierOffset + rankOffset + lps/1000)
Divido entre 1000 para evitar que entre las divisiones comunes, la parte entera sea afectada.
Ya si un CHALLENGER llega a 1000 LPS me da igual que se afecte el entero porque no hay ninguna otra división, además de que seria raro en LAN la verdad.
Pruebas
Realicé pruebas exhaustivas; ya que es muy importate que se el valor se calcule correctamente y parece funcionar todo bien:
Puntos Finales
Cabe destacar que estoy usando una librería que evita el problema del 0.1 + 0.2 != 0.3 para un cálculo preciso en js.
La parte del winrate la utilizaré para decidir en caso de empate, debo especificarlo en las reglas y la ecuación es la de promedio:
wins / (wins + loses)