Diferencia entre revisiones de «Lolstats Documentación Técnica»

De WikiGarcia
Línea 378: Línea 378:
Aunque hay varios formatos en que se puede crear el Data-set, usaremos CSV por su versatilidad.
Aunque hay varios formatos en que se puede crear el Data-set, usaremos CSV por su versatilidad.


Para cada partida, los datos que debemos llenar son:
Para cada partida, los datos que debemos llenar son (Todos los valores son normalizados con base en su máximo):


* Estadísticas del jugador (Para cada jugador):
* Estadísticas del jugador (Para cada jugador):
** '''Level'''
** '''Level''': Máximo permitido 1200.
** '''Rank''': Se omite por el momento ya que no es fácil obtener este dato.
** '''WinRate''': Porcentaje de victoria en esa cola. Últimas 50 partidas.
** '''WinRate''': Porcentaje de victoria en esa cola. Últimas 50 partidas.
** '''WinStreak''': Número de victorias seguidas al momento.
** '''WinStreak''': Número de victorias seguidas al momento. Máximo permitido 50.
** '''MeanKDA''': Promedio de KDA (Asesinatos, Muertes, Asistencias) en las últimas 50 partidas.
** '''MeanKDA''': Promedio de KDA (Asesinatos, Muertes, Asistencias) en las últimas 50 partidas.
** '''ChampionMastery''': Puntos de maestría con el campeón.
** '''ChampionMastery''': Puntos de maestría con el campeón. Máximo permitido 6,000,000.
** '''ChampionWinRate''': Porcentaje de victorias con ese campeón. Solo se buscará en las últimas 50 partidas jugadas.
** '''ChampionWinRate''': Porcentaje de victorias con ese campeón. Solo se buscará en las últimas 50 partidas jugadas.
** '''ChampionMeanKDA''': Promedio de KDA con el campeon.
** '''ChampionMeanKDA''': Promedio de KDA con el campeon.
** '''ChampionGames''': Partidas jugadas con el campeón.
** '''ChampionGames''': Partidas jugadas con el campeón. Máximo permitido 50.


Una vez que se obtienen los datos de cada jugador se tienen que unir en un arreglo que será nuestro vector de entrada, dicho arreglo se conformará de la concatenación de los vectores de cada uno de los 10 jugadores. Es importante destacar que siempre se colocarán primero las estadísticas del equipo 1 y luego los del equipo 2, sin revolver los vectores de los equipos.
Una vez que se obtienen los datos de cada jugador se tienen que unir en un arreglo que será nuestro vector de entrada, dicho arreglo se conformará de la concatenación de los vectores de cada uno de los 10 jugadores. Es importante destacar que siempre se colocarán primero las estadísticas del equipo 1 y luego los del equipo 2, sin revolver los vectores de los equipos.
Línea 403: Línea 402:
* Estadísticas jugador 4 equipo 2
* Estadísticas jugador 4 equipo 2
* Estadísticas jugador 5 equipo 2
* Estadísticas jugador 5 equipo 2
Estos datos se guardarán en un solo archivo csv donde cada renglón será un registro.

Revisión del 03:12 29 jun 2022

En este apartado se detalla el proceso de configuración, planeación y codificación del proyecto Lolstats.

Entorno y Herramientas

Dada su facilidad de uso, configuración y versatilidad para la IA, usaremos Python como lenguaje de programación principal.

La idea final del proyecto es poner el modelo disponible en una página web donde los usuarios puedan consultarlo, es por ello que usaremos Django como framework de desarrollo. También usaremos la facilidad que tiene para crear y administrar una base de datos.

Usaremos además el sistema operativo Linux para hacer todo el proyecto por su facilidad para trabajar en la Web. Las instrucciones siguientes aplican para cualquier distribución basada en Debian.

Configuración del entorno

Necesitaremos dos directorios principales:

  • Directorio de código: Aquí se colocará el proyecto Django y los cripts python necesarios. Ej: ~/lolstats/
  • Directorio de datos: Aquí se colocarán los datos extraídos de la API de Riot y del repositorio de recursos. Ej: ~/datos/

MariaDB (MySQL)

MySQL es un sistema de gestión de bases de datos basado en lenguaje SQL, es gratuito aunque es propiedad de Oracle, por eso mejor usaremos la versión de código libre llamada MariaDB la cuál tiene exactamente las mismas características.

Instalación

sudo apt update
sudo apt install mariadb-server
sudo mysql_secure_installation

A mi me gusta desactivar la validación de password porque es muy restrictiva.

mysql -u root -p
uninstall plugin validate_password;

Creación de Base de datos

mysql -u root -p
CREATE DATABASE lolstats;
CREATE USER 'usuario'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON `lolstats`.* TO 'usuario'@'localhost';

Herramientas extras (Opcinales)

  • Git: Para control de versiones.
  • Tmux: Para navegar entre ventanas de terminal.
  • Vim: Para editar archivos desde consola.

Django

Django es un framework de desarrollo web en Python basado en MVC, proporciona métodos convenientes para crear páginas web, servicios web y administrar bases de datos.

Instalación de Python

Las distribuciones Linux ya traen instalada una versión de Python. Asumiremos que con esa funciona.

Nótese que algunas veces el comando para usar python 3.x es python3 en lugar de python.

TODO: Agregar guía de instalación para la versión de Python usada.

Entorno virtual

Es recomendable trabajar en un entorno virtual para que futuras actualizaciones no afecten nuestro proyecto.

Instalamos el paquete.

pip install venv

Nos movemos al directorio de código y creamos el entorno virtual.

cd ~/lolstats/
python -m venv venv

Activamos el entorno:

source venv/bin/activate

A partir de ahora todo lo que hagamos en Python se hará con el entorno virtual. Recuerda siempre activar el entorno antes de ejecutar Python o pip.

Instalación Django

Para instalar el release oficial:

pip install django

Creación del proyecto

Solo cubriremos lo relacionado con el modelo de aprendizaje y no lo relativo a la página web.

Para crear el proyecto utilizamos el comando:

django-admin startproject lolstats

Para poder empezar a recopilar nuestros datos necesitamos configurar el acceso a base de datos. Me gusta colocar el usuario y contraseña en un archivo separado y usar el mecanismo nativo de MySQL para cargar las credenciales desde ahí.

Editar el archivo ~/lolstats/lolstats/settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'OPTIONS': {
            'read_default_file': '~/lolstats/.my.cnf',
        },
    }
}

Y generar el archivo en la ruta correspondiente ~/lolstats/.my.cnf:

[client]
user=lolstats
password=
database=lolstats

Keras

Keras es la librería de Inteligencia Artificial basada en Tensorflow que usaremos para entrenar los modelos de aprendizaje.

Instalar CUDA

Es una plataforma de desarrollo creada por Nvidia para realizar computo en paralelo, ya sea con CPU o con una GPU.

https://askubuntu.com/a/799185

Instalar CUDNN

Es una librería para crear Deep Neural Networks con la ayuda de GPUs.

https://developer.nvidia.com/cudnn https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html

Instalar Tensorflow

pip install tensorflow-gpu

Instalar Keras

pip install keras

Diseño de almacenamiento de datos

Dada la naturaleza de los datos y las fuentes de donde se obtienen, usaremos dos técnicas distintas para almacenarlos.

  • Base de datos: La idea es almacenar en tablas los datos generales de los jugadores y sus partidas, ej: IDs de jugadores o partidas, niveles, rangos, etc. El objetivo es poder utilizar consultas SQL para filtrar de forma eficiente y correcta los datos generales sin tener que parsear archivos.
  • Archivos JSON: Se usa JSON porque es el formato que usa el repositorio de recursos y la API. Se busca almacenar en texto plano el grueso de la información de los invocadores y las partidas, ya que es mucha información como para organizarla en una Base de datos (e innecesario). La idea es filtrar los datos con SQL y luego acceder a sus detalles buscando el archivo JSON correspondiente.

Diseño de Base de Datos

Las tablas que contendrá la base de datos se muestran en la siguiente figura.

Diagrama de Base de Datos

Estructura de Archivos

Se dividirán los archivos en dos directorios, dependiendo del tipo de archivo que se trate.

Data Dragon

  • Ubicación: /datos/data_dragon

Se trata de los documentos de dicho repositorio. Son documentos que contienen los datos del juego y solo se actualizan cada parche. Aquí se encuentran los catálogos del juego, como son datos de campeones, mapas, objetos, etc.

La estructura interna del directorio se mantiene igual a la original.

/datos/data_dragon
├── css
├── data
├── img
├── js
├── manifest.js
└── manifest.json

Documentos de información

  • Ubicación: /datos/lolstats

Les llamaremos así a los documentos que almacenan las respuestas de las peticiones a la API de Riot. Cuando se realiza una petición a la API (ej: Obtener los datos de una partida) se guarda la respuesta JSON en un archivo para su posterior procesamiento.

Los achivos se dividen por su tipo:

  • games: Información de los juegos.
  • summoners: Información de los invocadores.
  • tiers: Información de las colas clasificatorias.
/datos/lolstats/
├── games
├── summoners
└── tiers


Recopilación de datos

Data Dragon

La documentación completa sobre el repositorio puede encontrarse en la documentación de la API Riot para League of Legends.

El link directo de descarga se forma de la siguiente manera:

https://ddragon.leagueoflegends.com/cdn/dragontail-<version>.tgz

La información adicional que se encuentra disponible es:

Datos dinámicos

Entramos a donde el grueso de la información se concentra. La estrategia consiste en obtener la mayor cantidad de datos posible, empezando por los rangos más altos de clasificatorias.

Experimentalmente todos los datos obtenidos serán de la región de LAN.

Por la naturaleza y funcionamiento de la API de Riot, es necesario realizar una estrategia como la siguiente:

  1. Obtener los nombres e identificadores de los 1,000 primeros invocadores en el ranking (Challenger, Grandmaster, Master, etc.).
  2. Para cada invocador obtener su historial de las últimas 100 partidas clasificatorias. Esto para tener la referencia de otros invocadores en los mismos rangos.
  3. Para cada partida obtener los datos de los 9 invocadores restantes.
  4. Para cada uno de los invocadores restantes obtener los datos de las últimas 50 partidas clasificatorias (ir más allá traería datos irrelevantes).

Obtención top 1000 invocadores

Como trabajaremos con una API de pruebas con limitantes de cantidades de peticiones por minuto y por segundo, primero generaremos un algoritmo para delimitar cada petición.

global maxPerSecond = 20;
global maxPer2Minutes = 100;
global countPerSecond = 0;
global countPer2Minutes = 0;
global lastSecond = 0;
global lastMinute = 0;
function sendRequest:
    while true:
        if currentSecond = lastSecond:
            if countPerSecond < maxPerSecond:
                MaqueRequest()
                break;
            else:
                sleep 1
        else if abs(currentMinute - lastMinute) <= 2:
            if countPer2Minutes < maxPerMinute:
                MakeRequest()
                break;
            else:
                sleep 1
        else:
            MaqueRequest()
            break;

function MakeRequest():
    countPer2Minutes++;
    countPerSecond++;
    Send();
    if currentSecond != lastSecond:
        countPerSecond = 1;
        lastSecond = currentSecond;
        if not abs(currentMinute - lastMinute) <= 2:
            countPer2Minutes = 1;
            lastMinute = currentMinute;

A continuación podemos comenzar a hacer la recopilación de los datos. El proceso para obtener la lista de 1000 invocadores con sus partidas se describe en el código mostrado a continuación, donde se consultan los siguientes métodos de la API:

  • League-exp-v4 (getSummonersFromAPI): Devuelve la lista de los invocadores en una cola clasificatoria. La cola en la que se busca es RANKED_SOLO_5x5 en la división CHALLENGER I, GRANDMASTER I, MATER I y así sucesivamente hasta completar los 1,000.

https://la1.api.riotgames.com/lol/league-exp/v4/entries/RANKED_SOLO_5x5/CHALLENGER/I?page=1

  • Summoner-v4 (getSummonerById): Devuelve la información del invocador identificado con el ID de Invocador encriptado. Este dato es el que se obtiene de League-exp-v4.

https://la1.api.riotgames.com/lol/summoner/v4/summoners/{encryptedSummonerId}


  • Match-v5 (getSummonerGames): Devuelve el historial de partidas de un invocador identificado con su PUUID. Este dato se obtiene de Summoner-v4. Solo obtenemos las partidas de la cola clasificatoria.

https://la1.api.riotgames.com/lol/match/v5/matches/by-puuid/{puuid}/ids?queue=420&start=0&count=100

  • Match-v5 (getGameData): De este método también se consultan los detalles de cada partida identificada con su ID de partida.

https://la1.api.riotgames.com/lol/match/v5/matches/{matchid}

def getSummoners():
    summoners = getSummonersFromAPI();
    for sid in summoners:
        if not summonerInDB():
            summoner = getSummonerById();
            summoner.save();
        games = getSummonerGames(100)
        for game in games:
            if not gameInDB():
                game_data = getGameData(game)
                game_data.save()

Los tres elementos principales que se almacenan son:

  • Datos del invocador: Se almacena en base de datos los datos generales, mientras que se guarda un archivo json (identificado con el ID del registro) en /datos/lolstats/summoners con los detalles.
  • Datos generales de la partida: Se almacena en base de datos el identificador de Riot de la partida. Y se guarda un archivo json (identificado con el ID del registro) en /datos/lolstats/games con los detalles de la partida.
  • Relación de Invocador/Partida: En una tabla de base de datos se almacena la relación de cuáles jugadores participaron en las partidas y a qué equipo pertenecieron.

Las matemáticas indicarían que al finalizar el proceso tendríamos 100,000 partidas guardadas, sin embargo, muchas partidas se repiten ya que más de uno de los jugadores del top 100 participan en ellas.

Obtención de los invocadores restantes

A continuación se deben buscar los datos de los invocadores restantes, así que para cada partida guardada buscamos si ya se encuentra el invocador o si no lo buscamos.

Se consultan los siguientes métodos de la API:

  • Summoner-v4 (getSummoner): Devuelve la información del invocador identificado con el PUUID. Este dato es el que se obtiene del JSON de la partida.

https://la1.api.riotgames.com/lol/summoner/v4/summoners/by-puuid/{encryptedPUUID}

function fillSummonerss():
    matches = getSavedMatches()
    for match in matches:
        participants = match.getParticipants()
        for participant in participants:
            if not participantInDB():
                summoner = getSummoner()
                summoner.save()

Obtención de las partidas restantes

El último paso consiste en que para cada invocador se obtienen sus últimas 50 partidas.

  • Match-v5 (getSummonerGames): Devuelve el historial de partidas de un invocador identificado con su PUUID. Solo obtenemos las partidas de la cola clasificatoria.

https://la1.api.riotgames.com/lol/match/v5/matches/by-puuid/{puuid}/ids?queue=420&start=0&count=100

  • Match-v5 (getGameData): De este método también se consultan los detalles de cada partida identificada con su ID de partida.

https://la1.api.riotgames.com/lol/match/v5/matches/{matchid}

function fillMatches():
    summoners = getSavedSummoners()
    for summoner in summoners:
        matches = getSummonerGames(50)
        for game in games:
            if not gameInDB():
                game_data = getGameData(game)
                game_data.save()

Creación de Data Set

Una vez se tienen los datos crudos, es necesario crear el set de entrenamiento y pruebas. Este set solo debe contener los datos necesarios para el modelo.

Aunque hay varios formatos en que se puede crear el Data-set, usaremos CSV por su versatilidad.

Para cada partida, los datos que debemos llenar son (Todos los valores son normalizados con base en su máximo):

  • Estadísticas del jugador (Para cada jugador):
    • Level: Máximo permitido 1200.
    • WinRate: Porcentaje de victoria en esa cola. Últimas 50 partidas.
    • WinStreak: Número de victorias seguidas al momento. Máximo permitido 50.
    • MeanKDA: Promedio de KDA (Asesinatos, Muertes, Asistencias) en las últimas 50 partidas.
    • ChampionMastery: Puntos de maestría con el campeón. Máximo permitido 6,000,000.
    • ChampionWinRate: Porcentaje de victorias con ese campeón. Solo se buscará en las últimas 50 partidas jugadas.
    • ChampionMeanKDA: Promedio de KDA con el campeon.
    • ChampionGames: Partidas jugadas con el campeón. Máximo permitido 50.

Una vez que se obtienen los datos de cada jugador se tienen que unir en un arreglo que será nuestro vector de entrada, dicho arreglo se conformará de la concatenación de los vectores de cada uno de los 10 jugadores. Es importante destacar que siempre se colocarán primero las estadísticas del equipo 1 y luego los del equipo 2, sin revolver los vectores de los equipos.

  • Estadísticas jugador 1 equipo 1
  • Estadísticas jugador 2 equipo 1
  • Estadísticas jugador 3 equipo 1
  • Estadísticas jugador 4 equipo 1
  • Estadísticas jugador 5 equipo 1
  • Estadísticas jugador 1 equipo 2
  • Estadísticas jugador 2 equipo 2
  • Estadísticas jugador 3 equipo 2
  • Estadísticas jugador 4 equipo 2
  • Estadísticas jugador 5 equipo 2