maestro-server/analytics-maestro

View on GitHub
nootebooks/Grid - WorkFlow.ipynb

Summary

Maintainability
Test Coverage
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 352,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.618173Z",
     "start_time": "2018-10-29T00:48:11.614402Z"
    }
   },
   "outputs": [],
   "source": [
    "import networkx as nx\n",
    "import requests\n",
    "import json\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "url = '10.168.20.20:5010'\n",
    "entries = ['5b68a0ecea0637002f6a4e34', '5b97f3583cdad83c6c25aa56']\n",
    "rolesa = '5b688de7ea0637002f6a4e30'\n",
    "\n",
    "# If You like to test, can put url of data app and any entry app\n",
    "url = 'localhost:5010'\n",
    "entries = ['5bc8c4f839f34a229d490b76', '5bc8c4e939f34a229d490b73', '5bc8c4f039f34a229d490b74', '5bc8c4f439f34a229d490b75']\n",
    "rolesa = '593f49be42d3ed97390f25a7'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Execute GraphLookUp (MongoDB)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 353,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.651838Z",
     "start_time": "2018-10-29T00:48:11.620983Z"
    }
   },
   "outputs": [],
   "source": [
    "pipeline = [\n",
    "    {'$match': {'_id': {'$in': entries}, 'roles._id': rolesa}},\n",
    "    {\n",
    "        '$graphLookup': {\n",
    "            'from': 'applications',\n",
    "            'startWith': '$deps._id',\n",
    "            'connectFromField': 'deps._id',\n",
    "            'connectToField': '_id',\n",
    "            'as': 'nodes',\n",
    "            'maxDepth': 40,\n",
    "            'depthField': 'steps'\n",
    "        }\n",
    "    },\n",
    "    {'$project': {\n",
    "                    'name': 1, \n",
    "                    'family': 1,\n",
    "                    'environment': 1,\n",
    "                    'cluster': 1,\n",
    "                    'language': 1,\n",
    "                    'servers': 1,\n",
    "                    'datacenters': 1,\n",
    "                    'size': 1,\n",
    "                    'deps._id': 1, \n",
    "                    'deps.endpoint': 1, \n",
    "                    'nodes._id': 1, \n",
    "                    'nodes.deps': 1, \n",
    "                    'nodes.name': 1,\n",
    "                    'nodes.steps': 1,\n",
    "                    'nodes.family': 1,\n",
    "                    'nodes.environment': 1,\n",
    "                    'nodes.cluster': 1,\n",
    "                    'nodes.language': 1,\n",
    "                    'nodes.servers': 1,\n",
    "                    'nodes.system': 1,\n",
    "                    'nodes.datacenters': 1,\n",
    "                    'nodes.size': 1\n",
    "                }\n",
    "    }\n",
    "];\n",
    "\n",
    "jpipeline = json.dumps(pipeline)\n",
    "\n",
    "data = requests.post('http://%s/aggregate' % url, json={'entity': 'applications', 'pipeline': jpipeline})\n",
    "data = data.json()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 354,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.664925Z",
     "start_time": "2018-10-29T00:48:11.654184Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<networkx.classes.digraph.DiGraph at 0x108024da0>"
      ]
     },
     "execution_count": 354,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "class BaseNetwork(object):\n",
    "    def __init__(self, G=nx.DiGraph):\n",
    "        self.graph = G()\n",
    "        self.clear_duplicate()\n",
    "\n",
    "    def create_edge(self, item):\n",
    "        if 'deps' in item:\n",
    "            for dps in item['deps']:\n",
    "                w = item.get('steps', -1)\n",
    "                endpoint = dps.get('endpoint')\n",
    "                self.graph.add_edge(item['_id'], dps['_id'], weight=w+1, endpoint=endpoint)\n",
    "\n",
    "    def create_node(self, node_id, item, root = False):\n",
    "        if node_id not in self.duplicate:\n",
    "            self.graph.add_node(str(node_id), uid=item.get('_id'), root=root, attr=item)\n",
    "            self.duplicate.append(node_id)\n",
    "\n",
    "    def make(self, data, i=0):\n",
    "        for item in data:\n",
    "            self.create_node(item['_id'], item, i is 0)\n",
    "\n",
    "            if 'nodes' in item and len(item['nodes']) > 0:\n",
    "                self.make(item['nodes'], i + 1)\n",
    "\n",
    "            self.create_edge(item)\n",
    "\n",
    "        self.clear_duplicate()\n",
    "        return self\n",
    "\n",
    "    def get_graph(self):\n",
    "        return self.graph\n",
    "\n",
    "    def get_density(self):\n",
    "        return nx.density(self.graph)\n",
    "\n",
    "    def clear_duplicate(self):\n",
    "        self.duplicate = []\n",
    "    \n",
    "\n",
    "\n",
    "network = BaseNetwork()\n",
    "network.make(data.get('items')).get_graph()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 355,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.838195Z",
     "start_time": "2018-10-29T00:48:11.668139Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "class DrawNetwork(object):\n",
    "\n",
    "    def __init__(self, G):\n",
    "        self.graph = G\n",
    "        \n",
    "    def get_cardials(self):\n",
    "        return nx.circular_layout(self.graph)\n",
    "    \n",
    "    \n",
    "    def save_svg(self, options, labels):\n",
    "        #plt.figure(figsize=(4, 4))\n",
    "        pos = self.get_cardials()\n",
    "\n",
    "        nx.draw(self.graph, pos, **options)\n",
    "\n",
    "        labels = nx.get_edge_attributes(self.graph,'weight')\n",
    "        nx.draw_networkx_edge_labels(self.graph,pos,edge_labels=labels)\n",
    "\n",
    "        plt.axis('equal')\n",
    "        plt.show()\n",
    "    \n",
    "options = {\n",
    "    'with_labels': True,\n",
    "    'arrowsize': 15,\n",
    "    'node_shape': 's',\n",
    "    'node_size': 500,\n",
    "    'node_color': '#782675',\n",
    "    'font_color': 'white',\n",
    "    'alpha': 0.9,\n",
    "    'linewidths': 5\n",
    "}\n",
    "\n",
    "labels = {\n",
    "    'font_weight': 'bold'\n",
    "}\n",
    "\n",
    "draw = DrawNetwork(network.graph)\n",
    "draw.save_svg(options, labels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 356,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.843216Z",
     "start_time": "2018-10-29T00:48:11.840314Z"
    }
   },
   "outputs": [],
   "source": [
    "G=network.graph\n",
    "#nei = list(network.graph.neighbors('app1'))\n",
    "#print(nei)\n",
    "\n",
    "#network.graph.degree['app1']\n",
    "\n",
    "#G.out_degree('app1')\n",
    "#G.in_degree('app1')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 357,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.850421Z",
     "start_time": "2018-10-29T00:48:11.845767Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'5bc8c4e939f34a229d490b73': 0.25, '5bc8c4f439f34a229d490b75': 0.25, '5bc8c4f039f34a229d490b74': 0.25, '5bc8c4f839f34a229d490b76': 0.25}\n",
      "0.16666666666666666\n"
     ]
    }
   ],
   "source": [
    "pagerank = nx.pagerank(G, alpha=0.9)\n",
    "print(pagerank)\n",
    "\n",
    "density = nx.density(G)\n",
    "print(density)\n",
    "\n",
    "hist = nx.degree_histogram(G)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 358,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.865673Z",
     "start_time": "2018-10-29T00:48:11.852638Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{1: 2, None: 2}"
      ]
     },
     "execution_count": 358,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import collections\n",
    "\n",
    "class Histogram(object):\n",
    "    def __init__(self):\n",
    "        self._hist = None\n",
    "\n",
    "    def set_collections(self, data):\n",
    "        self._hist = collections.Counter(data)\n",
    "        return self\n",
    "\n",
    "    def get_counter(self):\n",
    "        return dict(self._hist)\n",
    "\n",
    "    def max_columm(self):\n",
    "        if self._hist != None:\n",
    "            return self._hist.most_common(1)[0]\n",
    "\n",
    "    def max_value(self):\n",
    "        n = self.max_columm()\n",
    "        if n:\n",
    "            return n[1]  \n",
    "    \n",
    "class GridHistogram(Histogram):\n",
    "    def __init__(self, grid):\n",
    "        super().__init__()\n",
    "        self._grid = grid\n",
    "        self.make()\n",
    "    \n",
    "    def make(self):\n",
    "        clear = {}\n",
    "        \n",
    "        for key, value in self._grid.items():\n",
    "            clear[key] = len(value)\n",
    "   \n",
    "        self.set_collections(clear)\n",
    "        \n",
    "class GraphHistogram(Histogram):\n",
    "    \n",
    "    def __init__(self, G):\n",
    "        super().__init__()\n",
    "        self._graph = G\n",
    "        self.make()\n",
    "    \n",
    "    def find_weight(self, item, weight=0):\n",
    "        weight = self._graph.nodes[item].get('weight')\n",
    "        \n",
    "        if not weight:\n",
    "            pred = self._graph.in_edges(item, data=True)\n",
    "\n",
    "            if pred and len(list(pred)) > 0:\n",
    "                weight = max([it[2].get('weight') for it in pred]) + 1\n",
    "        \n",
    "        return weight\n",
    "\n",
    "    def make(self):\n",
    "        nodes = self._graph.nodes()\n",
    "        weights = []\n",
    "        \n",
    "        for node in nodes:\n",
    "            w = self.find_weight(node)\n",
    "            weights.append(w)\n",
    "    \n",
    "        self.set_collections(weights)\n",
    " \n",
    "        \n",
    "GraphHistogram(G).get_counter()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 359,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.894707Z",
     "start_time": "2018-10-29T00:48:11.868092Z"
    }
   },
   "outputs": [],
   "source": [
    "from svgwrite import Drawing\n",
    "\n",
    "class DefsSVG(object):\n",
    "    \n",
    "    def __init__(self, draw):\n",
    "        self.dwg = draw\n",
    "\n",
    "    def app(self, pos, title, size=(20,20), unit=\"px\"):\n",
    "        opts = {\n",
    "            'size': (\"%s%s\"%(size[0], unit), \"%s%s\"%(size[1], unit)),\n",
    "            'stroke_width': \"1\",\n",
    "            'stroke': \"black\",\n",
    "            'fill': \"rgb(255,255,0)\"\n",
    "        }\n",
    "        \n",
    "        self.add(self.dwg.rect(insert = pos, **opts))\n",
    "        self.add(self.dwg.text(title, insert=(pos[0], pos[1]+10), fill='red'))\n",
    "    \n",
    "    def line(self, cx, cy):\n",
    "        opts = {\n",
    "            'stroke_width': \"1\",\n",
    "            'stroke': \"black\",\n",
    "            'fill': \"rgb(0,0,0)\"\n",
    "        }\n",
    "        \n",
    "        self.add(self.dwg.line(start=cx, end=cy, **opts))\n",
    "    \n",
    "    def add(self, svg):\n",
    "        self.dwg.add(svg)\n",
    "        \n",
    "class DrawArea(object):\n",
    "    def __init__(self, off, size, hist, nmax):\n",
    "        self._off = off\n",
    "        self._size = size\n",
    "        self._hist = hist\n",
    "        self._nmax = nmax\n",
    "        \n",
    "    def cal_area(self, n, pointer):\n",
    "        return (n * self._size[pointer]) + (n * self._off[pointer])\n",
    "    \n",
    "    def area(self):\n",
    "        area_y = self.cal_area(self._nmax, 1)\n",
    "        area_x = self.cal_area(max(self._hist, key=int) + 1, 1)\n",
    "        return (area_x, area_y)\n",
    "    \n",
    "class DrawSVG(object):\n",
    "    def __init__(self, hist, nmax, darea=DrawArea, draw=Drawing, defs=DefsSVG):\n",
    "        self._off = (40, 40)\n",
    "        self._size = (20, 20)\n",
    "    \n",
    "        self._hist = hist\n",
    "        self._nmax = nmax\n",
    "        \n",
    "        self._area = darea(self._off, self._size, hist, nmax).area()\n",
    "        \n",
    "        self.dwg = Drawing('test.svg', size=self._area)\n",
    "        self._grid_defs = defs(self.dwg)\n",
    "    \n",
    "    def draw_app(self, pos, w, label):\n",
    "        pos = self.cal_off(pos, w)\n",
    "        self._grid_defs.app(pos, label, self._size)\n",
    "    \n",
    "    def draw_connect(self, pos1, pos2, w1, w2):\n",
    "        pos1 = self.cal_pos_line(pos1, w1, self._size[0])\n",
    "        pos2 = self.cal_pos_line(pos2, w2)\n",
    "        \n",
    "        self._grid_defs.line(pos1, pos2)\n",
    "   \n",
    "    def cal_off(self, pos, w):\n",
    "        x = self.cal_offx(pos[0], w)\n",
    "        y = self.cal_offy(pos[1], w)\n",
    "        \n",
    "        return (x, y)\n",
    "        \n",
    "    def cal_offy(self, y, w):  \n",
    "        off = 0\n",
    "        #if self._hist[w] < self._nmax:\n",
    "        #    off = (self._nmax - self._hist[w]) / 2\n",
    "        #    off = off * (self._off[1] + self._size[1])\n",
    "        \n",
    "        return (y * self._off[1]) + (y * self._size[1]) + off \n",
    "    \n",
    "    def cal_offx(self, x, w):\n",
    "        return (x * self._off[0]) + (x * self._size[0])\n",
    "    \n",
    "    def cal_pos_line(self, pos, w, suff_x=0):\n",
    "        apos = self.cal_off(pos, w)\n",
    "        y = apos[1] + (self._size[1]/2)\n",
    "        x = apos[0] + suff_x\n",
    "        \n",
    "        return (x, y)\n",
    "    \n",
    "    def save(self):\n",
    "        self.dwg.save()\n",
    "        \n",
    "class DrawLayout(object):\n",
    "    def __init__(self, grid, index, gridhist=GridHistogram, draw=DrawSVG):\n",
    "        \n",
    "        self._grid = grid\n",
    "        self._index = index\n",
    "        \n",
    "        GridHistogram = gridhist(self._grid)\n",
    "        self._nmax = GridHistogram.max_value()\n",
    "        self._hist = GridHistogram.get_counter()\n",
    "        \n",
    "   \n",
    "        self.drawer = draw(self._hist, self._nmax)\n",
    "\n",
    "    def draw_nodes(self):\n",
    "        data = self._grid\n",
    "        for col_k, columm in data.items():\n",
    "            for line_k, label in columm.items():\n",
    "                if label in self._index:\n",
    "                    item = self._index[label]\n",
    "                    label = item[3].get('name')\n",
    "                self.drawer.draw_app((col_k, line_k), col_k, label)\n",
    "        \n",
    "        return self\n",
    "    \n",
    "    def draw_connections(self, edges):\n",
    "        for edge in edges:\n",
    "            pos = []\n",
    "            w = []\n",
    "            \n",
    "            for i in range(2):\n",
    "                ipos = self._index[edge[i]]\n",
    "                pos.append(ipos)\n",
    "                w.append(ipos[0])\n",
    "\n",
    "            self.drawer.draw_connect(*pos, *w)\n",
    "            \n",
    "        return self \n",
    "    \n",
    "    def save(self):\n",
    "        self.drawer.save()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 360,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.914521Z",
     "start_time": "2018-10-29T00:48:11.898075Z"
    }
   },
   "outputs": [],
   "source": [
    "class Grid(object):\n",
    "    def __init__(self):\n",
    "        self.clean()\n",
    "        self._dmark = '-'\n",
    "\n",
    "    def get_grid(self):\n",
    "        return self._grid\n",
    "\n",
    "    def has_pos(self, x, y):\n",
    "        return (x in self._grid) and (y in self._grid[x])\n",
    "\n",
    "    def get_pos(self, x, y, deft=None):\n",
    "        if self.has_pos(x, y):\n",
    "            return self._grid[x][y]\n",
    "\n",
    "        return deft\n",
    "\n",
    "    def in_grid(self, step):\n",
    "        return step in self._grid\n",
    "\n",
    "    def not_in_grid(self, step):\n",
    "        return step not in self._grid\n",
    "\n",
    "    def max_y(self, step):\n",
    "        return max(self._grid[step], key=int)\n",
    "\n",
    "    def max_x(self):\n",
    "        return max(self._grid, key=int)\n",
    "\n",
    "    def _add_grid(self, x, y, item):\n",
    "        if x not in self._grid:\n",
    "            self._grid[x] = {}\n",
    "\n",
    "        self._grid[x][y] = item\n",
    "        return (x, y)\n",
    "\n",
    "    def del_grid(self, columm, line):\n",
    "        del self._grid[columm][line]\n",
    "\n",
    "    def clean(self):\n",
    "        self._grid = {}\n",
    "        self._index = {}\n",
    "        \n",
    "class GridMapSwift(object):\n",
    "    def make_swift(self, node, loc):\n",
    "        pos = self.get_index(node)\n",
    "        max_x = self.max_x()\n",
    "        diff = loc - pos[0]\n",
    "\n",
    "        for columm in range(max_x, pos[0] - 1, -1):\n",
    "            end = pos[1] + pos[2]\n",
    "\n",
    "            for line in range(pos[1], end):\n",
    "                self.swift_update_line(columm, line, diff)\n",
    "\n",
    "    def swift_update_line(self, columm, line, diff):\n",
    "        if line in self._grid[columm]:\n",
    "            ccnode = self.get_pos(columm, line)\n",
    "            self.del_grid(columm, line)\n",
    "\n",
    "            self.swift_update_node(ccnode, diff)\n",
    "\n",
    "    def swift_update_node(self, ccnode, diff):\n",
    "        if ccnode in self._index:\n",
    "            npos = self.get_index(ccnode)\n",
    "            self.del_item(ccnode)\n",
    "\n",
    "            self.create_position((npos[0]+diff, npos[1]), ccnode, npos[2], npos[3])\n",
    "\n",
    "class GridMapDummies(object):\n",
    "    def create_dummy(self, pos, tpl=''):\n",
    "        if not self.has_pos(*pos):\n",
    "            mark = \"%s%s\" % (self._dmark, tpl)\n",
    "            return self._add_grid(*pos, mark)\n",
    "    \n",
    "class GridMap(Grid, GridMapSwift, GridMapDummies):\n",
    "\n",
    "    def get_item_pos(self, item):\n",
    "        if item in self._index:\n",
    "            return self._index[item]\n",
    "\n",
    "    def get_index(self, item=None):\n",
    "        if item:\n",
    "            return self._index.get(item)\n",
    "\n",
    "        return self._index\n",
    "\n",
    "    def is_node(self, x, y):\n",
    "        mark = self.get_pos(x, y, self._dmark)\n",
    "        return mark[0] != self._dmark\n",
    "\n",
    "    def in_index(self, item):\n",
    "        return item in self._index\n",
    "\n",
    "    def create_position(self, pos, label, size=1, attr={}):\n",
    "        self.create_index(label, pos, size, attr)\n",
    "        return self._add_grid(*pos, label)\n",
    "\n",
    "    def create_index(self, label, pos, size, attr):\n",
    "        self._index[label] = (*pos, size, attr)\n",
    "        return pos, size\n",
    "\n",
    "    def inc_size_index(self, anode, qtd=1):\n",
    "        tmp = self.get_index(anode)\n",
    "        self.update_index(anode, (tmp[0], tmp[1]), tmp[2] + qtd, tmp[3])\n",
    "\n",
    "    def update_index(self, anode, pos, size, attr):\n",
    "        self.del_item(anode)\n",
    "        self.create_index(anode, pos, size, attr)\n",
    "\n",
    "    def del_item(self, anode):\n",
    "        del self._index[anode]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 361,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.955835Z",
     "start_time": "2018-10-29T00:48:11.916747Z"
    },
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "class HelperDefineStep(object):\n",
    "    def get_weight(self, node):\n",
    "        dft = self._graph.nodes[node].get('weight')\n",
    "        return self._get_weight(node, dft)\n",
    "\n",
    "    def _get_weight(self, node, dft=0):\n",
    "        if self._grid.in_index(node):\n",
    "            idx = self._grid.get_index(node)\n",
    "            return idx[0]\n",
    "\n",
    "        return dft\n",
    "\n",
    "    def get_node_attr(self, attr):\n",
    "        return self._node.get(attr)\n",
    "\n",
    "    def get_step(self):\n",
    "        return self._step\n",
    "\n",
    "    def make_step(self):\n",
    "        node = self.get_id()\n",
    "\n",
    "        if self._grid.in_index(node):\n",
    "            idx = self._grid.get_index(node)\n",
    "            return idx[0]\n",
    "\n",
    "        return self.cal_step()\n",
    "\n",
    "    def cal_step(self):\n",
    "        predecessors = self.direct_predecessors()\n",
    "        default_x = self.get_node_attr('weight')\n",
    "\n",
    "        if len(predecessors) > 0:\n",
    "            most = default_x\n",
    "\n",
    "            for pre in predecessors:\n",
    "                wn = self._get_weight(pre)\n",
    "                diff = wn - default_x\n",
    "\n",
    "                if most < wn:\n",
    "                    most = wn + 1\n",
    "\n",
    "            default_x = most\n",
    "        return default_x\n",
    "\n",
    "class HelperDefineSuccersPredecessors(object):\n",
    "    def successors(self):\n",
    "        return (self.only_direct_successors(), self.only_subdirect_successors())\n",
    "\n",
    "    def only_direct_successors(self):\n",
    "        self.categorize_successors()\n",
    "        return self._direct_succers\n",
    "\n",
    "    def only_subdirect_successors(self):\n",
    "        self.categorize_successors()\n",
    "        return self._subdirect_succers\n",
    "\n",
    "    def only_direct_not_drawed(self, cat='direct'):\n",
    "        self.categorize_successors()\n",
    "        return self._succers_not_drawing.get(cat)\n",
    "\n",
    "    def only_subdirect_not_drawed(self, cat='subdirect'):\n",
    "        self.categorize_successors()\n",
    "        return self._succers_not_drawing.get(cat)\n",
    "\n",
    "    def categorize_successors(self):\n",
    "        succers = set(self._graph.successors(self.get_id()))\n",
    "\n",
    "        if (len(succers) > 0) and (not self._direct_succers):\n",
    "            for node in succers:\n",
    "                wg = self.get_weight(node)\n",
    "\n",
    "                diff = wg - self._step\n",
    "                self.grab_direct_succers(diff, node)\n",
    "                self.grab_subdirect_succers(diff, node)\n",
    "\n",
    "    def grab_direct_succers(self, diff, node):\n",
    "        if (diff <= 1) and (node not in self._direct_succers):\n",
    "            self._direct_succers.append(node)\n",
    "            self.grab_not_drawing(node, 'direct')\n",
    "\n",
    "    def grab_subdirect_succers(self, diff, node):\n",
    "        if (diff > 1) and (node not in self._subdirect_succers):\n",
    "            self._subdirect_succers.append(node)\n",
    "            self.grab_not_drawing(node, 'subdirect')\n",
    "\n",
    "    def grab_not_drawing(self, node, var):\n",
    "        if not self._grid.in_index(node):\n",
    "            self._succers_not_drawing[var].append(node)\n",
    "\n",
    "    def direct_predecessors(self):\n",
    "        if not self._predecessors:\n",
    "            self._predecessors = set(self._graph.predecessors(self.get_id()))\n",
    "\n",
    "        return self._predecessors\n",
    "\n",
    "    def grab_drawed_predecers(self):\n",
    "        preds = self.direct_predecessors()\n",
    "        dpreds = []\n",
    "\n",
    "        if len(preds) > 0:\n",
    "            for node in preds:\n",
    "                if self._grid.in_index(node):\n",
    "                    dpreds.append(node)\n",
    "\n",
    "        return dpreds\n",
    "\n",
    "    def grab_predecessors(self, node):\n",
    "        return set(self._graph.predecessors(node))\n",
    "    \n",
    "class HelperDefineAttributes(HelperDefineStep, HelperDefineSuccersPredecessors):\n",
    "    def __init__(self, node, grid, G):\n",
    "        self._graph = G\n",
    "        self._node = node\n",
    "        self._grid = grid\n",
    "\n",
    "        self._direct_succers = []\n",
    "        self._subdirect_succers = []\n",
    "        self._predecessors = []\n",
    "\n",
    "        self._succers_not_drawing = {'direct': [], 'subdirect': []}\n",
    "\n",
    "        self._step = self.make_step()\n",
    "\n",
    "    def get_attrs(self):\n",
    "        return self.get_node_attr('attr')\n",
    "\n",
    "    def get_id(self):\n",
    "        return self.get_node_attr('uid')\n",
    "\n",
    "    \n",
    "class BasePattern(object):\n",
    "    def __init__(self, grid, Helper):\n",
    "        self._helper = Helper\n",
    "        self._grid = grid\n",
    "        self._step = self._helper.get_step()\n",
    "\n",
    "        self._options = {\n",
    "            'max_inter': 30,\n",
    "            'grow_mark': '-',\n",
    "            'force_mark': 'f'\n",
    "        }\n",
    "\n",
    "    def _default_y(self):\n",
    "        return self._max_empty_y(self._step)\n",
    "\n",
    "    def _max_empty_y(self, step):\n",
    "        if self._grid.not_in_grid(step):\n",
    "            return 0\n",
    "\n",
    "        return self._grid.max_y(step) + 1\n",
    "\n",
    "    def find_next_node(self, y1, y2, step):\n",
    "        found = False\n",
    "\n",
    "        for it in range(y2, y1 - 1, -1):\n",
    "            if self._grid.in_grid(step) and self._grid.is_node(step, it):\n",
    "                found = self._grid.get_pos(step, it)\n",
    "                break\n",
    "\n",
    "        return found\n",
    "\n",
    "class SinglePattern(object):\n",
    "    def set_position(self):\n",
    "        start_y = self._default_y()\n",
    "\n",
    "        attr = self._helper.get_attrs()\n",
    "        size = self.grow_node(start_y + 1)\n",
    "        attr['root'] = self._helper.get_node_attr('root')\n",
    "\n",
    "        self._grid.create_position((self._step, start_y), self._helper.get_id(), size, attr)\n",
    "\n",
    "    def grow_node(self, start_y):\n",
    "        size = 1\n",
    "        succers = self._helper.only_direct_not_drawed()\n",
    "        succers_size = len(succers)\n",
    "\n",
    "        succers_size += self.chess_horse_growing(succers_size)\n",
    "\n",
    "        if (succers_size >= 2):\n",
    "\n",
    "            for ps in range(succers_size - 1):\n",
    "                nps = (self._step, start_y + ps)\n",
    "                self._grid.create_dummy(nps, self._options.get('grow_mark'))\n",
    "\n",
    "            size = succers_size\n",
    "\n",
    "        return size\n",
    "\n",
    "    def chess_horse_growing(self, succers_size):\n",
    "        subsuccers = self._helper.only_subdirect_successors()\n",
    "        subdirect = len(subsuccers)\n",
    "\n",
    "        sm = 0\n",
    "        sm += 1 if subdirect >= 1 else 0\n",
    "        return sm\n",
    "        \n",
    "class ChessHorsePattern(object):\n",
    "    def chess_horse(self):\n",
    "        succers = self._helper.only_subdirect_successors()\n",
    "        lsuccers = len(succers)\n",
    "\n",
    "        if (lsuccers >= 1):\n",
    "            notdrawed = self._helper.only_subdirect_not_drawed()\n",
    "            lnotdrawed = len(notdrawed)\n",
    "\n",
    "            is_not_drawed = lsuccers - lnotdrawed\n",
    "\n",
    "            posy = self._max_empty_y(self._step)\n",
    "\n",
    "            diff = 0\n",
    "            for item in succers:\n",
    "                w = self._helper.get_weight(item)\n",
    "                switch_y = self.chess_horse_eligible_y(item, w)\n",
    "                diff = ((w + switch_y) - self._step)\n",
    "\n",
    "            if is_not_drawed == 0:\n",
    "                diff -= 1\n",
    "\n",
    "            self.chess_horse_dummie(diff, posy)\n",
    "            self.chess_horse_balance()\n",
    "\n",
    "    def chess_horse_balance(self):\n",
    "        succers = self._helper.only_direct_not_drawed()\n",
    "        succers_size = len(succers)\n",
    "\n",
    "        if succers_size >= 1:\n",
    "            self.balance_nodes(1)\n",
    "\n",
    "    def chess_horse_dummie(self, diff, posy):\n",
    "        for rg in range(diff):\n",
    "            nstep = self._step + rg + 1\n",
    "\n",
    "            if not self._grid.has_pos(nstep, posy):\n",
    "                self._grid.create_dummy((nstep, posy))\n",
    "\n",
    "    def chess_horse_eligible_y(self, label, w):\n",
    "        diff = 0\n",
    "\n",
    "        if self._grid.in_index(label):\n",
    "            mypos = self._grid.get_index(label)\n",
    "            start_search_y = mypos[1] + mypos[2]\n",
    "            end_search_y = self._max_empty_y(w)\n",
    "\n",
    "            nstep = self.chess_horse_recursive_y(start_search_y, end_search_y, mypos[0], label)\n",
    "            diff = nstep - w\n",
    "\n",
    "            if nstep != w:\n",
    "                self._grid.make_swift(label, nstep)\n",
    "\n",
    "        return diff\n",
    "\n",
    "    def chess_horse_recursive_y(self, y1, y2, step, label):\n",
    "        mx = step + 20\n",
    "        while step <= mx:\n",
    "            check = self.chess_horse_find_y(y1, y2, step, label)\n",
    "\n",
    "            if check:\n",
    "                break\n",
    "            else:\n",
    "                step += 1\n",
    "\n",
    "        return step\n",
    "\n",
    "    def chess_horse_find_y(self, y1, y2, step, node):\n",
    "        last_node = self.find_next_node(y1, y2, step)\n",
    "        return (last_node == False or last_node == node)\n",
    "\n",
    "\n",
    "class ChessPawnPattern(object):\n",
    "    \n",
    "    def chess_pawn(self):\n",
    "        is_root = self._helper.get_node_attr('root')\n",
    "        step = self._helper.get_node_attr('weight')\n",
    "        posy = self._default_y()\n",
    "\n",
    "        if is_root and step > 0:\n",
    "            self._grid.create_dummy((self._step, posy), self._options.get('force_mark'))\n",
    "            self._step += 1\n",
    "        \n",
    "        \n",
    "class BalancePattern(object):\n",
    "\n",
    "    def soft_balance(self, step_pace=1):\n",
    "        subsuccers = self._helper.only_subdirect_successors()\n",
    "        succers = self._helper.only_direct_not_drawed()\n",
    "        succers_size = len(succers + subsuccers)\n",
    "\n",
    "        start_y = self._default_y()\n",
    "\n",
    "        nstep = self._step + step_pace\n",
    "        nposy = self._max_empty_y(nstep)\n",
    "\n",
    "        if (succers_size > 0) and (start_y > nposy):\n",
    "            diff = start_y - nposy\n",
    "            for i in range(diff):\n",
    "                posy = nposy + i\n",
    "                self._grid.create_dummy((nstep, posy))\n",
    "\n",
    "    def self_balance(self, step_pace=0):\n",
    "        subsuccers = self._helper.only_subdirect_successors()\n",
    "        succers = self._helper.only_direct_not_drawed()\n",
    "        succers_size = len(succers + subsuccers)\n",
    "\n",
    "        start_y = self._default_y()\n",
    "\n",
    "        nstep = self._step + step_pace\n",
    "        nposy = self._max_empty_y(nstep)\n",
    "\n",
    "        if (start_y < nposy):\n",
    "            diff = nposy - start_y\n",
    "            for i in range(diff):\n",
    "                posy = start_y + i\n",
    "                self._grid.create_dummy((self._step, posy))\n",
    "\n",
    "            self.balance_nodes(diff)\n",
    "\n",
    "    def predecessors_balance(self, step_pace=1):\n",
    "        preds = self._helper.grab_drawed_predecers()\n",
    "        succers_size = len(preds)\n",
    "\n",
    "        if succers_size > 0:\n",
    "            pred = self._grid.get_index(preds[0])\n",
    "            nposy = pred[1]\n",
    "            start_y = self._default_y()\n",
    "\n",
    "            if (start_y < nposy):\n",
    "                diff = nposy - start_y\n",
    "                for i in range(diff):\n",
    "                    posy = start_y + i\n",
    "                    self._grid.create_dummy((self._step, posy))\n",
    "\n",
    "    def child_balance(self):\n",
    "        succers = self._helper.only_direct_not_drawed()\n",
    "        succers_size = len(succers)\n",
    "\n",
    "        if succers_size >= 2:\n",
    "            self.balance_nodes(succers_size - 1)\n",
    "\n",
    "    def balance_nodes(self, qtd):\n",
    "        for nl in range(self._step):\n",
    "            last = self._max_empty_y(nl)\n",
    "            for np in range(qtd):\n",
    "                posy = last + np\n",
    "                self._grid.create_dummy((nl, posy), self._options.get('grow_mark'))\n",
    "\n",
    "            anode = self.find_next_node(0, last + 1, nl)\n",
    "            if anode:\n",
    "                self._grid.inc_size_index(anode, qtd)\n",
    "                \n",
    "                \n",
    "class IteratorMasterPattern(BasePattern, SinglePattern, BalancePattern, ChessHorsePattern, ChessPawnPattern):\n",
    "    def map(self):\n",
    "        return ['self_balance', 'predecessors_balance', 'chess_pawn', 'chess_horse', 'soft_balance', 'child_balance', 'set_position']\n",
    "\n",
    "    def find_rule(self):\n",
    "        for check in self.map():\n",
    "            getattr(self, check)()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 362,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.965388Z",
     "start_time": "2018-10-29T00:48:11.958100Z"
    }
   },
   "outputs": [],
   "source": [
    "\n",
    "class HelperClearEmptyLines(object):\n",
    "\n",
    "    def __init__(self):\n",
    "        self._dmark = '-'\n",
    "        self._tombstone = []\n",
    "        self._swfgrid = {}\n",
    "        self._swfindex = {}\n",
    "\n",
    "    def run(self, grid, index):\n",
    "        self._swfindex = index\n",
    "        self.cleanning(grid)\n",
    "        return self._swfgrid, self._swfindex\n",
    "\n",
    "    def cleanning(self, grid):\n",
    "        for row in grid:\n",
    "            empty = True\n",
    "\n",
    "            for line in grid[row]:\n",
    "                m = grid[row][line][-1]\n",
    "                \n",
    "                if (self._dmark != m):\n",
    "                    empty = False\n",
    "                    self.addSwf(row, grid[row])\n",
    "                    break;\n",
    "\n",
    "            if (empty):\n",
    "                self._tombstone.append(row)\n",
    "\n",
    "    def addSwf(self, row, line):\n",
    "        qtd = len(self._tombstone)\n",
    "        diff = row - qtd\n",
    "        self._swfgrid[diff] = line\n",
    "\n",
    "        if qtd > 0:\n",
    "            self.swfIndex(qtd, line)\n",
    "\n",
    "    def swfIndex(self, qtd, items):\n",
    "\n",
    "        for item in items:\n",
    "            uid = items[item]\n",
    "            if (self._dmark != uid[0]):\n",
    "                node = self._swfindex[uid]\n",
    "                swft = node[0] - qtd\n",
    "\n",
    "                self._swfindex[uid] = (swft, node[1], node[2], node[3])\n",
    "        \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 363,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:11.990673Z",
     "start_time": "2018-10-29T00:48:11.967351Z"
    }
   },
   "outputs": [],
   "source": [
    "from operator import itemgetter\n",
    "\n",
    "class HelperOrderedSuccers(object):\n",
    "    def __init__(self, helper):\n",
    "        self._temp = []\n",
    "        self._helper = helper\n",
    "\n",
    "    def get_succers(self):\n",
    "        subdirect = self._helper.only_subdirect_not_drawed()\n",
    "        direct = self.make_sorted()\n",
    "        return subdirect + direct\n",
    "\n",
    "    def make_sorted(self):\n",
    "        succers = self._helper.only_direct_not_drawed()\n",
    "\n",
    "        for succer in succers:\n",
    "            rating = self.find_rating(succer)\n",
    "            self._temp.append((rating, succer))\n",
    "\n",
    "        ordered = sorted(self._temp, key=itemgetter(0))\n",
    "        return [i[1] for i in ordered]\n",
    "\n",
    "    def find_rating(self, succer):\n",
    "        preds = self._helper.grab_predecessors(succer)\n",
    "\n",
    "        rating = 0\n",
    "        if len(preds) >= 2:\n",
    "            for pred in preds:\n",
    "                score = self.score(pred, self._helper.get_id())\n",
    "                rating += score\n",
    "\n",
    "        return rating\n",
    "\n",
    "    def score(self, pred, ignore):\n",
    "        sc = 0\n",
    "        if (pred != ignore):\n",
    "\n",
    "            if (self._helper._grid.in_index(pred)):\n",
    "                sc = -1\n",
    "            else:\n",
    "                sc = 1\n",
    "\n",
    "        return sc\n",
    "\n",
    "class HelperSetupWeight(object):\n",
    "    def __init__(self, G):\n",
    "        super().__init__()\n",
    "        self._graph = G\n",
    "\n",
    "    def find_weight(self, item, weight=0):\n",
    "        pred = self._graph.in_edges(item, data=True)\n",
    "\n",
    "        if pred and len(list(pred)) > 0:\n",
    "            weight = max([it[2].get('weight') for it in pred]) + 1\n",
    "\n",
    "        return weight\n",
    "\n",
    "    def setup(self):\n",
    "        nodes = self._graph.nodes()\n",
    "\n",
    "        for node in nodes:\n",
    "            w = self.find_weight(node)\n",
    "            self._graph.nodes[node]['weight'] = w\n",
    "\n",
    "class GridOrchestrator(object):\n",
    "    def __init__(self, G, GMap=GridMap):\n",
    "        self._graph = G\n",
    "        self._grid = GMap()\n",
    "\n",
    "    def get_mapping(self):\n",
    "        grid = self._grid.get_grid()\n",
    "        index = self._grid.get_index()\n",
    "        return HelperClearEmptyLines().run(grid, index)\n",
    "\n",
    "    def create(self, entries, SHelper=HelperSetupWeight):\n",
    "        SHelper(self._graph).setup()\n",
    "        self._recursive_draw(entries)\n",
    "\n",
    "    def add_pos_grid(self, node, CIterator=IteratorMasterPattern, CHelper=HelperDefineAttributes):\n",
    "        Helper = CHelper(node, self._grid, self._graph)\n",
    "        CIterator(self._grid, Helper).find_rule()\n",
    "\n",
    "        return Helper\n",
    "\n",
    "    def _recursive_draw(self, app, i=0, OHelper=HelperOrderedSuccers):\n",
    "        if i > 30:\n",
    "            return\n",
    "\n",
    "        for item in app:\n",
    "            if not self._grid.in_index(item):\n",
    "                node = self._graph.nodes[item]\n",
    "                helper = self.add_pos_grid(node)\n",
    "\n",
    "                succ = OHelper(helper).get_succers()\n",
    "                self._recursive_draw(succ, i + 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 364,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2018-10-29T00:48:12.013653Z",
     "start_time": "2018-10-29T00:48:11.994642Z"
    },
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-------------------------\n",
      "6\n",
      "f\n",
      "3\n",
      "f\n",
      "5\n"
     ]
    },
    {
     "data": {
      "image/svg+xml": [
       "<svg baseProfile=\"full\" height=\"120\" version=\"1.1\" width=\"300\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:ev=\"http://www.w3.org/2001/xml-events\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><defs/><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"0\" y=\"0\"/><text fill=\"red\" x=\"0\" y=\"10\">app5</text><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"0\" y=\"60\"/><text fill=\"red\" x=\"0\" y=\"70\">app2</text><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"60\" y=\"0\"/><text fill=\"red\" x=\"60\" y=\"10\">-f</text><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"60\" y=\"60\"/><text fill=\"red\" x=\"60\" y=\"70\">-</text><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"120\" y=\"0\"/><text fill=\"red\" x=\"120\" y=\"10\">app4</text><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"120\" y=\"60\"/><text fill=\"red\" x=\"120\" y=\"70\">-</text><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"180\" y=\"0\"/><text fill=\"red\" x=\"180\" y=\"10\">-f</text><rect fill=\"rgb(255,255,0)\" height=\"20px\" stroke=\"black\" stroke-width=\"1\" width=\"20px\" x=\"240\" y=\"0\"/><text fill=\"red\" x=\"240\" y=\"10\">app1</text><line fill=\"rgb(0,0,0)\" stroke=\"black\" stroke-width=\"1\" x1=\"140\" x2=\"240\" y1=\"10.0\" y2=\"10.0\"/><line fill=\"rgb(0,0,0)\" stroke=\"black\" stroke-width=\"1\" x1=\"20\" x2=\"120\" y1=\"70.0\" y2=\"10.0\"/></svg>"
      ],
      "text/plain": [
       "<IPython.core.display.SVG object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import SVG, display\n",
    "\n",
    "print(\"-------------------------\")\n",
    "Orchestration = GridOrchestrator(G)\n",
    "Orchestration.create(entries)\n",
    "\n",
    "Layout = DrawLayout(*Orchestration.get_mapping())\n",
    "Layout.draw_nodes()\n",
    "Layout.draw_connections(G.edges(data='endpoint'))\n",
    "Layout.save()\n",
    "\n",
    "#print(Orchestration.get_grid().get_grid())\n",
    "#print(Orchestration.get_grid()._index)\n",
    "#print(G.edges(data='endpoint'))\n",
    "   \n",
    "display(SVG(filename='test.svg'))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "an",
   "language": "python",
   "name": "an"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}