Read in a JSON file mapping Github users to those watching their repositories and output a GraphViz dot file representing the relationships. The file consumed is the output of the code found in https://gist.github.com/2468052
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import groovy.json.JsonSlurper | |
final rootUser = args[0] | |
final filename = args[1] | |
def data | |
new File(filename).withReader {reader -> | |
data = new JsonSlurper().parse(reader) | |
} | |
println "Number of mapped users = ${data.size()}" | |
println "Number of watchers = ${data.values().flatten().size()}" | |
println "Number of unique watchers = ${data.values().flatten().unique().size()}" | |
//group the data by the number of watchers | |
final Map groupedData = data.groupBy {it.value.size()}.sort {-it.key} | |
final Set allWatchers = data.collect {it.value}.flatten() | |
final Set allUsernames = data.keySet() | |
final Set leafNodes = allWatchers - allUsernames | |
final RANK_JOINER = '; ' | |
Closure generateNodeAttrs = { username, count -> | |
return "label=\"$username = $count\" URL=\"https://github.com/$username\"" | |
} | |
Closure generateNodeAttrsMemoized = generateNodeAttrs.memoize() | |
//create edges from each watcher to the username they are watching | |
Closure createEdges = {Map users -> | |
StringWriter writer = new StringWriter() | |
users.each { username, watchers -> | |
watchers.each { watcher -> | |
writer << "\t\"$watcher\" -> \"$username\";\n" | |
} | |
} | |
writer.toString() | |
} | |
Closure extraAttrs = {count, username -> | |
return "" | |
} | |
Closure extraAttrsMemoized = extraAttrs.memoize() | |
//style nodes for each username, including a link to their github page(useful only for certain output types like svg) | |
Closure createNodes = {Map groupedUsers -> | |
StringWriter writer = new StringWriter() | |
groupedUsers.each {count, users -> | |
users.each { username, watchers -> | |
def user = "\t\"$username\"" | |
def attrs = generateNodeAttrsMemoized(username, count) | |
def rootAttrs = "fillcolor=red style=filled $attrs" | |
if (username == rootUser) { | |
writer << "$user [$rootAttrs];\n" | |
} else { | |
writer << "$user [$attrs ${extraAttrsMemoized(count, username)}];\n" | |
} | |
} | |
} | |
leafNodes.each { leafNode -> | |
def user = "\t\"$leafNode\"" | |
def attrs = generateNodeAttrs(leafNode, 'U') | |
writer << "$user [$attrs ${extraAttrsMemoized(0, leafNode)}];\n" | |
} | |
writer.toString() | |
} | |
//rank the nodes based upon how many watchers | |
Closure createRanks = {Map groupedUsers -> | |
StringWriter writer = new StringWriter() | |
groupedUsers.each { count, Map users -> | |
writer << "\t{rank=same; ${users.keySet().collect {"\"$it\""}.join(RANK_JOINER)};} // $count watchers\n" | |
} | |
def max = groupedUsers.get(groupedUsers.keySet().max()) | |
def min = groupedUsers.get(groupedUsers.keySet().min()) | |
writer << "\t{rank=max; ${max.keySet().collect {"\"$it\""}.join(RANK_JOINER)};}\n" | |
writer << "\t{rank=min; ${min.keySet().collect {"\"$it\""}.join(RANK_JOINER)};}\n" | |
writer.toString() | |
} | |
new File('reposDigraph.dot').withWriter {writer -> | |
writer << "digraph \"Github social graph\" {\n" | |
writer << createNodes(groupedData) | |
writer << createEdges(data) | |
writer << createRanks(groupedData) | |
writer << "}\n" | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment