Universidad Politécnica de

Escuela Técnica Superior de Ingenieros Informáticos

Grado en Ingeniería Informática

Trabajo Fin de Grado

Modelización y Análisis del Ecosistema en España desde la Perspectiva de los Equipos

Autor: Samuel José de Morais Trajtengertz Tutor(a): Francisco Javier Segovia Pérez Co-Tutor(a): Alberto Tejero López

Madrid, Junio - 2020 Este Trabajo Fin de Grado se ha depositado en la ETSI Informáticos de la Universidad Politécnica de Madrid para su defensa.

Trabajo Fin de Grado Grado en Ingeniería Informática Título: Modelización y Análisis del Ecosistema Esports en España desde la Pers- pectiva de los Equipos Junio - 2020

Autor: Samuel José de Morais Trajtengertz Tutor: Francisco Javier Segovia Pérez Lenguajes y Sistemas Informáticos e Ingeniería de Software Co-Tutor: Alberto Tejero López Ingeniería de Organización y Administración de Empresas y Estadística ETSI Informáticos Universidad Politécnica de Madrid Resumen

La industria de los esports crece a pasos agigantados, en cambio no se puede con- siderar este ecosistema como un ecosistema maduro. Cada vez son más los actores existentes dentro de la escena esports, y son muchos más los interesados en formar parte de ella. Esto crea una necesidad de disponer de herramientas que permitan crear valor añadido durante la toma de decisiones de los distintos actores. Este trabajo nace con la idea de indagar en esa necesidad. Se busca crear una serie de herramientas que puedan ayudar a los actores que participan en el ecosistema. Uno de los recursos utilizados en donde se asientan estas herramientas son los grafos de conocimiento. Los grafos de conocimiento son una representación gráfica de una cierta información de la que se pretende realizar una interpretación. En España no se tiene conocimiento de otro intento de modelar y construir un grafo que represente el ecosistema esports. Para ello en este trabajo se va a buscar dar los pasos necesarios para obtener ese grafo. Se analizará el ecosistema, buscando cuales son los principales actores participantes en él. También se buscará la forma en que estos actores se relacionan entre sí. A continuación se realizará la búsqueda e investigación de las posibles fuentes de información que sean relevantes para este caso. Estas fuentes tienen que contener los datos necesarios para la creación del grafo. Pero la disponibilidad de esos datos no es lo único importante, también necesitaremos que la fuente disponga de herramientas con las que extraer esos datos y poder hacer uso de ellos. También se dará respuesta a la estructura necesaria para almacenar los datos obte- nidos de las fuentes de información. Y también el modo necesario para poder explo- tarlos. Se buscará una herramienta con la que se consiga visualizar el modelo creado y también poder realizar los análisis pertinentes. Mediante estas herramientas se realizará un análisis del ecosistema que permita obtener información sobre él mismo y los actores dentro de él. Se presentarán las conclusiones obtenidas de este análisis y se presentará una serie de líneas futuras sobre las que poder continuar el trabajo realizado.

i

Abstract

Esports industry grows at a very high pace, but it cannot be considered to be a mature industry yet. The number of actors within the ecosystem grows each day and much more are interested in being part of it. All of this creates the need to provide some tools that allows to create added value during the decision making from the different actores involve. This project begin with the idea of diving in this need. We search the creation of tools that could help the actors within the ecosystem. One of the resource which is going to be the foundation for those tools are knowledge graphs. The knowledge graphs are graphic representation of a certain information from which we pretend to provide an interpretation. In Spain there is no knowledge of an attempt on trying to model and construct a graph that represents the esports ecosystem. On this project we are going to aim to take the steps needed to obtain said graph. An analysis on the ecosystem is going to be made, searching for the main actors on it. Also the relationships between those actors has to be researched. Next we are going to look for and investigate the different sources of information that could fit this case. Those sources need to provide access to the information required to create the graph. But the data being available is not the only important task, also the availability of the proper tools to extract the data and make use of it needs to be in place. An answer to the proper infrastructure needed to store all the data extracted is going to be provided. Also the path taken to being able to exploit the data. A visualization tool is going to be search, giving us the power to see the model created and preform the analysis needed. With all this tools an analysis from the ecosystem is going to be made which will provide information on itself and the actors involve in it. All the conclusions extracted will be presented from this analysis and some future lines of action are gone be presented.

iii

Tabla de contenidos

1. Introducción 1 1.1. Contexto ...... 1 1.2. Objetivos ...... 2

2. Desarrollo 3 2.1. Identificación de actores del ecosistema esports ...... 3 2.1.1. Publishers ...... 3 2.1.2. Organizadores ...... 4 2.1.3. Patrocinadores ...... 4 2.1.4. Equipos ...... 5 2.1.5. Jugadores ...... 5 2.1.6. Creadores de contenido ...... 5 2.1.7. Relaciones ...... 6 2.2. Objetivo específico de estudio: Equipos ...... 8 2.3. Fuentes de información específica: Twitter ...... 9 2.3.1. Acceso a la API de Twitter ...... 9 2.4. Modelización del ecosistema ...... 10 2.4.1. Infraestructura y almacenamiento ...... 10 2.4.2. Versión 1 ...... 10 2.4.2.1. Modelo de Grakn ...... 10 2.4.2.2. Extracción de datos de Twitter ...... 12 2.4.2.3. Migración de datos a Grakn ...... 15 2.4.2.4. Visualización del modelo ...... 16 2.4.3. Versión 2 ...... 18 2.4.3.1. Modelo de Grakn ...... 19 2.4.3.2. Extracción de datos de Twitter ...... 20 2.4.3.2.1. Extracción de los datos de equipos ...... 21 2.4.3.2.2. Extracción de los datos de jugadores ...... 23 2.4.3.2.3. Extracción de los datos de creadores de contenido 25 2.4.3.3. Migración de datos a Grakn ...... 25 2.4.3.4. Visualización del modelo ...... 27

3. Análisis del ecosistema 31 3.1. ¿Cuántos jugadores existen en el ecosistema? ...... 31 3.2. ¿Cuántos equipos existen en el ecosistema? ...... 31 3.3. ¿Cuántos jugadores tiene cada equipo? ...... 32 3.4. ¿Cuántos creadores de contenido existen en el ecosistema? ...... 34 3.5. ¿Cuántos creadores tiene cada equipo? ...... 34

v TABLA DE CONTENIDOS

4. Conclusiones y líneas futuras 37 4.1. Conclusiones generales ...... 37 4.2. Conclusiones personales ...... 37 4.3. Líneas futuras ...... 38

Bibliografía 40

Anexo 41 .1. search_twitter.py ...... 41 .2. get_players.py ...... 42 .3. get_streamers.py ...... 43 .4. migrate.py ...... 43

vi Capítulo 1

Introducción

1.1. Contexto

El inicio de la industria de los videojuegos se puede remontar hasta los años 30, donde los primeros juegos creados sobre estructuras mecánicas empiezan a darse a conocer en el mercado. La evolución de la electrónica en las siguientes décadas y la creación de los primeros ordenadores, hacen que ha finales de los años 60 nazca, él que muchos consideran el primer videojuego, Pong [1]. Desde esa época hasta la actualidad, la industria de los videojuegos no ha dejado de crecer, superando en ingresos a muchas grandes industrias. A su vez, desde dentro de la industria de videojuegos y de forma paralela a ella, los juegos competitivos han ido creciendo igualmente [2].

Los «esports» es el nombre otorgado a todo el ecosistema alrededor de los juegos com- petitivos, desde los juegos en sí mismos hasta los jugadores que participan en las distintas competiciones. Este pequeño ecosistema dentro de la industria de los vi- deojuegos nace a finales de los años 80, y crece de manera muy rápida tanto en los años 90 como a principios del nuevo milenio [2]. Pero es en esta última década, don- de la industria de los esports empieza a recibir mayor atención y, en consecuencia, atraer mayor cantidad de capital. Son muchos los artículos que hablan del crecimien- to que ha sufrido la industria, y son muchos más los que hablan del crecimiento que está por venir.

Bajo el contexto de gran expansión que parece va a ocurrir en la industria de los esports y siendo éste un ecosistema poco maduro, se presenta la necesidad de crear herramientas que permitan dar apoyo a la toma de decisiones relacionadas con el ecosistema. Es necesario crear una representación de toda la información obtenida del ecosistema. Esta representación se conoce como grafos de conocimiento, que son lo que se utiliza para hacer una correcta interpretación de la información obtenida.

En España no existe una modelización del ecosistema esports en concreto. En cam- bio, son muchos los actores dentro del mismo que empiezan a necesitar análisis cuantitativos y cualitativos sobre los que obtener los conocimientos como valor aña- dido a sus decisiones.

1 1.2. Objetivos

1.2. Objetivos

En este trabajo se busca realizar una primera modelización del ecosistema de esports en España. Para ello se cuenta con una serie de objetivos concretos con los que intentar completar este trabajo. 1. Identificar a los actores y a las fuentes de información del ecosistema es- ports. El primer paso de este trabajo será crear un esquema de los posibles actores que existen en el ecosistema esports, así como las relaciones que exis- tan entre cada uno de ellos. Encontrar fuentes de información será crucial para disponer de un lugar de donde extraer los datos necesarios para representar la dinámica del ecosistema. 2. Definir el actor específico sobre el que enfocar el estudio. Se buscará en- contrar un actor dentro del ecosistema, con él que podamos obtener resultados más específicos. 3. Identificar una fuente de información específica para el actor elegido. Una vez elegido el actor sobre él que se enfocará el estudio, se tiene que buscar una fuente de información que permita obtener información acerca de ese actor en concreto. 4. Modelizar el ecosistema. Por supuesto se tiene que extraer la información en- contrada, y ser capaz de modelar el ecosistema con esa información. Se tendrá que buscar una serie de herramientas que las que poder realizar todo este pro- cedimiento. 5. Analizar el ecosistema. Una vez finalizado el modelado del ecosistema, sería necesario realizar un análisis del mismo para así obtener valor añadido y unas conclusiones. 6. Extraer conclusiones y una serie de líneas futuras. Se espera poder no sólo obtener unas conclusiones sobre el análisis realizado, sino que también obtener una lista de posibles recomendaciones a seguir para futuras iteraciones que se puedan realizar sobre este trabajo.

2 Capítulo 2

Desarrollo

2.1. Identificación de actores del ecosistema esports

Para realizar una correcta evaluación del ecosistema esports, primero debemos bus- car e identificar los posibles agentes que forman una estructura básica dentro de dicho ecosistema. También es importante conocer las relaciones existentes entre los actores encontrados y cómo interaccionan entre sí.

Los actores que intervienen en el ecosistema varían ligeramente a nivel global [3] [4] y a nivel estatal, como podemos ver en el Libro blanco de los esports en España [5]. Se puede obtener una serie de actores que se presentan en ambos escenarios, y que creemos, son los más relevantes para realizar nuestro estudio. Ellos son:

• Publishers

• Organizadores

• Patrocinadores

• Equipos

• Jugadores

• Creadores de Contenido (Streamers/Influencers)

2.1.1. Publishers

Un publisher se refiere a una organización/empresa que se encarga de publicar un videojuego que ha sido desarrollado por el mismo publisher o por una tercera em- presa, conocida como desarrolladora. Por lo general un publisher aporta recursos económicos, de personas (marketing, traducciones) o logísticos (medios de distribu- ción) a la desarrolladora. Como se puede ver en la tabla 1, estas empresas obtienen unos ingresos bastante considerable actualmente por venta de juegos [6] (En esta lista, no todos los publishers han publicado juegos que tengan una liga competiti- va). Dentro del ecosistema esports encontramos grandes publishers como Valve, Riot Games, Activision Blizzard, Epic Games o Electronic Games, entre otras [7].

3 2.1. Identificación de actores del ecosistema esports

Empresa Ingresos ($) Tencent 4,641M Sony 4,410M Microsoft 3,391M Apple 2,535M Activision Blizzard 2,131M Google 2,129M NetEase 1,694M EA 1,289M

Cuadro 1: Empresas con mayor ingreso en el Q2 de 2019 [6].

2.1.2. Organizadores

Los organizadores son empresas especializadas en la organización de los distintos eventos, ligas o torneos de esports. Ofrecen distintos servicios a los publishers, entre los que se pueden encontrar dar soporte televisivo y de producción para diferentes competiciones. En España los principales organizadores son LVP (Liga de Videojuegos Profesional), ESL (Electronic Sports League) o GAME Esports entre otras, según el Libro Blanco [5]. Actualmente, la mayoría de organizadores utilizan plataformas de streaming online, siendo las más conocidas Twitch1 y Youtube2. En la tabla 2, se pueden ver los principales juegos ordenados según las horas de competición emitidas a través de la plataforma Twitch en el mes de Marzo de 2020 [8].

Título Horas totales Horas de competición Counter-Strike: Global Offensive 66.5M 20.3M League of Legends 123.2M 10.3M Dota 2 41.7M 6.5M Rocket League 10.5M 4.8M Age of Empires II: Definitive Edition 3.7M 1.4M Tom Clancy’s Rainbow Six: Siege 13.0M 0.9M StarCraft II 4.2M 0.8M PLAYERUNKNOWN’S BATTLEGROUNDS 13.7M 0.6M Warcraft III 2.4M 0.5M Teamfight Tactics 13.6M 0.4M

Cuadro 2: Juegos con mayor número de horas de competición emitida en Mar-20 [8].

2.1.3. Patrocinadores

Los patrocinadores son empresas que buscan difundir sus propios productos o ser- vicios a cambio de una contraprestación económica. Según Antevenio [9], los patroci- nios representan un 42 % de los ingresos del sector esports, que está valorado en más de $450M. En España los principales patrocinadores son las grandes empresas de te- lecomunicaciones: Movistar, Orange y Vodafone. Aunque su patrocinio varía, Orange

1www.twitch.tv 2www.youtube.com

4 Desarrollo patrocina la Superliga de League of Legends; mientras Movistar y Vodafone patro- cinan diferentes equipos. También encontramos empresas de bebidas como Puleva o FontVella, así como Red Bull. Pero también es común encontrar empresas cuyos productos son parte del ecosistema, como marcas de ordenadores y periféricos.

2.1.4. Equipos

Los equipos son empresas que forman parte y compiten en las distintas ligas y tor- neos que son organizados para cada juego. En sus estructuras se encuentran no solo los jugadores, sino también entrenadores y otros componentes del staff técnico. Los equipos soportan económicamente a los jugadores y al staff, a cambio de que éstos les representen en las competiciones. Los equipos de esports pueden tener varias secciones dentro de su estructura. Un mismo equipo puede tener representación en diferentes juegos, incluso dentro de un mismo juego tener dos equipos en distintas ligas. Es común que varios equipos de alto nivel tengan un equipo de academia donde forman jóvenes talentos. En España se ha creado recientemente una asociación de clubes, la A.C.E. (Asociación de Clubes de Esports3). Entre los principales clubes en España se encuentran Movistar Riders, Vodafone Giants, Mad Lions, BCN o Team Queso.

2.1.5. Jugadores

Los jugadores profesionales son las personas que forman parte de los distintos equi- pos y compiten en las ligas. Por lo general reciben un salario por formar parte de un equipo, aunque éstos varían mucho dependiendo del nivel del jugador, el equipo al que pertenece y el juego que disputa. El número de jugadores profesionales ha ido en aumento tanto a nivel global como a nivel nacional. Nuestro país ha dado grandes nombres del panorama mundial como Enrique «xPeke» Cedeño o Carlos «Ocelote» Ro- dríguez en el ámbito del League of Legends4, pero actualmente existen muchos más jugadores en diferentes disciplinas. Entre los más destacados se encuentran [13]: • Jorge «MethodZ» Bancell, Giants Gaming, . • Adrián «Homi» Moldes, KIYF, League of Legends. • Jonathan «HarryHook» Tejedor, Dallas Fuel, Overwatch. • Christian «IoWel» García, Movistar Riders, Counter Strike: Global Offensive. • Esteban «AKAWonder» Serrano, Giants Gaming, Hearthstone.

2.1.6. Creadores de contenido

Los creadores de contenido (streamers/youtubers) son personas que no compiten de manera profesional, pero mantienen una influencia muy grande de cara al público del ecosistema. Los creadores de contenido utilizan las plataformas de difusión (Twitch,

3https://www.asociacionclubesports.org/ 4Juego competitivo desarrollado por Riot Games. Más información en: https://euw. leagueoflegends.com/es-es/

5 2.1. Identificación de actores del ecosistema esports

Youtube, Mixer, Facebook Gaming) como vía para mantener una audiencia. Muchos equipos ya cuentan con creadores dentro de sus estructuras como los europeos G2 [10] o los coreanos Gen.G [11]. Incluso encontramos programas de partners de algu- nos publishers como Riot Games [12]. Este agente permite extender la popularidad de equipos y juegos a un público que éstos no son capaces de alcanzar con facilidad.

2.1.7. Relaciones

Para obtener las relaciones entre los distintos actores se utiliza el modelo propuesto por Tejero et al. (2019) [14]. En él se definen 6 tipos de relaciones: Competition, Mutualism, Commensalism, Consumerism, Predation y Parasitism. En la figura 1 se puede ver una modelización de las distintas relaciones entre los actores. En la tabla 3 se explica con más detalle la relación establecida entre cada actor.

Figura 1: Relaciones simplificadas entre los actores del ecosistema.

Actor A Actor B Relación Explicación Los publishers utilizan los servicios de organización y producción televisiva de los organizadores para crear ligas com- Publishers Organizadores Consumerism petitivas en regiones donde no disponen de esos recursos de forma directa. Fuente de referencia: https://lvp. global/1656-2/ En algunos casos como la LEC (League of Legends European Championship), el publisher toma también el papel de or- ganizador. En estos casos, el publishers está directamente en contacto con los Publishers Equipos Consumerism equipos para ‘venderles’ una plaza en la liga que organiza. No se han encontrado casos en España de esta relación. Fuente de referencia: https: //esportsinsider.com/2018/11/ eu-lcs-lec-2019-franchise-partners/

6 Desarrollo

Actor A Actor B Relación Explicación Organizadores y patrocinadores se unen para llevar sus marcas al ma- yor ámbito posible. Los organizadores pueden ofrecer mejor calidad de pro- ducción, mayor despliegue territorial Organizadores Patrocinadores Mutualism y los patrocinadores son capaces de hacer llegar su marca a más público. Fuente de referencia: https: //www.nobbot.com/otros-medios/ superliga-orange-e-sports/ Esta relación es muy parecida a la que hay entre publishers y equipos. Los organizadores ponen a disposición de los equipos las plazas para sus ligas o torneos a cambio de cumplir unos cier- Organizadores Equipos Consumerism tos requisitos, a veces incluso a cambio de una compensación económica. Fuente de referencia: https: //unity.lvp.global/es/noticias/ nace-la-assault-division-lvlup/ Los equipos se hacen con los servicios de los jugadores para competir en las distintas ligas en las que participan. Los jugadores perciben un compensación Equipos Jugadores Mutualism económica a cambio de representar a los equipos. Fuente de referencia: https: //twitter.com/Movistar_Riders/ status/1216449771789082624 En esta relación los equipos unen su marca a la de los creadores de conteni- do que aportan sus redes de seguidores, a cambio de recursos tan diversos como infraestructuras, marketing o materia- Creadores de Equipos Mutualism les. No se ha encontrado noticias sobre contenido intercambio económico explícitos, pero tampoco se descarta en algunos casos. Fuente de referencia: https: //g2esports.com/2020/02/06/ g2-owns-spain/

7 2.2. Objetivo específico de estudio: Equipos

Actor A Actor B Relación Explicación Los equipos reciben recursos económi- cos o materiales a cambio de unir su imagen a la de los patrocinadores. Fuentes de referencia: https: Equipos Patrocinadores Mutualism //twitter.com/BMW/status/ 1251042736238661634 https://twitter.com/ Movistar_Riders/status/ 1252899949680840704 No se ha podido encontrar casos de esta relación en España. Actualmente solo algunas marcas buscan patrocinar di- rectamente a jugadores. La mayoría de Patrocinadores Jugadores Mutualism casos encontrados son a nivel mundial. Fuente de referencia: https: //www.redbull.com/int-en/ athlete/sebastian-xixo-bentert Los patrocinadores cuentan con los grandes números de seguidores de los creadores de contenido para llevar su marca a un mayor público. A cambio Creadores de los creadores de contenido reciben Patrocinadores Mutualism contenido recursos económicos o materiales. Fuente de referencia: https: //esports.as.com/bonus/ influencers/TheGrefg-Twitch_ 0_1290470941.html Cuadro 3: Explicación detallada de las relaciones del ecosistema.

2.2. Objetivo específico de estudio: Equipos

Analizando las distintas relaciones encontradas dentro del ecosistema, se ha decidido definir como objetivo del estudio a los equipos. Este actor es el único que presenta una relación con cada uno de los demás actores del ecosistema. Esta es la razón principal de esta elección, ya que nos permitirá enriquecer el análisis que podamos hacer del ecosistema.

Este actor es fundamental para el funcionamiento del ecosistema, la profesionaliza- ción de los esports viene acompañada de la creación de estructuras sólidas por parte de los diferentes equipos. Tanto jugadores como patrocinadores se pueden beneficiar directamente de este hecho, los jugadores pueden centrarse en mejorar sus rendi- miento y los patrocinadores pueden encontrar marcas sólidas y estables con las que asociar su propia marca.

8 Desarrollo

2.3. Fuentes de información específica: Twitter

Como fuente de información principal, se ha decidido utilizar Twitter5. Twitter es una plataforma de red social online, donde las personas se comunican mediante tweets. Estos tweets son mensajes cortos, de hasta 280 caracteres, que sirven tanto para realizar una publicación como para contestar a la publicación de otra persona. En el Q1 de 2019 se registraron 330M de usuarios activos al mes en la plataforma [15]. La principal razón de utilizar esta fuente de información, es debido a que en Twit- ter podemos encontrar la mayor conversación relacionada con videojuegos y gaming. Solo en 2019 se publicaron 1.200M de tweets sobre este tema en la plataforma [16]. Tanto es así que la empresa ESL en su ’II Estudio de audiencia de esports en Espa- ña’, afirma que el 52,08 % de los espectadores utilizan Twitter como red social para interactuar durante las retransmisiones en directo [17].

Además, Twitter ofrece una API (siglas en inglés, Application programming interface) muy potente sobre la que poder trabajar y extraer datos de la plataforma. Entre las operaciones que ofrece, se ha encontrado varias que nos permitirán realizar búsque- das con palabras clave sobre los tweets de un usuario que puedan ser de nuestro interés, y poder extraer información sobre usuarios a los que menciona. Otra opera- ción que puede ayudarnos es la de realizar búsquedas con palabras claves sobre los perfiles de todos los usuarios.

2.3.1. Acceso a la API de Twitter

Para poder extraer datos de dentro de la plataforma, Twitter ofrece varios rangos de acceso mediante una API. Cada rango permite el acceso a un número mayor de ope- raciones. La opción elegida para solicitar acceso a la API ha sido mediante «Academic» y «Doing academic research», esto nos da acceso al rango «Premium APIs» que ofre- ce Twitter. Con esta opción disponemos de la gran mayoría de operaciones que hay disponibles de manera gratuita. En el análisis de la herramienta se ha detectado que una operación de obtención de información de geo-posicionamiento se encuentra dis- ponible en el siguiente rango, siendo éste ya de pago, pudiendo facilitar la obtención de datos más depurados.

Para explotar el API de Twitter, se ha elegido utilizar el lenguaje Python. Este lenguaje dispone de varias librerías que facilitan la utilización de la API de Twitter, en este caso se ha decidido utilizar la librería Tweepy6.

Otra de las herramientas que encontramos dentro del rango «Premium» es la posibi- lidad de hacer búsquedas de información de los tweets en un rango de tiempo mayor que el permitido en la versión «Standard». En este caso se nos ofrece dos endpoints, uno para realizar búsquedas en los últimos 30 días, y otro para realizar búsquedas en todo el archivo de Twitter, que llega hasta el 2006. Estos dos endpoints contra los que realizar las llamadas permiten un número limitado de peticiones al mes. Un equipo de desarrollo de Twitter ha creado un proyecto en forma de «wrapper» en lenguaje Python que nos ofrece la posibilidad de realizar estas llamadas, llamado

5www.twitter.com 6www.tweepy.org

9 2.4. Modelización del ecosistema search-tweets7.

2.4. Modelización del ecosistema

2.4.1. Infraestructura y almacenamiento

Aunque al final se ha podido realizar dos iteraciones sobre la modelización del ecosis- tema, hay ciertos aspectos que se han mantenido idénticos en ambas versiones. Se ha utilizado para ambas versiones las mismas herramientas encargadas de proporcionar la infraestructura física y el almacenamiento requerido.

Para realizar la modelización, se ha elegido usar la herramienta Grakn 8. En este caso se está utilizando la versión 1.7.1 de Grakn Core, publicada el 24 de Abril. Esta he- rramienta proporciona no sólo un modo de visualización sino que también se incluye una base de datos, Apache Cassandra9, y se proporciona un lenguaje para realizar consultas sobre la información que se guarda en la base de datos, este lenguaje pro- pio se llama Graql. Todo ésto proporciona una plataforma completa para realizar los análisis necesarios sobre el ecosistema estudiado. Para la parte de visualización se tiene que descargar una herramienta auxiliar de la propia compañía, llamada Grakn Workbase10. Para el estudio se utiliza la versión 1.2.8, publicada el 14 de Mayo. La única dependencia necesaria para utilizar todo el sistema es disponer de Java 8 ins- talado.

Otra ventaja, es la posibilidad que ofrece Grakn de crear un modelo de datos propio que se adapte a las necesidades específicas de cada caso, pudiendo definirse las en- tidades, las relaciones y las jerarquías que sean necesarias. Mediante un esquema Grakn, construimos un modelo de alto nivel que el sistema tendrá en cuenta para crear la estructura de la base de datos y optimizar nuestro esquema a los recur- sos disponibles. Para crear nuestro esquema Grakn tenemos que utilizar el lenguaje Graql11. Este esquema se asemeja en muchos aspectos a la creación de una ontología en Web Semántica.

2.4.2. Versión 1

2.4.2.1. Modelo de Grakn

En esta primera versión se va a poner foco en la relación entre jugadores y creadores de contenido con los equipos. El esquema 1 define a la entidad «equipo» y a la entidad abstracta «trabajador». De esta entidad abstracta cuelgan las entidades «jugador» y «creador». Todas estas entidades presentan como único atributo su nombre, en este caso se va a utilizar el nombre de usuario dentro de Twitter (e.g. @informaticaupm),

7https://twitterdev.github.io/search-tweets-python/ 8https://grakn.ai/ 9https://cassandra.apache.org/ 10https://github.com/graknlabs/workbase/releases 11https://dev.grakn.ai/docs/schema/overview

10 Desarrollo

se elige ese campo por ser un identificador único (aunque los usuarios pueden cam- biarlo) y por no permitir la utilización de caracteres especiales como emojis o emo- ticonos. La relación que se define para conectar estas entidades se llama «empleo», haciendo que cada entidad tenga un rol concreto en esa relación. En la figura 2 se puede apreciar con más detalles el esquema representado en la herramienta Grakn Workbase12.

1 define 2 3 equipo sub entity, 4 has nombre, 5 plays team; 6 7 trabajador sub entity, abstract, 8 has nombre; 9 10 jugador sub trabajador, 11 plays player; 12 13 creador sub trabajador, 14 plays streamer; 15 16 empleo sub relation, 17 relates team, 18 relates player, 19 relates streamer; 20 21 nombre sub attribute, 22 datatype string;

Listing 1: Versión 1 del esquema.

Figura 2: Ejemplo gráfico en Grakn de la versión 1 del esquema.

12https://github.com/graknlabs/workbase

11 2.4. Modelización del ecosistema

2.4.2.2. Extracción de datos de Twitter

A continuación se entrará más en detalle en la utilización de las funciones de la API de Twitter para este caso en concreto. En esta primera versión se hace uso de las funciones de búsqueda que ofrece la API. Como ya se ha explicado anteriormente, se utiliza la librería Tweepy. En esta ver- sión, la idea es sacar la información de equipos y jugadores mediante la función search_users(q). Esta función devuelve una lista de usuarios que coincida con la query (q) que le pasamos a la función, se buscará coincidencias en las biografías que tienen los usuarios en sus perfiles. Ésto se puede reproducir en la web de Twitter realizando una búsqueda y seleccionando la pestaña «Personas», un ejemplo de esta funcionalidad de puede apreciar en la figura 3. Para recuperar los perfiles de equipos esports se ha utilizado como queries: • «club deportes electrónicos». • «esports club».

Figura 3: Ejemplo de la funcionalidad de búsqueda de usuarios en Twitter.

Estas dos queries devuelven una lista de equipos bastante grande. Pero para nuestro caso se introducía demasiado ruido, puesto la primera query devolvía perfiles de equipos latinoamericanos; y la segunda query, perfiles de equipos de todo el mundo. Nuestro principal objetivo es la modelización del ecosistema español. Una solución es realizar un filtro sobre un parámetro del objeto User que devuelve la API, llamado «location» [18]. Para ello se utiliza un diccionario en Python con los términos más comunes que aparecen en este parámetro para perfiles de equipos españoles. Aún así se presenta otro problema, este parámetro está definido por el usuario, pudiendo ser nulo. Incluso no tiene porque ser una localización exacta, como se muestra en

12 Desarrollo

la figura 4. Esto ocasiona que esta solución no aporte unos resultados completos, quedándose muchos equipos fuera de la lista definitiva.

Figura 4: Ejemplo del parámetro «location» de un usuario.

A pesar de los problemas de esta solución, con un sencillo programa escrito en Pyt- hon podemos obtener resultado. El programa get_team.py se encarga de realizar esta recolección, como se puede apreciar con más detalle en el código 2. Las claves de acceso que proporciona Twitter se guardan en un fichero «json» para poder acceder a ella y utilizarlas. Tweepy utiliza un objeto Cursor, éste se encarga de gestionar la paginación y la iteración sobre los objetos solicitados [19]. De los objetos User que recibimos de la llamada a la API, seleccionamos los campos deseados que guardamos en un fichero «csv» como se muestra en la figura 5. Los campos que se guardan son: • id_str. Un string del identificador numérico único del usuario. Se recomienda utilizar este campo en vez de id, puesto que este es un número largo (mayor de 53 bits) y puede provocar problemas en algunos lenguajes. • name. Nombre del usuario. • screen_name. Conocido como «handle» o alias, también es un identificador úni- co. • location. Ya se ha explicado anteriormente este campo.

1 import tweepy 2 import json 3 import csv 4 5 with open(’twitter_credentials.json’, ’r’) as file: 6 creds = json.load(file) 7 8 auth = tweepy.OAuthHandler(creds[’CONSUMER_KEY’], creds[’CONSUMER_SECRET’]) 9 auth.set_access_token(creds[’ACCESS_TOKEN’], creds[’ACCESS_SECRET’]) 10 11 teamsFile = open(’teams.csv’, ’a’) 12 teamsWriter = csv.writer(teamsFile) 13 user_objs = [] 14 keywords_location = [’España’, ’Madrid’, ’Barcelona’, ’Canaria’, ’Cantabria’, ’Galicia’, ’Cataluña’, ’’, ’Murcia’, ’Sevilla’, ’Bilbao’, ’Madrid, España’, ’Comunidad Valenciana, España’, ’Sevilla, España’, ’Villarreal, España’, ’Las Palmas, Islas Canarias’, ’Santander, Cantabria’, ’Barcelona, España’, ’Jerez de la Frontera’, ’Asturias, España’, ’Madrid, Comunidad de Madrid’, ’Spain’, ’Islas Canarias, España’, ’Barcelona, Cataluña’, ’Murcia, España’, ’Islas Baleares, España’, ’Las Palmas de Gran Canaria, Es’, ’Europe Spain’, ’Burgos, España’, ’Alicante, España’, ’Elche, España’, ’Canary Islands, Spain’, ’Región de Murcia, España’, ’Girona, España’, ’Málaga, Andalucía’, ’Palma, España’, ’Zaragoza, España’, ’Montijo, España’, ’Vigo, España’, ’Reus, España’, ’Granada, Andalucía’, ’Cartagena, España’, ’País Vasco, España’, ’La Rioja’, ’Granada, España’, ’Málaga, España’, ’Eivissa, España’, ’Comunidad de Madrid, España’, ’Cerdanyola del Vallès’, ’Barcelona, Spain’, ’Girona’, ’Córdoba, España’, ’Valencia, España’, ’Santa Cruz de Tenerife, España’, ’Oviedo, España’, ’Terrassa, España’, ’Castilla y León, España’, ’La selva’, ’Cádiz, España’, ’Spain, Barcelona’, ’Canarias’, ’Dénia, España’, ’Guadalajara, España’] 15 16 api = tweepy.API(auth) 17 for page in tweepy.Cursor(api.search_users, q=’esports club’).pages(50): 18 for user_objs in page:

13 2.4. Modelización del ecosistema

19 20 id_str = user_objs._json[’id_str’] 21 name = user_objs._json[’name’] 22 screen_name = user_objs._json[’screen_name’] 23 location = user_objs._json[’location’] 24 25 if location in keywords_location: 26 teamsWriter.writerow([id_str, name, screen_name, location]) 27 28 teamsFile.close()

Listing 2: Versión 1 del programa get_team.

Figura 5: Ejemplo del contenido del fichero csv de equipos.

Figura 6: Ejemplo de una búsqueda de jugadores.

Una vez obtenido una lista con los equipos, se procede a extraer los jugadores que forman parte de esas estructuras. Para realizar esta extracción de datos, se utiliza la misma idea que la empleada con los equipos, empleando la función search_users(q).

14 Desarrollo

En la investigación de la fuente de información, se detectó que muchos de los ju- gadores de los diferentes equipos mencionan el perfil de su equipo en su biografía junto a una serie de palabras claves que se suelen repetir. Además, Twitter permi- te introducir en los parámetros de búsqueda el «handle»13 de un perfil, permitiendo así realizar el filtro según el equipo. En la figura 6 se puede apreciar un ejemplo de una búsqueda utilizando el «handle» de un perfil de Twitter. Para los jugadores, las queries que se pasan a la función de búsquedas son: • «jugador + handle del equipo». • «player + handle del equipo». Para la obtención de los datos, se ha creado el programa get_players.py. Su estructu- ra es muy parecida a la de get_team.py, el principal cambio residen en un bucle donde iteraremos sobre las filas que haya en el fichero de equipos, como se puede ver en el código 3. La gestión de las credenciales de Twitter como de los ficheros «csv» es igual al programa anterior, incluso se importan las mismas librerías. Se crea una variable «query» donde almacenaremos la palabra clave más el «handle» que obtengamos del fichero de equipos. Los campos que almacenamos en el fichero «csv» se obtienen de un objeto User, por tanto representan los mismo que se ha explicado anteriormente, en este caso guardamos: • id_str. • name. • screen_name.

1 user_objs = [] 2 api = tweepy.API(auth) 3 4 for row in teamsReader: 5 query = ’player ’ + row[2] 6 7 for page in tweepy.Cursor(api.search_users, q=query).pages(): 8 for user_objs in page: 9 10 id_str = user_objs._json[’id_str’] 11 name = user_objs._json[’name’] 12 screen_name = user_objs._json[’screen_name’] 13 playersWriter.writerow([row[2], id_str, name, screen_name]) 14 15 playerFile.close() 16 teamsFile.close()

Listing 3: Versión 1 del programa get_players.

A pesar de incluir al actor «creadores de contenido» en el modelo, se toma la decisión de empezar con la versión 2 de la modelización del ecosistema antes de completar la extracción de los datos de este actor.

2.4.2.3. Migración de datos a Grakn

Para llevar la información almacenada en los ficheros «csv» al grafo de información, Grakn proporciona una serie de clientes en diferentes lenguajes de programación,

13Nombre de usuario que sirve de identificador único y aparece detrás de las @ en los perfiles [20].

15 2.4. Modelización del ecosistema

que facilitan las llamadas hacia la herramienta mediante un API. En nuestro caso se va a utilizar el cliente Python, que se puede instalar fácilmente a través del gestor de paquetes pip14. Mediante la terminal del sistema, se instala el paquete utilizando el comando:

1 pip install grakn-client

Para crear el programa que realiza la migración de los datos, se ha utilizado la docu- mentación proporcionada en la web del desarrollador. El tutorial que se proporciona en la web es muy completo y nos proporciona un ejemplo de programa que se conecta al servidor Grakn de la máquina, obtiene los datos de los ficheros «csv» y realiza las queries de inserción en la base de datos [21]. El programa migrate.py sigue la misma estructura que la planteada en la documentación, siendo necesario realizar cambios para adaptarlo a nuestro modelo. El principal cambio son las queries de inserción de nuestros datos en Grakn, estas funciones se muestran en el código 4. En este caso tenemos funciones de inserción para los equipos, los jugadores y para crear la relación entre ambos.

1 def teams_template(team): 2 return ’insert $equipo isa equipo, has nombre "’ + team["usuario"] + ’";’ 3 4 def players_template(player): 5 return ’insert $jugador isa jugador, has nombre "’ + player["usuario"] + ’";’ 6 7 def empleo_template(empleo): 8 graql_insert_query = ’match $equipo isa equipo, has nombre "’ + empleo["usuario_equipo "] + ’";’ 9 graql_insert_query += ’ $jugador isa jugador, has nombre "’ + empleo["usuario"] +’";’ 10 graql_insert_query += ’ insert (team: $equipo, player: $jugador) isa empleo;’ 11 return graql_insert_query

Listing 4: Funciones para insertar datos en Grakn.

2.4.2.4. Visualización del modelo

Llegados a este punto ya tenemos los datos en el servidor Grakn y utilizando Grakn Workbase podemos empezar a visualizar y realizar las consultas que consideramos oportunas sobre el grafo de conocimiento. En la figura 7 se puede ver un ejemplo de como se vería el grafo mostrando la relación «empleo», en este caso se introduce una limitación de 100 entidades. Una evaluación que se ha realizado sobre esta versión es que este modelo introducía repeticiones en las entidades de «equipo», y se debería de intentar eliminar los posibles casos de duplicidad en los datos. En la figura 8 se muestra un ejemplo de dicha duplicidad, donde un mismo equipo se repite dos veces, así como todas sus relaciones con los jugadores. Una vez finalizada la implementa- ción de esta versión, se realizan las evaluaciones necesarias que permitan mejorar la modelización de cara a la siguiente iteración que se va a realizar. Se comentará con más detalle estas mejoras en la explicación de la segunda versión.

14https://pypi.org/project/pip/

16 Desarrollo

Figura 7: Visualización de la relación empleo del ecosistema. [https://imgur.com/ a/p0Deb4k]

Figura 8: Ejemplo de duplicidad de datos en el grafo de conocimiento. [https:// imgur.com/a/p0Deb4k]

17 2.4. Modelización del ecosistema

2.4.3. Versión 2

Esta segunda iteración viene motivada por la mejor comprensión de las herramientas que se están utilizando, así como de las posibilidades que ofrece la API de Twitter. Para esta versión se utilizará la herramienta search-tweets, como se ha explicado en la sección 2.3.1. También se intentará eliminar algunos de los fallos detectados como la inclusión de datos duplicados. En esta segunda aproximación a la fuente de información, se ha detectado que una manera más correcta de extraer la información del actor «equipo» es a través de la relación de este actor con el actor «organizador». Los organizadores mediante sus per- files de Twitter pueden mencionar a los equipos que participan en las competiciones que organizan. Esto nos permite no depender del campo «location» cuando hacemos búsquedas sobre usuarios. Además la lista de organizadores no es tan grande como la de equipos, y nos permite encontrar organizadores de ligas o torneos en el territorio español (pudiendo ser en algunos casos en la Península Ibérica), y con esto realizar el filtro de equipos españoles. Como nota se tiene que decir que no todos los equi- pos que participan en una liga española son necesariamente españoles, hay casos de equipos portugueses, ingleses y latinoamericanos. Antes de realizar la extracción de datos, se ha buscado una lista de organizadores manualmente. Se ha buscado organizadores de varios juegos diferentes, y perfiles que estuvieran «activos» (que tuvieran publicaciones desde finales del año pasado hasta la actualidad). En la figura 9 se muestra un perfil considerado «inactivo», puesto que su última publicación es de diciembre de 2019. La lista final de organizadores que se han seleccionado se puede ver en la tabla 4.

Organizador Handle Juego LVP LVPesLoL League of Legends LVP LVPesCSGO Counter Strike: Global Offensive LVP LVPesClash Clash Royale LVP LVPesFIFA FIFA 2020 ESL España ESLspain Varios One Tap OneTapLeague Counter Strike: Global Offensive Call Of Duty: Modern Warfare Secret Tournament SecreTournament Clash Royale National Gaming League NGLSpain Call Of Duty: Modern Warfare VFOspain_pc Virtual Football Organization VFOspain_ps FIFA 2020 VFOspain_xbox La Liga esportslaliga FIFA 2020 Ubisoft España Rainbow6ES Rainbow Six Siege Sin Frenos League Sinfrenosleague Rocket League Clash Royale National League ES NationaLeague_ Rocket League Fortnite National League ES Nationaleague Counter Strike: Global Offensive La Franquicia LaFranquiciaCOD Call Of Duty: Modern Warfare Cuadro 4: Tabla de organizadores.

18 Desarrollo

Figura 9: Perfil de organizador considerado inactivo.

2.4.3.1. Modelo de Grakn

Utilizando como base la versión primera del modelo, se busca mejorar algunos de los aspectos de la definición propuesta. En esta versión se añade el actor «organizador», y se define la relación que mantiene con los equipos. La entidad «organizador», pre- senta como atributo unicamente un nombre, que como en la versión anterior será el handle de los perfiles de Twitter. A la relación entre organizadores y equipos la llamamos «liga», donde los organizadores tienen el rol de organizador; y los equipos, de participantes. Otra modificación en este modelo respecto al anterior ha sido la separación de las relaciones entre equipos y jugadores, y equipos y creadores de contenido. Antes se utilizaba la misma relación para ambos casos. La nueva definición del esquema se puede ver con más detalle en el código 5, y en la figura 10 se puede ver la modelización en la plataforma Grakn Workbase.

1 define 2 3 equipo sub entity, 4 has nombre, 5 plays team, 6 plays participante; 7 8 organizador sub entity, 9 has nombre, 10 plays org; 11 12 trabajador sub entity, abstract, 13 has nombre; 14 15 jugador sub trabajador, 16 plays player; 17 18 creador sub trabajador, 19 plays streamer;

19 2.4. Modelización del ecosistema

20 21 empleo_jugadores sub relation, 22 relates team, 23 relates player; 24 25 empleo_creadores sub relation, 26 relates team, 27 relates streamer; 28 29 liga sub relation, 30 relates org, 31 relates participante; 32 33 nombre sub attribute, 34 datatype string;

Listing 5: Versión 2 del esquema.

Figura 10: Ejemplo gráfico en Grakn de la versión 2 del esquema.

2.4.3.2. Extracción de datos de Twitter

En esta versión se ha utilizado el paquete «search-tweets» para extraer información de los equipos. También se ha usado la función search_users(q) de la librería Tweepy, para la recolección de información de jugadores. Como se ha comentado anteriormen- te, con este paquete («search-tweets») podemos realizar búsquedas de tweets según un parámetro de búsqueda en un rango de fechas mayor del permitido en la llamada estándar a la API, que sólo permite recuperar tweets de los últimos 7 días. Podemos realizar búsquedas contra dos endpoints: • 30-days. Nos permite realizar búsquedas en los últimos 30 días naturales. Se permiten realizar 250 peticiones y recuperar un límite de 25.000 tweets en un mes. Este endpoint se utilizará para realizar las pruebas en la codificación del programa para extraer datos.

20 Desarrollo

• Full Archive. Este endpoint permite recuperar tweets en el archivo completo de Twitter (desde el año 2006). Se permiten realizar tanto sólo 50 peticiones y recuperar un máximo de 5.000 tweets en un mes. Se utilizará este endpoint cuando tengamos el programa depurado. Se puede acotar las fechas sobre las que recuperar la información. En nuestro caso se ha identificado que para obte- ner la información mas actualizada posible se establece como fecha de inicio el 01-12-2019. La razón detrás de esta elección es que las temporadas de la ma- yoría de competiciones esports empiezan en Enero, y los organizadores suelen anunciar los equipos participantes a partir de Diciembre del año anterior.

2.4.3.2.1. Extracción de los datos de equipos Mediante estas llamadas, mencionadas anteriormente, se reciben objetos Tweet en- capsulados en JSON (JavaScript Object Notation). Aunque para nuestro caso solo interesan ciertos campos, mas información puede ser obtenida en la documentación de la API15. Un aspecto importante a tener en cuenta de los tweets es la extensión que se hizo del límite de caracteres dentro de un tweet. En el año 2017, Twitter ex- tendió el límite de 140 a 280 caracteres [23]. Dentro de los campos del objeto Tweet se añadió un campo llamado Extended Tweet. A los campos que había anteriormente se les conoce como «legacy», aquí se incluirá información disponible hasta el carácter 140 del tweet. Los campos dentro de extended_tweet incluyen información si el tweet tiene más de 140 caracteres. Buscamos tweets donde los organizadores elegidos «mencionen» a los equipos. Las menciones son tweets que contienen el nombre de usuario de una o más personas [22]. Con las menciones podemos recuperar información de esos usuarios. Depen- diendo del tamaño del tweet, y como se ha comentado anteriormente, tendremos que extraer los datos de los equipos de diferentes campos. Para controlar esta posibilidad existe un campo llamado «truncated», que no dice si la información de los campos «legacy» están truncadas o no. Si ese campo es False,eltweet tiene menos de 140 ca- racteres. Con el código 6 se puede apreciar la implementación en Python para tratar estos casos (El código completo se encuentra en el anexo .1).

1 if tweet[’truncated’] == False: 2 user_mentions = tweet[’entities’][’user_mentions’] 3 else: 4 user_mentions = tweet[’extended_tweet’][’entities’][’user_mentions’]

Listing 6: Solución con el campo «truncated».

La lista de campos que vamos a utilizar es la siguiente: • user.id_str. Identificador único del usuario en formato «String». Se refiere al usuario que ha escrito el tweet. • user.name. Nombre del usuario que escribe el tweet. • user.screen_name. Otro identificador único de usuario, también conocido como «handle». • Si el campo «truncated» es False:

15https://developer.twitter.com/en/docs/tweets/data-dictionary/overview/ intro-to-tweet-json

21 2.4. Modelización del ecosistema

• entities.user_mentions. Lista de usuarios mencionados. • Si el campo «truncated» es True: • extended_tweet.entities.user_mentions. Lista de usuarios mencionados. Dentro de la lista de usuarios mencionados se utilizan los campos: user.id_str, user.name y user.screen_name. Esta información es igual que la recuperada del usuario que escribió el tweet. Puede suceder que no hay usuario mencionados en algunos de los tweets que recibamos de las llamadas. Para resolver este problema simplemente hay que comprobar que el campo «user_mentions» está vacío o no, como se muestra en el código 7.

1 if user_mentions: 2 for user in user_mentions: 3 teamsWriter.writerow([id_str, name, screen_name, user[’id_str’], user[’name’], user[’screen_name’]]) 4 else: 5 pass

Listing 7: Comprobación de la lista de usuarios mencionados.

Para realizar las búsquedas contra los endpoints, se ha encontrado una query con la que recuperamos valores interesantes: • «equipos from: + handle del organizador» Al realizar estas búsquedas se va guardando los resultados en un fichero «csv». El formato de este fichero se puede apreciar en la figura 11.

Figura 11: Ejemplo del formato del fichero csv de equipos.

Mediante este método de extracción de información de equipos, se detecta que se introduce cierto ruido. Existen algunos motivos diferentes para la aparición de ruido: 1. En algunos tweets las organizaciones pueden mencionar jugadores, comenta- ristas o patrocinadores. En la figura 12 se puede apreciar algunos casos de este tipo de ruido. Este caso de ruido es fácil de lidiar. Como se ha tratado con ello se explicará en la extracción de datos de jugadores. 2. Algunas organizaciones realizan un seguimiento de ligas extranjeras, a parte de las que organizan en el territorio español. Debido a ésto podemos encontrar equipos que no participan en liga españolas. Se detectan estos casos de inser- ción de ruido por el conocimiento personal de los esports.

22 Desarrollo

Figura 12: Ejemplo de un caso de inserción de ruido.

3. Al recuperar todos los tweets en un rango de fechas, se da el caso de repetición de equipos entre los usuarios mencionados. Este caso de ruido se soluciona utilizando el paquete pandas16. Pandas es una herramienta de análisis y mani- pulación de datos, que ofrece una función para eliminar datos duplicados con facilidad. En el código 8 se muestra la implementación para tratar la problemá- tica con los duplicados.

1 import pandas as pd 2 3 df = pd.read_csv("teams.csv") 4 5 df.drop_duplicates(subset=[’user_id’], inplace=True) 6 7 df.to_csv("teams_without_dup.csv")

Listing 8: Implementación para la eliminación de duplicados.

2.4.3.2.2. Extracción de los datos de jugadores Para los datos de los jugadores se va a utilizar la misma técnica que en la versión anterior de la implementación, utilizando la función search_users(q) de Tweepy.Se ha intentado realizar esta extracción mediante la técnica empleado para los equipos, pero no se ha conseguido encontrar una query para los tweets que devolviera unos resultados que pudiéramos considerar interesantes. Se ha mejorado la query utilizada, para así recuperar unos resultados más completos así como intentar eliminar el mayor número posible de ruido al mismo tiempo. Se ha incrementado el número de palabras claves para la búsqueda de jugadores: • jugador. • jugadora. • player. • midlaner. • toplaner. • jungle. • adc.

16https://pandas.pydata.org/

23 2.4. Modelización del ecosistema

• support.

• professional.

También se ha utilizado la posibilidad que ofrece la API de eliminar usuario que contengan una serie de palabras claves en su biografía. En este caso las palabras elegidas para ser utilizadas como exclusión son:

• ex

• former

• coach

Además de estas palabras clave, leemos el fichero de equipos para extraer uno de los identificadores únicos que tienen esos perfiles. En este caso elegimos screen_name («handle»). Con todos estos elementos configuramos las queries siguiendo el formato:

• «[palabra clave][handle del equipo] -ex -former -coach».

El programa implementado para realizar este trabajo es similar al programa empleado en la versión anterior (ver código 3). El código completo se puede encontrar en el anexo .2. Uno de los cambios más significativos respecto a la versión anterior es la utilización de parámetros de Tweepy para esperar al límite de llamadas a la API. La API de Twitter tiene unos límites establecidos para las llamadas realizadas por cada usuario. Después de un número concreto de resultados recuperados, un usuario tiene que esperar 15 minutos antes de poder realizar más llamadas. La clase API de Tweepy se encarga de esperar el tiempo necesario y volver a la query que había quedado pendiente. En el código 9 se puede ver la utilización de estos parámetros.

1 api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)

Listing 9: Implementación para el control del rate limit.

Como en los programas anteriores, se guarda los datos extraídos en un fichero «csv». En la figura 13 se puede ver el formato empleado.

Figura 13: Ejemplo del formato del fichero csv de jugadores.

24 Desarrollo

Mediante este proceso de extracción de datos se consigue reducir el ruido que se introduce en la fase de procesado de los datos de equipos. Al utilizar el nombre de usuario de cada fila del fichero de equipos, se realizan búsquedas con el formato establecido para esos usuarios que se consideran ruido entre los equipos. Cuando se realizan estas llamadas, éstas no retornan resultados y por tanto esos usuarios quedan eliminados en el fichero de jugadores. En este caso también se puede introducir ruido mediante datos duplicados. Se utiliza el mismo programa empleado para eliminar estos casos en los equipos, lo único que tiene que cambiar son los ficheros de entrada y de salida (ver código 8).

2.4.3.2.3. Extracción de los datos de creadores de contenido Para realizar esta extracción de datos, se utilizan la misma técnica que la empleada con los jugadores. El programa creado para realizar es similar a get_players.py,a continuación se comentará los principales cambios. El código se puede ver en el anexo .3. También se ha detectado cierto ruido en modo de usuarios duplicados, para eliminarlo se utiliza el programa 8, cambiando unicamente los ficheros de entrada y salida. En este caso las palabras claves que utilizamos para realizar las búsquedas son: • creador. • youtuber. • streamer. En cambio las palabras que se utiliza para hacer eliminación son algunas de las que utilizamos como palabra clave en los jugadores. Existen muchos casos de jugadores que también realizan contenido en Youtube o Twitch, pero se considera «creador de contenido» aquellas personas que no sean jugadores profesionales a la vez. En este caso, las palabras de exclusión son: • player. • jugador. • jugadora. • coach. También se utiliza el nombre de usuario de los equipos para completar las queries. El formato de las queries realizadas es: • «[palabra clave][handle del equipo] -player -jugador -jugadora -coach». En la figura 14 se muestra el contenido del fichero «csv» creado con la extracción de los datos.

2.4.3.3. Migración de datos a Grakn

Antes de realizar la migración de los datos almacenados en los ficheros «csv», se ha tenido que crear dos ficheros extras con datos mas específicos. Al hacer la inserción, algunos ficheros tenían datos repetidos en varias filas. Grakn no mira por repeticiones

25 2.4. Modelización del ecosistema

Figura 14: Ejemplo del formato del fichero csv de creadores de contenido.

e inserta nuevas entidades por cada fila recibida. En la figura 15 se puede ver como hay varias filas para un mismo organizador. Cada fila representa uno de los equipos que participa en las ligas del organizador «Secret Tournament» y «VFO Spain». Usando este fichero como entrada de datos para organizadores, en el resultado final habrá 17 entidades «Secret Tournament» y 9 entidades «VFO Spain», siendo ésto incorrecto.

Figura 15: Fichero que introduce errores en la base de datos.

Para subsanar este problema se utiliza el código 8 para crear un fichero sin repeticio- nes de los organizadores de los que hemos podido extraer equipos. Del mismo modo se descubrió el mismo problema con los equipos. Para solucionar el problema con los equipos se crea un pequeño programa para obtener una lista solo de los equipos, como se muestra en el código 10.

1 import csv 2 3 f_list = open(’just_teams.csv’, ’a’) 4 w_list = csv.writer(f_list) 5 6 file_1_tuples = [] 7

26 Desarrollo

8 with open("teams_without_dup.csv") as fh: 9 csv_reader = csv.reader ( fh ) 10 for row in csv_reader: 11 file_1_tuples.append( tuple(row[2]) ) 12 13 with open("teams.csv") as fh: 14 csv_reader = csv.reader ( fh ) 15 for row in csv_reader: 16 if tuple(row[6]) in file_1_tuples: 17 w_list.writerow( row[3:7] )

Listing 10: Implementación para obtener lista de equipos.

Una vez solucionado estos problema podemos realizar la migración. Como en la ver- sión anterior, se utiliza el cliente Python Grakn Client. El código completo que se ha utilizado para hacer la migración se puede encontrar en el anexo .4. Destacar las funciones para realizar las inserciones; primero para insertar las entidades «juga- dor», «equipo», «organizador» y «creador de contenido», y a continuación una función por cada una de las relaciones. Estas funciones se encuentran entre la línea 22 y la línea 50 en dicho anexo.

2.4.3.4. Visualización del modelo

Para realizar la visualización del ecosistema creado se utiliza la herramienta Grakn Workbase. Se mostrará algunas llamadas generales que se pueden obtener. Para obtener todas las relaciones «liga» entre organizadores y equipos, se utiliza la query 11. En las figuras se puede observar a los organizadores en color morado y a los equipos en color naranja. En la figura 16 se puede ver todas las entidades que existen con esa relación. En la figura 17 se aprecia un zoom en dos de las entidades con más relaciones «liga».

1 match $x isa liga; get; offset 0; limit 200;

Listing 11: Query para las relaciones «liga».

27 2.4. Modelización del ecosistema

Figura 16: Visualización de todas las relaciones «liga». [https://imgur.com/a/ k7oSPSr]

Figura 17: Zoom sobre algunas entidades con relaciones «liga». [https://imgur. com/a/k7oSPSr]

28 Desarrollo

La relación «empleo_creadores» entre creadores de contenido y equipos se obtiene mediante la consulta 12. En la figura 18 se puede ver como se representa la relación; las entidades equipos se representan en naranja, y en morado las entidades creador. Y en la figura 19 se hace un zoom para ver la representación del equipo con más creadores, «ftwesports».

1 match $x isa empleo_creadores; get; offset 0; limit 300;

Listing 12: Query para las relaciones «empleo_creadores».

Figura 18: Visualización de todas las relaciones «empleo_creadores». [https:// imgur.com/a/Irq8qCZ]

Figura 19: Zoom sobre una entidad con relaciones «empleo_creadores». [https:// imgur.com/a/Irq8qCZ]

29 2.4. Modelización del ecosistema

La última relación que se va a mostrar es también la que más número de entida- des presenta. La relación «empleo_jugadores» entre jugadores y equipos se obtiene mediante la consulta 13. Del mismo modo que las representaciones anteriores se va presentar unas imágenes sobre la presentación final que tiene la relación en el grafo. En la figura 20 se puede apreciar una imagen de todas las entidades a la vez. Mien- tras en la figura 21 se hace un acercamiento sobre una de las entidades equipo con más relaciones con jugadores, «CreamRealBetis»

1 match $x isa empleo_jugadores; get; offset 0; limit 900;

Listing 13: Query para las relaciones «empleo_jugadores».

Figura 20: Visualización de todas las relaciones «empleo_jugadores». [https:// imgur.com/a/rkSvLWK]

Figura 21: Zoom sobre una entidad con relaciones «empleo_jugadores». [https:// imgur.com/a/rkSvLWK]

30 Capítulo 3

Análisis del ecosistema

Para realizar el análisis se emplea tanto la herramienta de visualización Grakn Work- base como Grakn Console1. El lenguaje de consultas Graql presenta una serie de instrucciones con la que podemos obtener información del grafo [24]. Workbase so- lo permite realizar consultas de lectura, por eso para realizar consultas de cómpu- to y agregación se utiliza Console. Grakn Console es un programa CLI (del inglés, Command-line Interface) que permite realizar consultas sobre un grafo almacenado en Grakn mediante una terminal.

3.1. ¿Cuántos jugadores existen en el ecosistema?

Podemos obtener una respuesta utilizando Console mediante la consulta:

1 match $x isa jugador; get; count; 2 764

Esta pregunta entra dentro de una serie de preguntas básicas para conocer el ecosis- tema. Aunque no se pueda sacar muchas conclusiones, es una información intere- sante sobre la que tener conocimiento. Una aplicación sería llevar un historial del número de jugadores que forman parte del ecosistema para analizar los cambios que sufre a lo largo de los años.

3.2. ¿Cuántos equipos existen en el ecosistema?

Mediante Console obtenemos respuesta con la consulta:

1 match $x isa equipo; get; count; 2 119

Otra pregunta para tener unos conocimientos básicos del ecosistema. De manera similar al número de jugadores que existe, este conocimiento nos podría ser muy

1https://dev.grakn.ai/docs/running-grakn/console

31 3.3. ¿Cuántos jugadores tiene cada equipo?

relevante de cara a un histórico temporal. A pesar de que esta cifra está limitada por el número de organizadores desde los que se han extraído los datos de equipos. Se puede consultar la lista de organizadores en la tabla 4. Aún así la cifra de 119 equipos puede considerarse bastante interesante para un mercado como el español.

3.3. ¿Cuántos jugadores tiene cada equipo?

A través de Console usamos la consulta:

1 match 2 $x isa jugador; 3 $y isa equipo, has nombre $n; 4 (team: $y, player: $x) isa empleo_jugadores; 5 get; group $n; count; 6 {"ftwesports" isa nombre: {20}} 7 {"TDarkpirates" isa nombre: {6}} 8 {"MADLions_LoLES" isa nombre: {4}} 9 {"Supremacy_FR" isa nombre: {12}} 10 {"DeadRabbitsClub" isa nombre: {7}} 11 {"Ravens_EC" isa nombre: {4}} 12 {"Aion_es" isa nombre: {7}} 13 {"team_empire" isa nombre: {5}} 14 {"QLASH_Spain" isa nombre: {39}} 15 {"TeamFoxesGaming" isa nombre: {1}} 16 {"x6tence" isa nombre: {33}} 17 {"Vanguard_eClub" isa nombre: {2}} 18 {"G2ArcticES" isa nombre: {4}} 19 {"Electrify_ES" isa nombre: {7}} 20 {"RambootClub" isa nombre: {9}} 21 {"TeamReciprocity" isa nombre: {1}} 22 {"RagnarSons_" isa nombre: {1}} 23 {"sace_tour" isa nombre: {1}} 24 {"GTZBulls" isa nombre: {3}} 25 {"DogminationOrg" isa nombre: {4}} 26 {"Sockers_" isa nombre: {3}} 27 {"SpacestationCR" isa nombre: {2}} 28 {"Resistance_eS" isa nombre: {1}} 29 {"VCFeSports" isa nombre: {8}} 30 {"TeamQuesoGG" isa nombre: {22}} 31 {"Eternal_Team" isa nombre: {1}} 32 {"EWUeSportsClub" isa nombre: {2}} 33 {"HUPTeamOfficial" isa nombre: {5}} 34 {"NasticeSports" isa nombre: {1}} 35 {"Venturini" isa nombre: {1}} 36 {"GainekoFc" isa nombre: {3}} 37 {"RapidGamers_" isa nombre: {1}} 38 {"TG_Paragon" isa nombre: {7}} 39 {"AmaruEsports" isa nombre: {2}} 40 {"CreamRealBetis" isa nombre: {44}} 41 {"MitologyEsports" isa nombre: {1}} 42 {"grillos_eSports" isa nombre: {1}} 43 {"orangemecanic1" isa nombre: {3}} 44 {"TheOfficialN2E" isa nombre: {1}} 45 {"ArcticGamingES" isa nombre: {12}} 46 {"SFCeSports" isa nombre: {1}} 47 {"TeamQLASH" isa nombre: {27}} 48 {"UCAM_esports" isa nombre: {16}} 49 {"GironaFCeSports" isa nombre: {1}} 50 {"Team_GalaxyzZ" isa nombre: {1}} 51 {"Murcielagos_ESP" isa nombre: {1}} 52 {"e_FITNERS" isa nombre: {3}} 53 {"_Inazuma_Eleven" isa nombre: {1}} 54 {"NextLevelEyE" isa nombre: {1}} 55 {"VeteranosClub" isa nombre: {16}} 56 {"SUPRMODEGaming" isa nombre: {4}}

32 Análisis del ecosistema

57 {"UltimaSquadra" isa nombre: {1}} 58 {"KawaiiKiwis" isa nombre: {11}} 59 {"ColossusSoccer" isa nombre: {6}} 60 {"KPI_Gaming" isa nombre: {7}} 61 {"22eSports" isa nombre: {4}} 62 {"DefuseClub" isa nombre: {3}} 63 {"zerozoneclub" isa nombre: {31}} 64 {"Cream_EsportsGG" isa nombre: {4}} 65 {"DanGeRousEsp" isa nombre: {2}} 66 {"N1_eSport" isa nombre: {1}} 67 {"sAwggofficial" isa nombre: {4}} 68 {"QHeSports" isa nombre: {1}} 69 {"UnicosGaming" isa nombre: {4}} 70 {"NacongamingES" isa nombre: {2}} 71 {"Offset_Esports" isa nombre: {7}} 72 {"KILLABEEZesport" isa nombre: {10}} 73 {"SDEibar_eSports" isa nombre: {2}} 74 {"Movistar_Riders" isa nombre: {20}} 75 {"EsportsHorus" isa nombre: {1}} 76 {"TalaveraCf" isa nombre: {1}} 77 {"WizardsClub" isa nombre: {6}} 78 {"BaeconGG" isa nombre: {4}} 79 {"ColumbusVCP" isa nombre: {3}} 80 {"ChaosEC" isa nombre: {9}} 81 {"SomosMamboFC" isa nombre: {1}} 82 {"RedsGamingFIFA" isa nombre: {3}} 83 {"Outplayedstaff" isa nombre: {8}} 84 {"Unit3k" isa nombre: {6}} 85 {"EC4Gaming" isa nombre: {1}} 86 {"FireVoidGaming" isa nombre: {7}} 87 {"RZ_eSports" isa nombre: {3}} 88 {"FACEIT" isa nombre: {21}} 89 {"Eternal_oficial" isa nombre: {7}} 90 {"S2Vesports" isa nombre: {27}} 91 {"eMonkeyzClub" isa nombre: {4}} 92 {"SavageGClub" isa nombre: {5}} 93 {"RCDeSports" isa nombre: {4}} 94 {"NeCOREgaming" isa nombre: {3}} 95 {"RMajadaheSports" isa nombre: {1}} 96 {"granitgaming" isa nombre: {9}} 97 {"GiantsGaming" isa nombre: {34}} 98 {"FlamengoStars" isa nombre: {2}} 99 {"TenerifeTitans" isa nombre: {7}} 100 {"eQuizersEC" isa nombre: {5}} 101 {"Gold_Legends" isa nombre: {3}} 102 {"EsportsLUD" isa nombre: {5}} 103 {"houkouteam" isa nombre: {1}} 104 {"FieldSoldiers" isa nombre: {1}} 105 {"Esports_CTM" isa nombre: {1}} 106 {"ADCeutaeSports" isa nombre: {1}} 107 {"CDBeSports" isa nombre: {1}} 108 {"MV3United" isa nombre: {13}} 109 {"WolvesCityFC" isa nombre: {1}} 110 {"TeamSinOrg" isa nombre: {3}} 111 {"PushingGaming" isa nombre: {7}} 112 {"exploitgg_" isa nombre: {4}} 113 {"FullEsports" isa nombre: {1}} 114 {"eSports_UDLP" isa nombre: {3}} 115 {"Cadiz_CFESports" isa nombre: {8}} 116 {"MADLions_LoLEN" isa nombre: {2}} 117 {"DarkSuneSports" isa nombre: {3}} 118 {"x6tence_mx" isa nombre: {1}} 119 {"Wygers" isa nombre: {18}} 120 {"VykingsClub" isa nombre: {2}} 121 {"eTaraGaming" isa nombre: {1}} 122 {"pinatar" isa nombre: {1}} 123 {"RSGeSports" isa nombre: {7}} 124 {"TeamHeretics" isa nombre: {11}}

33 3.4. ¿Cuántos creadores de contenido existen en el ecosistema?

Podemos apreciar como el número de jugadores dentro de los equipos es muy va- riado. El equipo que más jugadores presenta es «CreamRealBetis» con 44 jugadores en sus filas, seguido de «QLASH_spain» con 39 y «GiantsGaming» con 34. También sorprende ver muchos equipos con tan solo 1 jugador. Esto permite mostrar las estra- tegias seguidas por los equipos con respecto a los juegos, observando su interés por determinados juegos frente a otros, al disponer en ellos de más o menos jugadores (esto a su vez podría estar enlazado con el patrocinio que puedan obtener en uno u otro juego, etc.). En juegos como League of Legends o Counter Strike, «GiantsGaming» presenta un equipo principal, otro de academia y uno femenino.

3.4. ¿Cuántos creadores de contenido existen en el ecosis- tema?

A través de Console, obtenemos una respuesta mediante la consulta:

1 match $x isa creador; get; count; 2 149

El número de creadores de contenido es más bajo del esperado, se creía que los equipos apostarían por contar con este tipo de actor para dar más visibilidad a su marca. Apenas se tendría un creador de contenido por equipos con los números actuales.

3.5. ¿Cuántos creadores tiene cada equipo?

También mediante Console podemos obtener la respuesta:

1 match 2 $x isa creador; 3 $y isa equipo, has nombre $n; 4 (team: $y, streamer: $x) isa empleo_creadores; 5 get; group $n; count; 6 {"ftwesports" isa nombre: {23}} 7 {"KILLABEEZesport" isa nombre: {1}} 8 {"TDarkpirates" isa nombre: {4}} 9 {"MADLions_LoLES" isa nombre: {1}} 10 {"Movistar_Riders" isa nombre: {2}} 11 {"DeadRabbitsClub" isa nombre: {4}} 12 {"BaeconGG" isa nombre: {1}} 13 {"WizardsClub" isa nombre: {4}} 14 {"Ravens_EC" isa nombre: {2}} 15 {"Aion_es" isa nombre: {1}} 16 {"team_empire" isa nombre: {1}} 17 {"QLASH_Spain" isa nombre: {3}} 18 {"x6tence" isa nombre: {13}} 19 {"FireVoidGaming" isa nombre: {2}} 20 {"EC4Gaming" isa nombre: {3}} 21 {"FACEIT" isa nombre: {5}} 22 {"Electrify_ES" isa nombre: {1}} 23 {"S2Vesports" isa nombre: {1}} 24 {"Eternal_oficial" isa nombre: {5}} 25 {"eMonkeyzClub" isa nombre: {2}} 26 {"RambootClub" isa nombre: {1}} 27 {"TeamReciprocity" isa nombre: {1}}

34 Análisis del ecosistema

28 {"NeCOREgaming" isa nombre: {1}} 29 {"granitgaming" isa nombre: {1}} 30 {"GiantsGaming" isa nombre: {4}} 31 {"GTZBulls" isa nombre: {2}} 32 {"Sockers_" isa nombre: {1}} 33 {"TeamQuesoGG" isa nombre: {5}} 34 {"VCFeSports" isa nombre: {1}} 35 {"Eternal_Team" isa nombre: {1}} 36 {"EsportsLUD" isa nombre: {1}} 37 {"houkouteam" isa nombre: {1}} 38 {"NasticeSports" isa nombre: {1}} 39 {"TG_Paragon" isa nombre: {1}} 40 {"CreamRealBetis" isa nombre: {3}} 41 {"MitologyEsports" isa nombre: {1}} 42 {"CDBeSports" isa nombre: {1}} 43 {"MV3United" isa nombre: {7}} 44 {"PushingGaming" isa nombre: {1}} 45 {"ArcticGamingES" isa nombre: {2}} 46 {"TheOfficialN2E" isa nombre: {1}} 47 {"TeamQLASH" isa nombre: {1}} 48 {"UCAM_esports" isa nombre: {1}} 49 {"_Inazuma_Eleven" isa nombre: {1}} 50 {"VeteranosClub" isa nombre: {8}} 51 {"SUPRMODEGaming" isa nombre: {2}} 52 {"KawaiiKiwis" isa nombre: {2}} 53 {"x6tence_mx" isa nombre: {1}} 54 {"Wygers" isa nombre: {2}} 55 {"DefuseClub" isa nombre: {1}} 56 {"zerozoneclub" isa nombre: {7}} 57 {"Cream_EsportsGG" isa nombre: {1}} 58 {"UnicosGaming" isa nombre: {1}} 59 {"TeamHeretics" isa nombre: {4}}

Podemos ver como solo dos equipos cuentan con mas de 10 creadores de contenido en sus filas, «ftwesports» con 23 y «x6tence» con 13. Aunque no se ha podido encontrar una consulta que devuelva el número de equipos que tienen creadores, podemos ver que son solo 54 equipos (de un total de 119), menos de la mitad. Los equipos todavía no están explotando la utilización de este actor dentro del ecosistema.

35

Capítulo 4

Conclusiones y líneas futuras

4.1. Conclusiones generales

Las posibilidades que ofrecen las tecnologías empleadas en este trabajo son enormes. El hecho de utilizar Twitter como fuente de información nos permite poner de ma- nifiesto la importancia que tiene en la actualidad las redes sociales. Poder obtener un flujo de información masivo y con una gran dinamicidad diariamente, pone en relieve el increíble potencial que presentan las herramientas de análisis de las redes sociales. Y todo ello con suma facilidad, permitiendo el filtrado de los datos para su análisis. Dentro de la API de Twitter, existe un rango que proporciona acceso a herramientas que añaden información de geo-posicionamiento dentro de los objetos encapsula- dos en la respuesta JSON. Se tiene que tener en cuenta que para acceder a este rango se tiene que adquirir una licencia comercial. Pese a ello, la información de geo- posicionamiento que proporcionan resultaría de gran utilidad para la obtención, el filtrado y el análisis de los datos. A pesar que no haber sido posible encontrar la manera de extraer información de los actores «publishers» y «patrocinadores» mediante Twitter, se podría obtener datos de ellos a través de otras fuentes de información. Utilizando los grafos de información junto con las ontologías, agregar estos flujos de datos de diferentes fuentes en un modelo único resulta sencillo. Ésta es una de las grandes ventajas que ofrecen estas tecnologías.

4.2. Conclusiones personales

Este trabajo me ha permitido adentrarme en una industria que me gusta perso- nalmente, la industria de los esports. He descubierto detalles que desconocía y he aprendido a mirar a esta industria desde una perspectiva completamente nueva. Los esports crecen a pasos agigantados y eso permite que crezca la necesidad de crear herramientas de apoyo. Exceptuando el lenguaje de programación Python, el resto de tecnologías utilizadas en este trabajo nunca las había manejado. Las posibilidades que ofrecen los grafos de

37 4.3. Líneas futuras conocimiento, y mas en concreto Grakn, son muy interesantes. La capacidad de crear esquemas específicos para cada caso hace de ésta una herramienta muy potente. La Web Semántica y las ontologías están en boga actualmente, y la similitud de Grakn con estas tecnologías es una gran ventaja. Pero Grakn ofrece una gran documenta- ción para los usuarios que no tengan conocimiento acerca de estas tecnologías. Otra de las tecnologías es la API de Twitter. Esta red social es una de las grandes pla- taformas de la actualidad, y ha sido sorprendente conocer algunas de las posibilidad que ofrece así como la gran cantidad de información que se puede obtener de ella. Al nunca haber utilizado esta tecnología, el aprendizaje ha sido mediante «prueba y error». Y a medida que se iba avanzando durante el trabajo se descubrían nuevas funciones y formas de obtener información. Algunas no se han podido implementar, y hablaremos de estas posibilidades en las líneas futuras. En definitiva estoy satisfecho con el trabajo realizado, pero me quedo con ganas de realizar una siguiente iteración e intentar añadir más información al grafo e informa- ción más depurada. Aun así creo que he podido asentar unas bases de conocimiento para poder avanzar sobre este trabajo.

4.3. Líneas futuras

Al mirar atrás al trabajo aparecen muchas ideas que no se han podido implementar. Aquí comentaré esas ideas sin un orden de importancia específico. • Durante la parte final de implementación, he descubierto que al crear la rela- ción entre organizadores y equipo estaba eliminando algunas de esas relaciones por evitar añadir duplicados. Esta relación sería mucho más interesante si se pudiera ver la existencia de equipos que participan de varias ligas. • No se ha encontrado una manera de recuperar la información de las relaciones entre patrocinadores con el resto de actores del ecosistema. Completar estas relaciones sería muy importante para añadir un actor fundamental como son los patrocinadores. • Añadir de alguna manera el juego en el que participan cada jugador, cada equipo y las ligas que organizan los distintos organizadores. Sería una relación compleja pero creo que la información se puede extraer de Twitter, quizás en combinación con otras fuentes de información, gracias a que las ontologías permiten esta integración y combinación de fuentes. • Añadir información adicional a los distintos actores. En este trabajo solo se ha añadido el nombre de las entidades. Resultaría interesante añadir otro campos como nacionalidad de los jugadores y de los equipos (mediante Twitter creo que resultaría difícil). Una más fácil podría ser el número de seguidores en Twit- ter, también en unión con otras fuentes, de entre las que se ha presentado al comienzo del trabajo, durante la identificación de los actores. • Se ha descubierto que algunos equipos tienen varios perfiles de Twitter, uno para cada uno de los equipos dentro de sus estructuras (e.g. Mad Lions). Unifi- carlos bajo una misma entidad daría más peso al grafo y reportaría información más depurada.

38 Bibliografía

[1] S.L. Kent, The Ultimate History of Video Games: Volume Two: from Pong to Poke- mon and beyond... the story behind the craze that touched our lives and changed the world. Three Rivers Press, 2010.

[2] Jerkrot, Henrik Nel, and Shahin Adl Zarrabi. Value creation and appropriation in the esports industry. MS thesis. 2016.

[3] The Esports Observer, An Introduction to the Esports Ecosystem. [Online] Dispo- nible: https://esportsobserver.com/the-esports-eco-system/

[4] P. Jurkic, Esports Ecosystem | Key Components of Competitive Gaming, Agosto 10, 2019. [Online] Disponible: https://www.esportstalk.com/blog/ esports-ecosystem-key-components-competitive-33087/

[5] Asociación Española de Videojuegos, Libro blanco de los esports en España, Mayo 2018. [Online] Disponible: http://www.aevi.org.es/web/wp-content/ uploads/2018/05/ES_libroblanco_online.pdf

[6] Newzoo, Top 25 Public Companies by Game Revenues, 2019. [Online] Disponible: https://newzoo.com/insights/rankings/ top-25-companies-game-revenues/

[7] Gambling Sites, Major esports Game Developers and Publishers in 2018. [Online] Disponible: https://www.gamblingsites.com/esports-betting/ game-developers-publishers/

[8] Newzoo, Most Watch Games on Twitch, Marzo 2020. [Online] Disponible: https: //newzoo.com/insights/rankings/top-games-twitch/

[9] Antevenio, Principales patrocinadores de esports en España, Septiembre 4, 2019. [Online] Disponible: https://www.antevenio.com/blog/2019/09/ principales-patrocinadores-de-esports-en-espana/

[10] G2, Creators. https://g2esports.com/teams/creators/

[11] Gen.G, Content Creators. https://geng.gg/blogs/content-creators

[12] Riot Games, Partner Program. https://partners.leagueoflegends.com/en_ US/

[13] R. Martín, Los cinco mejores jugadores españoles de eSports que están en mo- do Leyenda, Mayo 31, 2019. [Online] Disponible: https://www.marca.com/ esports/2019/05/31/5cf14606ca47419d708b459d.html

39 BIBLIOGRAFÍA

[14] A. Tejero, I. Pau and G. León, Analysis of the Dynamism in University-Driven Innovation Ecosystems Through the Assessment of Entrepreneurship Role,inIEEE Access, vol. 7, pp. 89869-89885, 2019. [15] J. Clement, Statista, Twitter: number of monthly active users 2010-2019, Agos- to 14, 2019. [Online] Disponible: https://www.statista.com/statistics/ 282087/number-of-monthly-active-twitter-users/ [16] R.Chadha, 2019 Gaming on Twitter, Enero 7, 2020. [Online] Dis- ponible: https://blog.twitter.com/en_us/topics/events/2019/ 2019-gaming-on-twitter.html [17] Esports Bureau, ESL presenta en MGE el “II Estudio de audiencia de esports de España” con datos reveladores sobre el sector, Octubre 27, 2017. [Online] Disponible: https://www.esportsbureau.com/esl-estudio-esports/ [18] Twitter, User Object, Twitter Developers. [Online] Disponible: https: //developer.twitter.com/en/docs/tweets/data-dictionary/overview/ user-object [19] tweepy, Cursor Tutorial. [Online] Disponible: http://docs.tweepy.org/en/ latest/cursor_tutorial.html [20] SproutSocial, What is a Twitter handle?. [Online] Disponible: https:// sproutsocial.com/glossary/twitter-handle/ [21] Grakn Labs, Migrating CSV, JSON and XML Data with Client Pyt- hon. [Online] Disponible: https://dev.grakn.ai/docs/examples/ phone-calls-migration-python [22] Twitter, About replies and mentions. [Online] Disponible: https://help. twitter.com/en/using-twitter/mentions-and-replies [23] S. Perez, Twitter officially expands its character count to 280 starting today, No- viembre 7, 2017. [Online] Disponible: https://techcrunch.com/2017/11/07/ twitter-officially-expands-its-character-count-to-280-starting-today/ [24] Grakn Labs, Graql Queries. [Online] Disponible: https://dev.grakn.ai/docs/ query/overview

40 Anexo

.1. search_twitter.py

1 from searchtweets import ResultStream, gen_rule_payload, load_credentials, collect_results 2 import json 3 import csv 4 5 ’’’ 6 Se cargan las credenciales necesarias para 7 realizar las llamadas premium. Para cambiar 8 entre distintos endpoints, hay que modificar 9 el campo yaml_key. 10 ’’’ 11 premium_search_args = load_credentials("twitter_credentials.yaml", yaml_key=" fullarchive_search_api", env_overwrite=False) 12 13 teamsFile = open(’teams.csv’, ’a’) 14 teamsWriter = csv.writer(teamsFile) 15 16 with open("organizadores.json", "r") as org: 17 organizadores = json.load(org) 18 19 for orgs in organizadores[’organizadores’]: 20 21 ’’’ Rule para 30-day endpoint ’’’ 22 # rule = gen_rule_payload("equipos from:" + orgs) 23 24 ’’’ Rule para Full Archive endpoint ’’’ 25 rule = gen_rule_payload("equipos from:" + orgs, from_date="2019-12-01", to_date=" 2020-05-25", results_per_call=100) 26 27 ’’’ El ResultStream se utiliza necesariamente para 30-day ’’’ 28 # rs = ResultStream(rule_payload=rule, max_results=100, **premium_search_args) 29 30 ’’’ collect_results se utiliza necesariamente para Full Archive ’’’ 31 tweets = collect_results(rule, max_results=100, result_stream_args=premium_search_args ) 32 33 ’’’ rs = ResultStream. Utilizar esta entrada de bucle para 30-day ’’’ 34 # for tweet in rs.stream(): 35 36 ’’’ Esta entrada de bucle se utiliza para Full Archive ’’’ 37 for tweet in tweets: 38 39 ’’’ 40 Para tener todos los campos del objeto Tweet 41 json.dump(tweet, f) 42 f.write(’\n’) 43 ’’’ 44 45 id_str = tweet[’user’][’id_str’] 46 name = tweet[’user’][’name’] 47 screen_name = tweet[’user’][’screen_name’]

41 .2. get_players.py

48 ’’’ 49 Dependiendo del tamaño del tweet hay unos campos u otros. 50 Si el tweet es menor a 140 caracteres, no recibimos el 51 campo ’extended_tweet’. Se puede consultar el campo ’truncated’ 52 para saber si es un tweet extendido o no. 53 truncated == False. Tweet NO extendido. 54 truncated == True. Tweet extendido. 55 ’’’ 56 if tweet[’truncated’] == False: 57 user_mentions = tweet[’entities’][’user_mentions’] 58 else: 59 user_mentions = tweet[’extended_tweet’][’entities’][’user_mentions’] 60 ’’’ 61 Puede suceder que no haya usuarios mencionados en el tweet, 62 en ese caso simplemente desechamos el tweet. 63 ’’’ 64 if user_mentions: 65 for user in user_mentions: 66 teamsWriter.writerow([id_str, name, screen_name, user[’id_str’ ], user[’name’], user[’screen_name’]]) 67 else: 68 pass 69 70 teamsFile.close()

.2. get_players.py

1 import tweepy 2 import json 3 import csv 4 5 with open("twitter_credentials.json", "r") as file: 6 creds = json.load(file) 7 with open("keywords_players.json", "r") as kfile: 8 kwords = json.load(kfile) 9 10 auth = tweepy.OAuthHandler(creds[’CONSUMER_KEY’], creds[’CONSUMER_SECRET’]) 11 auth.set_access_token(creds[’ACCESS_TOKEN’], creds[’ACCESS_SECRET’]) 12 13 teamsFile = open(’teams_without_dup.csv’, ’r’) 14 playerFile = open(’players.csv’, ’a’) 15 teamsReader = csv.reader(teamsFile) 16 playersWriter = csv.writer(playerFile) 17 18 user_objs = [] 19 api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) 20 21 for row in teamsReader: 22 if row[6] == ’user_screen_name’: continue 23 24 for word in kwords[’keywords’]: 25 query = word+’’+row[6] + ’ -ex -former -coach’ 26 for page in tweepy.Cursor(api.search_users, q=query).pages(): 27 for user_objs in page: 28 29 id_str = user_objs._json[’id_str’] 30 name = user_objs._json[’name’] 31 screen_name = user_objs._json[’screen_name’] 32 playersWriter.writerow([row[6], id_str, name, screen_name]) 33 34 playerFile.close() 35 teamsFile.close()

42 BIBLIOGRAFÍA

.3. get_streamers.py

1 import tweepy 2 import json 3 import csv 4 5 with open("twitter_credentials.json", "r") as file: 6 creds = json.load(file) 7 with open("keywords_streamers.json", "r") as kfile: 8 kwords = json.load(kfile) 9 10 auth = tweepy.OAuthHandler(creds[’CONSUMER_KEY’], creds[’CONSUMER_SECRET’]) 11 auth.set_access_token(creds[’ACCESS_TOKEN’], creds[’ACCESS_SECRET’]) 12 13 teamsFile = open(’just_teams.csv’, ’r’) 14 streamerFile = open(’streamers.csv’, ’a’) 15 teamsReader = csv.reader(teamsFile) 16 streamerWriter = csv.writer(streamerFile) 17 18 user_objs = [] 19 api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) 20 21 for row in teamsReader: 22 if row[2] == ’team_screen_name’: continue 23 24 for word in kwords[’keywords’]: 25 query = word+’’+row[2] + ’ -player -jugador -jugadora -coach’ 26 for page in tweepy.Cursor(api.search_users, q=query).pages(): 27 for user_objs in page: 28 29 id_str = user_objs._json[’id_str’] 30 name = user_objs._json[’name’] 31 screen_name = user_objs._json[’screen_name’] 32 streamerWriter.writerow([row[2], id_str, name, screen_name]) 33 34 streamerFile.close() 35 teamsFile.close()

.4. migrate.py

1 from grakn.client import GraknClient 2 import csv 3 4 def build_esports_graph(inputs): 5 with GraknClient(uri="localhost:48555") as client: 6 with client.session(keyspace = "esports_v2") as session: 7 for input in inputs: 8 print("Cargando desde [" + input["data_path"] + "] en Grakn... ") 9 load_data_into_grakn(input, session) 10 11 def load_data_into_grakn(input, session): 12 items = parse_data_to_dictonaries(input) 13 14 for item in items: 15 with session.transaction().write() as transaction: 16 graql_insert_query = input["template"](item) 17 print("Ejecutando Grakn Query: " + graql_insert_query) 18 transaction.query(graql_insert_query) 19 transaction.commit() 20 print("\nInsertados " + str(len(items)) + " items desde["+input["data_path"] + "] en Grakn. \n") 21

43 .4. migrate.py

22 def teams_template(team): 23 return ’insert $equipo isa equipo, has nombre "’ + team["team_screen_name"] + ’";’ 24 25 def players_template(player): 26 return ’insert $jugador isa jugador, has nombre "’ + player["player_screen_name"] + ’ ";’ 27 28 def orgs_template(orgs): 29 return ’insert $org isa organizador, has nombre "’ + orgs["org_screen_name"] + ’";’ 30 31 def streamer_template(streamer): 32 return ’insert $streamer isa creador, has nombre "’ + streamer["streamer_screen_name"] + ’";’ 33 34 def empleo_template(empleo): 35 graql_insert_query = ’match $equipo isa equipo, has nombre "’ + empleo[" team_screen_name"] + ’";’ 36 graql_insert_query += ’ $jugador isa jugador, has nombre "’ + empleo[" player_screen_name"] +’";’ 37 graql_insert_query += ’ insert (team: $equipo, player: $jugador) isa empleo_jugadores; ’ 38 return graql_insert_query 39 40 def creador_template(empleo): 41 graql_insert_query = ’match $equipo isa equipo, has nombre "’ + empleo[" team_screen_name"] + ’";’ 42 graql_insert_query += ’ $creador isa creador, has nombre "’ + empleo[" streamer_screen_name"] +’";’ 43 graql_insert_query += ’ insert (team: $equipo, streamer: $creador) isa empleo_creadores;’ 44 return graql_insert_query 45 46 def liga_template(liga): 47 graql_insert_query = ’match $equipo isa equipo, has nombre "’ + liga["team_screen_name "] + ’";’ 48 graql_insert_query += ’ $org isa organizador, has nombre "’ + liga["org_screen_name"] +’";’ 49 graql_insert_query += ’ insert (participante: $equipo, org: $org) isa liga;’ 50 return graql_insert_query 51 52 def parse_data_to_dictonaries(input): 53 items = [] 54 with open(input["data_path"] + ".csv") as data: 55 for row in csv.DictReader(data, skipinitialspace = True): 56 item = { key: value for key, value in row.items() } 57 items.append(item) 58 return items 59 60 inputs = [ 61 { 62 "data_path": "./just_teams", 63 "template": teams_template 64 }, 65 { 66 "data_path": "./players_without_dup", 67 "template": players_template 68 }, 69 { 70 "data_path": "./orgs_without_dup", 71 "template": orgs_template 72 }, 73 { 74 "data_path": "./streamers_without_dup", 75 "template": streamer_template 76 }, 77 { 78 "data_path": "./players_without_dup", 79 "template": empleo_template 80 }, 81 {

44 BIBLIOGRAFÍA

82 "data_path": "./orgs_teams", 83 "template": liga_template 84 }, 85 { 86 "data_path": "./streamers_without_dup", 87 "template": creador_template 88 } 89 ] 90 91 build_esports_graph(inputs=inputs)

45 Este documento esta firmado por Firmante CN=tfgm.fi.upm.es, OU=CCFI, O=Facultad de Informatica - UPM, C=ES Fecha/Hora Sat Jun 06 10:36:03 CEST 2020 Emisor del [email protected], CN=CA Facultad de Certificado Informatica, O=Facultad de Informatica - UPM, C=ES Numero de Serie 630 Metodo urn:adobe.com:Adobe.PPKLite:adbe.pkcs7.sha1 (Adobe Signature)