Qiita apiでライバルを探せ。

#概要
Qiita apiを叩いて、自分をフォローしている方々のフォローリストの中にライバルとなる方がいないか、調べてみた。
いた。knoguchiさんだ。

#写真
![](http://jsdo-static-contents.s3.amazonaws.com/images/capture/6/P/o/6Pow.jpg?t=1489184649)

#成果物

http://jsdo.it/ohisama1/kbaP
http://jsdo.it/ohisama1/6Pow

#サンプルコード

```
var usr = [{
    "name": "ohisama@github",
    "imports": ["knoguchi","yukimori","stone89son","soburi","kexi","7of9","ienaga","takish","nubata","selious","tm1122@github"]
}];
var main = [];
var map = {};
main.push(usr[0]);
var res = [];
for (var a in usr[0].imports)
{
    var name = usr[0].imports[a];
    var url = "https://qiita.com/api/v2/users/" + name + "/followees?page=1&per_page=20";
    alert(url);
    res.push($.ajax({
        url: url,
        type: 'GET'
    }));
}
$.when.apply($, res).done(function() {
    for (var i = 0; i < arguments.length; i++) 
    {
        var result = arguments[i];
        var name = usr[0].imports[i];
        var json = result[0];
        var nl = []; 
        for (var j in json)
        {
            var jj = json[j].id;
            nl.push(jj);
            var node = map[jj];
            if (!node) 
            {
                map[jj] = 0;
                main.push({ 
                    "name": jj,
                    "imports": [name]
                });
            }
        }
        main.push({
            "name": name,
            "imports": nl
        });
    }
    var json = JSON.stringify(main);
    var blob = new Blob([json], {
        type: "application/json"
    });
    var url1 = URL.createObjectURL(blob);
    var a = document.createElement('a');    
    a.download = "koko2.json";
    a.href = url1;
    a.textContent = "Download koko2.json";
    document.getElementById('koko').appendChild(a);
});
```

#サンプルコード

```
var diameter = 960,
    radius = diameter / 2,
    innerRadius = radius - 120;
var cluster = d3.layout.cluster().size([360, innerRadius]).sort(null).value(function(d) { 
    return d.size;
});
var bundle = d3.layout.bundle();
var line = d3.svg.line.radial().interpolate("bundle").tension(.85).radius(function(d) {
    return d.y;
}).angle(function(d) {
    return d.x / 180 * Math.PI;
});
var svg = d3.select("body").append("svg").attr("width", diameter).attr("height", diameter).append("g").attr("transform", "translate(" + radius + "," + radius + ")");
var link = svg.append("g").selectAll(".link"),
    node = svg.append("g").selectAll(".node");
function mouseovered(d) {
    node.each(function(n) { 
        n.target = n.source = false;
    });
    link.classed("link--target", function(l) {
        if (l.target === d) return l.source.source = true;
    }).classed("link--source", function(l) { 
        if (l.source === d) return l.target.target = true;
    }).filter(function(l) { 
        return l.target === d || l.source === d;
    }).each(function() { 
        this.parentNode.appendChild(this); 
    });
    node.classed("node--target", function(n) {
        return n.target;
    }).classed("node--source", function(n) {
        return n.source;
    });
}
function mouseouted(d) {
    link.classed("link--target", false).classed("link--source", false);
    node.classed("node--target", false).classed("node--source", false);
}
d3.select(self.frameElement).style("height", diameter + "px");
function packageHierarchy(classes) {
    var map = {};
    function find(name, data) {
        var node = map[name],
            i;
        if (!node) 
        {
            node = map[name] = data || {
                name: name, 
                children: []
            };
            if (name.length)
            {
                node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
                node.parent.children.push(node);
                node.key = name.substring(i + 1);
            }
        }
        return node;
    }
    classes.forEach(function(d) {
        find(d.name, d);
    });
    return map[""];
}
function packageImports(nodes) {
    var map = {},
        imports = [];
    nodes.forEach(function(d) {
        map[d.name] = d;
    });
    nodes.forEach(function(d) {
        if (d.imports) d.imports.forEach(function(i) {
            imports.push({
                source: map[d.name],
                target: map[i]
            });
        });
    });
    return imports;
}
d3.json("http://jsrun.it/assets/4/Y/j/5/4Yj5j", function(error, classes) {
    if (error) throw error;
    var nodes = cluster.nodes(packageHierarchy(classes)),
        links = packageImports(nodes);
    node = node.data(nodes.filter(function(n) {
        return !n.children;
    })).enter().append("text").attr("class", "node").attr("dy", ".31em").attr("transform", function(d) {
        return "rotate(" + (d.x - 90) + ")translate(" + (d.y + 8) + ",0)" + (d.x < 180 ? "" : "rotate(180)"); 
    }).style("text-anchor", function(d) {
        return d.x < 180 ? "start" : "end";
    }).text(function(d) {
        return d.key; 
    }).on("mouseover", mouseovered).on("mouseout", mouseouted);
    link = link.data(bundle(links)).enter().append("path").each(function(d) {
        d.source = d[0],
        d.target = d[d.length - 1];
    }).attr("class", "link").attr("d", line);
});
```