Skip to content

Instantly share code, notes, and snippets.

@kellyrob99
Created April 24, 2012 01:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kellyrob99/2475460 to your computer and use it in GitHub Desktop.
Save kellyrob99/2475460 to your computer and use it in GitHub Desktop.
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
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