Upgrade to Pro — share decks privately, control downloads, hide ads and more …

League of Graphs \w Neo4j

League of Graphs \w Neo4j

In this show-and-tell session we’ll find out how Neo4j can make us a professional League of Legends player. First, we’ll import game data into a Neo4j graph. Then we will push the limits of Cypher to uncover hidden secrets that lie in the depth of LoL.
• Which champions perform best as allies?
• What is the most effective strategy to advance your champion?
• What enemy team setup is the most dangerous?
This session covers a rarely seen graph domain (gaming) and will provide you will solid, factual advice on how to play LoL.

https://github.com/FylmTM/league-of-legends-research

Dmitrijs Vrublevskis

May 26, 2016
Tweet

More Decks by Dmitrijs Vrublevskis

Other Decks in Programming

Transcript

  1. Neueda4j / awesome-neo4j {75 ̣} A curated list of Neo4j

    resources. Neueda4j / jetbrains-plugin-cypher {24 ̣} Cypher plugin for Jetbrains IDE’s. ? / ? {? ̣} Next awesome project!
  2. Winner? League of Legends “Poros are the mysterious, magical and

    most-loved inhabitants originating from the Howling Abyss.”
  3. League of Legends is multiplayer online battle arena, real-time strategy

    video game developed and published by Riot Games
  4. League of Legends? 1. I play this game a lot

    2. Rich API 3. There is library for API https://developer.riotgames.com
  5. meraki-analytics/Orianna A Java adaptation of the Riot Games LoL API

    Summoner summoner = RiotAPI.getSummonerByName(“FylmTM"); 
 println(summoner.getName() + " is a level “ + summoner.getLevel());
  6. Neo4j Highly scalable native graph database that leverages data relationships

    as 
 first-class entities. by Neo Technology, Inc.
  7. Features Native Processing & Storage ACID Cypher - Graph Query

    Language REST & Native API Lock Manager High-performance cache Clustering Backups Monitoring Community Enterprise
  8. “Native” processing Efficient way of processing graph data since connected

    nodes physically “point” to each other a.k.a. “index-free adjacency”
  9. Storage layout Node (15 bytes) in_use next_rel_id next_prop_id labels extra

    Relationship (34 bytes) directed | in_use first_node second_node rel_type first_prev_rel_id first_next_rel_id second_prev_rel_id second_next_rel_id next_prop_id first_in_chain_markers
  10. Traversal (Node -> Relationship) {5} Node (15 bytes) next_rel_id {2}

    {<int>} - entity id <int>B - offset Relationships (34 bytes) {0} 2 * 34 = 68 0B {1} 34B {2} 68B {3} 102B {4} 136B {5} 170B
  11. Traversal (Relationship -> Node) {2} Relationship (34 bytes) {<int>} -

    entity id <int>B - offset Nodes (15 bytes) {0} 0B {1} 15B {2} 30B {3} 45B {4} 60B {5} 75B first_node {1} second_node {4}
  12. Cypher Cypher is a declarative graph query language that allows

    for expressive and efficient querying. https://github.com/opencypher/openCypher
  13. Cypher ( ) - node --> - relationship Keywords: -

    MATCH - CREATE - WHERE - RETURN MATCH (jug) RETURN jug MATCH (attendees)-->(jug) 
 RETURN * MATCH (attendees)-->(jug) WHERE jug.city = “Kaunas”
 RETURN *
  14. CREATE (alice:Person {name: "Alice"})
 CREATE (bob:Person {name: "Bob"})
 CREATE (carol:Person

    {name: "Carol"})
 CREATE (iphone:Device {name: "iPhone"})
 
 CREATE (alice)-[:HAS]->(iphone)
 CREATE (bob)-[:WANTS]->(iphone)
 
 CREATE (alice)<-[:FOLLOWS]-(bob)
 CREATE (alice)-[:FOLLOWS]->(bob)
 CREATE (carol)-[:FOLLOWS]->(bob)
 
 CREATE (bob)<-[:AUTHOR]-(:Comment {text: "Thoughts?"})
 <-[:COMMENT]-(iphone)
 CREATE (carol)<-[:AUTHOR]-(:Comment {text: "<3 it"})
 <-[:COMMENT]-(iphone)
  15. Create database File dbDir = new File(databasePath); 
 GraphDatabaseService db

    = new GraphDatabaseFactory()
 .newEmbeddedDatabaseBuilder(dbDir)
 .newGraphDatabase();
  16. Load data Summoner summoner = RiotAPI.getSummonerByName(“FylmTM"); Node node = db.createNode();


    node.addLabel(Labels.Summoner);
 node.setProperty(KEY_ID, summoner.getID());
 node.setProperty(KEY_NAME, summoner.getName());
 node.setProperty(KEY_LEVEL, summoner.getLevel());
  17. neo4j-contrib/neo4j-apoc-procedures Awesome procedures for Neo4j 3.0 - codenamed "apoc" //

    examines the full graph to create the meta-graph
 CALL apoc.meta.graph(); Apoc was the technician and driver on board of the Nebuchadnezzar in the Matrix movie. He was killed by Cypher.
  18. Import result • Season 6, EUNE region • Players: me

    & 7 friends MATCH (n) RETURN count(n) as nodeCount nodeCount 336729
  19. Query #1 How many games I have played? MATCH (s:Summoner

    {name: "FylmTM"})
 MATCH (s)-[:PARTICIPATED|:PARTICIPATED_IN_MATCH]->(sMatch)
 RETURN count(sMatch); // 59 ms Count 110
  20. Query #2 Who are my friends? MATCH (s:Summoner {name: "FylmTM"})


    MATCH (s)-[:PARTICIPATED]-()-[:PARTICIPATED_IN_MATCH]
 ->(sMatch)<-
 [:PARTICIPATED_IN_MATCH]-()-[:PARTICIPATED]-(f)
 WITH f.name as friendName, count(f) as gamesTogether
 WHERE gamesTogether > 2
 RETURN friendName, gamesTogether
 ORDER BY gamesTogether DESC // 55 ms friendName gamesTogether Cryptael 107 Henua 28 Iger 11 XXpoMMou 10 yesCold 8 eskiuzi 3
  21. Query #3 Most dangerous champions? name total won lost %

    Alistar 7 1 6 86% Jax 12 3 9 75% LeBlanc 8 2 6 75% Dr. Mundo 7 2 5 71% Miss Fortune 10 3 7 70% MATCH (s:Summoner {name: "FylmTM"})
 MATCH (s)-[:PARTICIPATED]->()-[:PLAYED_FOR_TEAM]->
 (team {winner: true})<-[:HAS_TEAM]-()-[:HAS_TEAM]->(o)
 <-[:PLAYED_FOR_TEAM]-()-[:PARTICIPATED_WITH_CHAMPION]->(c)
 RETURN c.name as championName, count(c) as winCount
 ORDER BY winCount DESC
  22. Query #4 Any statistics? MATCH (s:Summoner) WHERE s.name IN ["MrMgr",

    "Cryptael"]
 MATCH (s)-[:PARTICIPATED|:PARTICIPANT_TIMELINE*2]->(pt)-[r]->(ptd)
 WHERE pt.role = "SOLO" AND pt.lane = "MIDDLE"
 AND r.name IN ["getCreepsPerMinDeltas", "getGoldPerMinDeltas"]
 WITH s.name as name, r.name as stat,
 sum(ptd.zero_to_ten) as `sum_0-10`,
 size(filter(x IN collect(ptd.zero_to_ten) WHERE x <> 0))
 as `size_0-10`,
 sum(ptd.ten_to_twenty) as `sum_10-20`,
 size(filter(x IN collect(ptd.ten_to_twenty) WHERE x <> 0))
 as `size_10-20`,
 sum(ptd.twenty_to_thirty) as `sum_20-30`,
 size(filter(x IN collect(ptd.twenty_to_thirty) WHERE x <> 0))
 as `size_20-30`,
 sum(ptd.thirty_to_end) as `sum_30+`,
 size(filter(x IN collect(ptd.thirty_to_end) WHERE x <> 0))
 as `size_30+`
 RETURN name, stat,
 `sum_0-10` / `size_0-10` as `0-10`,
 `sum_10-20` / `size_10-20` as `10-20`,
 `sum_20-30` / `size_20-30` as `20-30`,
 `sum_30+` / `size_30+` as `30+`
 ORDER BY name, stat
  23. creeps/min 0 2 4 6 8 0-10 10-20 20-30 30+

    Cryptael MrMgr gold/min 0 150 300 450 600 0-10 10-20 20-30 30+ Cryptael MrMgr Cryptael MrMgr (#27 in EUNE)
  24. Takeaways • Neo4j is easy to use • Build schema

    on the fly • Cypher is a handy tool for exploration • Find value in your data