{
  "nbformat_minor": 0, 
  "nbformat": 4, 
  "cells": [
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "%matplotlib inline"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }, 
    {
      "source": [
        "\n# Chess Masters\n\n\nAn example of the MultiDiGraph clas\n\nThe function chess_pgn_graph reads a collection of chess matches stored in the\nspecified PGN file (PGN =\"Portable Game Notation\").  Here the (compressed)\ndefault file::\n\n    chess_masters_WCC.pgn.bz2\n\ncontains all 685 World Chess Championship matches from 1886--1985.\n(data from http://chessproblem.my-free-games.com/chess/games/Download-PGN.php)\n\nThe `chess_pgn_graph()` function returns a `MultiDiGraph` with multiple edges.\nEach node is the last name of a chess master. Each edge is directed from white\nto black and contains selected game info.\n\nThe key statement in `chess_pgn_graph` below is::\n\n    G.add_edge(white, black, game_info)\n\nwhere `game_info` is a `dict` describing each game.\n\n"
      ], 
      "cell_type": "markdown", 
      "metadata": {}
    }, 
    {
      "execution_count": null, 
      "cell_type": "code", 
      "source": [
        "#    Copyright (C) 2006-2017 by\n#    Aric Hagberg <hagberg@lanl.gov>\n#    Dan Schult <dschult@colgate.edu>\n#    Pieter Swart <swart@lanl.gov>\n#    All rights reserved.\n#    BSD license.\n\nimport matplotlib.pyplot as plt\nimport networkx as nx\n\n# tag names specifying what game info should be\n# stored in the dict on each digraph edge\ngame_details = [\"Event\",\n                \"Date\",\n                \"Result\",\n                \"ECO\",\n                \"Site\"]\n\n\ndef chess_pgn_graph(pgn_file=\"chess_masters_WCC.pgn.bz2\"):\n    \"\"\"Read chess games in pgn format in pgn_file.\n\n    Filenames ending in .gz or .bz2 will be uncompressed.\n\n    Return the MultiDiGraph of players connected by a chess game.\n    Edges contain game data in a dict.\n\n    \"\"\"\n    import bz2\n    G = nx.MultiDiGraph()\n    game = {}\n    datafile = bz2.BZ2File(pgn_file)\n    lines = (line.decode().rstrip('\\r\\n') for line in datafile)\n    for line in lines:\n        if line.startswith('['):\n            tag, value = line[1:-1].split(' ', 1)\n            game[str(tag)] = value.strip('\"')\n        else:\n            # empty line after tag set indicates\n            # we finished reading game info\n            if game:\n                white = game.pop('White')\n                black = game.pop('Black')\n                G.add_edge(white, black, **game)\n                game = {}\n    return G\n\n\nif __name__ == '__main__':\n    G = chess_pgn_graph()\n\n    ngames = G.number_of_edges()\n    nplayers = G.number_of_nodes()\n\n    print(\"Loaded %d chess games between %d players\\n\"\n          % (ngames, nplayers))\n\n    # identify connected components\n    # of the undirected version\n    Gcc = list(nx.connected_component_subgraphs(G.to_undirected()))\n    if len(Gcc) > 1:\n        print(\"Note the disconnected component consisting of:\")\n        print(Gcc[1].nodes())\n\n    # find all games with B97 opening (as described in ECO)\n    openings = set([game_info['ECO']\n                    for (white, black, game_info) in G.edges(data=True)])\n    print(\"\\nFrom a total of %d different openings,\" % len(openings))\n    print('the following games used the Sicilian opening')\n    print('with the Najdorff 7...Qb6 \"Poisoned Pawn\" variation.\\n')\n\n    for (white, black, game_info) in G.edges(data=True):\n        if game_info['ECO'] == 'B97':\n            print(white, \"vs\", black)\n            for k, v in game_info.items():\n                print(\"   \", k, \": \", v)\n            print(\"\\n\")\n\n    # make new undirected graph H without multi-edges\n    H = nx.Graph(G)\n\n    # edge width is proportional number of games played\n    edgewidth = []\n    for (u, v, d) in H.edges(data=True):\n        edgewidth.append(len(G.get_edge_data(u, v)))\n\n    # node size is proportional to number of games won\n    wins = dict.fromkeys(G.nodes(), 0.0)\n    for (u, v, d) in G.edges(data=True):\n        r = d['Result'].split('-')\n        if r[0] == '1':\n            wins[u] += 1.0\n        elif r[0] == '1/2':\n            wins[u] += 0.5\n            wins[v] += 0.5\n        else:\n            wins[v] += 1.0\n    try:\n        pos = nx.nx_agraph.graphviz_layout(H)\n    except:\n        pos = nx.spring_layout(H, iterations=20)\n\n    plt.rcParams['text.usetex'] = False\n    plt.figure(figsize=(8, 8))\n    nx.draw_networkx_edges(H, pos, alpha=0.3, width=edgewidth, edge_color='m')\n    nodesize = [wins[v] * 50 for v in H]\n    nx.draw_networkx_nodes(H, pos, node_size=nodesize, node_color='w', alpha=0.4)\n    nx.draw_networkx_edges(H, pos, alpha=0.4, node_size=0, width=1, edge_color='k')\n    nx.draw_networkx_labels(H, pos, fontsize=14)\n    font = {'fontname': 'Helvetica',\n            'color': 'k',\n            'fontweight': 'bold',\n            'fontsize': 14}\n    plt.title(\"World Chess Championship Games: 1886 - 1985\", font)\n\n    # change font and write text (using data coordinates)\n    font = {'fontname': 'Helvetica',\n            'color': 'r',\n            'fontweight': 'bold',\n            'fontsize': 14}\n\n    plt.text(0.5, 0.97, \"edge width = # games played\",\n             horizontalalignment='center',\n             transform=plt.gca().transAxes)\n    plt.text(0.5, 0.94, \"node size = # games won\",\n             horizontalalignment='center',\n             transform=plt.gca().transAxes)\n\n    plt.axis('off')\n    plt.show()"
      ], 
      "outputs": [], 
      "metadata": {
        "collapsed": false
      }
    }
  ], 
  "metadata": {
    "kernelspec": {
      "display_name": "Python 2", 
      "name": "python2", 
      "language": "python"
    }, 
    "language_info": {
      "mimetype": "text/x-python", 
      "nbconvert_exporter": "python", 
      "name": "python", 
      "file_extension": ".py", 
      "version": "2.7.12", 
      "pygments_lexer": "ipython2", 
      "codemirror_mode": {
        "version": 2, 
        "name": "ipython"
      }
    }
  }
}