<!DOCTYPE html>
<html>

  <head>
     <meta charset="utf-8">     
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Tangerine">
     <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
     <title>graph</title>

     <script src='http://d3js.org/d3.v3.min.js'></script>     
     <link rel="stylesheet" type="text/css" href="style.css">
 </head>

<body ng-app="myApp">
     <script src="GenerateGraph.js" type="text/javascript"></script>
     <script src="svgGraph.js" type="text/javascript"></script>
     <h1 class="title">Simulating a network</h1>
     <div id="outer" ng-controller="MainCtrl" class="col-md-6">
        <network-inputs val="data" inputs="networkInputs" submit="submit(inputs)"></network-inputs>
     </div> 
    <!--test -->
     <script type="text/javascript">

        //get the input parameters for plotting
         angular.module("myApp", [])

         .directive('networkInputs', function() {

         return {
                restrict: 'E',                
                scope: {
                   inputs: '<',
                   submit: '&',
                   val:'='
                },
                link : link,               
                template: 
              '<h3 >Initialise new parameters to generate a network </h3>'+
                    '<form name="form" novalidate ng-submit="submit({inputs: inputs})" class="form-inline">'+
                      '<div class="form-group">'+
                         '<label>Number of nodes</label>'+
                         '<input type="number" min="10" class="form-control" ng-model="inputs.N" ng-required="true">'+
                      '</div>'+
                      '<div class="form-group">'+
                         '<label>Number of links</label>'+
                          '<input type="number" min="0.1" class="form-control" ng-model="inputs.m" ng-required="true">'+
                      '</div>'+
                      '<button style="color:black; margin: 1rem 4rem;" type="submit">Generate</button>' +
                   '</form>'};
         })
         .factory("initialiseNetwork",function(){
            var data = {
                            N: 20,
                            m: 50,

                       };

            return {
                networkInputs:data
            };      

         })

         .controller("MainCtrl",  ['$scope','initialiseNetwork' ,function($scope,initialiseNetwork) {

               $scope.networkInputs={};
               $scope.mySVG=function(){
                         var graph=randomGraph($scope.networkInputs.N, $scope.networkInputs.m);

                };

               function init(){
                  $scope.networkInputs=initialiseNetwork.networkInputs;
                   //Run the function which generates the graph and plot it 
                  $scope.data = randomGraph($scope.networkInputs.N, $scope.networkInputs.m);
               }
               init();

               $scope.submit = function(inputs) {

                   var dataObject = {
                       N: inputs.N,
                       m: inputs.m
                   };
                   $scope.data = randomGraph(dataObject.N, dataObject.m);
                   //lets simply log them but you can plot or smth other 
                   console.log($scope.networkInputs); 

               }

         }]);

    </script>
</body>
</html>
// Code goes here
function link(scope, element, attrs) {
  //SVG size
  var width = 500,
    height = 300;

  // We only need to specify the dimensions for this container.

  var vis = d3.select(element[0]).append('svg')
    .attr('width', width)
    .attr('height', height);

  var force = d3.layout.force()
    .gravity(.05)
    .distance(100)
    .charge(-100)
    .size([width, height]);
  // Extract the nodes and links from the data.
  scope.$watch('val', function(newVal, oldVal) {
    vis.selectAll('*').remove();
    if (!newVal) {
      return;
    }

    var Glinks = newVal.Links;
    var W = degree(newVal.Node, newVal.ListEdges);

    var Gnodes = [];
    var obj = newVal.Node;
    Object.keys(obj).forEach(function(key) {
      Gnodes.push({
        "name": key,
        "count": W[key]
      });
    });
    //Creates the graph data structure 
    force.nodes(Gnodes)
      .links(Glinks)
      .linkDistance(function(d) {
        return (0.1 * Glinks.length);
      }) //link length
      .start();
    //Create all the line svgs but without locations yet
    var link = vis.selectAll(".link")
      .data(Glinks)
      .enter().append("line")
      .attr("class", "link")
      .style("stroke-width", "0.3px");

    //Do the same with the circles for the nodes - no 
    var node = vis.selectAll(".node")
      .data(Gnodes)
      .enter().append("g")
      .attr("class", "node")
      .call(force.drag);
    node.append("circle")
      .attr("r", function(d) {
        return d.count * 0.5;
      })
      .style("opacity", .3)
      .style("fill", "red");
    //add degree of node as text 
    node.append("text")
      .attr("text-anchor", "middle")
      .text(function(d) {
        return d.count
      })
      .attr("font-family", 'Raleway', "Tangerine");
    //Now we are giving the SVGs co-ordinates - the force layout is generating the co-ordinates which this code is using to update the attributes of the SVG elements
    force.on("tick", function() {
      link.attr("x1", function(d) {
          return d.source.x;
        })
        .attr("y1", function(d) {
          return d.source.y;
        })
        .attr("x2", function(d) {
          return d.target.x;
        })
        .attr("y2", function(d) {
          return d.target.y;
        });

      node.attr("transform", function(d) {
        return "translate(" + d.x + "," + d.y + ")";
      });
    });
  });
}
.title {
            font-family: 'Tangerine', serif;
            font-size: 80px;
            font-weight: Bold;
            color:darkblue;
            text-align: center;
            padding-bottom: 20px;
}

.node {
            fill: #ccc;
            stroke: #fff;
            stroke-width: 1px;
}

.link {
            stroke: #777;
            stroke-width: 2px;
}
svg{
            background-color:burlywood;   
}
form{
            display: flex;
            flex-direction: column;
            align-items: flex-end;
}
input {
            margin: 5px 5px;
            padding:5px 5px;
            width:30%;
}
h3 {
            font-family:'Tangerine'; 
            text-align:left;
            color:aquamarine;
            font-size: 55px;
            font-weight: Bold; 
}
label{
            color:blueviolet;
            font-family:'Tangerine'; 
            font-weight: Bold;
            font-size: 40px;
}
body{
            background-color: #F07575; 
            background-image: -webkit-linear-gradient(top, hsl(0, 80%, 70%), #bada55); 
            background-image: -moz-linear-gradient(top, hsl(0, 80%, 70%), #bada55); 
            background-image: -o-linear-gradient(top, hsl(0, 80%, 70%), #bada55);  
            background-image: linear-gradient(to bottom, hsl(0, 80%, 70%), #bada55); 
            width=100%;
            height: 600px;
}

function degree(node,list){
  var deg=new Array();
  for (var i=0; i<node.length; i++){
    var count=0;
    for (var j=0; j<list.length; j++){
        if (node[i]==list[j][0] || node[i]==list[j][1]){
          count++;
        }
    }
    deg.push(count);
  }
  return deg;
}
function randomGraph (n, m) { //creates a random graph on n nodes and m links
  var graph={};
  var nodes = d3.range(n).map(Object),
      list  = randomChoose(unorderedPairs(d3.range(n)), m),
      links = list.map(function (a) { return {source: a[0], target: a[1]} });
  graph={
  Node:nodes,
  ListEdges:list,
  Links:links
  }
  return graph;
}

function randomChoose (s, k) { // returns a random k element subset of s
  var a = [], i = -1, j;
  while (++i < k) {
    j = Math.floor(Math.random() * s.length);
    a.push(s.splice(j, 1)[0]);
  }
  return a;
}

function unorderedPairs (s) { // returns the list of all unordered pairs from s
  var i = -1, a = [], j;
  while (++i < s.length) {
    j = i;
    while (++j < s.length) a.push([s[i],s[j]])
  }
  return a;
}